【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。

相关推荐
AI码农小姐姐几秒前
AI漫剧推文短视频推理加速:LCM-LoRA与少步采样实践
人工智能·音视频·ai工具·ai漫剧
宸津-代码粉碎机6 分钟前
微服务线上踩坑复盘:接口超时、负载倾斜隐形问题根治方案(生产级配置)
java·大数据·人工智能·python·spring
阿里云大数据AI技术11 分钟前
阿里云PAI推出InferX:Agent时代重塑企业专属的高保障SLO推理服务
人工智能·agent
Raas10012 分钟前
MAI Gateway(魔芋企业级AI网关)能力解析:AI网关支持OpenAI吗?AI网关核心功能详解
人工智能·网关·ai网关·mai gateway·企业级产品·独立团队
多多鼠15 分钟前
System Prompt 的“版本漂移”问题:从变更管理到 A/B 测试体系
开发语言·网络·人工智能·python·langchain
LuTshoes17 分钟前
spring ai 实战RAG(4)-模块化RAG
java·人工智能·spring
Thom58019 分钟前
【迅投 QMT】QMT如何实现布林带突破策略?Python指标与交易信号示例
人工智能·经验分享·量化交易·量化编程
m0_7345717623 分钟前
深入理解人工智能 chatGPT 基础设施与数据层 (Infrastructure & Data Layer)
人工智能
魔众26 分钟前
写歌、翻唱、可编辑乐谱,YuE2-3B 在 AIGCPanel 一键跑通
人工智能·开源
Python自动化直播30 分钟前
用 Python 爬虫给 AI 直播间做数据反馈机制
人工智能·python·ai·直播