大模型对话不是“字符串输入、字符串输出”这么简单。真正进入模型上下文的,是一组带角色、内容和元数据的消息列表。
1. Messages 是大模型对话的骨架很多人刚学 LangChain,会把模型调用理解成:我给模型一段文本,模型返回一段文本。这个理解不能说错,但它只适合最简单的 Demo。真实的大模型应用,尤其是智能客服、知识库问答、Agent 工具调用、多轮对话,绝对不能只靠一大段字符串拼接。
LangChain 官方文档把 messages 定义为模型上下文的基本单位。一个 Message 不只是内容,它还包含 role、content、metadata。role 表示谁说的,content 表示说了什么,metadata 用来记录消息 ID、token 用量、模型响应信息等。也就是说,一条消息本身就是一个结构化对象。
为什么这件事重要?因为大模型要理解对话,首先要知道“谁在说话”。系统规则、用户问题、模型回复、工具结果,如果全部揉成一段字符串,模型就需要自己猜边界;而 Messages 直接把边界标出来,模型理解上下文会更稳定。
SystemMessage 是模型行为的“底层规则”。它通常放在消息列表最前面,用来告诉模型:你是谁、要怎么回答、有什么边界、哪些事情不能做。
比如智能客服里,SystemMessage 可以写:你是金融客服助手,必须基于知识库和订单系统回答;涉及退款、借款、改手机号等高风险操作时,只能引导用户走官方流程,不能直接替用户操作。
SystemMessage 的价值不是让回答看起来更好,而是把业务规则前置,让模型在整个对话中始终被规则约束。
SystemMessage("""你是一个企业知识库问答助手。回答必须基于已检索到的资料。如果资料中没有答案,要明确说不知道,不能编造。""")
4.2 HumanMessage:承载用户输入HumanMessage 代表用户输入。它可以是纯文本,也可以包含图片、音频、文件等多模态内容。对智能客服来说,它就是用户说的每一句话;对文档问答来说,它就是用户的问题;对多模态应用来说,它还可能包含截图、合同图片、商品图。
从工程角度看,HumanMessage 最好不要只存 content,还要记录 user_id、session_id、message_id、时间戳等信息,方便后续排查。
4.3 AIMessage:承载模型输出AIMessage 是模型返回的消息。它不一定只有最终答案,还可能包含 tool_calls,也就是模型认为自己需要调用某个工具。
比如用户问“帮我查订单 123 到哪了”,模型可能不会直接回答,而是在 AIMessage 里发起 query_order_status 这个工具调用请求。等工具返回结果后,模型再生成最终回复。
AIMessage 里通常还会带 usage_metadata、response_metadata 等信息。这些信息对成本统计、性能分析、线上排查很重要。
4.4 ToolMessage:把工具结果送回模型ToolMessage 是 Agent 工具调用链路里的关键角色。模型发起工具调用后,业务系统真正执行工具,比如查数据库、查订单、查天气、查股票行情。执行结果不能随便拼进 prompt,而是应该作为 ToolMessage 回传给模型。
ToolMessage 需要和 AIMessage 里的 tool_call_id 对齐。这样模型就能知道:这个工具结果对应的是刚才哪一次工具请求。

举个客服场景:
messages = [SystemMessage("你是金融客服助手,回答必须合规。"),HumanMessage("我想提前还款。"),AIMessage("可以,请提供贷款编号。"),HumanMessage("编号是 LN2026。"),ToolMessage(content="查询结果:用户可提前还款,手续费 0 元。",tool_call_id="call_loan_query_001",name="query_loan_plan"),]
这段消息历史比一坨字符串清晰得多。模型能看到:用户想提前还款,模型曾经追问贷款编号,工具已经查出可提前还款,最后就可以基于工具结果生成准确回复。
6. Message content:不只是文本,还可以是多模态内容早期很多人把大模型应用理解成文本问答,但现在模型已经越来越多模态。用户可能上传图片、合同截图、PDF、音频,模型也可能返回带引用、推理块、工具调用块的内容。
LangChain 的 Message content 是比较灵活的:既可以是字符串,也可以是内容块列表。官方文档提到,content 可以承载文本、图片、音频、文档等内容,同时还支持不同模型提供商的原生结构。
这意味着 Messages 不只是聊天记录,更像是一种统一上下文容器。它把用户输入、模型输出、工具结果、多模态内容和元数据都放进同一套结构里。
如果你的主系统是 Spring Boot,AI 能力放在 Python FastAPI 服务里,建议 Java 负责业务身份和会话管理,Python 负责构造 LangChain Messages 并调用模型。
Java 侧不要只给 Python 传一个 prompt 字符串,而应该传结构化请求。例如用户 ID、会话 ID、业务场景、用户问题、历史消息、检索结果、工具权限等。Python AI 服务再把这些内容组装成 SystemMessage、HumanMessage、AIMessage、ToolMessage。
这样做有三个好处:第一,Java 仍然掌握权限和业务边界;第二,Python 可以灵活使用 LangChain 生态;第三,后续接 LangGraph、Memory、LangSmith、评测系统时,不需要推倒重来。
# Java 主服务传给 Python AI 服务的请求示例{"request_id": "req_20260613_001","session_id": "s_10086","user_id": "u_123","scene": "customer_service","question": "我的订单 123 到哪了?","history": [{"role": "human", "content": "我想查订单"},{"role": "ai", "content": "请提供订单号"}],"allowed_tools": ["query_order_status"]}
# Python AI 服务中构造 LangChain Messagesmessages = [SystemMessage("你是客服助手,只能调用授权工具回答。"),HumanMessage("我想查订单"),AIMessage("请提供订单号"),HumanMessage("我的订单 123 到哪了?"),]response = agent.invoke({"messages": messages})
9. 常见错误:很多 LangChain 项目都栽在这里错误做法
为什么有问题
正确做法
把全部历史对话拼成一个字符串
角色边界丢失,越拼越乱
用 messages 列表保存多轮对话
把工具结果直接拼到用户问题后面
模型分不清这是工具结果还是用户输入
用 ToolMessage 回填工具结果
SystemMessage 写得太随意
业务规则不稳定,模型容易跑偏
把角色、边界、输出要求写清楚
不记录 usage_metadata
上线后无法统计成本
保存 token 用量和模型响应信息
无脑保留全部历史消息
上下文变长,成本增加,效果下降
结合 Memory、摘要、窗口裁剪
忽略 tool_call_id
多工具调用时结果容易错配
工具请求和结果必须一一对应
10. 总结:Messages 是后面所有高级能力的地基这章看起来只是在讲消息类型,但它其实是 LangChain 后续所有高级能力的地基。Prompt Template 要生成消息,Chat Model 要消费消息,Memory 要保存和裁剪消息,Tools 要通过 AIMessage 和 ToolMessage 交互,Agent 要围绕消息不断循环,LangGraph 也会把消息作为状态的一部分来流转。
所以,学 LangChain 不要只记 API。你真正要理解的是:大模型应用的上下文,不是一段随便拼出来的字符串,而是一组可组织、可追踪、可扩展、可治理的消息。
记住一句话:Messages 是大模型应用里的“对话账本”。每一条消息都要知道是谁说的、说了什么、和后续动作有什么关系。
相关文章



猜你喜欢
成员 网址收录40418 企业收录2986 印章生成263660 电子证书1157 电子名片68 自媒体113525