引言
langchain新版本1.1.0 出来了,老版的api看了一些,api写法看起来有些凌乱,感觉还是SpringAI相对好好记忆一些。不知到1.x版本的会好使一些不。我们先来看看新版的langchain、langgraph、deepagents。
python vscode安装了一个backformater插件,这玩意没卵用,格式化不了。python这个玩意使用缩进表达代码块,实际上没法判断你的代码在块,选中代码格式化完全没反应。即使因为缩进出现了错误(IDE都发现了),这家伙还是不会格式化。python用缩进体现代码块出这个幺蛾子不好解决了,要是它有动作,也有可能把逻辑搞乱。pyhon用缩进做代码块,鼓吹的就是简洁优雅,实际上优雅个毛线,真的是很智障,经常手动补空格。语言充满陷阱,这玩意就只适合用来打草稿,感觉不太好,每次提到python都要吐槽😂
LangChain:基础开发框架
LangChain 是一个用于开发由大语言模型(LLM)驱动的应用程序的开源框架。它的核心目标是提供一个统一的抽象层,让开发者可以方便地组合各种组件,而无需关心底层与不同模型API对接的细节。
- 核心定位:Agent 与 LLM 应用的开发框架(DSL)。它解决了"从零到一"的构建问题。
- 主要能力 :
- 标准化模型接口:统一封装不同厂商(如 OpenAI、Anthropic)的模型,支持流式输出、工具调用等,避免供应商锁定。
- 结构化提示词 :提供
PromptTemplate等工具,将提示词工程化、可维护。 - 工具抽象:将函数封装成 LLM 可以理解和调用的"工具"(Tool),赋予智能体行动能力。
- 预构建的智能体循环:内置了 ReAct 等经典智能体模式,可以快速搭建一个能与工具交互的智能体。
总而言之,LangChain 提供了构建智能体所需的基础组件,但它本身并不解决智能体在长时间运行中的可靠性、状态持久化等问题。
LangGraph:状态化执行引擎
LangGraph 是一个低级别的编排框架,可以看作是 LangChain 的扩展,专门用于构建和管理长期运行、有状态的智能体。它将智能体的执行过程建模为一个图(Graph),从而实现对复杂工作流的精确控制。
- 核心定位:面向智能体的状态化执行引擎(Stateful Runtime)。它解决了智能体"如何跑得稳"的问题。
- 主要能力 :
- 基于图的执行模型:将智能体的工作流建模为有向图,节点(Node)代表功能模块(如 LLM 调用、工具执行),边(Edge)代表控制流。这使得支持循环、条件分支等复杂逻辑变得非常简单。
- 显式状态管理:维护一个中央状态对象(State),图中的每个节点都可以读写这个状态。这让智能体的行为变得可观测、可解释。
- 持久化执行(Durable Execution):能够自动保存执行过程中的检查点(Checkpoint)。即使任务因故障中断,也能从断点处恢复,保证了长时间运行任务的工程级可靠性。
- 人在循环(Human-in-the-loop):支持在执行过程中暂停,等待人工审核或干预,修改状态后再继续执行,这对于需要人类监督的关键任务至关重要。
LangGraph 将 LangChain 的组件作为"砖瓦",并提供了让它们稳定、可靠、有序运行的"地基"和"脚手架"。
DeepAgents:高级智能体应用框架
DeepAgents 是一个构建在 LangChain 和 LangGraph 之上的高级智能体开发库,旨在快速构建具备自主规划、长期记忆等高级能力的复杂智能体。它不是一个从零开始的框架,而是一个"开箱即用"的智能体脚手架(Harness)。
- 核心定位:面向长期自治任务的智能体能力整合层(Harness)。它解决了如何让智能体从"稳定运行"到"高度自主"的问题。
- 主要能力 :
- 任务规划与拆解 :内置
write_todos等规划工具,智能体可以自动将复杂目标拆解为一系列离散的步骤,并跟踪进度。 - 上下文管理(文件系统) :提供
ls,read_file,write_file等类操作系统工具,允许智能体将大量上下文信息外置到文件系统中,有效避免了上下文窗口溢出的问题。 - 子智能体生成(Subagent Spawning):主智能体可以动态创建并委派任务给专门的子智能体,实现上下文隔离和任务的并行或专注处理。
- 长期记忆:依托 LangGraph 的存储能力,实现跨会话的持久化记忆,使智能体能够记住历史交互信息,适用于个人助理、客服等场景。
- 任务规划与拆解 :内置
| 组件 | 类比 | 核心职责 | 解决的问题 |
|---|---|---|---|
| LangChain | 标准零件库 | 提供电机、传感器、机械臂等通用组件。 | 解决"从零到一"的构建问题。 |
| LangGraph | 工厂控制系统 | 负责零件的组装流程、状态监控、故障恢复和人工干预。 | 解决"从一到稳定"的运行问题。 |
| DeepAgents | 高级自动化生产线 | 在控制系统之上,实现自主排产、物料管理、任务分发等高级功能。 | 解决"从稳定到自主"的智能问题。 |
1 三者关系
这三者并非相互独立的三个选项,而是一个层层递进、相互依赖的技术栈 。你可以把它们看作是一个从底层到顶层的完整生态系统。为了让你一目了然,我们可以用**"建造和运营一座自动化工厂"**来类比它们的关系:
🧱 LangChain:基础开发框架(标准零件库)
- 角色 :"提供砖瓦"
- 关系 :它是整个体系的基础。LangGraph 和 DeepAgents 都构建在 LangChain 提供的抽象之上。
- 类比 :它就像一个巨大的标准零件库,里面装满了电机、传感器、机械臂(即:模型接口、提示词模板、工具抽象)。它解决了"从零到一"的构建问题,让你不用自己去造轮子(比如不用自己去写连接 OpenAI 的底层代码)。
⚙️ LangGraph:状态化执行引擎(工厂控制系统)
- 角色 :"提供地基与骨架"
- 关系 :它是 LangChain 的扩展与核心运行时 。实际上,最新版的 LangChain(1.0+)底层就是基于 LangGraph 构建的。
- 类比 :它就像工厂的控制系统和地基。它负责把 LangChain 提供的零件组装起来,并确保流水线能稳定运行。它解决了"从一到稳"的问题,比如处理循环逻辑、故障恢复(持久化执行)和人工干预。
🚀 DeepAgents:高级智能体应用框架(精装生产线)
- 角色 :"提供精装房"
- 关系 :它构建在 LangChain 之上 ,并利用 LangGraph 的运行能力 。它是这个技术栈的顶层应用。
- 类比 :它就像一条开箱即用的精装生产线。它不仅仅是给你零件,而是直接给了你一个具备"自主规划"、"文件读写"、"长期记忆"等高级能力的智能体脚手架。它解决了"从稳到智"的问题,让你快速拥有一个像"数字员工"一样的智能体。
2 选择
简单流程:LangChain
你可以把一个简单的线性流程(A → B → C)看作是 LangGraph 图结构中最基础的一种形态。
- 如何实现:在 LangGraph 中,你只需要定义几个节点(Node),然后用普通的边(Edge)把它们按顺序连接起来即可。
- 是否必要:对于一个纯粹的、没有任何分支和循环的简单任务,直接使用 LangChain 的 LCEL 表达式会更简洁、更高效。用 LangGraph 来做,虽然完全可以,但有点像"杀鸡用牛刀",会引入一些不必要的图结构定义代码。
复杂流程:LangGraph
LangGraph 的真正价值在于它原生支持复杂流程,这是传统线性框架的短板。
- 循环 (Loops):可以轻松实现"生成 → 审核 → 不满意则返回重新生成"的循环逻辑。
- 分支 (Branching):可以根据上一步的结果,动态决定下一步走向哪个节点。例如,根据用户意图,将流程路由到"客服节点"或"技术支持节点"。
- 状态管理 (State):在整个复杂流程中,有一个全局共享的状态对象,所有节点都可以读写,确保数据在不同步骤间无缝传递。
- 持久化 (Persistence):支持"时间旅行"功能,可以将流程的每一步状态保存下来。即使程序中断,也能从断点恢复,这对于长时间运行的复杂任务至关重要。
进阶:DeepAgents
这是你的加速器。 当你发现 LangChain 写起来太累,或者你需要一个能"自己干活"的智能体时,选它。
- 适用场景 :
- 需要智能体自主规划任务(比如:"帮我调研一下竞品,写个报告")。
- 任务非常长,需要跨会话记忆(比如:个人助理,需要记住你上周的偏好)。
- 需要处理大量文件(利用其内置的文件系统工具)。
- 理由 :
- 开箱即用:它帮你把规划、记忆、文件读写这些复杂功能都写好了,你直接配置一下就能用,不用自己造轮子。
📜 官方建议翻译
LangChain 对比 LangGraph 对比 Deep Agents
如果你打算构建一个智能体,我们建议你从 Deep Agents 开始。它采用了"开箱即用"的模式,内置了各种现代特性,例如:长对话的自动压缩、虚拟文件系统,以及用于管理和隔离上下文的子智能体生成能力。
Deep Agents 本质上是 LangChain 智能体的具体实现。如果你不需要上述这些高级能力,或者希望为自己的智能体和自主应用进行深度定制,那么请从 LangChain 开始。
当你有更高级的需求,需要结合"确定性工作流"与"智能体工作流",并且需要进行大量定制化开发时,请使用 LangGraph ------ 这是我们底层的智能体编排框架和运行时引擎。
说了这么多,基本上有一定的认识,具体也要用了之后应该就能体会更深刻,下面主要针对1.1.0最新稳定的版本
3 langchain
本地python版本使用的是3.13.5 官方推荐是3.10+
3.1 安装langchain
使用命令:poetry add langchain 安装
Using version ^1.2.14 for langchain
Updating dependencies
Resolving dependencies... (7.9s)
Package operations: 32 installs, 0 updates, 0 removals
- Installing certifi (2026.2.25)
- Installing charset-normalizer (3.4.6)
- Installing h11 (0.16.0)
- Installing idna (3.11)
- Installing typing-extensions (4.15.0)
- Installing urllib3 (2.6.3)
- Installing annotated-types (0.7.0)
- Installing anyio (4.13.0)
- Installing requests (2.33.1)
- Installing pydantic-core (2.41.5)
- Installing typing-inspection (0.4.2)
- Installing httpcore (1.0.9)
- Installing orjson (3.11.8)
- Installing packaging (26.0)
- Installing requests-toolbelt (1.0.0)
- Installing pydantic (2.12.5)
- Installing jsonpointer (3.1.1)
- Installing uuid-utils (0.14.1)
- Installing httpx (0.28.1)
- Installing xxhash (3.6.0)
- Installing zstandard (0.25.0)
- Installing jsonpatch (1.33)
- Installing langsmith (0.7.23)
- Installing tenacity (9.1.4)
- Installing pyyaml (6.0.3)
- Installing langchain-core (1.2.23)
- Installing ormsgpack (1.12.2)
- Installing langgraph-checkpoint (4.0.1)
- Installing langgraph-prebuilt (1.0.8)
- Installing langgraph-sdk (0.3.12)
- Installing langgraph (1.1.4)
- Installing langchain (1.2.14)
看上面的版本,已经到了1.2.14,发展很快,AI应用API是在快速发展中,这玩意要是重度使用,每次迁移成本都很高。python语言和其生态兼容性都比较差,大家都是图块,没人会管你,有些人搞烂了,就开始想找工程师做工程化收拾烂摊子,实际上只有自己搞的人才是最适合收拾烂摊子的,图快总得付出点代价😊。pyhon本身工程化能力就很弱,现在各种标准和最佳实践还在演进。
安装langchain的同时也安装了langgraph,版本是1.1.4,没有看见deepagents
3.2 安装langchain-ollama
这里我使用ollama安装本地模型,所以安装这个模型依赖,其他的可以根据具体需求安装
poetry add langchain-ollama
# Installing the OpenAI integration
pip install -U langchain-openai
# Installing the Anthropic integration
pip install -U langchain-anthropic
3.3 简单聊天测试
3.3.1 模型直接调用
from langchain_ollama import ChatOllama
def test_chat_model():
# 初始化模型,默认连接 http://localhost:11434
llm = ChatOllama(
model="qwen3:8b", # 替换为你通过 `ollama pull` 下载的模型名
temperature=0.7,
base_url="http://localhost:11434",
)
response = llm.invoke("你好,请介绍一下自己")
print(response)
test_chat_model()
print('finish')
输出是一个AIMessage 对象,这玩意一点都不好跟踪代码,点击进去看源码,感觉就是一团糟。不先写个response.content,你直接在response对象上还跳不到AIMessage,IDE提示不了。要么通过invoke跳过,再通过类型提示跳到源码。我也是醉了。
content='你好!我是通义千问,由通义实验室研发的超大规模语言模型。我具备广泛的知识和强大的语言理解能力,可以回答各种问题、创作文字、编程、逻辑推理等。我的目标是成为您可靠的助手,帮助您解决各种问题和完成任务。有什么我可以帮您的吗?' additional_kwargs={} response_metadata={'model': 'qwen3:8b', 'created_at': '2026-04-01T03:41:06.349658Z', 'done': True, 'done_reason': 'stop', 'total_duration': 88827315600, 'load_duration': 76283938800, 'prompt_eval_count': 14, 'prompt_eval_duration': 417483900, 'eval_count': 377, 'eval_duration': 12089060800, 'logprobs': None, 'model_name': 'qwen3:8b', 'model_provider': 'ollama'} id='lc_run--019d4720-0aba-7cc3-9c23-9f3ef121dcea-0' tool_calls=[] invalid_tool_calls=[] usage_metadata={'input_tokens': 14, 'output_tokens': 377, 'total_tokens': 391}
实际上需要用的是content,我也看过别人写热文章,也是慢慢分析返回的字段内容来找想要的而结果。我这里用的是本地模型,如果要用网上的,需要到对应官网开通权限,拿到访问的API_KEY,设置环境变量,才可以访问。如果是像java这种强静态类型语言,直接看response结构,基本上能知道会拿到什么结果,那些字段是自己想要的。
3.2.2 模型参数
原始模型参数,这玩意参数,多
pip install -U langchain
# Requires Python 3.10+
class ChatOllama(
name: str | None,
cache: BaseCache | bool | None,
verbose: bool,
callbacks: Callbacks,
tags: list[str] | None,
metadata: dict[str, Any] | None,
custom_get_token_ids: ((str) -> list[int]) | None,
rate_limiter: BaseRateLimiter | None,
disable_streaming: bool | Literal['tool_calling'],
output_version: str | None,
profile: ModelProfile | None,
model: str,
reasoning: bool | str | None,
validate_model_on_init: bool,
mirostat: int | None,
mirostat_eta: float | None,
mirostat_tau: float | None,
num_ctx: int | None,
num_gpu: int | None,
num_thread: int | None,
num_predict: int | None,
repeat_last_n: int | None,
repeat_penalty: float | None,
temperature: float | None,
seed: int | None,
stop: list[str] | None,
tfs_z: float | None,
top_k: int | None,
top_p: float | None,
format: JsonSchemaValue | Literal['', 'json'] | None,
keep_alive: int | str | None,
base_url: str | None,
client_kwargs: dict | None,
async_client_kwargs: dict | None,
sync_client_kwargs: dict | None
)
网上查了一些解释
# Requires Python 3.10+
class ChatOllama(
# === 核心基础参数 ===
model: str, # [必填] 模型名称,例如 "qwen2.5:7b" 或 "llama3"。必须与 Ollama 本地运行的模型名称匹配。
# === 核心推理参数 (最常用) ===
temperature: float | None, # [推荐] 采样温度 (0.0 - 1.0)。值越低越确定(适合逻辑/代码),值越高越随机(适合创意写作)。
top_p: float | None, # [推荐] 核采样阈值。与 temperature 配合使用,通常建议二选一,不要同时调整。
top_k: int | None, # [推荐] 限制采样时考虑的 top-k 个 token 数量。
num_predict: int | None, # [推荐] 模型生成的最大 token 数量(即回答的长度)。
stop: list[str] | None, # [推荐] 停止生成的词元列表。遇到列表中的任何一个词元,生成即停止。
# === 上下文与窗口 ===
num_ctx: int | None, # [重要] 上下文窗口大小(最大 token 数)。默认通常为 2048。如果对话变长或输入文本很大,需要调大此值。
# === 高级推理控制 ===
repeat_penalty: float | None, # 重复惩罚系数。值越大,模型越不容易重复生成相同的短语。
repeat_last_n: int | None, # 考虑重复惩罚的最近 n 个 token 数量。
seed: int | None, # 随机种子。设置固定的种子可以保证生成的确定性(如果其他参数也固定)。
tfs_z: float | None, # 尾部自由采样 (Tail-Free Sampling)。用于减少低概率 token 的长尾影响。
mirostat: int | None, # 启用 Mirostat 采样算法 (1 或 2)。这是一种控制生成文本惊喜度的算法。
mirostat_tau: float | None, # Mirostat 算法的目标熵值(控制输出的随机性)。
mirostat_eta: float | None, # Mirostat 算法的学习率。
# === 硬件与性能 ===
num_thread: int | None, # 运行时使用的 CPU 线程数。
num_gpu: int | None, # 指定使用的 GPU 层数(用于控制显存占用)。
# === 连接与客户端配置 ===
base_url: str | None, # Ollama API 的基础 URL。默认为 "http://localhost:11434"。
keep_alive: int | str | None, # 模型在 Ollama 中保持加载状态的时间(例如 "5m" 或 300 秒)。
client_kwargs: dict | None, # 传递给同步 HTTP 客户端的额外参数。
async_client_kwargs: dict | None, # 传递给异步 HTTP 客户端的额外参数。
sync_client_kwargs: dict | None, # 传递给同步客户端的特定参数。
# === 输出格式控制 ===
format: JsonSchemaValue | Literal['', 'json'] | None, # 强制输出格式。设置为 "json" 可强制模型返回 JSON 格式,或传入 JSON Schema 进行结构化输出。
# === LangChain 集成与内部参数 (通常无需手动修改) ===
name: str | None, # 此 LLM 实例在 LangChain 链中的名称。
cache: BaseCache | bool | None, # 是否启用响应缓存。
verbose: bool, # 是否打印详细的调试信息。
callbacks: Callbacks, # LangChain 的回调函数列表。
tags: list[str] | None, # 用于标记此 LLM 实例的标签。
metadata: dict[str, Any] | None, # 附加的元数据。
custom_get_token_ids: ((str) -> list[int]) | None, # 自定义的 Tokenizer 函数。
rate_limiter: BaseRateLimiter | None, # 速率限制器,防止请求过快。
disable_streaming: bool | Literal['tool_calling'], # 是否禁用流式输出。
output_version: str | None, # 输出消息的版本格式。
profile: ModelProfile | None, # 模型配置文件,用于自动调整参数。
reasoning: bool | str | None, # 是否启用推理模式(针对特定模型)。
validate_model_on_init: bool # 初始化时是否验证模型是否存在。
)
搞了一个表格
| 参数名称 | 类型 | 说明 |
|---|---|---|
| 核心基础 | ||
model |
str |
[必填] 模型名称,如 "qwen2.5:7b"。需与本地 Ollama 运行的模型一致。 |
| 推理控制 | ||
temperature |
float |
[常用] 采样温度 (0.0 - 1.0)。越低越确定(逻辑/代码),越高越随机(创意)。 |
top_p |
float |
[常用] 核采样阈值。通常与 temperature 二选一调整。 |
top_k |
int |
[常用] 限制采样时考虑的 top-k 个 token 数量。 |
num_predict |
int |
[常用] 模型生成的最大 token 数量(回答长度)。 |
stop |
list[str] |
[常用] 停止词元列表。遇到任意一个即停止生成。 |
repeat_penalty |
float |
重复惩罚系数。值越大,越不容易重复生成相同的短语。 |
repeat_last_n |
int |
考虑重复惩罚的最近 n 个 token 数量。 |
seed |
int |
随机种子。固定种子可保证生成的确定性。 |
tfs_z |
float |
尾部自由采样。用于减少低概率 token 的长尾影响。 |
mirostat |
int |
启用 Mirostat 采样算法 (1 或 2),用于控制生成文本的惊喜度。 |
mirostat_tau |
float |
Mirostat 算法的目标熵值(控制输出的随机性)。 |
mirostat_eta |
float |
Mirostat 算法的学习率。 |
| 上下文与硬件 | ||
num_ctx |
int |
[重要] 上下文窗口大小(最大 token 数)。默认通常 2048,长文本需调大。 |
num_thread |
int |
运行时使用的 CPU 线程数。 |
num_gpu |
int |
指定使用的 GPU 层数(用于控制显存占用)。 |
| 连接与配置 | ||
base_url |
str |
Ollama API 地址。默认 "http://localhost:11434"。 |
keep_alive |
int/str |
模型在 Ollama 中保持加载状态的时间(如 "5m" 或 300)。 |
client_kwargs |
dict |
传递给同步 HTTP 客户端的额外参数。 |
async_client_kwargs |
dict |
传递给异步 HTTP 客户端的额外参数。 |
sync_client_kwargs |
dict |
传递给同步客户端的特定参数。 |
| 输出格式 | ||
format |
str/dict |
强制输出格式。设为 "json" 强制返回 JSON,或传入 JSON Schema。 |
| LangChain 集成 | ||
name |
str |
此 LLM 实例在 LangChain 链中的名称。 |
cache |
bool |
是否启用响应缓存。 |
verbose |
bool |
是否打印详细的调试信息。 |
callbacks |
Callbacks |
LangChain 的回调函数列表。 |
tags |
list[str] |
用于标记此 LLM 实例的标签。 |
metadata |
dict |
附加的元数据。 |
custom_get_token_ids |
func |
自定义的 Tokenizer 函数。 |
rate_limiter |
BaseRateLimiter |
速率限制器,防止请求过快。 |
disable_streaming |
bool |
是否禁用流式输出。 |
output_version |
str |
输出消息的版本格式。 |
profile |
ModelProfile |
模型配置文件,用于自动调整参数。 |
reasoning |
bool/str |
是否启用推理模式(针对特定模型)。 |
validate_model_on_init |
bool |
初始化时是否验证模型是否存在。 |
基本的都加粗了。
3.4 工具调用
这里演示一个直接注册工具的一个官方例子
3.4.1 调用工具代码
from langchain.agents import create_agent
from langchain_ollama import ChatOllama
def get_weather(city: str) -> str:
"""Get weather for a given city."""
return f"It's always sunny in {city}!"
def test_tool_call_by_agents():
modelStr = "qwen3:8b";
chatModel = ChatOllama(
model=modelStr,
temperature=0.7,
base_url="http://localhost:11434",
)
agent = create_agent(
# model=modelStr,
model=chatModel,
tools=[get_weather],
system_prompt="You are a helpful assistant",
)
# Run the agent
result = agent.invoke(
{"messages": [{"role": "user", "content": "what is the weather in sf"}]}
)
print(result)
test_tool_call_by_agents()
3.4.2 返回值
result是个字典,草这玩意真是,就像看见一个java程序员,所有入参和返回值都用Ojbect一样。
{
"messages": [
{
"role": "user",
"type": "HumanMessage",
"content": "what is the weather in sf",
"id": "a1261883-6677-4082-84d9-cbd9a2f24209"
},
{
"role": "assistant",
"type": "AIMessage",
"content": "",
"id": "lc_run--019d47cc-9c2b-7433-ab56-ecb9909de0a5-0",
"tool_calls": [
{
"id": "36886be6-6441-49d5-b364-cab6137452b0",
"name": "get_weather",
"args": {
"city": "San Francisco"
},
"type": "tool_call"
}
],
"usage_metadata": {
"input_tokens": 148,
"output_tokens": 105,
"total_tokens": 253
},
"response_metadata": {
"model": "qwen3:8b",
"created_at": "2026-04-01T06:48:11.9092517Z",
"model_provider": "ollama"
}
},
{
"role": "tool",
"type": "ToolMessage",
"name": "get_weather",
"content": "It's always sunny in San Francisco!",
"id": "0c827960-37e2-4c37-b37a-4d76ed4f3321",
"tool_call_id": "36886be6-6441-49d5-b364-cab6137452b0"
},
{
"role": "assistant",
"type": "AIMessage",
"content": "The weather in San Francisco is sunny! ☀️ It's one of the best things about the city---always a bright day ahead. Let me know if you need more details!",
"id": "lc_run--019d47cc-b789-78b1-9a0a-dad8552c7eef-0",
"tool_calls": [],
"usage_metadata": {
"input_tokens": 188,
"output_tokens": 136,
"total_tokens": 324
},
"response_metadata": {
"model": "qwen3:8b",
"created_at": "2026-04-01T06:48:16.6699577Z",
"model_provider": "ollama"
}
}
],
"finish": "finish"
}
这一条是调用工具返回的信息
{
"role": "tool",
"type": "ToolMessage",
"name": "get_weather",
"content": "It's always sunny in San Francisco!",
"id": "0c827960-37e2-4c37-b37a-4d76ed4f3321",
"tool_call_id": "36886be6-6441-49d5-b364-cab6137452b0"
}
下面这一条是模型拿到工具返回信息后,优化的内容
{
"role": "assistant",
"type": "AIMessage",
"content": "The weather in San Francisco is sunny! ☀️ It's one of the best things about the city---always a bright day ahead. Let me know if you need more details!",
"id": "lc_run--019d47cc-b789-78b1-9a0a-dad8552c7eef-0",
"tool_calls": [],
"usage_metadata": {
"input_tokens": 188,
"output_tokens": 136,
"total_tokens": 324
},
"response_metadata": {
"model": "qwen3:8b",
"created_at": "2026-04-01T06:48:16.6699577Z",
"model_provider": "ollama"
}
}
这家伙这又返回一个字典,内部带数组,取内容都不好取,这玩意写多了,这屁股有点难擦,写代码通常都不是一个人写,烂代码会传染,有很多人都会复制以前的代码,或者写得更乱,没有强限制很难搞。难怪有些公司想找个搞工程化的,他又不知道问题出在哪里,出问题的人一般是不知道问题就出在自己身上,所以总是找不到适合的人处理这个问题,一上来就问题有没有深入研究、算法,有没有看过源码,有点搞笑哈。
函数最重要的两个信息就是入参和返回值,很多时候不需要去看源码的,看源码一般只是抽样的看,python类型提示稍微在这方面起到了一些作用。
3.5 一个更真实的Agent
下面是一个官方说的更接近真实世界的例子,看看是不是更好使用