掘金 人工智能 07月16日 10:17
五、(基础)别让大模型 “断网”!教你用 LangChain 开发联网 AI Agent,实操教程来了
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了如何在LangChain中创建代理,实现与联网搜索和模型的交互,使模型能够自动操作并获取所需结果。内容涵盖了准备工作、构建Tavily搜索引擎、结合大模型、创建代理、流式消息、流式令牌以及会话管理等关键步骤,帮助读者逐步掌握LangChain代理的构建与应用。

💡 **准备工作**: 介绍了使用LangChain构建代理的基础知识,包括安装LangChain库、申请免费的大模型API密钥(如腾讯元宝、智谱AI、OpenAI)以及申请Tavily搜索引擎API密钥。

🔍 **构建Tavily搜索引擎**: 演示了如何使用TavilySearchResults工具进行联网搜索,并展示了搜索结果的输出方式,为后续代理的联网搜索功能奠定基础。

🤖 **结合大模型**: 通过.bind_tools方法将工具绑定到大模型上,使大模型能够识别和调用工具,从而实现更智能的交互。

🛠️ **创建代理**: 使用create_react_agent函数创建代理,使模型能够根据用户输入自动判断并执行相应的操作,例如调用搜索引擎获取信息。

💬 **流式消息与令牌**: 介绍了如何通过.stream()和.astream_events()方法实现流式消息和令牌的返回,以便实时查看代理的执行过程,增强用户体验。

🧠 **会话管理**: 讲解了如何通过MemorySaver实现会话管理,使代理能够记住之前的互动,从而实现更连贯的对话和更个性化的服务。

前言

    上一章讲解了如何调用向量模型、使用向量数据库等,并将其融入到 langchain 的链式操作中本章将讲解使用联网搜索和模型进行交互,并如何创建代理,使 langchain 自动操作模型获得我们想要的结果

准备工作

1. 构建 Tavily

语言模型本身其实做不了什么实际动作,它们能做的不过是输出一些文字而已。但 LangChain 有个挺重要的用法,就是搭建出一种 “代理” 机制。这种代理会把大型语言模型当成思考的核心,让它来判断该做哪些事,以及具体要给这些事提供什么信息。等这些事做完之后,得到的结果还能再送回给大型语言模型,让它接着判断:是还得再做点什么,还是说这事到这儿就可以结束了。

from langchain_community.tools.tavily_search import TavilySearchResultssearch = TavilySearchResults(max_results=2, tavily_api_key="申请的key")search_results = search.invoke("北京的天气怎么样")#print(search_results)for search_result in search_results:    print(search_result["content"])
|  |  |  |  |  |  |  |  |  || --- | --- | --- | --- | --- | --- | --- | --- | --- || 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 || 天气 |  |  |  |  |  |  |  |  || 气温 | 21.4℃ | 23.6℃ | 26.8℃ | 29.8℃ | 24.4℃ | 23.3℃ | 21.6℃ | 20.2℃ || 降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 || 风速 | 2.9m/s | 6.8m/s | 7.5m/s | 7.9m/s | 7.6m/s | 2.9m/s | 2.7m/s | 3.2m/s || 风向 | 东北风 | 东南风 | 西南风 | 西北风 | 西北风 | 西北风 | 东北风 | 西北风 | [...] |  |  |  |  |  |  |  |  |  || --- | --- | --- | --- | --- | --- | --- | --- | --- || 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 || 天气 |  |  |  |  |  |  |  |  || 气温 | 23.7℃ | 27℃ | 30.2℃ | 30.8℃ | 28.1℃ | 26.5℃ | 21.1℃ | 19.2℃ || 降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 || 风速 | 3.3m/s | 7.4m/s | 7.3m/s | 7m/s | 7.9m/s | 3.3m/s | 2.2m/s | 1.8m/s || 风向 | 西南风 | 西北风 | 西北风 | 西北风 | 东北风 | 西北风 | 西北风 | 西北风 | [...] |  |  |  |  |  |  |  |  |  || --- | --- | --- | --- | --- | --- | --- | --- | --- || 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 || 天气 |  |  |  |  |  |  |  |  || 气温 | 24.4℃ | 26.9℃ | 29.8℃ | 28.8℃ | 26℃ | 24.6℃ | 21.8℃ | 19.2℃ || 降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 || 风速 | 3.3m/s | 1.9m/s | 2m/s | 3.3m/s | 1.4m/s | 3.3m/s | 3.1m/s | 2.1m/s || 风向 | 东北风 | 东北风 | 东南风 | 西南风 | 东南风 | 东南风 | 东北风 | 东北风 |....省略

2. 结合大模型

可以通过传入消息列表来调用语言模型,而且还能看到这模型调用工具的具体情况。为了实现这一点,我们使用 .bind_tools 来让语言模型了解这些工具。

from langchain_community.tools.tavily_search import TavilySearchResultsfrom langchain_openai import ChatOpenAIfrom langchain_core.messages import HumanMessagemodel = ChatOpenAI(model="GLM-4-Flash-250414", api_key="申请的key", base_url="https://open.bigmodel.cn/api/paas/v4/")search = TavilySearchResults(max_results=2, tavily_api_key="申请的key")tools = [search]# 查看是否调用了搜索引擎插件model_with_tools = model.bind_tools(tools)response = model_with_tools.invoke([HumanMessage(content="你好")])print(f"ContentString: {response.content}")print(f"ToolCalls: {response.tool_calls}")

可以看到我们现在的问题没有触发搜索服务

ContentString: 你好,请问有什么可以帮到您的吗?ToolCalls: []

我们将问题换一下

response = model_with_tools.invoke([HumanMessage(content="北京的天气怎么样")])

可以看到已经成功触发搜索服务

ContentString: ToolCalls: [{'name': 'tavily_search_results_json', 'args': {'query': '北京天气'}, 'id': 'call_-8535024601817840514', 'type': 'tool_call'}]

现在这儿没什么文本内容,但有个工具调用的提示 —— 它想让我们用 Tavily Search 这个工具。不过这还不算真的调用了工具,只是告诉我们该去调用而已。要想真把这个工具用起来,还得我们自己来创建代理才行。

3. 创建代理

工具和大型语言模型都定义好了,接下来就能创建代理了。使用 LangGraph 来做这个事。目前用的是高级接口来代理,不过 LangGraph 有个好处,就是这个高级接口背后有套低级的 API 支撑着,可控性很强。现在,咱们可以用大型语言模型和工具来初始化代理了。注意:咱们传进去的是 model,不是 model_with_tools。这是因为 create_react_agent 会在后台自动调用.bind_tools,不用咱们手动弄。

from langchain_community.tools.tavily_search import TavilySearchResultsfrom langchain_openai import ChatOpenAIfrom langchain_core.messages import HumanMessagefrom langgraph.prebuilt import create_react_agentmodel = ChatOpenAI(model="GLM-4-Flash-250414", api_key="申请的key", base_url="https://open.bigmodel.cn/api/paas/v4/")search = TavilySearchResults(max_results=2, tavily_api_key="申请的key")tools = [search]agent_executor = create_react_agent(model, tools)response = agent_executor.invoke({"messages": [HumanMessage(content="你好")]})print(response["messages"])

通过返回值,可以看到模型现在并没有调用搜索服务,因为我们问的问题不对

[HumanMessage(content='你好', additional_kwargs={}, response_metadata={}, id='6e48786c-51c2-4528-906a-d2c845dae667'), AIMessage(content='你好,请问有什么可以帮到你的吗?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 12, 'prompt_tokens': 144, 'total_tokens': 156, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-Flash-250414', 'system_fingerprint': None, 'id': '20250711163033d5df63a239d44385', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--e5e4f578-512a-40d4-878e-781e85cfd572-0', usage_metadata={'input_tokens': 144, 'output_tokens': 12, 'total_tokens': 156, 'input_token_details': {}, 'output_token_details': {}})]

我们将问题换一下

response = agent_executor.invoke({"messages": [HumanMessage(content="北京的天气怎么样")]})

现在成功触发搜索服务

[HumanMessage(content='北京的天气怎么样', additional_kwargs={}, response_metadata={}, id='b4892f56-0a54-4600-8166-2fd8fee00e72'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_-8535004707527408014', 'function': {'arguments': '{"query": "北京天气"}', 'name': 'tavily_search_results_json'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 15, 'prompt_tokens': 146, 'total_tokens': 161, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-Flash-250414', 'system_fingerprint': None, 'id': '20250711163503f85b0431d2de4f4d', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--ad0fc16e-d273-48db-aef8-1ee7e4883f1c-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': '北京天气'}, 'id': 'call_-8535004707527408014', 'type': 'tool_call'}], usage_metadata={'input_tokens': 146, 'output_tokens': 15, 'total_tokens': 161, 'input_token_details': {}, 'output_token_details': {}}), ToolMessage(content='[{"title": "北京-天气预报 - 中央气象台", "url": "......", "content": "土壤水分监测\\n       农业干旱综合监测\\n       关键农时农事\\n       农业气象周报\\n       农业气象月报\\n       农业气象专报\\n       生态气象监测评估\\n       作物发育期监测\\n\\n   数值预报\\n\\n       CMA全球天气模式\\n       CMA全球集合模式\\n       CMA区域模式\\n       CMA区域集合模式\\n       CMA台风模式\\n       海浪模式\\n\\n1.    当前位置:首页\\n2.   北京市\\n3.   北京天气预报\\n\\n省份:城市:\\n\\n09:50更新\\n\\n日出04:45\\n\\n 北京 \\n\\n30℃\\n\\n日落19:43\\n\\n 降水量 \\n\\n0mm\\n\\n西南风\\n\\n3级\\n\\n 相对湿度 \\n\\n43%\\n\\n 体感温度 \\n\\n29.9℃\\n\\n空气质量:良 \\n\\n舒适度:温暖,较舒适\\n\\n 雷达图 \\n\\nImage 4\\n\\n24小时预报7天预报10天预报11-30天预报\\n\\n 发布时间:06-12 08:00 \\n\\n 06/12 \\n\\n周四 \\n\\nImage 5\\n\\n 多云 \\n\\n 南风 \\n\\n 3~4级 \\n\\n 35℃ \\n\\n 23℃ \\n\\nImage 6 [...] 北京-天气预报\\n\\n===============\\n\\n北京Image 1Image 235℃ / 23℃\\n\\n | \\n\\nEnglish\\n\\nImage 3\\n\\n 热门城市 \\n\\n北京\\n\\n天津\\n\\n石家庄\\n\\n太原\\n\\n呼和浩特\\n\\n沈阳\\n\\n长春\\n\\n哈尔滨\\n\\n上海\\n\\n南京\\n\\n杭州\\n\\n合肥\\n\\n福州\\n\\n南昌\\n\\n济南\\n\\n郑州\\n\\n武汉\\n\\n长沙\\n\\n广州\\n\\n深圳\\n\\n南宁\\n\\n海口\\n\\n重庆\\n\\n成都\\n\\n贵阳\\n\\n昆明\\n\\n拉萨\\n\\n西安\\n\\n兰州\\n\\n西宁\\n\\n银川\\n\\n乌鲁木齐\\n\\n香港\\n\\n澳门\\n\\n台北\\n\\n 天气实况 \\n\\n天气图\\n\\n卫星云图\\n\\n雷达图\\n\\n降水量\\n\\n气温\\n\\n风\\n\\n能见度\\n\\n强对流\\n\\n土壤水分\\n\\n 天气预报 \\n\\n天气公报\\n\\n每日天气提示\\n\\n春运气象服务专报\\n\\n气象灾害预警\\n\\n重要天气提示\\n\\n重要天气盘点\\n\ [...] |  |  |  |  |  |  |  |  |  |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 |\n| 天气 |  |  |  |  |  |  |  |  |\n| 气温 | 24.4℃ | 26.9℃ | 29.8℃ | 28.8℃ | 26℃ | 24.6℃ | 21.8℃ | 19.2℃ |\n| 降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 |\n| 风速 | 3.3m/s | 1.9m/s | 2m/s | 3.3m/s | 1.4m/s | 3.3m/s | 3.1m/s | 2.1m/s |\n| 风向 | 东北风 | 东北风 | 东南风 | 西南风 | 东南风 | 东南风 | 东北风 | 东北风 |', 'score': 0.77364457, 'raw_content': None}], 'response_time': 2.54}), AIMessage(content='根据中央气象台的最新数据,北京当前的天气情况为:温度为30℃,相对湿度为43%,西南风3级,空气质量良好,舒适度温暖,较舒适。预计未来24小时天气多云,气温在35℃到23℃之间变化。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 56, 'prompt_tokens': 2174, 'total_tokens': 2230, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'GLM-4-Flash-250414', 'system_fingerprint': None, 'id': '202507111635074ea4af78c2ae42f6', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--1e2153aa-62ef-47b0-9c57-7af231edb353-0', usage_metadata={'input_tokens': 2174, 'output_tokens': 56, 'total_tokens': 2230, 'input_token_details': {}, 'output_token_details': {}})]

3.1 流式消息

咱们已经知道怎么用.invoke 调用代理来拿到最终的回应了。但要是代理得走好几个步骤,那可能就得等上一会儿。想实时看到中间的进展也不难,只要在消息产生的时候,让它们一条条流式返回就行。

from langchain_community.tools.tavily_search import TavilySearchResultsfrom langchain_openai import ChatOpenAIfrom langchain_core.messages import HumanMessagefrom langgraph.prebuilt import create_react_agentmodel = ChatOpenAI(model="GLM-4-Flash-250414", api_key="申请的key", base_url="https://open.bigmodel.cn/api/paas/v4/")search = TavilySearchResults(max_results=2, tavily_api_key="申请的key")tools = [search]agent_executor = create_react_agent(model, tools)for chunk in agent_executor.stream(    {"messages": [HumanMessage(content="北京的天气怎么样")]}):    print(chunk)    print("----")

返回值

3.2 流式令牌

除了流式返回消息,流式返回令牌也是有用的。 我们可以使用 .astream_events 方法来实现这一点。

from langchain_community.tools.tavily_search import TavilySearchResultsfrom langchain_openai import ChatOpenAIfrom langchain_core.messages import HumanMessagefrom langgraph.prebuilt import create_react_agentmodel = ChatOpenAI(model="GLM-4-Flash-250414", api_key="申请的key", base_url="https://open.bigmodel.cn/api/paas/v4/")search = TavilySearchResults(max_results=2, tavily_api_key="申请的key")tools = [search]agent_executor = create_react_agent(model, tools)async for event in agent_executor.astream_events(    {"messages": [HumanMessage(content="北京的天气怎么样?")]}, version="v1"):    kind = event["event"]    if kind == "on_chain_start":        if (            event["name"] == "Agent"        ):              print(                f"Starting agent: {event['name']} with input: {event['data'].get('input')}"            )    elif kind == "on_chain_end":        if (            event["name"] == "Agent"        ):              print()            print("--")            print(                f"Done agent: {event['name']} with output: {event['data'].get('output')['output']}"            )    if kind == "on_chat_model_stream":        content = event["data"]["chunk"].content        if content:            print(content, end="|")    elif kind == "on_tool_start":        print("--")        print(            f"Starting tool: {event['name']} with inputs: {event['data'].get('input')}"        )    elif kind == "on_tool_end":        print(f"Done tool: {event['name']}")        print(f"Tool output was: {event['data'].get('output')}")        print("--")

返回值,是不是有点像我们常用的的一些ai助手深度思考的模样

4. 加入会话管理

代理本身是没什么记忆的,之前的互动它都记不住。要是想让它能记住东西,就得给它传个检查点。传检查点的时候,调用代理时还得带上 thread_id,这样它才知道该从哪个对话线程接着来。

from langchain_community.tools.tavily_search import TavilySearchResultsfrom langchain_openai import ChatOpenAIfrom langchain_core.messages import HumanMessagefrom langgraph.prebuilt import create_react_agentfrom langgraph.checkpoint.memory import MemorySavermodel = ChatOpenAI(model="GLM-4-Flash-250414", api_key="申请的key", base_url="https://open.bigmodel.cn/api/paas/v4/")memory = MemorySaver()search = TavilySearchResults(max_results=2, tavily_api_key="申请的key")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="北京的天气怎么样?")]}, config):    print(chunk)    print("----")for chunk in agent_executor.stream(    {"messages": [HumanMessage(content="我刚问了什么?")]}, config):    print(chunk)    print("----")

返回值

本章讲解使用联网搜索和模型进行交互,如何创建代理,使 langchain 自动操作模型获得我们想要的结果,至此我们基础部分已经讲完,接下来我们将讲解进阶部分,包括构建检索增强生成 (RAG) 、操作sql数据库、图数据库、分析pdf等文档、B站视频分析等,欢迎持续关注

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

LangChain 代理 联网搜索 大模型 会话管理
相关文章