【LangChain】 对话模板(ChatPromptTemplate)实战指南

LangChain 对话模板(ChatPromptTemplate)实战指南

从单轮问答到多轮对话,掌握 ChatPromptTemplate 的核心用法与工程落地技巧。


一、为什么需要对话模板?

大语言模型(LLM)本质上是无状态的------每次请求都是独立的。要让模型"记住"上下文、维持角色一致性,需要我们在 prompt 中显式拼接历史对话。

LangChain 的 ChatPromptTemplate 就是为这个场景设计的:它区分 system/human/ai 三种消息角色,让多轮对话的结构清晰可控。


二、核心消息类型

消息类型 类名 角色标识 用途
系统消息 SystemMessage system 设定全局角色、规则、约束
用户消息 HumanMessage human / user 用户的输入问题或指令
AI 回复 AIMessage ai / assistant 模型的历史回复
工具消息 ToolMessage tool 工具/函数执行结果

三、基础用法

3.1 直接传入元组列表(最常用)

python 复制代码
from langchain.prompts import ChatPromptTemplate

chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一名专业的机床维护工程师,擅长解析海德汉CNC报警代码。"),
    ("human", "报警码 {code} 是什么意思?"),
])

messages = chat_prompt.format_messages(code="E-616")
print(messages)

输出:

python 复制代码
[
    SystemMessage(content="你是一名专业的机床维护工程师..."),
    HumanMessage(content="报警码 E-616 是什么意思?")
]

3.2 使用专门的模板对象(更灵活)

python 复制代码
from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate
)

system_template = "你是一名{role},擅长{skill}。"
human_template = "请分析以下报警:{alarm}"

chat_prompt = ChatPromptTemplate.from_messages([
    SystemMessagePromptTemplate.from_template(system_template),
    HumanMessagePromptTemplate.from_template(human_template),
])

messages = chat_prompt.format_messages(
    role="机床维护工程师",
    skill="解析海德汉报警",
    alarm="E-616 chuck not clamped"
)

四、多轮对话:MessagesPlaceholder

实际工程中,对话历史是动态生成的,长度不固定。MessagesPlaceholder 就是用来插入可变长度历史记录的占位符。

python 复制代码
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一名机床维护专家,根据历史对话和当前问题给出建议。"),
    MessagesPlaceholder(variable_name="history"),  # 动态插入历史消息
    ("human", "{input}")
])

# 模拟历史对话
history = [
    ("human", "E-616 是什么报警?"),
    ("ai", "工件夹紧信号未到位。"),
    ("human", "怎么处理?"),
    ("ai", "1.检查夹具气压 2.确认工件位置 3.复位传感器。"),
]

messages = chat_prompt.format_messages(
    history=history,
    input="还是不行,夹具气压正常"
)

生成的完整消息序列:

复制代码
System: 你是一名机床维护专家...
Human: E-616 是什么报警?
AI: 工件夹紧信号未到位。
Human: 怎么处理?
AI: 1.检查夹具气压 2.确认工件位置 3.复位传感器。
Human: 还是不行,夹具气压正常

五、少样本 + 对话模板的结合

在对话中嵌入少样本示例,教模型输出格式:

python 复制代码
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一名机床维护专家。回答时请遵循以下规则:\n"
               "1. 先给出根因分析\n"
               "2. 再列出处理步骤(编号)\n"
               "3. 最后标注严重程度"),

    # 少样本示例(教格式)
    ("human", "报警码 E-616,信息:chuck not clamped"),
    ("ai", "根因:工件夹紧信号未到位。\n"
           "处理:1.检查气压 2.确认工件位置\n"
           "严重:严重"),

    ("human", "报警码 W-617,信息:Robot signal not dropped"),
    ("ai", "根因:换料时机器人夹具闭合信号未断开。\n"
           "处理:1.检查IO信号线 2.确认换料节拍\n"
           "严重:警告"),

    # 动态历史
    MessagesPlaceholder(variable_name="history"),

    # 当前问题
    ("human", "报警码 {code},信息:{message}")
])

六、对话 + RAG 的结合

将检索到的文档作为上下文注入对话:

python 复制代码
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一名机床维护专家。以下是从知识库检索到的相关文档,请结合文档内容回答问题。"),

    ("human", "相关文档:\n{context}"),

    MessagesPlaceholder(variable_name="history"),

    ("human", "当前问题:{input}")
])

# 使用示例
messages = chat_prompt.format_messages(
    context="E-616: 工件夹紧信号异常,常见于气压不足或传感器故障...",
    history=[("human", "之前遇到过 E-616"), ("ai", "已记录。")],
    input="现在报警变成了 E-618,主轴过载"
)

七、完整工程示例:对话式报警诊断系统

python 复制代码
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

class AlarmChatSystem:
    def __init__(self):
        self.prompt = ChatPromptTemplate.from_messages([
            ("system", "你是一名资深机床维护工程师,拥有20年海德汉系统维修经验。"),

            # 少样本:教输出格式
            ("human", "报警:E-616 chuck not clamped"),
            ("ai", "【根因】工件夹紧信号未到位\n"
                   "【处理】1.检查夹具气压(>0.5MPa)\n"
                   "        2.确认工件放置到位\n"
                   "        3.复位夹紧传感器\n"
                   "【严重】严重"),

            MessagesPlaceholder(variable_name="history"),

            ("human", "{input}")
        ])
        self.history = []

    def chat(self, user_input: str) -> str:
        messages = self.prompt.format_messages(
            history=self.history,
            input=user_input
        )
        # 调用 LLM(此处省略具体调用代码)
        # response = llm.invoke(messages)

        # 更新历史
        self.history.append(("human", user_input))
        # self.history.append(("ai", response.content))

        return messages  # 实际应返回 response.content

# 使用
system = AlarmChatSystem()
print(system.chat("E-618 主轴过载怎么处理?"))

八、各类模板对比

模板类型 核心类 消息角色 适用场景
基础模板 PromptTemplate 单轮问答、简单任务
少样本模板 FewShotPromptTemplate 需要示例引导格式
对话模板 ChatPromptTemplate system/human/ai 多轮对话、角色扮演
历史占位 MessagesPlaceholder 动态 历史长度不固定

九、总结

  1. ChatPromptTemplate 的本质:用角色区分消息,让 LLM 理解"谁在说话"
  2. MessagesPlaceholder 是关键:解决动态历史长度的工程问题
  3. 组合使用威力更大:对话模板 + 少样本(教格式)+ RAG(给知识)= 完整的对话式 AI 应用
  4. 历史管理要注意:对话过长时要做截断或摘要,避免超出模型上下文窗口

注:本文基于 LangChain 框架,核心思想适用于所有支持消息角色区分的 LLM API。

相关推荐
www.021 小时前
Linux 终端守护神 Tmux :如何优雅地管理后台实验与恢复会话
linux·运维·服务器·人工智能·tmux
Agent手记1 小时前
制造业物流延迟预警系统,从0到1落地实操指南 | 企业级AI Agent架构实战
人工智能·ai
老马95271 小时前
opencode7-桌面应用实战2
java·人工智能·后端
DogDaoDao1 小时前
【GitHub】Ruflo:面向 Claude Code 的企业级多智能体编排平台深度解析
人工智能·深度学习·大模型·github·ai编程·claude·ruflo
璞华Purvar1 小时前
2026化工新材料PLM行业白皮书:璞华易研,以垂直深耕重构研发数智底座
人工智能
广州灵眸科技有限公司1 小时前
瑞芯微(EASY EAI)RV1126B yolov11-track多目标跟踪部署教程
linux·开发语言·网络·人工智能·yolo·机器学习·目标跟踪
灵动小溪1 小时前
claude code工具PC安装部署
人工智能·算法
扬帆破浪1 小时前
免费开源AI软件.桌面单机版,可移动的AI知识库,察元 AI桌面版:Windows装包被防病毒拦了 看安装日志和签名链的实战
人工智能·windows·开源·知识图谱
YuanDaima20481 小时前
WSL2 与 Ubuntu 22.04 基础环境部署指南
linux·运维·服务器·人工智能·ubuntu·docker