核心模块(Modules)
记忆(Memory)
数据库中带记忆的代理(AgentWithMemoryInDb)

由数据库支持的代理中的消息内存

这篇笔记介绍了向代理添加内存的过程,其中内存使用外部消息存储。在阅读本笔记之前,请先学习以下几篇笔记,因为这将建立在它们的基础之上:

要将带有外部消息存储的内存添加到代理中,我们将执行以下步骤:

  1. 我们将创建一个 RedisChatMessageHistory 来连接外部数据库以存储消息。
  2. 我们将使用该聊天历史创建一个 LLMChain 作为内存。
  3. 我们将使用该 LLMChain 创建自定义代理。

为了完成这个练习,我们将创建一个简单的自定义代理,该代理可以访问搜索工具并利用 ConversationBufferMemory 类。

import os
 
from langchain import hub
from langchain.agents import AgentExecutor, Tool
from langchain_community.chat_message_histories import RedisChatMessageHistory
from langchain_community.utilities import SerpAPIWrapper
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import OpenAI
os.environ["GOOGLE_API_KEY"] = "GOOGLE_API_KEY"
os.environ["GOOGLE_CSE_ID"] = "GOOGLE_CSE_ID"
os.environ["OPENAI_API_KEY"] = "OPENAI_API_KEY"
 
search = SerpAPIWrapper()
tools = [
    Tool(
        name="Search",
        func=search.run,
        description="有助于回答有关当前事件的问题",
    )
]

注意 PromptTemplate 中 chat_history 变量的使用,该变量与 ConversationBufferMemory 中的动态键名匹配。

prompt = hub.pull("hwchase17/react")

现在我们可以创建由数据库支持的 RedisChatMessageHistory。

message_history = RedisChatMessageHistory(
    url="redis://127.0.0.1:6379/0", ttl=600, session_id="my-session"
)

现在我们可以构建 LLMChain,使用 Memory 对象,然后创建代理。

from langchain.agents import create_react_agent
 
model = OpenAI()
agent = create_react_agent(model, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_with_chat_history = RunnableWithMessageHistory(
    agent_executor,
    # 这是必需的,因为在大多数真实场景中都需要会话 id
    # 这里实际上不会用到它,因为我们使用的是简单的内存 ChatMessageHistory
    lambda session_id: message_history,
    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>"}},
)
> 进入新的 AgentExecutor 链...
 我应该使用搜索工具查找加拿大最新的人口数据。
行动: 搜索
行动输入: "population of canada"{'type': 'population_result', 'place': 'Canada', 'population': '38.93 million', 'year': '2022'}现在我知道了最终答案
最终答案: 原始输入问题的最终答案是:截至 2022 年,加拿大有 3893 万人口。

> 完成链。
{'input': 'How many people live in canada?',
 'chat_history': [],
 'output': 'The final answer to the original input question is 38.93 million people live in Canada as of 2022.'}

要测试这个代理的记忆,我们可以问一个后续问题,该问题依赖于前一个交流中的信息才能被正确回答。

agent_with_chat_history.invoke(
    {"input": "what is their national anthem called?"},
    config={"configurable": {"session_id": "<foo>"}},
)
> 进入新的 AgentExecutor 链...
 世界上有许多国家拥有不同的国歌,所以我可能需要指明我在查找哪个国家的国歌。
行动: 搜索
行动输入: "national anthem" + country name['"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 ; DjiboutiDjibouti, Djibouti ; DominicaDominica, Isle of Beauty, Isle of Splendour ; Dominican RepublicDominican ...', "Today, the total number is massive, with all 193 UN countries having a national anthem. Former and non-UN countries' anthems add to the list. Due to space ...", '1. United States of America - The Star-Spangled Banner · 2. United Kingdom - God Save the Queen/King · 3. Canada - O Canada · 4. France - La ...', "Pedro I wrote the song that was used as the national anthem of Brazil from 1822 to 1831. The song is now recognized as the country's official patriotic song. 7."]现在我知道了最终答案
最终答案: 在未指明所指的是哪个国家的国歌之前,无法确定最终答案。

> 完成链。
{'input': 'what is their national anthem called?',
 'chat_history': [HumanMessage(content='How many people live in canada?'),
  AIMessage(content='The final answer to the original input question is 38.93 million people live in Canada as of 2022.')],
 'output': "The final answer cannot be determined without specifying which country's national anthem is being referred to."}

我们可以看到,代理记住了前一个问题是关于加拿大,正确询问了 Google 搜索加拿大国歌的名称。

现在,让我们将其与没有内存的代理进行比较。

agent = create_react_agent(model, tools, prompt)
agent_executor__without_memory = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_executor__without_memory.invoke({"input": "How many people live in canada?"})
> 进入新的 AgentExecutor 链...
 为了找出居住在加拿大的人口数,我应该使用搜索引擎查找可靠的来源。
行动: 搜索
行动输入: "Population of Canada"{'type': 'population_result', 'place': 'Canada', 'population': '38.93 million', 'year': '2022'}截至 2022 年,加拿大有 3893 万人口。
最终答案: 加拿大有 3893 万人口。

> 完成链。
{'input': 'How many people live in canada?',
 'output': '38.93 million people live in Canada.'}
agent_executor__without_memory.invoke(
    {"input": "what is their national anthem called?"}
)
> 进入新的 AgentExecutor 链...
 我应该始终思考该做什么
行动: 搜索
行动输入: "national anthem of [country name]"['Most nation states have an anthem, defined as "a song, as of praise, devotion, or patriotism"; most anthems are either marches or hymns in style.', '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: First sung in 1844 with the title,. Sang till Norden (Song of the North). Its use as a. National Anthem dates from 1880-90. 1. Thou ancient ...', 'National anthem · Afghanistan · Akrotiri · Albania · Algeria · American Samoa · Andorra · Angola · Anguilla.', 'Background > National anthems: Countries Compared ; IndiaIndia, Jana Gana Mana ( Hail the ruler of all minds ) ; IndonesiaIndonesia, Indonesia Raya ( Great ...', '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 ...', 'Himno Nacional del Perú, also known as Marcha Nacional del Perú or Somos libres, was selected as the national anthem of Peru in a public contest. Shortly after ...']现在我知道了最终答案
最终答案: 这取决于国家,但可以通过搜索 "national anthem of [country name]" 找到该国的国歌。

> 完成链。
{'input': 'what is their national anthem called?',
 'output': 'It depends on the country, but their national anthem can be found by searching "national anthem of [country name]".'}