精读 LangChain 官方文档(七)Messages 篇:把对话上下文讲清楚

发布时间:2026/6/26 6:10:52

精读 LangChain 官方文档(七)Messages 篇:把对话上下文讲清楚 精读 LangChain 官方文档七Messages 篇把对话上下文讲清楚本文基于 LangChain Python 官方文档整理Messageshttps://docs.langchain.com/oss/python/langchain/messagesMarkdown 版本https://docs.langchain.com/oss/python/langchain/messages.md对应开源文档源码https://github.com/langchain-ai/docs/blob/main/src/oss/langchain/messages.mdx刚学 LangChain 时会把模型调用理解成“给模型一段字符串模型返回一段字符串”。这个理解能跑通第一个 demo但很快就会在真实业务里卡住系统提示词放哪多轮历史怎么保存模型想调用工具时怎么表达工具执行结果怎么回传图片、PDF、音频这些多模态内容又怎么进入上下文LangChain 的Messages页面讲的就是这件事。这篇文档的核心主线可以概括成一句话Message role content metadata。消息不是普通文本而是 LangChain 统一模型上下文、工具调用、多模态输入、流式输出和可观测数据的最小工程单元。如果说上一篇 Agents 篇讲的是“智能体怎么组织行动”Models 篇讲的是“推理引擎怎么接入”那 Messages 篇讲的就是模型到底是靠什么看懂一段对话的。1. Messages消息到底解决什么问题它解决的问题Messages 把一次模型调用里的上下文从一段普通字符串升级成一组可解释、可追踪、可组合的消息对象。官方文档开头强调消息是 LangChain 中模型上下文的基本单位。每条消息通常包含三类信息role消息角色例如系统、用户、助手、工具。content消息内容可以是文本、图片、音频、文件也可以是内容块列表。metadata元数据例如消息 ID、响应信息、token 用量。示例importosfromlangchain_openaiimportChatOpenAIfromlangchain.messagesimportSystemMessage,HumanMessage modelChatOpenAI(modelqwen3.7-max,api_keyos.environ[QWEN_API_KEY],base_urlos.environ[QWEN_BASE_URL],)messages[SystemMessage(你是一名耐心的烘焙客服助手只回答和订单、商品、售后相关的问题。),HumanMessage(我昨天买的蛋糕什么时候能发货),]responsemodel.invoke(messages)print(response.text())这里ChatOpenAILangChain 的 OpenAI-compatible 聊天模型封装这里用来接入qwen3.7-max。QWEN_API_KEY环境变量名保存模型 API 密钥不能把真实密钥写进代码。QWEN_BASE_URL环境变量名保存 OpenAI-compatible 服务地址。messages消息列表按顺序描述模型本次调用能看到的上下文。SystemMessage系统消息用来设置模型行为边界。HumanMessage用户消息用来表示真实用户输入。response模型返回的AIMessage不是普通字符串。业务场景在智能客服系统里你不希望每次都把“你是客服助手”拼进用户问题也不希望把工具调用结果伪装成用户说的话。消息对象让不同来源的信息各归其位。最简记法字符串只能表达“说了什么”Message 还能表达“谁说的、带着什么结构、后续怎么追踪”。2. Text Prompt、Message Prompt、Dictionary Format 怎么选它解决的问题LangChain 支持多种输入形式让简单任务保持简单让复杂对话保留结构。官方文档把基础用法分成三类Text prompts直接传字符串。Message prompts传消息对象列表。Dictionary format传 OpenAI chat completions 风格的字典列表。示例# 方式一直接字符串适合一次性任务summarymodel.invoke(请用三句话解释 LangChain Messages 的作用)# 方式二消息对象适合多轮对话和系统约束replymodel.invoke([SystemMessage(你是一名技术讲解助手回答要简洁。),HumanMessage(Messages 和普通字符串有什么区别),])# 方式三字典格式适合和 OpenAI 风格协议对齐reply_from_dictmodel.invoke([{role:system,content:你是一名技术讲解助手回答要简洁。},{role:user,content:Messages 和普通字符串有什么区别},])这里Text prompts文本提示词适合不需要历史、不需要角色区分的单次生成。Message prompts消息提示词适合系统提示词、多轮历史、多模态内容和工具调用。Dictionary format字典格式role和content字段与 OpenAI chat completions 协议接近。role消息角色字段告诉模型这条消息属于系统、用户、助手还是工具。content消息正文可以是字符串也可以是结构化内容列表。业务场景如果只是“帮我写一句促销文案”字符串就够了。如果是“用户问订单状态系统先查库再结合售后规则回答”就应该使用消息对象或字典格式。最简记法一次性任务用字符串多轮和工程化任务用消息列表。3. SystemMessage系统消息给模型划定行为边界它解决的问题SystemMessage用来告诉模型应该扮演什么角色、遵守什么规则、采用什么回答风格。系统消息通常放在消息列表最前面。它不代表用户的问题而代表应用开发者给模型设置的行为协议。示例fromlangchain.messagesimportSystemMessage,HumanMessage messages[SystemMessage(你是一名资深 Python 后端工程师。回答时先给结论再给最小可运行示例最后解释关键参数。),HumanMessage(如何用 FastAPI 写一个健康检查接口),]responsemodel.invoke(messages)print(response.text())这里SystemMessage系统级指令不是用户消息主要控制模型行为。HumanMessage用户输入表示用户真正想问的问题。资深 Python 后端工程师角色设定用来影响模型回答视角。先给结论、最小可运行示例、解释关键参数回答格式约束。业务场景企业内部知识库助手可以用系统消息固定边界只回答公司制度不编造链接不回答员工隐私不执行高风险操作。最简记法SystemMessage是应用给模型的“岗位说明书”。4. HumanMessage用户消息承载真实输入它解决的问题HumanMessage表示用户输入它可以是普通文本也可以承载图片、音频、文件等多模态内容。官方文档还提到用户消息可以携带name和id这样的元数据。示例fromlangchain.messagesimportHumanMessage human_msgHumanMessage(content请帮我判断这条用户反馈属于物流问题还是商品质量问题蛋糕到货时已经变形。,namecustomer_service_user,idmsg_20260614_001,)responsemodel.invoke([human_msg])这里content用户消息正文。name可选发送者名称不同模型供应商对它的支持不完全一致。id消息唯一标识常用于日志追踪、问题复现和链路排查。human_msg变量名表示一条用户消息对象。业务场景客服系统可以把每次用户输入都保存成HumanMessage再用id对齐数据库里的会话记录。出现误答时就能从日志里找到完整上下文。最简记法HumanMessage不是“用户说的一句话”而是“用户输入这件事”的结构化记录。5. AIMessage模型消息模型输出也不是普通字符串它解决的问题AIMessage表示模型输出它不仅包含文本还可能包含工具调用、内容块、token 用量和响应元数据。很多初学者会习惯把模型返回值当字符串处理。但在 LangChain 里模型返回的通常是AIMessage它常见属性包括text模型输出的文本内容。content原始内容可能是字符串也可能是内容块列表。content_blocksLangChain 标准化后的内容块列表。tool_calls模型请求调用的工具。id消息唯一标识。usage_metadatatoken 用量。response_metadata模型供应商返回的响应信息。示例responsemodel.invoke(请用一句话解释 AIMessage 的作用)print(type(response))print(response.text())print(response.usage_metadata)print(response.response_metadata)这里response.text()读取模型文本输出的便捷方法。usage_metadata记录输入 token、输出 token、总 token 等用量信息适合做成本统计。response_metadata记录供应商侧响应信息例如模型名、结束原因、请求标识等。type(response)用于确认返回值是消息对象而不是普通字符串。业务场景企业 AI 平台需要统计每个用户、每条业务线、每个模型的调用成本。只保存最终文本不够还要保存usage_metadata这样的用量字段。最简记法AIMessage是模型输出的“完整回执”文本只是其中一部分。6. tool_calls工具调用模型想做事时怎么表达它解决的问题tool_calls用结构化方式表示“模型想调用哪个工具、传什么参数、这次调用编号是什么”。当模型绑定工具后模型可以不直接回答而是在AIMessage.tool_calls里提出工具调用请求。程序再执行工具把结果返回给模型。示例fromlangchain_openaiimportChatOpenAI# 查询订单状态真实项目中可以替换为数据库查询或物流系统 API 调用。defquery_order_status(order_id:str)-str:returnf订单{order_id}已出库预计明天送达。model_with_toolsmodel.bind_tools([query_order_status])responsemodel_with_tools.invoke(请帮我查一下订单 DD20260614001 的物流状态)fortool_callinresponse.tool_calls:print(tool_call[name])print(tool_call[args])print(tool_call[id])这里bind_tools把可调用工具绑定到模型让模型知道有哪些外部能力可以使用。query_order_status函数名表示查询订单物流状态的工具。order_id函数参数名表示订单编号。tool_calls模型生成的工具调用列表。name工具名称通常对应函数名。args工具参数通常是一个字典。id本次工具调用的唯一编号后续ToolMessage必须用它对齐。业务场景用户问“我的订单在哪”模型不应该编造答案而应该生成工具调用让后端系统去查询真实订单数据。最简记法tool_calls是模型递给程序的“我要调用工具”申请单。7. ToolMessage工具消息把工具结果交还给模型它解决的问题ToolMessage用来把工具执行结果放回对话上下文并且和前面的工具调用精确对齐。工具调用不是“模型说一句程序随便回一句”。它必须通过tool_call_id对应到前一个AIMessage.tool_calls里的id。示例fromlangchain.messagesimportAIMessage,HumanMessage,ToolMessage ai_messageAIMessage(content[],tool_calls[{name:query_order_status,args:{order_id:DD20260614001},id:call_order_001,}],)tool_messageToolMessage(content订单 DD20260614001 已出库预计明天送达。,tool_call_idcall_order_001,namequery_order_status,)messages[HumanMessage(我的订单 DD20260614001 到哪里了),ai_message,tool_message,]final_responsemodel.invoke(messages)这里ToolMessage工具结果消息表示程序已经执行了工具并拿到结果。tool_call_id工具调用编号必须匹配前面AIMessage.tool_calls中的id。name工具名称便于追踪是哪个工具返回了结果。content会交给模型看的工具结果文本。业务场景订单助手、CRM 助手、数据分析助手都需要这个闭环模型提出查询后端执行查询工具结果回到模型模型再组织成用户能看懂的回答。最简记法ToolMessage是工具执行后的“回执单”必须贴上原工具调用编号。8. artifact附加产物有些数据要给程序看不必给模型看它解决的问题artifact用来存放程序后续需要、但不适合塞进模型上下文的附加数据。官方文档给出的典型场景是检索工具。模型只需要看到检索片段但应用可能还需要文档 ID、页码、相似度分数用来渲染引用来源或做调试。示例fromlangchain.messagesimportToolMessage tool_messageToolMessage(content《配送规则》第 3 条说明冷链商品发货后通常 24 小时内送达。,tool_call_idcall_search_policy_001,namesearch_policy,artifact{document_id:policy_delivery_2026,page:3,score:0.92,},)这里artifact附加产物字段不一定发送给模型但程序可以读取。document_id文档编号用来定位原始资料。page页码用来做引用跳转。score检索相似度分数用来辅助排序或调试。search_policy工具名称表示检索公司规则文档。业务场景知识库问答需要在答案下方展示“引用自哪篇文档第几页”。这些引用信息没必要全部塞给模型但前端展示时必须能拿到。最简记法content给模型看artifact给程序用。9. content 与 content_blocks原始内容和标准内容块它解决的问题content保留消息原始内容content_blocks提供跨供应商更一致、更类型安全的访问方式。官方文档指出消息的content可以是三种形态字符串。供应商原生内容块列表。LangChain 标准内容块列表。为了让不同供应商的结构更好统一LangChain v1 引入了content_blocks属性。它不是要替代content而是提供标准化视图。示例fromlangchain.messagesimportHumanMessage messageHumanMessage(content_blocks[{type:text,text:请识别这张商品图里的包装是否破损。},{type:image,url:https://example.com/order-package.jpg},])forblockinmessage.content_blocks:print(block[type])这里content消息原始内容可能带有供应商格式差异。content_blocksLangChain 标准内容块列表。type内容块类型例如text、image、file、reasoning。url图片或文件地址。业务场景同一个应用可能先接 OpenAI-compatible 模型后接 Anthropic 或其他供应商。如果业务代码都依赖供应商原生字段迁移成本会很高。content_blocks可以降低这类耦合。最简记法content是原始载荷content_blocks是 LangChain 帮你整理后的标准视图。10. Standard Content Blocks标准内容块把复杂内容分门别类它解决的问题标准内容块让文本、推理、多模态、工具调用和供应商特有数据都能被统一描述。官方文档列了很多内容块类型。对于工程落地可以先记住这几组类型中文解释常见用途TextContentBlock文本内容块普通回答、提示词、摘要ReasoningContentBlock推理内容块模型推理摘要或思考过程ImageContentBlock图片内容块图片理解、商品识别、截图分析AudioContentBlock音频内容块语音输入、录音理解VideoContentBlock视频内容块视频片段理解FileContentBlock文件内容块PDF、文档、附件ToolCall工具调用块模型请求调用函数ToolCallChunk工具调用流式片段流式生成工具参数InvalidToolCall无效工具调用捕获 JSON 解析失败等异常ServerToolCall服务端工具调用供应商侧执行的工具请求ServerToolResult服务端工具结果供应商侧工具执行结果NonStandardContentBlock非标准内容块供应商特有结构兜底示例message{role:user,content:[{type:text,text:请总结这份售后说明文档的核心规则。},{type:file,url:https://example.com/after-sale-policy.pdf,mime_type:application/pdf,},],}这里file文件内容块类型。mime_type文件媒体类型告诉模型或供应商这是 PDF、图片、音频还是其他格式。application/pdfPDF 文件的媒体类型。NonStandardContentBlock当供应商提供了 LangChain 标准之外的结构时用来保留原始数据。业务场景一个售后助手既要看用户文字也要看用户上传的破损照片还要分析 PDF 规则文档。标准内容块让这些不同形态的数据可以出现在同一条消息里。最简记法标准内容块就是 LangChain 给消息内容做的“类型目录”。11. Multimodal多模态图片、文件、音频和视频怎么进入消息它解决的问题多模态消息让模型上下文不再只有文本而可以接收图片、PDF、音频和视频等不同数据。官方文档示例里多模态内容可以来自url外部资源地址。base64base64 编码数据。file_id供应商托管文件 ID。示例message{role:user,content:[{type:text,text:请判断这张蛋糕照片是否存在明显破损。},{type:image,url:https://example.com/cake-damaged.jpg,},],}responsemodel.invoke([message])这里image图片内容块类型。url图片地址。base64把二进制文件编码成文本后放入消息适合没有公网 URL 的文件。file_id供应商托管文件编号适合先上传文件再引用。mime_typebase64 文件通常需要这个字段说明数据类型。业务场景生鲜、烘焙、服装售后经常需要用户上传图片。多模态消息能让模型直接结合图片和文字判断问题类型而不是只靠用户描述。最简记法多模态消息把“看图、读文件、听音频”都纳入同一套消息协议。12. Streaming and Chunks流式与消息片段为什么 chunk 能拼回完整消息它解决的问题流式输出时模型不会一次返回完整AIMessage而是持续返回可以累加的AIMessageChunk。官方文档里的关键点是流式 chunk 可以组合成完整消息对象。也就是说流式不是“随便吐字”而是仍然沿用消息协议。示例chunks[]full_messageNoneforchunkinmodel.stream(请用三句话解释 LangChain 的消息机制):chunks.append(chunk)print(chunk.text(),end)full_messagechunkiffull_messageisNoneelsefull_messagechunkprint(\n完整消息)print(full_message.text())这里stream流式调用方法适合前端实时展示。chunk流式返回的消息片段。AIMessageChunkAI 消息片段类型可以累加。full_message把多个片段合并后的完整消息。业务场景长答案生成、报告撰写、代码解释都适合流式输出。前端可以实时展示 token后端最终仍然保存完整消息便于审计和复盘。最简记法流式输出是“分片返回”不是“脱离消息协议”。13. usage_metadata 与 response_metadata消息里的成本和供应商信息它解决的问题元数据让模型调用可以被计费、监控、排查和治理。官方文档提到AIMessage可以通过usage_metadata保存 token 用量通过response_metadata保存响应信息。示例responsemodel.invoke(请给出三条提升客服回复质量的建议)usageresponse.usage_metadata provider_inforesponse.response_metadataprint(输入 token,usage.get(input_tokens))print(输出 token,usage.get(output_tokens))print(总 token,usage.get(total_tokens))print(供应商响应信息,provider_info)这里input_tokens输入消耗 token 数。output_tokens输出消耗 token 数。total_tokens本次调用总 token 数。provider_info变量名表示模型供应商返回的响应信息。response_metadata常用于查看模型名、结束原因、请求 ID 等。业务场景如果一个团队有多个 AI 功能例如客服、文案、知识库、数据分析就需要按功能统计成本。usage_metadata是成本看板的基础字段。最简记法没有元数据就很难把 AI 能力从 demo 管成平台。14. Message History消息历史从单次调用走向可恢复对话它解决的问题聊天模型通常是无状态的应用需要自己管理不断增长的消息列表并在必要时裁剪、总结或持久化。官方文档最后提醒Chat model 接收消息序列作为输入返回AIMessage。多轮应用会维护一组越来越长的消息历史并结合记忆管理策略处理上下文窗口。示例fromlangchain.messagesimportAIMessage,HumanMessage,SystemMessage messages[SystemMessage(你是一名电商客服助手。),HumanMessage(我想买低糖蛋糕有推荐吗),]first_replymodel.invoke(messages)messages.append(first_reply)messages.append(HumanMessage(如果明天生日宴用配送时间怎么安排))second_replymodel.invoke(messages)messages.append(second_reply)这里messages.append(first_reply)把模型回复加入历史下一轮模型才能看到之前说过什么。Message History消息历史表示同一会话里的上下文集合。context window上下文窗口表示模型一次调用能容纳的最大上下文长度。trimming裁剪消息删除或压缩不重要的历史。summarizing总结消息把长历史压缩成更短摘要。业务场景用户先问“推荐低糖蛋糕”再问“明天生日宴用怎么安排”第二个问题里的“它”依赖第一轮上下文。没有消息历史模型就无法理解指代关系。最简记法多轮对话不是模型天生记得而是应用把消息历史带回去了。总结把 Messages 当成工程协议而不是聊天文本读完 LangChain 的 Messages 文档最重要的不是记住每个类名而是换一个心智模型层次你看到的表面工程里真正要管理的东西普通字符串用户说了一句话没有角色、历史和元数据适合简单任务Message 对象一条带角色的消息可以区分系统、用户、助手和工具AIMessage模型回答文本、工具调用、token 用量、供应商元数据ToolMessage工具结果和工具调用 ID 对齐的执行回执content_blocks内容块文本、图片、文件、推理、工具调用的标准表示Message History聊天记录可恢复、可裁剪、可总结、可审计的上下文链路所以Messages 的最简记法是字符串负责表达内容Messages 负责表达上下文协议。下一篇如果继续沿着 Agent 核心循环往下读就可以进入 Runtime 篇看看 LangChain 为什么要站在 LangGraph 之上以及运行时上下文如何影响 Agent 的执行过程。

相关新闻