核心模块(Modules)
记忆(Memory)
类型(Types)
向量存储检索记忆(VectorstoreRetrieverMemory)

支持向量存储

VectorStoreRetrieverMemory将记忆存储在向量存储中,并在每次调用时查询最“显著”的前K个文档。

与大多数其他记忆类不同,它不明确跟踪交互的顺序。

在这种情况下,“文档”是先前的对话片段。这可以用来引用AI在对话早期告诉的相关信息。

from datetime import datetime
from langchain_openai import OpenAIEmbeddings
from langchain_openai import OpenAI
from langchain.memory import VectorStoreRetrieverMemory
from langchain.chains import ConversationChain
from langchain_core.prompts import PromptTemplate

初始化向量存储

根据您选择的存储方式,此步骤可能会有所不同。有关详细信息,请参阅相关向量存储的文档。

import faiss
 
from langchain.docstore import InMemoryDocstore
from langchain_community.vectorstores import FAISS
 
 
embedding_size = 1536  # OpenAIEmbeddings的维度
index = faiss.IndexFlatL2(embedding_size)
embedding_fn = OpenAIEmbeddings().embed_query
vectorstore = FAISS(embedding_fn, index, InMemoryDocstore({}), {})

创建VectorStoreRetrieverMemory

从任何向量存储检索器实例化内存对象。

# 在实际使用中,您可以将“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,
    memory=memory,
    verbose=True
)
conversation_with_summary.predict(input="你好,我叫Perry,怎么样?")



    > 进入新的ConversationChain链...
    格式化后的提示:
    以下是AI与人类之间的友好对话。AI健谈,提供了很多上下文的具体细节。如果AI不知道问题的答案,它会诚实地说它不知道。

    先前对话的相关片段:
    输入:我最喜欢的食物是比萨饼
    输出:这是个好消息

    (如果不相关,您不需要使用这些信息)

    当前对话:
    人类:你好,我叫Perry,怎么样?
    AI:

    > 完成链





    “嗨Perry,我很好。你呢?”

# 这里展示了与篮球相关的内容
conversation_with_summary.predict(input="我最喜欢的运动是什么?")



    > 进入新的ConversationChain链...
    格式化后的提示:
    以下是AI与人类之间的友好对话。AI健谈,提供了很多上下文的具体细节。如果AI不知道问题的答案,它会诚实地说它不知道。

    先前对话的相关片段:
    输入:我最喜欢的运动是足球
    输出:...

    (如果不相关,您不需要使用这些信息)

    当前对话:
    人类:我最喜欢的运动是什么?
    AI:

    > 完成链





    '你之前告诉我你最喜欢的运动是足球。'

# 即使语言模型是无状态的,由于获取了相关的记忆,它可以“推理”出时间的概念。
# 对记忆和数据进行时间戳是有用的,以便让代理程序确定时态相关性
conversation_with_summary.predict(input="我的最爱是什么食物")



    > 进入新的ConversationChain链...
    格式化后的提示:
    以下是AI与人类之间的友好对话。AI健谈,提供了很多上下文的具体细节。如果AI不知道问题的答案,它会诚实地说它不知道。

    先前对话的相关片段:
    输入:我最喜欢的食物是比萨饼
    输出:这是个好消息

    (如果不相关,您不需要使用这些信息)

    当前对话:
    人类:我的最爱是什么食物
    AI:

    > 完成链





    '你说过你最喜欢的食物是比萨饼。'

# 对话中的记忆会被自动存储,
# 由于此查询最符合上述引言聊天,代理程序能够“记住”用户的名字。
conversation_with_summary.predict(input="我的名字是什么?")



    > 进入新的ConversationChain链...
    格式化后的提示:
    以下是AI与人类之间的友好对话。AI健谈,提供了很多上下文的具体细节。如果AI不知道问题的答案,它会诚实地说它不知道。

    先前对话的相关片段:
    输入:你好,我叫Perry,怎么样?
    响应:嗨Perry,我很好。你呢?

    (如果不相关,您不需要使用这些信息)

    当前对话:
    人类:我的名字是什么?
    AI:

    > 完成链





    '你的名字是Perry。'