基于向量存储的内存
VectorStoreRetrieverMemory 将内存存储在 VectorDB 中,并在每次调用时查询前 K 个最“显著”的文档。
与大多数其他内存类不同的是,它不明确跟踪交互的顺序。
在这种情况下,“文档”是先前的对话片段。这对于引用 AI 在对话中早些时候被告知的相关信息是有用的。
from datetime import datetime
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.memory import VectorStoreRetrieverMemory
from langchain.chains import ConversationChain
from langchain.prompts import PromptTemplate
初始化您的 VectorStore
根据您选择的存储,此步骤可能会有所不同。请参考相关的VectorStore文档以获取更多详细信息。
import faiss
from langchain.docstore import InMemoryDocstore
from langchain.vectorstores import FAISS
embedding_size = 1536 # OpenAIEmbeddings的维度
index = faiss.IndexFlatL2(embedding_size)
embedding_fn = OpenAIEmbeddings().embed_query
vectorstore = FAISS(embedding_fn, index, InMemoryDocstore({}), {})
创建您的VectorStoreRetrieverMemory
从任何VectorStoreRetriever实例化内存对象。
# 在实际使用中,您可以将`k`设置为较高的值,但我们使用k=1来显示向量查找仍然返回语义相关信息
retriever = vectorstore.as_retriever(search_kwargs=dict(k=1))
memory = VectorStoreRetrieverMemory(retriever=retriever)
# 当添加到代理时,内存对象可以保存对话或使用工具的相关信息
memory.save_context({"input": "我最喜欢的食物是披萨"}, {"output": "好的,我知道了"})
memory.save_context({"input": "我最喜欢的运动是足球"}, {"output": "..."})
memory.save_context({"input": "我不喜欢凯尔特人队"}, {"output": "好的"})
# 注意,返回的第一个结果是与税务帮助相关的记忆,语言模型认为这比其他文档更具语义相关性,尽管它们都包含数字。
print(memory.load_memory_variables({"prompt": "我应该看什么运动?"})["history"])
input: 我最喜欢的运动是足球
output: ...
在链中使用
让我们通过一个例子来说明,再次设置verbose=True以便我们可以看到提示。
llm = OpenAI(temperature=0) # 可以是任何有效的LLM
_DEFAULT_TEMPLATE = """以下是人类和AI之间友好对话的一部分。AI健谈并从其上下文中提供了许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。
先前对话的相关部分:
{history}
(如果不相关,您不需要使用这些信息)
当前对话:
人类:{input}
AI:"""
PROMPT = PromptTemplate(
input_variables=["history", "input"], template=_DEFAULT_TEMPLATE
)
conversation_with_summary = ConversationChain(
llm=llm,
prompt=PROMPT,
# 为了测试目的,我们设置了一个非常低的max_token_limit。
memory=memory,
verbose=True
)
conversation_with_summary.predict(input="嗨,我叫佩里,你好吗?")
> 进入新的ConversationChain链...
格式化后的提示:
以下是人类和AI之间友好对话的一部分。AI健谈并从其上下文中提供了许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。
先前对话的相关部分:
input: 我最喜欢的食物是披萨
output: 好的,我知道了
(如果不相关,您不需要使用这些信息)
当前对话:
人类:嗨,我叫佩里,你好吗?
AI:
> 完成链。
"嗨佩里,我很好。你呢?"
在这里,与篮球相关的内容被展示出来。
conversation_with_summary.predict(input="我的最喜欢的运动是什么?")
> 进入新的ConversationChain链...
格式化后的提示:
以下是人类和AI之间友好对话的一部分。AI健谈并从其上下文中提供了许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。
先前对话的相关部分:
input: 我最喜欢的运动是足球
output: ...
(如果不相关,您不需要使用这些信息)
当前对话:
人类:我的最喜欢的运动是什么?
AI:
> 完成链。
'你之前告诉我你最喜欢的运动是足球。'
尽管语言模型是无状态的,但由于获取了相关的记忆,它可以“推理”时间。
conversation_with_summary.predict(input="我的最喜欢的食物是什么")
> 进入新的ConversationChain链...
格式化后的提示:
以下是人类和AI之间友好对话的一部分。AI健谈并从其上下文中提供了许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。
先前对话的相关部分:
input: 我最喜欢的食物是披萨
output: 好的,我知道了
(如果不相关,您不需要使用这些信息)
当前对话:
人类:我的最喜欢的食物是什么
AI:
> 完成链。
'你说你最喜欢的食物是披萨。'
对话中的记忆会自动存储,由于此查询最符合上述介绍聊天,代理能够“记住”用户的姓名。
conversation_with_summary.predict(input="我的名字是什么?")
> 进入新的ConversationChain链...
格式化后的提示:
以下是人类和AI之间友好对话的一部分。AI健谈并从其上下文中提供了许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。
先前对话的相关部分:
input: 嗨,我叫佩里,你好吗?
response: 嗨佩里,我很好。你呢?
(如果不相关,您不需要使用这些信息)
当前对话:
人类:我的名字是什么?
AI:
> 完成链。
'你的名字是佩里。'
