代理程序中的内存
本笔记本介绍了如何给代理程序添加内存。在阅读本笔记本之前,请先阅读以下两个笔记本,因为本笔记本是在这两个笔记本的基础上构建的:
为了给代理程序添加内存,我们需要执行以下步骤:
- 我们将创建一个带有内存的
LLMChain。 - 我们将使用该
LLMChain来创建一个自定义代理程序。
为了完成这个练习,我们将创建一个简单的自定义代理程序,该代理程序可以访问一个搜索工具,并利用 ConversationBufferMemory 类。
import os
from langchain.agents import Tool
from langchain_community.utilities import GoogleSearchAPIWrapperos.environ["GOOGLE_API_KEY"] = "GOOGLE_API_KEY"
os.environ["GOOGLE_CSE_ID"] = "GOOGLE_CSE_ID"
os.environ["OPENAI_API_KEY"] = "OPENAI_API_KEY"
search = GoogleSearchAPIWrapper()
tools = [
Tool(
name="Search",
func=search.run,
description="有助于回答有关当前事件的问题",
)
]注意在 PromptTemplate 中使用的 chat_history 变量,它与 ConversationBufferMemory 中的动态键名匹配。
from langchain import hub
from langchain.agents import AgentExecutor, create_react_agent
from langchain.memory import ChatMessageHistory
prompt = hub.pull("hwchase17/react")
memory = ChatMessageHistory(session_id="test-session")from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import OpenAI
llm = OpenAI(temperature=0)
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
# 这是必需的,因为在大多数真实场景中都需要会话 id
# 这里实际上不会用到它,因为我们使用的是简单的内存 ChatMessageHistory
lambda session_id: memory,
input_messages_key="input",
history_messages_key="chat_history",
)agent_with_chat_history.invoke(
{"input": "How many people live in canada?"},
config={"configurable": {"session_id": "<foo>"}},
)[1m> 进入新的 AgentExecutor 链...[0m
[32;1m[1;3m 我应该使用搜索工具查找加拿大最新的人口数据。
行动: 搜索
行动输入: "population of Canada"[0m[36;1m[1;3m{'type': 'population_result', 'place': 'Canada', 'population': '38.93 million', 'year': '2022'}[0m[32;1m[1;3m截至 2022 年,加拿大有 3893 万人口。
最终答案: 3893 万[0m
[1m> 完成链。[0m{'input': 'How many people live in canada?',
'chat_history': [],
'output': '38.93 million'}我们可以测试该代理的记忆功能,我们可以问一个随后的问题,这个问题依赖于之前的交流中的信息才能正确回答。
agent_with_chat_history.invoke(
{"input": "what is their national anthem called?"},
config={"configurable": {"session_id": "<foo>"}},
)[1m> 进入新的 AgentExecutor 链...[0m
[32;1m[1;3m 我应该搜索该国家的名称以及 "national anthem"
行动: 搜索
行动输入: "country name" national anthem[0m[36;1m[1;3m['"Liberté" ("Freedom") · "Esta É a Nossa Pátria Bem Amada" ("This Is Our Beloved Country") · "Dear Land of Guyana, of Rivers and Plains" · "La Dessalinienne" ("Song ...', 'National Anthem of Every Country ; Fiji, “Meda Dau Doka” (“God Bless Fiji”) ; Finland, “Maamme”. (“Our Land”) ; France, “La Marseillaise” (“The Marseillaise”).', 'List of national anthems ; Albania · Hymni i Flamurit · Algeria ; The Bahamas · March On, Bahamaland · Bahrain ; Cambodia · Nokoreach · Cameroon ; Madagascar · Ry ...', 'General information: Hatikvah (the Hope) is now firmly established as the Anthem of the State of Israel as well as the Jewish National Anthem. 1. While yet ...', 'National anthem · Afghanistan · Akrotiri · Albania · Algeria · American Samoa · Andorra · Angola · Anguilla.', 'Background > National anthems: Countries Compared ; IndonesiaIndonesia, Indonesia Raya ( Great Indonesia ) ; IranIran, Soroud-e Melli-e Jomhouri-e Eslami-e Iran ( ...', '1. Afghanistan, "Milli Surood" (National Anthem) · 2. Armenia, "Mer Hayrenik" (Our Fatherland) · 3. Azerbaijan (a transcontinental country with ...', 'National Anthems of all the countries of the world ; Star Spangled Banner with Lyrics, Vocals, and Beautiful Photos. Musicplay ; Russia National ...', "The countries with the ten newest anthem additions adopted them between 2006 to as recently as 2021. Let's take a look: ... Afghanistan's “Dā də bātorāno kor” (“ ..."][0m[32;1m[1;3m现在我知道了最终答案
最终答案: 某个国家的国歌可以通过搜索该国家的名称以及 "national anthem" 来找到。[0m
[1m> 完成链。[0m{'input': 'what is their national anthem called?',
'chat_history': [HumanMessage(content='How many people live in canada?'),
AIMessage(content='38.93 million')],
'output': 'The national anthem of a country can be found by searching for the country\'s name and "national anthem".'}我们可以看到,代理记得之前的问题是关于加拿大的,并正确地询问 Google 搜索加拿大的国歌叫什么。
为了好玩,让我们将其与没有内存的代理进行比较。
agent = create_react_agent(llm, tools, prompt)
agent_executor_without_memory = AgentExecutor(agent=agent, tools=tools)agent_executor_without_memory.invoke({"input": "How many people live in canada?"})[1m> 进入新的 AgentExecutor 链...[0m
[32;1m[1;3m 我应该使用搜索工具查找加拿大最新的人口数据。
行动: 搜索
行动输入: "population of Canada"[0m[36;1m[1;3m{'type': 'population_result', 'place': 'Canada', 'population': '38.93 million', 'year': '2022'}[0m[32;1m[1;3m我应该检查数据来源以确保其可靠。
行动: 搜索
行动输入: "population of Canada source"[0m[36;1m[1;3m2021 年加拿大人口普查共统计到总人口 36,991,981 人,比 2016 年的数据增长约 5.2%。据估计,加拿大人口在 2023 年超过 4000 万,在 2024 年超过 4100 万。[0m[32;1m[1;3m 现在我知道了最终答案。
最终答案: 2022 年加拿大的人口估计为 3893 万。[0m
[1m> 完成链。[0m{'input': 'How many people live in canada?',
'output': 'The estimated population of Canada in 2022 is 38.93 million.'}agent_executor_without_memory.invoke({"input": "what is their national anthem called?"})[1m> 进入新的 AgentExecutor 链...[0m
[32;1m[1;3m 我应该搜索该国家的名称以及 "national anthem"
行动: 搜索
行动输入: "country name" national anthem[0m[36;1m[1;3m['"Liberté" ("Freedom") · "Esta É a Nossa Pátria Bem Amada" ("This Is Our Beloved Country") · "Dear Land of Guyana, of Rivers and Plains" · "La Dessalinienne" ("Song ...', 'National Anthem of Every Country ; Fiji, “Meda Dau Doka” (“God Bless Fiji”) ; Finland, “Maamme”. (“Our Land”) ; France, “La Marseillaise” (“The Marseillaise”).', 'List of national anthems ; Albania · Hymni i Flamurit · Algeria ; The Bahamas · March On, Bahamaland · Bahrain ; Cambodia · Nokoreach · Cameroon ; Madagascar · Ry ...', 'General information: Hatikvah (the Hope) is now firmly established as the Anthem of the State of Israel as well as the Jewish National Anthem. 1. While yet ...', 'National anthem · Afghanistan · Akrotiri · Albania · Algeria · American Samoa · Andorra · Angola · Anguilla.', 'Background > National anthems: Countries Compared ; IndonesiaIndonesia, Indonesia Raya ( Great Indonesia ) ; IranIran, Soroud-e Melli-e Jomhouri-e Eslami-e Iran ( ...', '1. Afghanistan, "Milli Surood" (National Anthem) · 2. Armenia, "Mer Hayrenik" (Our Fatherland) · 3. Azerbaijan (a transcontinental country with ...', 'National Anthems of all the countries of the world ; Star Spangled Banner with Lyrics, Vocals, and Beautiful Photos. Musicplay ; Russia National ...', "The countries with the ten newest anthem additions adopted them between 2006 to as recently as 2021. Let's take a look: ... Afghanistan's “Dā də bātorāno kor” (“ ..."][0m[32;1m[1;3m现在我知道了最终答案
最终答案: 阿富汗的国歌叫做 "Milli Surood"。[0m
[1m> 完成链。[0m{'input': 'what is their national anthem called?',
'output': 'The national anthem of Afghanistan is called "Milli Surood".'}我们可以看到,不带内存的代理使用相同的输入,但无法记住之前的交流。
结果表明,通过添加内存,代理程序可以记住对话的历史,从而在后续的交谈中更多地参考先前的信息。这使得代理程序能够回答依赖于之前的交流的问题,并提供更一致和准确的答案。