Redis 作为上下文存储与 OpenAI Chat
本笔记本演示了如何将 Redis 用作 ChatGPT 的高速上下文内存。
先决条件
- 具有 Redis Search 和 Redis JSON 模块的 Redis 实例
- Redis-py 客户端库
- OpenAI Python 客户端库
- OpenAI API 密钥
安装
安装示例所需的 Python 模块。
! pip install -q redis openai python-dotenv 'openai[datalib]'
OpenAI API 密钥
创建一个 .env 文件并将您的 OpenAI 密钥添加到其中。
OPENAI_API_KEY=your_key
OpenAI 设置
密钥加载 + 用于聊天补全的辅助函数。
from openai import OpenAI
import os
from dotenv import load_dotenv
load_dotenv()
oai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def get_completion(prompt, model="gpt-3.5-turbo"):
messages = [{"role": "user", "content": prompt}]
response = oai_client.chat.completions.create(
model=model,
messages=messages,
temperature=0,
)
return response.choices[0].message.content
实验 - 对模型知识截止日期之外的主题进行聊天补全
Gpt-3.5-turbo 的训练数据截止到 2021 年 9 月。让我们问它一个关于该日期之后的事情。在这种情况下,是 FTX/Sam Bankman-Fried 的丑闻。我们在这里使用一个旧模型进行演示。较新的模型,如 gpt-4o,具有较晚的知识截止日期(2023 年末),在这里也能正常工作。
prompt = "FTX,Sam Bankman-Fried 的公司,是否被认为是一家管理良好的公司?"
response = get_completion(prompt)
print(response)
是的,FTX 通常被认为是一家管理良好的公司。FTX 的创始人兼首席执行官 Sam Bankman-Fried 在加密货币行业拥有良好的业绩记录,并已成功将该公司发展成为全球领先的加密货币交易所之一。FTX 还因其用户友好的平台、创新的产品和强大的客户服务而获得好评。此外,FTX 在监管合规方面一直很积极,并已采取措施确保用户资金的安全。总的来说,FTX 被视为加密货币领域的管理良好的公司。
信息不完整
这些 AI 系统的一个不幸行为是,即使系统对其结果没有信心,它也会提供听起来很自信的响应。一种缓解此问题的方法是进行提示工程,如下所示。
prompt ="FTX,Sam Bankman-Fried 的公司,是否被认为是一家管理良好的公司? 如果您不确定,请说未知。"
response = get_completion(prompt)
print(response)
FTX 通常被认为是一家管理良好的公司。其创始人兼首席执行官 Sam Bankman-Fried 在加密货币行业以其领导力和战略眼光而闻名。自 2017 年成立以来,FTX 也经历了显著的增长和成功。然而,如果没有具体的内部知识或数据,最终无法确定 FTX 是否被明确认为是一家管理良好的公司。
附加上下文
对抗信息不完整的另一种方法是为系统提供更多信息,以便它可以做出明智的决定,而不是猜测。我们将使用 Redis 作为该附加上下文的来源。我们将从 GPT 知识截止日期之后提取商业新闻文章,以便系统能够更好地理解 FTX 的实际管理情况。
启动 Redis Stack Docker 容器
! docker compose up -d
连接 Redis 客户端
from redis import from_url
REDIS_URL = 'redis://localhost:6379'
client = from_url(REDIS_URL)
client.ping()
True
创建索引
from redis.commands.search.field import TextField, VectorField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
schema = [ VectorField('$.vector',
"FLAT",
{ "TYPE": 'FLOAT32',
"DIM": 1536,
"DISTANCE_METRIC": "COSINE"
}, as_name='vector' ),
TextField('$.content', as_name='content')
]
idx_def = IndexDefinition(index_type=IndexType.JSON, prefix=['doc:'])
try:
client.ft('idx').dropindex()
except:
pass
client.ft('idx').create_index(schema, definition=idx_def)
b'OK'
将数据文件加载到 Redis 中,作为具有文本和向量字段的 JSON 对象
directory = './assets/'
model = 'text-embedding-3-small'
i = 1
for file in os.listdir(directory):
with open(os.path.join(directory, file), 'r') as f:
content = f.read()
# 使用新的基于客户端的方法创建嵌入
response = oai_client.embeddings.create(
model=model,
input=[content]
)
# 从响应对象访问嵌入
vector = response.data[0].embedding
# 使用您的 JSON 客户端存储内容和向量
client.json().set(f'doc:{i}', '$', {'content': content, 'vector': vector})
i += 1
嵌入问题并执行 VSS 以查找最相关的文档
from redis.commands.search.query import Query
import numpy as np
response = oai_client.embeddings.create(
input=[prompt],
model=model
)
# 从响应中提取嵌入向量
embedding_vector = response.data[0].embedding
# 将嵌入转换为 float32 类型的 numpy 数组,然后转换为字节
vec = np.array(embedding_vector, dtype=np.float32).tobytes()
# 构建并执行 Redis 查询
q = Query('*=>[KNN 1 @vector $query_vec AS vector_score]') \
.sort_by('vector_score') \
.return_fields('content') \
.dialect(2)
params = {"query_vec": vec}
context = client.ft('idx').search(q, query_params=params).docs[0].content
print(context)
将问题重复给 OpenAI 并附带上下文
现在我们有了相关的上下文,将其添加到 OpenAI 的提示中,并获得一个截然不同的响应。
prompt = f"""
使用三引号分隔的信息,回答这个问题:FTX,Sam Bankman-Fried 的公司,是否被认为是一家管理良好的公司?
上下文:```{context}```
"""
response = get_completion(prompt)
print(response)
根据提供的信息,FTX,Sam Bankman-Fried 的公司,并不被认为是一家管理良好的公司。该公司已面临破产程序、客户资金处理不当、未经授权的交易、被监管机构冻结资产,以及缺乏可信赖的财务信息。新任首席执行官 John J. Ray III 将此情况描述为“公司控制的完全失败”,并表示存在严重的管理不善。此外,该公司在处理数十亿美元业务时,其财务状况、记录保存的缺乏以及不充分的会计工具的使用,都引发了对其管理实践的严重担忧。