LangChain 提示模板概念指南

概述
提示模板帮助将用户输入和参数转换为语言模型的指令。这可以用来指导模型的响应,帮助它理解上下文并生成相关且连贯的基于语言的输出。
提示模板接受一个字典作为输入,其中每个键代表提示模板中要填充的变量。
提示模板输出一个PromptValue。这个PromptValue可以传递给LLM或ChatModel,也可以转换为字符串或消息列表。存在PromptValue的原因是为了方便在字符串和消息之间切换。
提示模板的类型
LangChain中有几种不同类型的提示模板:
1. String PromptTemplates(字符串提示模板)
这些提示模板用于格式化单个字符串,通常用于较简单的输入。例如,构造和使用PromptTemplate的常见方式如下:
from langchain_core.prompts import PromptTemplate
# 创建提示模板
prompt_template = PromptTemplate.from_template("Tell me a joke about {topic}")
# 调用模板并传入参数
prompt_template.invoke({"topic": "cats"})
详细示例
from langchain_core.prompts import PromptTemplate
# 方式1:使用from_template方法
prompt = PromptTemplate.from_template(
"你是一个{role},请回答关于{topic}的问题:{question}"
)
# 方式2:使用构造函数
prompt = PromptTemplate(
input_variables=["role", "topic", "question"],
template="你是一个{role},请回答关于{topic}的问题:{question}"
)
# 使用模板
result = prompt.invoke({
"role": "专业的Python开发者",
"topic": "机器学习",
"question": "如何选择合适的算法?"
})
print(result.to_string())
# 输出: 你是一个专业的Python开发者,请回答关于机器学习的问题:如何选择合适的算法?
高级字符串模板功能
# 支持条件逻辑的模板
conditional_template = PromptTemplate.from_template(
"""
{%- if user_type == "premium" -%}
欢迎尊贵的用户!您可以享受以下高级功能:
{%- else -%}
欢迎普通用户!
{%- endif -%}
请问您需要什么帮助?关于:{topic}
"""
)
# 支持循环的模板
list_template = PromptTemplate.from_template(
"""
以下是关于{topic}的要点:
{%- for item in items %}
- {{ item }}
{%- endfor %}
"""
)
2. ChatPromptTemplates(聊天提示模板)
这些提示模板用于格式化消息列表。这些"模板"由模板列表本身组成。例如,构造和使用ChatPromptTemplate的常见方式如下:
from langchain_core.prompts import ChatPromptTemplate
# 创建聊天提示模板
prompt_template = ChatPromptTemplate([
("system", "You are a helpful assistant"),
("user", "Tell me a joke about {topic}")
])
# 调用模板
prompt_template.invoke({"topic": "cats"})
在上面的示例中,这个ChatPromptTemplate在调用时将构造两条消息。第一条是系统消息,没有要格式化的变量。第二条是HumanMessage,将由用户传入的topic变量进行格式化。
详细的聊天模板示例
from langchain_core.prompts import ChatPromptTemplate
# 复杂的聊天模板
chat_template = ChatPromptTemplate([
("system", "你是一个{role},专门帮助用户解决{domain}相关的问题。"),
("human", "我的问题是:{question}"),
("ai", "我理解您的问题。让我为您详细解答。"),
("human", "请提供更多细节关于{specific_aspect}")
])
# 使用模板
messages = chat_template.invoke({
"role": "技术专家",
"domain": "人工智能",
"question": "什么是深度学习?",
"specific_aspect": "神经网络架构"
})
# 输出将包含4条格式化的消息
for message in messages.to_messages():
print(f"{message.type}: {message.content}")
不同消息类型的使用
from langchain_core.prompts import ChatPromptTemplate
# 支持多种消息类型
multi_role_template = ChatPromptTemplate([
("system", "你是一个{assistant_type}助手。"),
("human", "{user_input}"),
("ai", "我明白了。让我来帮助您。"),
("human", "具体来说,{specific_request}"),
("ai", "好的,我会{action}。")
])
# 实际使用
result = multi_role_template.invoke({
"assistant_type": "编程",
"user_input": "我需要学习Python",
"specific_request": "我想了解面向对象编程",
"action": "为您详细解释面向对象编程的概念"
})
3. MessagesPlaceholder(消息占位符)
这个提示模板负责在特定位置添加消息列表。在上面的ChatPromptTemplate中,我们看到了如何格式化两条消息,每条都是字符串。但是如果我们希望用户传入一个消息列表,我们将其插入到特定位置呢?这就是使用MessagesPlaceholder的方式。
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage
# 创建包含消息占位符的模板
prompt_template = ChatPromptTemplate([
("system", "You are a helpful assistant"),
MessagesPlaceholder("msgs")
])
# 调用时传入消息列表
prompt_template.invoke({"msgs": [HumanMessage(content="hi!")]})
这将产生两条消息的列表,第一条是系统消息,第二条是我们传入的HumanMessage。如果我们传入了5条消息,那么总共会产生6条消息(系统消息加上传入的5条)。这对于让消息列表插入到特定位置很有用。
MessagesPlaceholder的高级用法
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage
# 复杂的消息占位符使用
complex_template = ChatPromptTemplate([
("system", "你是一个{role},当前时间是{current_time}。"),
MessagesPlaceholder("chat_history"),
("human", "{user_input}"),
MessagesPlaceholder("additional_context", optional=True)
])
# 准备聊天历史
chat_history = [
HumanMessage(content="你好"),
AIMessage(content="您好!我是您的助手。"),
HumanMessage(content="我想了解机器学习")
]
# 准备额外上下文
additional_context = [
HumanMessage(content="请注意我是初学者")
]
# 使用模板
result = complex_template.invoke({
"role": "AI导师",
"current_time": "2025年1月",
"chat_history": chat_history,
"user_input": "请解释什么是监督学习",
"additional_context": additional_context
})
替代语法
不使用MessagesPlaceholder类的替代方式:
# 使用占位符语法
prompt_template = ChatPromptTemplate([
("system", "You are a helpful assistant"),
("placeholder", "{msgs}") # <-- 这是改变的部分
])
# 这与使用MessagesPlaceholder("msgs")效果相同
实际应用场景
1. 客服机器人模板
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# 客服场景的提示模板
customer_service_template = ChatPromptTemplate([
("system", """
你是{company_name}的客服代表。请遵循以下准则:
1. 保持友好和专业的态度
2. 如果无法解决问题,请转接给人工客服
3. 始终询问客户是否还有其他需要帮助的地方
当前客户等级:{customer_level}
"""),
MessagesPlaceholder("conversation_history"),
("human", "{customer_message}"),
])
# 使用示例
response = customer_service_template.invoke({
"company_name": "科技公司",
"customer_level": "VIP",
"conversation_history": [],
"customer_message": "我的订单还没有收到"
})
2. 代码助手模板
# 代码助手的提示模板
code_assistant_template = ChatPromptTemplate([
("system", """
你是一个{programming_language}编程专家。请:
1. 提供清晰、可运行的代码示例
2. 解释代码的工作原理
3. 指出潜在的问题和最佳实践
4. 如果需要,提供测试用例
"""),
("human", "编程语言:{programming_language}"),
("human", "问题描述:{problem_description}"),
("human", "代码要求:{requirements}"),
MessagesPlaceholder("code_context", optional=True)
])
# 使用示例
code_response = code_assistant_template.invoke({
"programming_language": "Python",
"problem_description": "实现一个二分查找算法",
"requirements": "需要处理边界情况,包含详细注释",
"code_context": []
})
3. 教育辅导模板
# 教育辅导的提示模板
tutoring_template = ChatPromptTemplate([
("system", """
你是一个{subject}的专业导师,学生的水平是{student_level}。
教学风格:{teaching_style}
请:
1. 根据学生水平调整解释的复杂度
2. 使用具体例子帮助理解
3. 鼓励学生思考和提问
4. 提供练习建议
"""),
MessagesPlaceholder("learning_history"),
("human", "学生问题:{student_question}"),
("human", "学习目标:{learning_objective}")
])
高级模板技术
1. 条件模板
from langchain_core.prompts import ChatPromptTemplate
# 基于条件的动态模板
def create_conditional_template(user_type, has_premium=False):
base_messages = [
("system", f"你是为{user_type}用户服务的助手。")
]
if has_premium:
base_messages.append(
("system", "用户拥有高级权限,可以访问所有功能。")
)
base_messages.extend([
("human", "{user_query}"),
("ai", "我来帮助您解决这个问题。")
])
return ChatPromptTemplate(base_messages)
# 使用条件模板
premium_template = create_conditional_template("企业", has_premium=True)
basic_template = create_conditional_template("个人", has_premium=False)
2. 模板组合
from langchain_core.prompts import ChatPromptTemplate
# 可组合的模板组件
def create_base_system_prompt(role, domain):
return f"你是一个{role},专门处理{domain}相关的问题。"
def create_context_prompt(context_type):
contexts = {
"technical": "请提供技术细节和代码示例。",
"business": "请从商业角度分析问题。",
"educational": "请用简单易懂的方式解释。"
}
return contexts.get(context_type, "请提供详细的回答。")
# 组合模板
def create_specialized_template(role, domain, context_type):
return ChatPromptTemplate([
("system", create_base_system_prompt(role, domain)),
("system", create_context_prompt(context_type)),
("human", "{user_question}"),
MessagesPlaceholder("additional_info", optional=True)
])
# 创建特定用途的模板
tech_template = create_specialized_template(
"软件架构师", "系统设计", "technical"
)
3. 模板验证和错误处理
from langchain_core.prompts import ChatPromptTemplate
from typing import Dict, Any
class ValidatedChatTemplate:
def __init__(self, template: ChatPromptTemplate, required_vars: list):
self.template = template
self.required_vars = set(required_vars)
def invoke(self, variables: Dict[str, Any]):
# 验证必需变量
missing_vars = self.required_vars - set(variables.keys())
if missing_vars:
raise ValueError(f"缺少必需的变量: {missing_vars}")
# 验证变量类型
for var, value in variables.items():
if var.endswith("_list") and not isinstance(value, list):
raise TypeError(f"变量 {var} 应该是列表类型")
return self.template.invoke(variables)
# 使用验证模板
validated_template = ValidatedChatTemplate(
ChatPromptTemplate([
("system", "你是{role}"),
("human", "{question}")
]),
required_vars=["role", "question"]
)
性能优化和最佳实践
1. 模板缓存
from functools import lru_cache
from langchain_core.prompts import ChatPromptTemplate
class TemplateCache:
def __init__(self):
self._cache = {}
@lru_cache(maxsize=100)
def get_template(self, template_key: str):
"""缓存常用模板以提高性能"""
templates = {
"qa": ChatPromptTemplate([
("system", "你是一个问答助手"),
("human", "{question}")
]),
"summarize": ChatPromptTemplate([
("system", "请总结以下内容"),
("human", "{content}")
]),
"translate": ChatPromptTemplate([
("system", "请将以下内容翻译成{target_language}"),
("human", "{text}")
])
}
return templates.get(template_key)
# 使用缓存
template_cache = TemplateCache()
qa_template = template_cache.get_template("qa")
2. 异步模板处理
import asyncio
from langchain_core.prompts import ChatPromptTemplate
class AsyncTemplateProcessor:
def __init__(self):
self.templates = {}
async def process_template_async(self, template_name: str, variables: dict):
"""异步处理模板以提高并发性能"""
template = self.templates.get(template_name)
if not template:
raise ValueError(f"模板 {template_name} 不存在")
# 模拟异步处理
await asyncio.sleep(0.01) # 模拟I/O操作
return template.invoke(variables)
async def batch_process(self, requests: list):
"""批量处理多个模板请求"""
tasks = [
self.process_template_async(req["template"], req["variables"])
for req in requests
]
return await asyncio.gather(*tasks)
3. 模板版本管理
from datetime import datetime
from typing import Dict, List
class TemplateVersionManager:
def __init__(self):
self.templates: Dict[str, List[dict]] = {}
def add_template_version(self, name: str, template: ChatPromptTemplate,
version: str, description: str = ""):
"""添加模板版本"""
if name not in self.templates:
self.templates[name] = []
self.templates[name].append({
"version": version,
"template": template,
"description": description,
"created_at": datetime.now(),
"active": True
})
def get_template(self, name: str, version: str = "latest"):
"""获取指定版本的模板"""
if name not in self.templates:
raise ValueError(f"模板 {name} 不存在")
versions = self.templates[name]
if version == "latest":
# 返回最新的活跃版本
active_versions = [v for v in versions if v["active"]]
if not active_versions:
raise ValueError(f"模板 {name} 没有活跃版本")
return max(active_versions, key=lambda x: x["created_at"])["template"]
else:
# 返回指定版本
for v in versions:
if v["version"] == version:
return v["template"]
raise ValueError(f"模板 {name} 版本 {version} 不存在")
def deactivate_version(self, name: str, version: str):
"""停用指定版本"""
for v in self.templates.get(name, []):
if v["version"] == version:
v["active"] = False
break
错误处理和调试
1. 模板调试工具
from langchain_core.prompts import ChatPromptTemplate
import json
class TemplateDebugger:
@staticmethod
def debug_template(template: ChatPromptTemplate, variables: dict):
"""调试模板,显示详细信息"""
print("=== 模板调试信息 ===")
print(f"输入变量: {json.dumps(variables, ensure_ascii=False, indent=2)}")
try:
result = template.invoke(variables)
print(f"生成的消息数量: {len(result.to_messages())}")
for i, message in enumerate(result.to_messages()):
print(f"\n消息 {i+1}:")
print(f" 类型: {message.type}")
print(f" 内容: {message.content}")
return result
except Exception as e:
print(f"错误: {e}")
print(f"错误类型: {type(e).__name__}")
raise
# 使用调试器
debugger = TemplateDebugger()
template = ChatPromptTemplate([
("system", "你是{role}"),
("human", "{question}")
])
result = debugger.debug_template(template, {
"role": "助手",
"question": "什么是人工智能?"
})
2. 常见错误处理
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
from langchain_core.exceptions import LangChainException
def safe_template_invoke(template, variables):
"""安全地调用模板,处理常见错误"""
try:
return template.invoke(variables)
except KeyError as e:
missing_var = str(e).strip("'\"")
raise ValueError(f"模板需要变量 '{missing_var}',但未提供")
except TypeError as e:
raise ValueError(f"变量类型错误: {e}")
except LangChainException as e:
raise ValueError(f"LangChain错误: {e}")
except Exception as e:
raise ValueError(f"未知错误: {e}")
# 使用安全调用
try:
template = PromptTemplate.from_template("Hello {name}, you are {age} years old")
result = safe_template_invoke(template, {"name": "Alice"}) # 缺少age变量
except ValueError as e:
print(f"处理错误: {e}")
与其他LangChain组件的集成
1. 与LLM集成
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# 创建模板和模型的组合
def create_qa_chain():
template = ChatPromptTemplate([
("system", "你是一个专业的{domain}专家。请基于你的知识回答问题。"),
("human", "{question}")
])
# 注意:这里使用模拟,实际使用时需要配置真实的模型
# model = ChatOpenAI(temperature=0.7)
# 创建链
# chain = template | model
return template
# 使用链
qa_template = create_qa_chain()
prompt = qa_template.invoke({
"domain": "人工智能",
"question": "什么是深度学习?"
})
2. 与输出解析器集成
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser
from pydantic import BaseModel, Field
# 定义输出结构
class AnalysisResult(BaseModel):
summary: str = Field(description="分析摘要")
key_points: list = Field(description="关键要点")
confidence: float = Field(description="置信度 (0-1)")
# 创建解析器
parser = JsonOutputParser(pydantic_object=AnalysisResult)
# 创建包含格式指令的模板
analysis_template = ChatPromptTemplate([
("system", """
你是一个数据分析专家。请分析以下内容并按照指定格式返回结果。
{format_instructions}
"""),
("human", "请分析:{content}")
])
# 使用模板
formatted_prompt = analysis_template.invoke({
"content": "人工智能在医疗领域的应用越来越广泛...",
"format_instructions": parser.get_format_instructions()
})
总结
提示模板是LangChain中的核心组件,它们提供了一种结构化的方式来构建和管理与语言模型的交互。
关键要点
-
模板类型:
- 字符串模板:适用于简单的文本格式化
- 聊天模板:适用于多轮对话和复杂交互
- 消息占位符:允许动态插入消息列表
-
最佳实践:
- 使用清晰、具体的变量名
- 为模板添加适当的验证
- 考虑性能优化和缓存
- 实现错误处理和调试功能
-
高级功能:
- 条件逻辑和动态模板
- 模板组合和重用
- 版本管理和A/B测试
- 与其他LangChain组件的集成
实施建议
- 从简单开始:先使用基本的字符串模板,然后逐步采用更复杂的聊天模板
- 模块化设计:创建可重用的模板组件
- 测试和验证:确保模板在各种输入下都能正常工作
- 性能监控:跟踪模板的性能和效果
提示模板是构建高质量AI应用的基础,通过合理使用这些工具,您可以创建更加智能和用户友好的应用程序。
参考链接:LangChain Prompt Templates 官方文档
文档版本:基于 LangChain v0.3
最后更新:2025年1月
2181

被折叠的 条评论
为什么被折叠?



