Langchain的联网搜索Agent,使用Tavily工具
在 LangChain 中,Tavily 是一款专为大型语言模型(LLMs)和检索增强生成(RAG)优化的搜索引擎 API。它能够提供结构化、带溯源的搜索结果,非常适合用来赋予 Agent 实时联网搜索的能力。
下面我将为你演示如何在 LangChain 中配置并使用 Tavily 工具来构建一个搜索 Agent。
第一步:安装依赖与配置 API Key
首先,你需要安装 LangChain 的 Tavily 集成包,并获取 Tavily 的 API Key(可以在 Tavily 官网注册获取)。
bash
pip install -U langchain-tavily langchain-openai
在代码或环境变量中配置你的密钥:
python
import os
os.environ["TAVILY_API_KEY"] = "你的Tavily-API-Key"
os.environ["OPENAI_API_KEY"] = "你的OpenAI-API-Key"
第二步:基础工具绑定与调用
LangChain 提供了 TavilySearch 工具类。你可以将其直接绑定到支持工具调用的 LLM(如 GPT-4o)上:
python
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langchain_tavily import TavilySearch
# 1. 定义模型与工具
model = ChatOpenAI(model="gpt-4o-mini")
tool = TavilySearch(max_results=4)
# 2. 将工具绑定到模型
model_with_tools = model.bind_tools([tool])
# 3. 发起对话,触发模型调用工具
messages = [HumanMessage("北京今天的天气怎么样?")]
ai_message = model_with_tools.invoke(messages)
messages.append(ai_message)
# 4. 手动执行工具并将结果反馈给模型
for tool_call in ai_message.tool_calls:
tool_message = tool.invoke(tool_call)
messages.append(tool_message)
# 5. 模型根据搜索结果生成最终回答
final_response = model.invoke(messages)
print(final_response.content)
第三步:构建自动化的搜索 Agent
在实际应用中,我们通常不希望手动去循环执行工具,而是使用 LangChain 的 Agent 框架让它自主决策。你可以使用 create_tool_calling_agent 配合 AgentExecutor 来实现:
python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import create_tool_calling_agent, AgentExecutor
# 1. 定义提示词模板(必须包含 agent_scratchpad 用于记录工具调用过程)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个乐于助人的AI助手。当遇到不确定的实时信息时,请使用搜索工具获取答案。"),
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
# 2. 创建 Agent 并传入工具
agent = create_tool_calling_agent(
llm=model,
tools=[tool],
prompt=prompt
)
# 3. 使用 AgentExecutor 包装并运行
agent_executor = AgentExecutor(agent=agent, tools=[tool], verbose=True)
result = agent_executor.invoke({"input": "最近一周有什么重大的AI科技新闻?"})
print(result["output"])
核心机制解析
- Function Call 模式 :Tavily 在 LangChain 中主要通过 Function Call(结构化函数调用)模式工作。LLM 会生成 JSON 格式的调用参数(如
{"query": "北京天气"}),LangChain 拦截后自动调用 Tavily API,并将返回的 URL、摘要等结构化数据作为ToolMessage传回给 LLM。 - 丰富的返回数据 :通过
tool_msg.artifact,你不仅能获取到网页的标题和摘要(Snippets),还能获取到原始搜索结果列表、图片链接甚至后续追问建议(Follow-up questions),这对于构建高质量的 RAG 系统非常有帮助。
要不要我把这个联网搜索 Agent 整合到之前搭建的 LangGraph 多智能体客服系统中?比如当用户问实时新闻或天气时,自动触发搜索节点。
LangGraph的联网搜索 Agent ,使用Tavily工具
将联网搜索 Agent 整合到 LangGraph 多智能体系统中,最优雅的方式是构建一个**"混合检索路由(Agentic Hybrid RAG)"**架构。在这个架构中,系统会先对用户的问题进行意图分类,然后动态决定是查询本地知识库(向量搜索),还是调用 Tavily 进行实时网络搜索。
下面为你提供完整的实战代码,演示如何将 Tavily 搜索工具无缝集成到之前的客服系统中:
核心代码实现
python
import os
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import create_react_agent
from langchain_core.messages import HumanMessage, AIMessage
from langchain_tavily import TavilySearch
from langchain_openai import ChatOpenAI
# ================= 1. 初始化模型与工具 =================
llm = ChatOpenAI(model="gpt-4o-mini")
# 初始化 Tavily 搜索工具
search_tool = TavilySearch(max_results=3, tavily_api_key=os.getenv("TAVILY_API_KEY"))
tools = [search_tool]
# ================= 2. 定义共享状态 =================
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
intent: str # 记录路由意图
# ================= 3. 定义专职节点 =================
# 意图识别节点:判断是否需要联网搜索
def router_node(state: AgentState):
last_msg = state["messages"][-1].content.lower()
# 简单的关键词判断,实际生产中可替换为 LLM 意图分类
if any(keyword in last_msg for keyword in ["天气", "新闻", "最新", "今天"]):
return {"intent": "SEARCH"}
return {"intent": "LOCAL"}
# 本地客服节点(模拟)
def local_agent_node(state: AgentState):
return {"messages": [AIMessage(content="【本地客服】:已为您查询本地知识库...")]}
# 联网搜索节点:使用预构建的 ReAct Agent 处理复杂搜索
def search_agent_node(state: AgentState):
# 利用 LangGraph 预构建的 ReAct Agent 自动调用 Tavily
search_agent = create_react_agent(
model=llm,
tools=tools,
prompt="你是一个搜索助手,请根据用户问题调用 Tavily 搜索工具,并总结搜索结果。"
)
result = search_agent.invoke({"messages": state["messages"]})
return {"messages": result["messages"]}
# ================= 4. 构建工作流图 =================
workflow = StateGraph(AgentState)
workflow.add_node("router", router_node)
workflow.add_node("local_agent", local_agent_node)
workflow.add_node("search_agent", search_agent_node)
# 设置入口
workflow.add_edge(START, "router")
# 条件路由
def route_by_intent(state: AgentState):
return "search" if state["intent"] == "SEARCH" else "local"
workflow.add_conditional_edges(
"router",
route_by_intent,
{"search": "search_agent", "local": "local_agent"}
)
# 所有分支最终汇聚到结束节点
workflow.add_edge("local_agent", END)
workflow.add_edge("search_agent", END)
app = workflow.compile()
# ================= 5. 运行测试 =================
test_queries = [
"帮我查一下我的订单到哪了",
"北京今天天气怎么样?",
"最近一周有什么重大的AI科技新闻?"
]
for query in test_queries:
print(f"👤 用户: {query}")
result = app.invoke({"messages": [HumanMessage(content=query)]})
print(f"🤖 AI: {result['messages'][-1].content}\n")
架构亮点解析
- 动态路由决策 :系统不再盲目地执行固定流水线。通过
router_node,系统能够根据用户的问题特征,动态决定是将任务交给本地知识库,还是交给联网搜索 Agent。 - ReAct 框架的无缝集成 :在
search_agent_node中,我们使用了 LangGraph 预构建的create_react_agent。它遵循"推理-行动-观察"(Reason-Act-Observe)框架,能够自主决定何时调用 Tavily,并处理返回的复杂结构化数据,无需我们手动编写循环逻辑。 - 状态隔离与共享 :
AgentState作为全局状态,既包含了对话历史messages,也包含了路由决策依据intent。搜索节点在获取到实时信息后,会将结果追加到messages中,保证上下文的连贯性。
通过这套架构,你的多智能体系统不仅具备了"记忆"和"多专家协作"的能力,还长出了"感知外部实时世界"的眼睛,真正达到了生产级智能客服的标准!
要不要我把 Tavily 的返回结果结构化处理一下,让 AI 在总结时能直接引用来源 URL,方便用户点击查看原始信息?