13ChatPromptTemplate的使用

📄 文件代码内容

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.chat_models.tongyi import ChatTongyi

chat_prompt_template = ChatPromptTemplate.from_messages( #from_messages可以用来创建模版对象
    [
        ("system", "你是一个边塞诗人,可以作诗。"),
        MessagesPlaceholder("history"), # 消息的占位符,提供history作为key 基于invoke动态注入历史回话记录
        ("human", "请再来一首唐诗"),
    ]
)

history_data = [
    ("human", "你来写一个唐诗"),
    ("ai", "床前明月光,疑是地上霜,举头望明月,低头思故乡"),
    ("human", "好诗再来一个"),
    ("ai", "锄禾日当午,汗滴禾下锄,谁知盘中餐,粒粒皆辛苦"),
]

# StringPromptValue    to_string()
prompt_text = chat_prompt_template.invoke({"history": history_data}).to_string()

model = ChatTongyi(model="qwen3-max")

res = model.invoke(prompt_text)

print(res.content, type(res))

🔄 代码流程梳理

  1. 导入依赖

    • langchain_core.prompts 导入 ChatPromptTemplateMessagesPlaceholder
    • langchain_community.chat_models.tongyi 导入 ChatTongyi(通义千问模型封装)。
  2. 创建聊天提示模板

    • 使用 ChatPromptTemplate.from_messages() 构建模板,包含三个部分:
      • 系统消息(固定角色设定:边塞诗人)。
      • MessagesPlaceholder("history")------运行时将插入一整段历史对话记录。
      • 人类消息(当前用户问题:"请再来一首唐诗")。
  3. 准备历史对话数据

    • history_data 是一个列表,包含两轮对话的交替消息(human/ai),模拟多轮对话上下文。
  4. 模板填充(生成最终提示)

    • 调用 chat_prompt_template.invoke({"history": history_data}),将历史消息注入占位符,得到 PromptValue 对象。
    • 调用 .to_string() 将该对象转为纯字符串形式(便于传给模型或调试)。
  5. 初始化模型并调用

    • 创建 ChatTongyi 实例,指定模型为 "qwen3-max"
    • 将生成的提示字符串传入 model.invoke(),获得模型响应(AIMessage 对象)。
  6. 输出结果

    • 打印响应内容(res.content)和响应对象的类型(AIMessage)。

💡 高频面试知识点与回答思路

1. ChatPromptTemplatePromptTemplate 的区别
  • PromptTemplate 生成纯文本字符串,适用于非聊天模型(如 text-davinci-003)。
  • ChatPromptTemplate 生成消息列表(包含角色),专为聊天模型设计,支持 system、human、ai 角色区分,更符合 ChatGPT 等模型的要求。
2. MessagesPlaceholder 的作用及使用场景
  • 它用于在模板中预留一个"插槽",运行时可以插入一整段消息序列(如历史对话、工具返回结果)。
  • 与普通字符串占位符不同,它保留消息的角色结构,避免手动拼接丢失角色信息。
  • 典型场景:多轮对话历史、工具调用链、记忆注入。
3. invokeformat_messages / to_string 的区别
  • invoke 执行模板填充,返回 PromptValue(一个封装对象,可能包含多种格式)。
  • format_messages 直接返回消息列表(List[BaseMessage]),适合直接传给聊天模型。
  • to_stringPromptValue 转为纯字符串,方便调试或与不支持消息列表的接口对接。
4. 如何实现真正的"多轮对话记忆"?
  • 该示例只是静态注入预设历史,未实现增量记忆。
  • 真正的记忆需要在每次对话后将新消息追加到历史列表,并在下一轮调用时传入更新后的完整列表。
  • 可以结合 RunnableWithMessageHistory 或自定义状态管理(如 LangGraph 中的 State)实现。
5. 如果历史消息过长,如何应对 Token 限制?
  • 截断 :只保留最近 N 轮对话(ConversationBufferWindowMemory)。
  • 摘要 :使用 ConversationSummaryMemory 对旧消息进行压缩。
  • 向量检索记忆 :将历史消息存入向量库,按需检索相关片段(VectorStoreRetrieverMemory)。
  • LangChain 提供的 trim_messages 工具可对消息列表按 token 数修剪。
6. ChatTongyiChatOpenAI 的异同
  • 两者均继承自 BaseChatModel,接口一致(invokegenerate 等)。
  • 区别在于底层调用的 API 提供商不同(阿里云 vs OpenAI),需配置不同的 API Key 和 Base URL。
  • 在 LangChain 中可通过统一的 ChatModel 接口无缝切换。

📌 面试回答话术(示例)

"该文件演示了如何使用 ChatPromptTemplate 构建聊天提示,利用 MessagesPlaceholder 注入多轮对话历史,并调用通义千问模型生成诗歌。MessagesPlaceholder 是管理对话记忆的关键,它能保持消息角色结构。在实际项目中,我会结合 RunnableWithMessageHistory 和向量记忆来处理长上下文,确保多轮对话的连贯性,同时避免超长历史带来的 Token 浪费。"