🚀 免费试用 Zilliz Cloud,完全托管的 Milvus,体验 10 倍的性能提升!立即试用>

milvus-logo
LFAI

LangChain 中的对话记忆

  • Engineering
June 06, 2023
Yujian Tang

LangChain 是构建 LLM 应用程序的强大框架。然而,强大的功能也带来了一定的复杂性。LangChain 提供了许多提示 LLM 的方法以及会话记忆等基本功能。会话记忆为 LLM 提供了上下文以记住您的聊天内容。

在本篇文章中,我们将介绍如何在 LangChain 和 Milvus 中使用会话记忆。要继续学习,您需要pip 安装四个库和一个 OpenAI API 密钥。您可以通过运行pip install langchain milvus pymilvus python-dotenv 来安装所需的四个库。或执行本文CoLab Notebook中的第一个区块。

在本篇文章中,我们将学习以下内容:

  • 使用 LangChain 进行对话记忆
  • 设置对话上下文
  • 使用 LangChain 提示对话记忆
  • LangChain 对话记忆总结

使用 LangChain 的对话记忆

在默认状态下,您通过单个提示与 LLM 进行交互。增加上下文记忆或 "对话记忆 "意味着您不必再通过一个提示发送所有内容。LangChain 提供了存储与 LLM 对话的功能,以便日后检索这些信息。

要通过向量存储建立持久对话记忆,我们需要从 LangChain 获取六个模块。首先,我们必须获得OpenAIEmbeddingsOpenAI LLM。我们还需要VectorStoreRetrieverMemory 和 LangChain 版本的Milvus 来使用向量存储后台。然后,我们需要ConversationChainPromptTemplate 来保存对话并进行查询。

osdotenvopenai 库主要用于操作符。我们使用它们来加载和使用 OpenAI API 密钥。最后一个设置步骤是启动本地Milvus Lite实例。我们通过使用 Milvus Python 软件包中的default_server 来完成。

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
from langchain.vectorstores import Milvus
embeddings = OpenAIEmbeddings()


import os
from dotenv import load_dotenv
import openai
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")


from milvus import default_server
default_server.start()

设置对话上下文

现在,我们已经设置好了所有的先决条件,可以开始创建对话内存了。第一步是使用 LangChain 创建与 Milvus 服务器的连接。接下来,我们使用空字典创建 LangChain Milvus Collections。此外,我们还会传入上文创建的嵌入式数据以及 Milvus Lite 服务器的连接详情。

要将向量数据库用于会话记忆,我们需要将其实例化为检索器。在这种情况下,我们只检索前 1 个结果,设置为k=1 。最后一个会话内存设置步骤是通过刚才设置的检索器和向量数据库连接,将VectorStoreRetrieverMemory 对象用作我们的会话内存。

要使用我们的会话内存,它必须有一些上下文。因此,让我们给记忆体一些上下文。在这个例子中,我们提供了五条信息。让我们存储我最喜欢的零食(巧克力)、运动(游泳)、啤酒(吉尼斯)、甜点(芝士蛋糕)和音乐家(泰勒-斯威夫特)。每个条目都将通过save_context 功能保存到存储器中。

vectordb = Milvus.from_documents(
   {},
   embeddings,
   connection_args={"host": "127.0.0.1", "port": default_server.listen_port})
retriever = Milvus.as_retriever(vectordb, search_kwargs=dict(k=1))
memory = VectorStoreRetrieverMemory(retriever=retriever)
about_me = [
   {"input": "My favorite snack is chocolate",
    "output": "Nice"},
   {"input": "My favorite sport is swimming",
    "output": "Cool"},
   {"input": "My favorite beer is Guinness",
    "output": "Great"},
   {"input": "My favorite dessert is cheesecake",
    "output": "Good to know"},
   {"input": "My favorite musician is Taylor Swift",
    "output": "Same"}
]
for example in about_me:
   memory.save_context({"input": example["input"]}, {"output": example["output"]})

使用 LangChain 提示会话内存

现在我们来看看如何使用会话记忆库。首先,让我们通过 LangChain 连接 OpenAI LLM。我们使用温度 0 来表示我们不希望 LLM 具有创造性。

接下来,我们创建一个模板。我们告诉 LLM,它正在与人类进行友好对话,并插入两个变量。history 变量提供对话记忆中的上下文。input 变量提供当前输入。我们使用PromptTemplate 对象插入这些变量。

我们使用ConversationChain 对象将提示、LLM 和内存结合起来。现在,我们可以通过给对话一些提示来检查对话记忆。我们首先告诉 LLM,我们的名字叫加里,是口袋妖怪系列中的主要对手(对话记忆中的其他内容都是关于我的事实)。

llm = OpenAI(temperature=0) # Can be any valid LLM
_DEFAULT_TEMPLATE = """The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.


Relevant pieces of previous conversation:
{history}


(You do not need to use these pieces of information if not relevant)


Current conversation:
Human: {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="Hi, my name is Gary, what's up?")

下图显示了 LLM 的预期回复。在这个例子中,它的回答是它的名字叫 "AI"。

现在,让我们来测试一下到目前为止的内存。我们使用之前创建的ConversationChain 对象,查询我最喜欢的音乐家。

conversation_with_summary.predict(input="who is my favorite musician?")

下图显示了对话链的预期响应。由于我们使用了 "verbose"(详细说明)选项,因此它还显示了相关对话。我们可以看到,正如预期的那样,它返回了我最喜欢的艺术家是泰勒-斯威夫特(Taylor Swift)。

接下来,让我们查询我最喜欢的甜点--芝士蛋糕。

conversation_with_summary.predict(input="Whats my favorite dessert?")

当我们查询我最喜欢的甜点时,我们可以看到对话链再次从 Milvus 挑选了正确的信息。它发现我最喜欢的甜点是芝士蛋糕,正如我之前告诉它的那样。

既然我们已经确认可以查询我们之前提供的信息,那么我们再来检查一件事--我们在对话开始时提供的信息。对话开始时,我们告诉人工智能我们的名字叫加里。

conversation_with_summary.predict(input="What's my name?")

我们最后的检查结果是,对话链在向量存储对话记忆中存储了关于我们名字的信息。它返回的结果是,我们说了我们的名字叫加里。

LangChain 对话内存总结

在本教程中,我们学习了如何在 LangChain 中使用会话内存。LangChain 提供了像 Milvus 这样的向量存储后端访问,以实现持久的会话内存。我们可以在提示中注入历史记录,并将历史上下文保存在ConversationChain 对象中,从而使用会话记忆。

在本教程示例中,我们向对话链提供了关于我的五个事实,并假装自己是《口袋妖怪》中的主要对手加里。然后,我们用我们存储的先验知识--我最喜欢的音乐家和甜点--提问对话链。它正确回答了这两个问题,并显示了相关条目。最后,我们向它询问了对话开始时我们的名字,它正确地回答了我们说我们的名字是 "加里"。

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started

Like the article? Spread the word

扩展阅读