大模型:MessagesPlaceholder 是什么?

📅 2026/7/6 1:37:19
大模型:MessagesPlaceholder 是什么?
MessagesPlaceholder是什么MessagesPlaceholder是 LangChain 中专门用于ChatPromptTemplate的一个特殊占位符组件。它与普通字符串占位符如{input}最大的不同在于它用来接收并注入一整个“消息列表List[BaseMessage]”而不是一个普通的字符串值。在代码中它的写法是MessagesPlaceholder(变量名)其中变量名是运行时传入的字典中对应的键名。一句话定义MessagesPlaceholder是 LangChain 在提示模板中预留的“插槽”用于在运行时把一整套带有角色System/Human/AI/Tool的对话消息无损地插入到模板中。为什么需要它普通占位符 vs MessagesPlaceholder如果我们只用普通字符串占位符{chat_history}我们需要手动把历史消息列表拼接成一个长字符串例如用户你好\nAI你好有什么可以帮您\n用户...。这样做有两个致命问题问题说明丢失角色信息拼接成的字符串失去了HumanMessage、AIMessage这类结构化标签模型无法区分哪句是谁说的除非你在字符串里强行加“用户”前缀但这是纯文本不是原生结构。无法传输工具消息ToolMessageRAG 或 Agent 中涉及工具调用时历史里可能包含ToolMessage工具返回结果。纯文本拼接无法保留其特殊结构。MessagesPlaceholder恰恰解决了这两个问题它直接传递BaseMessage对象列表保持每条消息的完整角色、内容和元数据让聊天模型ChatModel可以原生解析不用再手动去做字符串拼接。在代码中如何使用1. 定义模板fromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholder promptChatPromptTemplate.from_messages([(system,你是一个乐于助人的助手。),MessagesPlaceholder(chat_history),# ① 预留历史消息插槽(human,{input})# ② 当前用户输入])运行时chat_history会替换成一整段历史消息列表。input仍是一个普通的字符串占位符。2. 运行时注入fromlangchain_core.messagesimportHumanMessage,AIMessage# 模拟历史对话history_msgs[HumanMessage(content我叫小明),AIMessage(content你好小明很高兴认识你。)]# 注入数据final_messagesprompt.invoke({chat_history:history_msgs,input:你还记得我叫什么吗}).to_messages()# 此时 final_messages 包含:# [SystemMessage, HumanMessage(我叫小明), AIMessage(...), HumanMessage(你还记得我叫什么吗)]最终生成的final_messages会保留每一条消息的角色直接传给模型。与RunnableWithMessageHistory的关系MessagesPlaceholder负责“占位”RunnableWithMessageHistory负责“填充”。在实战中MessagesPlaceholder最常见的搭配就是RunnableWithMessageHistory如你之前写的代码。它的工作流程是RunnableWithMessageHistory根据session_id从chat_history_store里取出一整个消息列表。在调用base_chain时它自动把这个列表塞进invoke字典的chat_history键里。prompt里的MessagesPlaceholder(chat_history)收到这个列表完成注入。模型生成回复。框架自动把新的UserMessage和AIMessage追加回存储中。没有MessagesPlaceholderRunnableWithMessageHistory就无处安放历史消息没有RunnableWithMessageHistoryMessagesPlaceholder就只能手动传参。面试高频追问与回答Q1如果我用普通字符串占位符{chat_history}然后传一个 JSON 字符串效果一样吗A不一样。ChatModel如通义千问、GPT-4的 API 接收的是结构化的消息数组[{role: user, content: ...}]。如果传 JSON 字符串模型会把它当成一段普通的content而无法识别其中的角色信息。这会导致系统提示和用户消息界限模糊严重影响模型的指令遵循能力。Q2MessagesPlaceholder能传ToolMessage吗A可以。只要是BaseMessage的子类HumanMessage,AIMessage,SystemMessage,ToolMessage等MessagesPlaceholder都能无损传递。这在 Agent 场景中非常关键因为工具调用结果必须原样送回模型模型才能据此做下一步推理。Q3MessagesPlaceholder和StringPromptTemplate能混用吗A不能。StringPromptTemplate生成的是纯文本提示不区分角色。MessagesPlaceholder是专为ChatPromptTemplate设计的。二者不能混用。Q4如何限制MessagesPlaceholder里消息的数量AMessagesPlaceholder本身不提供限制功能。你需要在使用RunnableWithMessageHistory时配合trim_messages工具或者在自定义的ChatMessageHistory的add_messages方法里做截断。官方推荐的做法是在传给MessagesPlaceholder之前用trim_messages对历史列表进行裁剪。总结MessagesPlaceholder是 LangChain 实现结构化多轮对话的基石。它让历史消息得以“原汁原味”地传入模型让 Agent 和 RAG 系统能精准理解上下文。在面试中能清晰区分MessagesPlaceholder和普通字符串占位符并能解释其在RunnableWithMessageHistory中的协作关系是体现你对 LangChain 理解深度的标志性知识点之一。