当前位置: 首页 > news >正文

LangChain:构建一个Agent(入门篇四)

前言

单靠语言模型无法采取行动 - 它们只是输出文本。 LangChain的一个重要用例是创建代理。 代理是使用大型语言模型作为推理引擎的系统,以确定采取哪些行动以及传递给它们的输入。 在执行操作后,结果可以反馈到大型语言模型中,以确定是否需要更多操作,或者是否可以结束。

在本教程中,我们将构建一个可以与搜索引擎互动的代理。您将能够向这个代理提问,观看它调用搜索工具,并与它进行对话。

目录

前言

一、环境篇

二、定义工具

三、使用模型

四、创建代理

五、流式消息

六、添加记忆

结论


一、环境篇

pip install -U langchain-community langgraph langchain-anthropic tavily-python langgraph-checkpoint-sqlite

 准备大模型apikey(本文基于硅基流动提供的apikey)

硅基流动用户系统,统一登录 SSO

model.py

from langchain_openai import ChatOpenAI
from langchain_openai import OpenAIEmbeddings
from langchain_community.tools.tavily_search import TavilySearchResults# 1、创建模型
model = ChatOpenAI(model='Pro/deepseek-ai/DeepSeek-V3',base_url="https://api.siliconflow.cn/v1/",api_key="sk-xxx"
)emb =OpenAIEmbeddings(model="BAAI/bge-m3",base_url="https://api.siliconflow.cn/v1/",api_key="sk-xxx"
)search = TavilySearchResults(max_results=2,tavily_api_key="tvly-dev-xxx"
)

二、定义工具

首先需要先申请一个 Tavily API 密钥 在这个地址申请https://app.tavily.com/

然后我们基于langchain内置的一个工具,可以轻松使用Tavily搜索引擎作为工具。

from model import model, searchsearch_results = search.invoke("what is the weather in SF")
print(search_results)
# If we want, we can create other tools.
# Once we have all the tools we want, we can put them in a list that we will reference later.
tools = [search]
print(tools)

[{'title': 'Saturday, June 7, 2025. San Francisco, CA - Weather Forecast', 'url': 'https://weathershogun.com/weather/usa/ca/san-francisco/480/june/2025-06-07', 'content': 'San Francisco, California Weather: Saturday, June 7, 2025. Cloudy weather, overcast skies with clouds. Day 68°. Night 54°.', 'score': 0.94326943}, {'title': 'San Francisco Bay Area Weather June 7, 2025 - Yahoo', 'url': 'https://www.yahoo.com/news/san-francisco-bay-area-weather-150943705.html', 'content': "Separate art from the artist?\n   Diddy trial recap\n   Young women and Botox\n   High protein foods\n   Musk-Trump feud\n   What's buried in GOP bill\n   Manhunt for Washington father\n   \u200b\u200bBaltimore Harbor oil spill\n   Trump's travel ban\n   Boulder attack vigil\n\nKRON San Francisco\n\nSan Francisco Bay Area Weather June 7, 2025\n===========================================\n\nKRON San Francisco\n\nSat, June 7, 2025 at 3:09 PM UTC\n\nKRON4 meteorologist Kathy Trafton forecasts the weather\n\nView comments [...] Published Time: 2025-06-07T15:09:43.000Z\n\nSan Francisco Bay Area Weather June 7, 2025\n\n===============\n\n[]( query \n\nSearch the web\n\n   Skip to main\n\nNews\n\nFinance\n\nSports\n\nMore\n\nMailSign in\n\nSearch the web\n\nAdvertisement\n\n[](\n\nReturn to Homepage\n\nTop Stories:\n------------", 'score': 0.8687491}]
[TavilySearchResults(max_results=2, api_wrapper=TavilySearchAPIWrapper(tavily_api_key=SecretStr('**********')))]

三、使用模型

接下来,让我们学习如何通过调用工具来使用语言模型。LangChain支持许多不同的语言模型,您可以互换使用 - 请选择您想要使用的模型!以基于openai协议的硅基流动api为例

from model import model, search
from langchain_core.messages import HumanMessagetools = [search]
response = model.invoke([HumanMessage(content="hi!")])
print(response.content)model_with_tools = model.bind_tools(tools)response = model_with_tools.invoke([HumanMessage(content="What's the weather in SF?")])print(f"ContentString: {response.content}")
print(f"ToolCalls: {response.tool_calls}")

Hello! 👋 How can I help you today? 😊
ContentString: 
ToolCalls: [{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in San Francisco'}, 'id': '0197e05543d27c705b2765f2de8ecd99', 'type': 'tool_call'}]

我们可以看到现在没有文本内容,但有一个工具调用!它希望我们调用 Tavily Search 工具。

这还没有调用那个工具 - 它只是告诉我们去调用。为了实际调用它,我们需要创建我们的代理。

四、创建代理

目前 我们已经定义了工具与模型,现在我们用langgraph来构建一个代理。我们可以用大型语言模型和工具初始化代理。

from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import HumanMessage
from model import model, search
from langgraph.prebuilt import create_react_agenttools = [search]model_with_tools = model.bind_tools(tools)agent_executor = create_react_agent(model, tools)response = agent_executor.invoke({"messages": [HumanMessage(content="hi!")]})print("无需工具时的返回;", response["messages"])response2 = agent_executor.invoke({"messages": [HumanMessage(content="whats the weather in sf?")]}
)
print("需要工具时的返回", response2["messages"])

无需工具时的返回; [HumanMessage(content='hi!', additional_kwargs={}, response_metadata={}, id='631cce33-8b9e-4337-982e-54d66431b981'), AIMessage(content='Hello! How can I assist you today? 😊', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 129, 'total_tokens': 140, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Pro/deepseek-ai/DeepSeek-V3', 'system_fingerprint': '', 'id': '0197e062d12b0ecc213102dfc582f72a', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--0868f0e0-6dd1-47b1-bc49-27e25078be8b-0', usage_metadata={'input_tokens': 129, 'output_tokens': 11, 'total_tokens': 140, 'input_token_details': {}, 'output_token_details': {'reasoning': 0}})]
需要工具时的返回 [HumanMessage(content='whats the weather in sf?', additional_kwargs={}, response_metadata={}, id='ff2c90a3-819a-446b-90bb-9b1e38bba71d'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': '0197e062e0b7bb3a4d67d52e1af0eb1d', 'function': {'arguments': '{"query":"current weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 26, 'prompt_tokens': 134, 'total_tokens': 160, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Pro/deepseek-ai/DeepSeek-V3', 'system_fingerprint': '', 'id': '0197e062d7574a85c8275c3e2a06896e', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--cf7471e3-a3f9-48c8-a96c-bf63ec65ecf6-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in San Francisco'}, 'id': '0197e062e0b7bb3a4d67d52e1af0eb1d', 'type': 'tool_call'}], usage_metadata={'input_tokens': 134, 'output_tokens': 26, 'total_tokens': 160, 'input_token_details': {}, 'output_token_details': {'reasoning': 0}}), ToolMessage(content='SSLError(MaxRetryError("HTTPSConnectionPool(host=\'api.tavily.com\', port=443): Max retries exceeded with url: /search (Caused by SSLError(SSLEOFError(8, \'EOF occurred in violation of protocol (_ssl.c:997)\')))"))', name='tavily_search_results_json', id='cbe80fb0-30d4-4968-b167-3677a109faff', tool_call_id='0197e062e0b7bb3a4d67d52e1af0eb1d', artifact={}), AIMessage(content='I encountered an issue while trying to fetch the current weather in San Francisco. Let me try again or provide an alternative way to get this information. \n\nWould you like me to try another method or specify a particular source for the weather update?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 48, 'prompt_tokens': 235, 'total_tokens': 283, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Pro/deepseek-ai/DeepSeek-V3', 'system_fingerprint': '', 'id': '0197e062ee375568a0d877d7b6d89e61', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--002d00d3-3b68-4fc9-ac2c-7ff107a6ab7d-0', usage_metadata={'input_tokens': 235, 'output_tokens': 48, 'total_tokens': 283, 'input_token_details': {}, 'output_token_details': {'reasoning': 0}})]
 

可见 后者的返回中有tool_calls信息 可看到调用的搜索工具信息,即正确调用了工具。

五、流式消息

我们已经看到如何使用 .invoke 调用代理以获取最终响应。如果代理正在执行多个步骤,这可能需要一些时间。为了显示中间进度,我们可以在消息发生时流式返回消息。

from langchain_core.messages import HumanMessage
from model import model, search
from langgraph.prebuilt import create_react_agenttools = [search]model_with_tools = model.bind_tools(tools)agent_executor = create_react_agent(model, tools)for chunk in agent_executor.stream({"messages": [HumanMessage(content="whats the weather in sf?")]}
):print(chunk)print("----")

{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': '0197e06df938d2753c075cb4cf81497c', 'function': {'arguments': '{"query":"current weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 26, 'prompt_tokens': 134, 'total_tokens': 160, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Pro/deepseek-ai/DeepSeek-V3', 'system_fingerprint': '', 'id': '0197e06dee8dbb485447c1cc4a093c0e', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--1f4f5560-d77c-422a-b7cd-b231b5e29731-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in San Francisco'}, 'id': '0197e06df938d2753c075cb4cf81497c', 'type': 'tool_call'}], usage_metadata={'input_tokens': 134, 'output_tokens': 26, 'total_tokens': 160, 'input_token_details': {}, 'output_token_details': {'reasoning': 0}})]}}
----
{'tools': {'messages': [ToolMessage(content='[{"title": "Saturday, June 7, 2025. San Francisco, CA - Weather Forecast", "url": "https://weathershogun.com/weather/usa/ca/san-francisco/480/june/2025-06-07", "content": "San Francisco, California Weather: Saturday, June 7, 2025. Cloudy weather, overcast skies with clouds. Day 68°. Night 54°.", "score": 0.9310187}, {"title": "Weather in San Francisco in June 2025 (California)", "url": "https://world-weather.info/forecast/usa/san_francisco/june-2025/", "content": "San Francisco Weather Forecast for June 2025 is based on statistical data. ... Saturday, 7 June. +55°. Day. +64°. Broken clouds. Sunday, 8 June. +55°. Day. +63", "score": 0.9055316}]', name='tavily_search_results_json', id='1de65433-3a0e-469a-b497-4c90209b4b75', tool_call_id='0197e06df938d2753c075cb4cf81497c', artifact={'query': 'current weather in San Francisco', 'follow_up_questions': None, 'answer': None, 'images': [], 'results': [{'url': 'https://weathershogun.com/weather/usa/ca/san-francisco/480/june/2025-06-07', 'title': 'Saturday, June 7, 2025. San Francisco, CA - Weather Forecast', 'content': 'San Francisco, California Weather: Saturday, June 7, 2025. Cloudy weather, overcast skies with clouds. Day 68°. Night 54°.', 'score': 0.9310187, 'raw_content': None}, {'url': 'https://world-weather.info/forecast/usa/san_francisco/june-2025/', 'title': 'Weather in San Francisco in June 2025 (California)', 'content': 'San Francisco Weather Forecast for June 2025 is based on statistical data. ... Saturday, 7 June. +55°. Day. +64°. Broken clouds. Sunday, 8 June. +55°. Day. +63', 'score': 0.9055316, 'raw_content': None}], 'response_time': 7.39})]}}
----
{'agent': {'messages': [AIMessage(content='The current weather in San Francisco is cloudy with overcast skies. The temperature is around 68°F during the day and drops to about 54°F at night. For more details, you can check [WeatherShogun](https://weathershogun.com/weather/usa/ca/san-francisco/480/june/2025-06-07).', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 79, 'prompt_tokens': 383, 'total_tokens': 462, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Pro/deepseek-ai/DeepSeek-V3', 'system_fingerprint': '', 'id': '0197e06e22d6f6e7574ca422b2ae0c87', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--91cbccc2-8c18-47be-a334-996b9a4748ae-0', usage_metadata={'input_tokens': 383, 'output_tokens': 79, 'total_tokens': 462, 'input_token_details': {}, 'output_token_details': {'reasoning': 0}})]}}
----

六、添加记忆

如前所述,该代理是无状态的。这意味着它不记得之前的交互。为了给它添加记忆,我们需要传入一个检查点。当传入检查点时,我们还必须在调用代理时传入 thread_id(以便它知道从哪个线程/对话恢复)。

from langchain_core.messages import HumanMessage
from model import model, search
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import MemorySavermemory = MemorySaver()
tools = [search]model_with_tools = model.bind_tools(tools)agent_executor = create_react_agent(model, tools, checkpointer=memory)
config = {"configurable": {"thread_id": "abc123"}}print("第一轮对话:")
for chunk1 in agent_executor.stream({"messages": [HumanMessage(content="hi im bob!")]}, config
):print(chunk1)print("----")
print("第二轮对话:")
for chunk2 in agent_executor.stream({"messages": [HumanMessage(content="whats my name?")]}, config
):print(chunk2)print("----")

第一轮对话:
{'agent': {'messages': [AIMessage(content='Hi Bob! Nice to meet you. How can I assist you today? 😊', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 131, 'total_tokens': 148, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Pro/deepseek-ai/DeepSeek-V3', 'system_fingerprint': '', 'id': '0197e07456ca9c8528978cd534a1cd77', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--c3cd9bf9-eb07-435f-b51c-875c64b3696e-0', usage_metadata={'input_tokens': 131, 'output_tokens': 17, 'total_tokens': 148, 'input_token_details': {}, 'output_token_details': {'reasoning': 0}})]}}
----
第二轮对话:
{'agent': {'messages': [AIMessage(content='Your name is **Bob**—you just told me! 😊 How can I assist you, Bob?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 156, 'total_tokens': 178, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 0, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Pro/deepseek-ai/DeepSeek-V3', 'system_fingerprint': '', 'id': '0197e074609741f681df5179cfafd9ae', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--34ea8733-7c23-41b8-9985-b83f52abbd16-0', usage_metadata={'input_tokens': 156, 'output_tokens': 22, 'total_tokens': 178, 'input_token_details': {}, 'output_token_details': {'reasoning': 0}})]}}
----

这样就构建了一个带有记忆的多轮对话Agent

结论

到此为止!在这个快速入门中,我们介绍了如何创建一个简单的代理。 我们已经展示了如何流式返回响应 - 不仅是中间步骤,还有令牌! 我们还添加了内存功能,这样你就可以与它们进行对话。 代理是一个复杂的话题,还有很多需要学习的内容!

有关代理的更多信息,请查看LangGraph文档。它有自己的一套概念、教程和使用指南。

http://www.dtcms.com/a/267863.html

相关文章:

  • [leetcode] C++ 并查集模板
  • 【机器学习笔记 Ⅱ】1 神经网络
  • 云原生 Serverless 架构下的智能弹性伸缩与成本优化实践
  • 基于HTML与Java的简易在线会议系统实现
  • Javaweb - 10.5 HttpServletRequest 和 HttpServletResponse
  • Flink ClickHouse 连接器维表源码深度解析
  • 【Note】《Kafka: The Definitive Guide》第四章:Kafka 消费者全面解析:如何从 Kafka 高效读取消息
  • 深入理解Kafka幂等性:原理、边界与最佳实践
  • Neo4j 综合练习作业
  • Android 应用开发 | 一种限制拷贝速率解决因 IO 过高导致系统卡顿的方法
  • java ThreadLocal源码分析
  • 深度学习6(多分类+交叉熵损失原理+手写数字识别案例TensorFlow)
  • 高效处理大体积Excel文件的Java技术方案解析
  • 安卓之service
  • QT 菜单栏设计使用方法
  • 基于AndServer的RPC架构:Android原生SO文件远程调用实战指南
  • Python 机器学习核心入门与实战进阶 Day 4 - 支持向量机(SVM)原理与分类实战
  • 深度学习图像分类数据集—蘑菇识别分类
  • plantuml用法总结
  • Java设计模式之行为型模式(策略模式)介绍与说明
  • 利用低空无人机影像进行树种实例分割
  • 深入解析Vue中v-model的双向绑定实现原理
  • 牛客周赛99
  • 关于 栈帧变化完整流程图(函数嵌套)
  • 大模型面试:RAG与Agent相关
  • 《Redis》集群
  • 【Note】《Kafka: The Definitive Guide》 第二章 Installing Kafka:Kafka 安装与运行
  • Redis--主从复制详解
  • 【Docker基础】Docker容器挂载方式深度解析:--volume与--mount参数对比
  • QT6 源(155)模型视图架构里的列表视图 QListView:接着学习成员函数,信号函数,附上本类的源代码带注释。