手把手教你用 LangChain 构建可实时搜索的智能代理:从工具集成到代理闭环
工具集成:将外部能力(如搜索引擎)转化为模型可调用的「动作」闭环决策:让模型学会判断「何时需要工具」「如何使用工具」「如何处理结果」用户体验:通过流式输出和记忆管理,让代理更像一个有交互感的智能体现在,你可以尝试将 Tavily 搜索替换为其他工具(如股票查询、新闻检索),或者扩展多个工具让代理具备更强能力。如果在实践中遇到问题,欢迎在评论区留言,我们一起探讨解决方案。
在 LangChain 的世界里,代理(Agent)就像一个会思考的执行者 —— 它能决定何时调用工具、如何处理工具返回,并最终整合成人类能理解的答案。今天我们就以「构建可调用 Tavily 搜索引擎的天气查询代理」为例,一步步拆解这个「思考 - 行动 - 反馈」的智能闭环,确保不遗漏任何关键技术细节。
一、核心组件准备:让模型与工具对话
1. 选择「思考引擎」:DeepSeek 大语言模型
我们首先需要一个具备推理能力的大脑。这里选用 DeepSeek 的聊天模型,通过langchain_deepseek
库轻松集成:
python
from langchain_deepseek import ChatDeepSeek
llm = ChatDeepSeek(
model="deepseek-chat", # 使用深度求索的聊天模型
temperature=0, # 禁用随机性,确保回答确定性
max_retries=2, # 自动重试2次应对网络波动
api_key="sk-xxxxxxxx" # 记得替换为你的真实API密钥(已脱敏处理)
)
2. 接入「信息雷达」:Tavily 搜索引擎工具
LangChain 社区已经为我们封装好了 Tavily 搜索工具,只需简单两步即可启用实时搜索能力:
python
from langchain_community.tools.tavily_search import TavilySearchResults
# 初始化工具:最多返回2条搜索结果(可根据需求调整)
search = TavilySearchResults(max_results=2)
# 测试调用:获取旧金山实时天气(返回结构化的列表数据)
raw_results = search.invoke("what is the weather in SF")
print(f"首次搜索结果:{raw_results[:50]}...") # 输出前50个字符预览
返回的raw_results
是列表形式的字典,每个元素包含url
(网页链接)和content
(原始内容),既包含 JSON 格式的天气数据,也有人类可读的文本描述,为后续解析提供丰富信息。
二、关键步骤:从「单独调用」到「代理协作」
1. 让模型「认识」工具:绑定工具库
直接调用llm.invoke()
只会得到纯文本回答,而我们需要模型学会主动调用工具。通过bind_tools
方法建立模型与工具的关联:
python
model_with_tools = llm.bind_tools([search]) # 绑定搜索工具到模型
# 发送提问:观察模型的「工具调用意图」
response = model_with_tools.invoke([HumanMessage(content="What's the weather in SF?")])
print(f"工具调用指令:{response.tool_calls}") # 输出包含工具名称和参数的调用指令
此时模型返回的不再是直接回答,而是一个tool_calls
字段,说明它已经意识到「需要实时数据,应该调用 Tavily 搜索」。这是代理能自主决策的关键一步。
2. 构建完整代理:基于 REACT 模式的智能闭环
REACT 模式(推理→行动→观察→工具)是 LangChain 代理的核心逻辑。我们通过create_react_agent
快速创建具备完整闭环的代理:
python
from langgraph.prebuilt import create_react_agent
# 初始化代理:传入模型和工具列表(内部自动完成工具绑定)
agent_executor = create_react_agent(llm, [search])
# 执行完整交互:代理会自动完成「调用工具→处理结果→生成回答」
full_response = agent_executor.invoke({"messages": [HumanMessage(content="whats the weather in sf?")]})
这个过程中,代理会经历两次 LLM 调用:
- 第一次:生成工具调用指令(解决「如何获取信息」)
- 第二次:解析工具返回数据并生成自然语言回答(解决「如何整合信息」)
三、深度解析:代理的三次关键「对话阶段」
当用户提问「whats the weather in sf?」时,代理的对话历史会呈现清晰的三阶段演进:
1. 第一阶段:工具调用决策(Reasoning→Action)
LLM 分析问题后生成的 AIMessage 包含关键信息:
python
{
"tool_calls": [
{
"name": "tavily_search_results_json", # 工具名称与注册的工具匹配
"args": {"query": "weather in san francisco"} # 自动优化后的搜索关键词
}
],
"response_metadata": {"stop_reason": "tool_use"} # 明确告知需要暂停以调用工具
}
这表明模型已具备「自我认知」—— 知道自己没有实时数据,需要借助外部工具。
2. 第二阶段:工具执行与数据获取(Observation)
代理框架自动捕获工具返回的ToolMessage
,内容是结构化的搜索结果:
python
[
{
"content": '{"temp_c": 13.3, "condition": "Light rain"...}', # 天气API返回的JSON数据
"url": "https://www.weatherapi.com/"
},
{
"content": "San Francisco... Night 43°", # 另一个来源的文本描述
"url": "https://weathershogun.com/"
}
]
这些多源数据为后续回答提供了丰富的事实依据。
3. 第三阶段:结果整合与回答生成(再次 Reasoning)
LLM 基于工具返回数据二次处理,生成最终回答:
plaintext
Based on the search results, the current weather in San Francisco is light rain...
(整合了温度、天气状况、风速等关键信息,并用自然语言呈现)
此时response_metadata
中的stop_reason
变为end_turn
,标志对话闭环完成。
四、进阶能力:让代理更智能的两个技巧
1. 实时反馈:两种流式输出模式对比
模式一:调试友好的「阶段式输出」(stream_mode="values")
适合开发者观察代理决策流程,每个step
包含完整对话历史:
python
for step in agent_executor.stream(
{"messages": [HumanMessage(content="提问")]},
stream_mode="values"
):
print(f"当前阶段消息:{step['messages'][-1].type}") # 输出当前是工具调用还是回答生成阶段
模式二:用户友好的「逐字流式」(stream_mode="messages")
模拟人类思考过程,逐令牌实时显示回答生成,提升交互体验:
python
for step, metadata in agent_executor.stream(
{"messages": [HumanMessage(content="提问")]},
stream_mode="messages"
):
if metadata["langgraph_node"] == "agent":
print(step.text(), end="") # 实时拼接生成的文本
2. 对话记忆:让代理记住历史交互
通过MemorySaver
组件添加状态记忆,解决无状态代理的局限:
python
from langgraph.checkpoint.memory import MemorySaver
# 初始化记忆组件
memory = MemorySaver()
# 创建带记忆的代理
agent_with_memory = create_react_agent(llm, [search], checkpointer=memory)
# 调用时传入thread_id标识对话线程
response = agent_with_memory.invoke(
{"messages": [HumanMessage(content="hi")]},
config={"configurable": {"thread_id": "unique_id"}}
)
这样代理就能记住之前的对话内容,实现上下文相关的连续交互。
五、避坑指南:开发中需要注意的细节
- 工具参数调优:
TavilySearchResults
的max_results
决定返回结果数量,过多可能增加解析负担,过少可能导致信息不足,需根据任务调整(示例中设为 2 是平衡选择)。 - 模型配置:
temperature=0
确保回答确定性,适合需要精确数据的场景;如果是创意类任务,可适当调高温度增加多样性。 - 错误处理:
max_retries=2
能自动重试工具调用,避免偶发网络问题导致的失败。
六、总结:从代码到能力的本质提升
通过这个案例,我们不仅实现了「天气查询代理」,更掌握了 LangChain 代理的核心设计思想:
- 工具集成:将外部能力(如搜索引擎)转化为模型可调用的「动作」
- 闭环决策:让模型学会判断「何时需要工具」「如何使用工具」「如何处理结果」
- 用户体验:通过流式输出和记忆管理,让代理更像一个有交互感的智能体
现在,你可以尝试将 Tavily 搜索替换为其他工具(如股票查询、新闻检索),或者扩展多个工具让代理具备更强能力。如果在实践中遇到问题,欢迎在评论区留言,我们一起探讨解决方案。觉得有帮助的话,别忘了点赞收藏,关注我们获取更多 LangChain 实战技巧!
更多推荐
所有评论(0)