【8】补充与拓展:Langchain的联网搜索Agent,使用Tavily工具
Langchain的联网搜索Agent,使用Tavily工具
在 LangChain 中,Tavily 是一款专为大型语言模型(LLMs)和检索增强生成(RAG)优化的搜索引擎 API。它能够提供结构化、带溯源的搜索结果,非常适合用来赋予 Agent 实时联网搜索的能力。
下面我将为你演示如何在 LangChain 中配置并使用 Tavily 工具来构建一个搜索 Agent。
第一步:安装依赖与配置 API Key
首先,你需要安装 LangChain 的 Tavily 集成包,并获取 Tavily 的 API Key(可以在 Tavily 官网注册获取)。
pipinstall-Ulangchain-tavily langchain-openai在代码或环境变量中配置你的密钥:
importos os.environ["TAVILY_API_KEY"]="你的Tavily-API-Key"os.environ["OPENAI_API_KEY"]="你的OpenAI-API-Key"第二步:基础工具绑定与调用
LangChain 提供了TavilySearch工具类。你可以将其直接绑定到支持工具调用的 LLM(如 GPT-4o)上:
fromlangchain_core.messagesimportHumanMessagefromlangchain_openaiimportChatOpenAIfromlangchain_tavilyimportTavilySearch# 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. 手动执行工具并将结果反馈给模型fortool_callinai_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来实现:
fromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholderfromlangchain.agentsimportcreate_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 搜索工具无缝集成到之前的客服系统中:
核心代码实现
importosfromtypingimportTypedDict,Annotatedfromlanggraph.graphimportStateGraph,START,ENDfromlanggraph.graph.messageimportadd_messagesfromlanggraph.prebuiltimportcreate_react_agentfromlangchain_core.messagesimportHumanMessage,AIMessagefromlangchain_tavilyimportTavilySearchfromlangchain_openaiimportChatOpenAI# ================= 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. 定义共享状态 =================classAgentState(TypedDict):messages:Annotated[list,add_messages]intent:str# 记录路由意图# ================= 3. 定义专职节点 =================# 意图识别节点:判断是否需要联网搜索defrouter_node(state:AgentState):last_msg=state["messages"][-1].content.lower()# 简单的关键词判断,实际生产中可替换为 LLM 意图分类ifany(keywordinlast_msgforkeywordin["天气","新闻","最新","今天"]):return{"intent":"SEARCH"}return{"intent":"LOCAL"}# 本地客服节点(模拟)deflocal_agent_node(state:AgentState):return{"messages":[AIMessage(content="【本地客服】:已为您查询本地知识库...")]}# 联网搜索节点:使用预构建的 ReAct Agent 处理复杂搜索defsearch_agent_node(state:AgentState):# 利用 LangGraph 预构建的 ReAct Agent 自动调用 Tavilysearch_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")# 条件路由defroute_by_intent(state:AgentState):return"search"ifstate["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科技新闻?"]forqueryintest_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,方便用户点击查看原始信息?
