LangChain 调用 invoke 时会向 LLM 发送哪些消息字段?
结论
会。再次将包含工具调用的历史 AIMessage 传给聊天模型的 invoke(messages) 时,工具名称、调用 ID 和参数通常会转换成供应商要求的格式,作为下一次请求的输入。即使 content 为空,消息中仍可能有需要发送的内容。
你观察到的差异很可能与两处工具调用信息的优先级有关。如果使用的是 ChatAnthropic,当 content 中的普通 tool_use 块与 tool_calls 中的记录 ID 相同时,所查阅的适配器实现会优先采用 tool_calls。这时,只修改 tool_use.input,最终发送的参数可能不会变化。LangChain Anthropic 消息转换源码
原问题没有提供模型供应商、集成包版本和最小复现代码。上述解释有源码依据,但仍需对照实际环境确认。
为什么两个字段看起来重复,却有不同效果?
AIMessage.tool_calls 是 LangChain 提供的统一工具调用表示,content 则可以保留供应商原生内容块。对于 Anthropic,同一次调用可能同时表示为:
tool_calls中的name、id和args。content中的type="tool_use"、name、id和input。
这两处可能描述同一次调用。适配器会在转换时处理重叠记录,请求不一定携带两份相同参数。在上述普通调用分支中,同 ID 的 tool_calls.args 会用于生成发送的 tool_use.input;没有对应记录的原生 tool_use 块也可以被发送。因此,不能据此认定“tool_use 中的参数不会发送”。LangChain 工具调用说明、Anthropic 适配器源码
如何确认实际采用了哪一份参数?
先记录模型类、供应商,以及已安装的 langchain-core 和供应商集成包版本,再检查对应版本的消息转换实现。
如果使用 langchain-anthropic,可以在本地用两个不同的短字符串观察转换结果。下面的代码针对所查阅源码中的函数签名,只检查转换过程,不会调用模型或执行 write_file:
import json
from langchain_core.messages import AIMessage
from langchain_anthropic.chat_models import _format_messages
message = AIMessage(
content=[{
"type": "tool_use",
"id": "call_example",
"name": "write_file",
"input": {"content": "FROM_CONTENT"},
}],
tool_calls=[{
"id": "call_example",
"name": "write_file",
"args": {"content": "FROM_TOOL_CALLS"},
}],
)
system, formatted = _format_messages([message], model=None)
print(json.dumps(formatted, ensure_ascii=False, indent=2))
这里的 content 参数名只是示例,实际应使用你的工具定义。_format_messages 是私有函数,不同版本的签名可能变化,适合临时诊断,不适合作为业务依赖。它展示的是消息转换结果;要确认完整请求,还应检查 SDK 实际发送的请求体,包括系统提示词和绑定的工具定义。
比较 input_tokens 可以提供线索,但无法单独证明某个字段是否发送。排查时应保持其他输入不变,直接比较转换结果或请求体,再结合 token 用量判断。
如何裁剪 write_file 的长参数?
优先压缩已经完成的工具调用记录
对于已经执行完、后续也不需要逐字引用文件内容的调用,可以将整段调用及结果替换为简短的历史摘要,例如保留实际文件路径、执行状态和必要的内容说明。完整文件内容继续保存在应用可访问的存储中。
移除工具调用时,要同时处理对应结果。不要删除 AIMessage.tool_calls 后留下引用其 ID 的 ToolMessage;如果一条消息有多个工具调用,也要检查所有调用与结果是否对应。LangChain 文档明确提醒,裁剪后仍须满足供应商对消息顺序和工具结果配对的要求。消息删除与有效性要求
只压缩参数时,保持相关表示一致
如果需要保留调用结构,应在用于下一次模型请求的消息副本上处理相关参数,并检查 tool_calls、原生内容块及其他可能保存调用信息的字段,避免只改了一处。
裁剪会改变模型能看到的历史信息,应保留明确的省略说明,并保存原始执行记录。如果工具尚未执行,不要把裁剪后的参数交给执行器,否则实际写入内容也会被改变。
能调整工具接口时,考虑传递内容引用
如果应用能提前保存文件内容,可以设计让工具接收路径或内容引用的接口,由工具实现读取完整数据。这需要同时修改工具定义和执行逻辑,不能假设现有 write_file 已支持这种方式。
如果只是工具结果过大,可以让 ToolMessage.content 返回简短结果,将额外数据保存在 ToolMessage.artifact 中。官方文档说明 artifact 不会发送给模型,但这只能减少工具结果中的内容,不能自动消除历史 AIMessage 已有的长参数。ToolMessage artifact 说明
备注:内容仅供参考。
