当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > LangChain 怎样为工具调用保留中间消息

LangChain 怎样为工具调用保留中间消息

来源:17golang原创 2026-10-29 02:00:40 0浏览 收藏

LangChain 的工具调用不是“模型输出一段文字、工具再返回一段文字”这么简单。要让下一次模型调用知道刚才调用了哪个工具,应用需要保留消息序列:用户消息、带有 tool_calls 的 AIMessage、带有对应 tool_call_id 的 ToolMessage,以及后续模型消息。

官方地址:https://docs.langchain.com/oss/python/langchain/messages

最实用的做法是把 agent 返回的 result["messages"] 当作中间状态保存,而不是只取最后一条 content。这样既能继续对话,也能在日志或持久化层中追踪工具调用的对应关系。

为什么中间消息不能只保存最终文本

LangChain 的消息对象同时承载角色、内容和元数据。模型决定调用工具时,工具调用信息位于 AIMessage.tool_calls;工具执行后的结果则用 ToolMessage 回传。只保存最终回答,会丢掉工具名、参数和调用标识,下一次模型就无法可靠地把结果对应回原调用。

HumanMessage、AIMessage、ToolMessage、消息历史与模型上下文的静态结构说明图
图1:消息历史结构说明图,区分模型发出的工具调用与工具返回的消息对象。

这条消息链应被视为一个整体:AIMessage 说明模型提出了什么调用,ToolMessage 说明该调用得到什么结果。二者之间最关键的连接不是文本相似,而是调用 ID。

旧写法的问题:只取最后一条消息

下面这种写法适合只展示最终答案,却不适合保留中间状态:

# 只取最终文本,工具调用名称和参数会被丢掉
final_text = result["messages"][-1].content
print(final_text)

它的问题不在于最后一条消息一定错误,而在于它把“展示结果”和“保存状态”混在一起。展示时可以读取最后一条;保存时应保留整个列表,并按消息类型提取需要的字段。

新规则:从 agent 返回值保留完整 messages

使用 create_agent 时,返回值包含消息状态。下面的示例只做消息收集,不把示例输出描述成已经在本机运行的结果:

from langchain.agents import create_agent
from langchain.tools import tool
from langchain.messages import AIMessage, ToolMessage

@tool
def lookup_weather(city: str) -> str:
    """返回一个供示例使用的天气结果。"""
    # 工具返回值会进入 ToolMessage.content,保持结果可序列化
    return f"{city}:晴,26℃"

agent = create_agent(
    model="openai:gpt-5-nano",
    tools=[lookup_weather],
    system_prompt="你是一个会使用工具的助手",
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "查询上海天气"}]
})

# 保存完整消息列表,而不是只保存最后的回答文本
messages = result["messages"]
for message in messages:
    if isinstance(message, AIMessage):
        print("AI 调用:", message.tool_calls)
    elif isinstance(message, ToolMessage):
        print("工具结果:", message.content)

这里的核心只有两点:messages 是可继续交给模型的上下文,AIMessage 与 ToolMessage 则让应用可以分别记录模型调用和工具结果。若只需要展示最终答案,再从列表末尾读取即可。

手动续接工具结果时,调用标识必须对应

如果应用没有直接使用 agent 循环,而是自己执行工具并把结果交回模型,必须把 ToolMessage.tool_call_id 设置为 AIMessage.tool_calls 中对应调用的 id:

from langchain.messages import AIMessage, HumanMessage, ToolMessage

ai_message = AIMessage(
    content=[],
    tool_calls=[{
        "name": "lookup_weather",
        "args": {"city": "上海"},
        "id": "call_weather_001",
    }],
)

# 真实工具执行后,把同一个 id 写回结果消息
tool_message = ToolMessage(
    content="上海:晴,26℃",
    tool_call_id="call_weather_001",
)

messages = [
    HumanMessage("查询上海天气"),
    ai_message,
    tool_message,
]
# 下一次模型调用接收的是完整的消息关系
response = model.invoke(messages)
AIMessage tool_calls 调用 id 与 ToolMessage tool_call_id、content、artifact 的字段关系说明图
图2:工具结果字段关系说明图,突出 tool_call_id 与工具调用 id 的对应边界。

如果一次 AIMessage 含有多个工具调用,就要为每个结果建立独立的 ToolMessage,逐一匹配各自的 ID。不能用“最后一次调用”或工具名称猜测对应关系。

兼容边界:content、artifact 与持久化

ToolMessage.content 是发送给模型的工具结果;若应用还需要保存检索文档编号、原始响应或渲染信息,可以把这类不必直接进入模型上下文的附加数据放入 artifact,并在业务层按需序列化。

因此可以按三层保存:第一层是完整 messages,用于继续调用;第二层是每条消息的类型、调用 ID 和内容,便于日志检索;第三层是 artifact 等应用侧数据,服务展示或审计。跨请求、跨线程的长期保留还需要接入自己的存储或 LangGraph 的持久化能力,不能把一次 invoke 返回值自动当成永久数据库。

最终采用建议很简单:展示回答时取末条消息,恢复上下文时保存完整消息列表,手动回填工具结果时严格复用调用 ID。这样既保留中间消息,也不会把工具结果错接到另一条调用上。

常见问题

只保存 AIMessage 可以吗?不建议。模型发出的调用和工具返回的结果是一对关系,缺少 ToolMessage 后,后续上下文不完整。

artifact 会自动发送给模型吗?不应这样假设。把需要模型理解的结果放在 content,应用侧附加数据再单独放进 artifact。

为什么工具结果必须带 tool_call_id?它用来对应 AIMessage 中具体的调用 ID;多个工具并行调用时尤其不能省略。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Hugging Face Tokenizers 怎样保存自定义词表Hugging Face Tokenizers 怎样保存自定义词表
上一篇
Hugging Face Tokenizers 怎样保存自定义词表
LlamaIndex 怎样把元数据加入向量检索过滤
下一篇
LlamaIndex 怎样把元数据加入向量检索过滤
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    764次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    760次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    842次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    813次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    641次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码