系列文章索引
LangChain教程 - 系列文章
在本教程中,我们将学习如何使用 LangChain 创建一个能够与搜索引擎交互的智能代理。代理可以通过大语言模型(LLM)作为推理引擎来确定执行的操作和输入,执行这些操作后,再将结果反馈到 LLM 以决定是否需要继续操作或结束对话。
前提条件
本教程假设你已经熟悉以下概念:
- 聊天模型(Chat Models)
- 工具(Tools)
- 代理(Agents)
语言模型本身不能直接执行操作,它们只能生成文本。LangChain 的一个重要用例就是创建代理,代理系统能够使用 LLM 进行推理,确定执行哪些操作以及传递什么输入。然后根据操作结果,代理可以继续决定下一步的动作或结束任务。
最终效果预览
下面的代码段展示了一个完整的代理,它使用 LLM 来决定调用哪些工具,并具备与搜索引擎交互的能力。这是一个多轮对话代理,它还带有对话记忆。
# 导入所需模块
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
import getpass
import os
# 设置 Tavily API 密钥
os.environ["TAVILY_API_KEY"] = getpass.getpass(prompt="请输入 Tavily API Key: ")
# 设置语言模型 API 密钥
os.environ["OPENAI_API_KEY"] = getpass.getpass(prompt="请输入 OpenAI API Key: ")
# 创建代理
memory = MemorySaver()
model = ChatOpenAI(model="gpt-4")
search = TavilySearchResults(max_results=2)
tools = [search]
agent_executor = create_react_agent(model, tools, checkpointer=memory)
# 使用代理
config = {"configurable": {"thread_id": "abc123"}}
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="你好,我是Bob,住在旧金山")]}, config
):
print(chunk)
print("----")
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="我住的地方现在天气怎么样?")]}, config
):
print(chunk)
print("----")
通过上面的代码,你可以使用一个与搜索引擎互动的代理来回答关于天气的问题,并且代理具备记忆对话内容的能力。
安装依赖
为了安装所需的依赖,可以运行以下命令:
pip install -U langchain-community langgraph langchain-anthropic tavily-python langgraph-checkpoint-sqlite langchain-openai
设置 Tavily 搜索工具
我们将在代理中使用 Tavily 作为搜索引擎工具。首先需要获取 API 密钥并设置环境变量:
import getpass
import os
os.environ["TAVILY_API_KEY"] = getpass.getpass()
接着,我们可以定义搜索工具:
from langchain_community.tools.tavily_search import TavilySearchResults
search = TavilySearchResults(max_results=2)
search_results = search.invoke("旧金山的天气怎么样")
print(search_results)
使用语言模型
接下来,我们将配置语言模型来调用这些工具。这里使用的是 ChatOpenAI 提供的 gpt-4 作为语言模型。
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
model = ChatOpenAI(model="gpt-4")
response = model.invoke([HumanMessage(content="你好!")])
print(response.content)
可以看到,模型返回了简单的对话内容。接下来,我们将模型与工具结合,使其能够调用 Tavily 搜索工具。
model_with_tools = model.bind_tools([search])
response = model_with_tools.invoke([HumanMessage(content="旧金山的天气怎么样?")])
print(response.content)
print(response.tool_calls)
在这里,模型会识别需要调用工具并生成相应的工具调用指令。
创建代理
现在,我们可以使用 LangGraph 来构建这个代理,并结合语言模型和工具:
from langgraph.prebuilt import create_react_agent
agent_executor = create_react_agent(model, [search])
我们现在可以通过代理执行一系列查询,并且代理会根据需要调用工具:
response = agent_executor.invoke({"messages": [HumanMessage(content="旧金山的天气怎么样?")]})
print(response["messages"])
代理会根据输入自动判断是否需要调用搜索工具,并返回搜索结果。
实现记忆功能
默认情况下,代理是无状态的(不记得之前的对话)。为了使代理具备记忆能力,我们可以为其添加记忆模块。通过传入 MemorySaver
,代理可以记住对话内容:
from langgraph.checkpoint.memory import MemorySaver
memory = MemorySaver()
agent_executor = create_react_agent(model, [search], checkpointer=memory)
config = {"configurable": {"thread_id": "abc123"}}
response = agent_executor.invoke({"messages": [HumanMessage(content="我叫Bob")], config=config})
print(response["messages"])
代理现在可以记住之前的对话内容,并在后续查询中使用这些记忆。
整体代码
# 导入所需的库
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
import getpass
import os
# 设置 Tavily API 密钥
os.environ["TAVILY_API_KEY"] = getpass.getpass(prompt="请输入 Tavily API Key: ")
# 设置语言模型 API 密钥
os.environ["OPENAI_API_KEY"] = getpass.getpass(prompt="请输入 OpenAI API Key: ")
# 初始化记忆模块
memory = MemorySaver()
# 初始化语言模型 (gpt-4)
model = ChatOpenAI(model="gpt-4")
# 初始化 Tavily 搜索工具
search = TavilySearchResults(max_results=2)
# 将工具和模型结合,创建代理
tools = [search]
agent_executor = create_react_agent(model, tools, checkpointer=memory)
# 定义对话配置,使用线程 ID 来区分不同的对话上下文
config = {"configurable": {"thread_id": "abc123"}}
# 第一次对话:问候并告诉代理你的名字
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="你好,我叫Bob,我住在旧金山")]}, config
):
print(chunk)
print("----")
# 第二次对话:询问代理关于当前所在地的天气
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="我住的地方现在天气怎么样?")]}, config
):
print(chunk)
print("----")
# 第三次对话:测试代理是否记得你的名字
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="你还记得我叫什么吗?")]}, config
):
print(chunk)
print("----")
# 开启一个新的对话上下文(新线程),验证代理是否不记得以前的对话
new_config = {"configurable": {"thread_id": "xyz123"}}
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="你知道我叫什么吗?")]}, new_config
):
print(chunk)
print("----")
结论
通过本教程,我们展示了如何使用 LangChain 构建一个具备工具调用和记忆功能的智能代理。代理可以根据输入的内容自动调用工具,并在需要时记住对话内容。这为构建复杂、多轮对话的智能系统提供了灵活的基础。
如果你想进一步了解代理的高级用法和功能,请查阅 LangGraph 文档,那里有更多教程和深入指南。