
大模型对话不是“字符串输入、字符串输出”这么简单。真正进入模型上下文的是一组带角色、内容和元数据的消息列表。1. Messages 是大模型对话的骨架很多人刚学 LangChain会把模型调用理解成我给模型一段文本模型返回一段文本。这个理解不能说错但它只适合最简单的 Demo。真实的大模型应用尤其是智能客服、知识库问答、Agent 工具调用、多轮对话绝对不能只靠一大段字符串拼接。LangChain 官方文档把 Messages 定义为模型上下文的基本单位。一个 Message 不只是内容它还包含 role、content、metadata。role 表示谁说的content 表示说了什么metadata 用来记录消息 ID、token 用量、模型响应信息等。也就是说一条消息本身就是一个结构化对象。为什么这件事重要因为大模型要理解对话首先要知道“谁在说话”。系统规则、用户问题、模型回复、工具结果如果全部揉成一段字符串模型就需要自己猜边界而 Messages 直接把边界标出来模型理解上下文会更稳定。普通字符串和 Messages 列表的区别你可以把 Messages 理解成一次会议纪要不是只记录一句话而是记录谁说的、什么时候说的、说的内容是什么、这句话和后续动作有什么关系。2. 为什么不能一直用字符串拼接小项目里用字符串拼接确实能跑起来。例如把系统提示词、用户问题、历史对话全部拼成一段 prompt然后丢给模型。但是项目稍微复杂一点问题马上出现。第一角色混乱。系统规则、用户提问、模型历史回复和工具结果都混在一起模型可能分不清哪些是必须遵守的规则哪些只是用户随口说的话。第二多轮对话容易乱。用户第一轮说“我想退款”第二轮说“订单号 123”第三轮说“那多久能到账”。如果没有消息角色和顺序管理你只能不断拼字符串越拼越乱成本也越来越高。第三工具调用不好接。Agent 场景里模型可能先请求调用订单查询工具工具返回结果后模型再生成最终答案。这个过程需要 AIMessage 和 ToolMessage 精确对应普通字符串很难优雅表达。第四线上问题难排查。生产系统需要知道每一轮输入输出、token 用量、工具调用 ID、模型响应元数据。字符串只有一大段文本排查时很难定位问题发生在哪里。问题字符串拼接的风险Messages 的优势角色边界系统规则、用户问题、模型回复混在一起每条消息都有明确 role多轮上下文越拼越长越拼越乱消息按顺序保存可裁剪、摘要、持久化工具调用工具请求和结果难对应AIMessage.tool_calls 与 ToolMessage.tool_call_id 可关联可观测只能看到最终 prompt可以记录 message_id、token、response_metadata多模态文本拼接难承载图片、音频、文件content 可以承载多种内容块3. LangChain 的 Message 到底长什么样LangChain 里的 Message 可以先用三个字段理解字段含义例子role这句话是谁说的system / user / assistant / toolcontent消息内容可以是文本也可以是多模态内容块“你是一个客服助手” / 图片 / 文件metadata额外信息用于追踪和工程化治理id、token 用量、模型响应信息、工具调用信息最简单的写法可以是这样from langchain.chat_models import init_chat_modelfrom langchain.messages import SystemMessage, HumanMessagemodel init_chat_model(gpt-5-nano)messages [SystemMessage(你是一个专业、谨慎的技术文章助手。),HumanMessage(帮我解释 LangChain 的 Messages 是什么。),]response model.invoke(messages)print(response.text)你也可以用更接近 OpenAI Chat Completions 的字典格式messages [{role: system, content: 你是一个技术文章助手},{role: user, content: 解释一下 LangChain Messages},]response model.invoke(messages)两种写法背后的思想是一样的把一次对话拆成多条有角色的消息而不是拼成一坨字符串。4. 四类核心消息System、Human、AI、Tool4.1 SystemMessage给模型定规矩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 对齐。这样模型就能知道这个工具结果对应的是刚才哪一次工具请求。5. 多轮对话为什么必须用 Messages单轮问答里Messages 的优势可能不明显。但是一旦进入多轮对话Messages 就非常关键。多轮对话不是“当前问题 历史文本”这么简单。模型需要知道第一句是谁说的第二句是谁回答的第三句是不是工具返回的结果第四句是不是用户在追问。消息顺序和消息角色一起构成了对话状态。LangChain 官方文档也明确提到message prompts 适合管理多轮对话、处理多模态内容、包含系统指令。也就是说只要你要做真正的聊天应用就应该进入 Messages 的世界。举个客服场景messages [SystemMessage(你是金融客服助手回答必须合规。),HumanMessage(我想提前还款。),AIMessage(可以请提供贷款编号。),HumanMessage(编号是 LN2026。),ToolMessage(content查询结果用户可提前还款手续费 0 元。,tool_call_idcall_loan_query_001,namequery_loan_plan),]这段消息历史比一坨字符串清晰得多。模型能看到用户想提前还款模型曾经追问贷款编号工具已经查出可提前还款最后就可以基于工具结果生成准确回复。6. Message content不只是文本还可以是多模态内容早期很多人把大模型应用理解成文本问答但现在模型已经越来越多模态。用户可能上传图片、合同截图、PDF、音频模型也可能返回带引用、推理块、工具调用块的内容。LangChain 的 Message content 是比较灵活的既可以是字符串也可以是内容块列表。官方文档提到content 可以承载文本、图片、音频、文档等内容同时还支持不同模型提供商的原生结构。这意味着 Messages 不只是聊天记录更像是一种统一上下文容器。它把用户输入、模型输出、工具结果、多模态内容和元数据都放进同一套结构里。7. Message metadata线上排查靠它救命很多教程只讲 role 和 content但企业级项目一定要重视 metadata。因为线上出现问题时你不能只看最终回答还要知道模型到底看到了什么、用了多少 token、有没有调用工具、调用哪个工具、工具结果是什么。AIMessage 里常见的 usage_metadata 可以记录输入 token、输出 token、总 tokenresponse_metadata 可以记录模型供应商返回的响应信息。HumanMessage 也可以带 name、id 等字段用于标识不同用户或不同消息。如果你做智能客服、股票分析助手、企业知识库系统建议从第一天就把消息结构化落库。否则等线上回答错了你只能翻日志猜问题很痛苦。字段建议是否落库用途request_id必须一次请求的唯一编号方便串联完整链路session_id必须区分不同会话支持多轮对话role必须区分 system、human、ai、toolcontent必须消息正文或工具结果message_id建议单条消息追踪tool_call_id工具场景必须把工具请求和工具结果对应起来usage_metadata强烈建议统计 token 和成本response_metadata建议排查模型供应商响应问题8. 在 Java Python 架构里Messages 应该怎么设计如果你的主系统是 Spring BootAI 能力放在 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 是大模型应用里的“对话账本”。每一条消息都要知道是谁说的、说了什么、和后续动作有什么关系。内容来源LangChain 系列之 Messages为什么大模型对话不是简单字符串功能变化与行业影响解析_热闻岛