注:本文是Langchain框架的学习笔记,内容可能有所疏漏,欢迎交流指正。后续将持续更新学习笔记,分享我的学习心得和实践经验。
在大语言模型应用开发中,提示词(Prompt)的设计是决定应用成败的关键因素。一个精心设计的提示词能够:
Langchain框架提供了完整的提示模板管理体系,从基础的变量替换到复杂的多轮对话,为开发者提供了强大而灵活的工具集。
PromptTemplate是Langchain中的核心组件,它解决了传统字符串拼接方式的诸多问题:
传统方式的问题:
PromptTemplate的优势:
PromptTemplate由三个核心组件构成:
input_variables(输入变量)
template(模板字符串)
{变量名}
格式标记可替换部分partial_variables(可选的部分变量)
from langchain_core.prompts import PromptTemplate
# 基础示例:文章生成模板
article_template = PromptTemplate(
input_variables=["主题", "字数", "风格"],
template="请写一篇关于{主题}的{字数}字文章,风格要求{风格}。"
)
# 使用模板
prompt = article_template.format(
主题="人工智能发展趋势",
字数="1000",
风格="深入浅出,适合大众阅读"
)
Langchain内置了严格的验证机制,能够在模板创建时就发现潜在问题:
验证内容包括:
# 验证示例:这会抛出异常
try:
invalid_template = PromptTemplate(
input_variables=["主题", "字数"], # 缺少"语言"变量声明
template="请用{语言}写一篇关于{主题}的{字数}字文章。"
)
except ValueError as e:
print(f"模板验证失败: {e}")
部分变量填充(partial)是一个强大的功能,特别适用于以下场景:
场景1:分阶段构建复杂提示词
# 创建基础模板
base_template = PromptTemplate(
input_variables=["角色", "任务", "输出格式", "具体问题"],
template="你是一位{角色}。{任务}请以{输出格式}格式回答:{具体问题}"
)
# 第一阶段:设定角色和任务
role_template = base_template.partial(
角色="资深Python开发工程师",
任务="请根据你的专业知识和经验,"
)
# 第二阶段:设定输出格式
formatted_template = role_template.partial(输出格式="详细的步骤说明")
# 最终使用
final_prompt = formatted_template.format(具体问题="如何优化Python代码性能?")
场景2:动态变量计算
from datetime import datetime
def get_current_time():
return datetime.now().strftime("%Y年%m月%d日 %H:%M")
# 使用函数作为部分变量
time_template = PromptTemplate(
input_variables=["任务"],
template="当前时间:{时间}\n请完成以下任务:{任务}",
partial_variables={"时间": get_current_time}
)
在实际应用中,我们经常需要处理复杂的数据结构:
传统的简单变量替换无法满足这些需求,因此需要更强大的格式化机制。
策略1:预处理数据
将复杂数据转换为字符串后再传入模板
# 处理示例数据
examples = [
{"问题": "什么是机器学习?", "答案": "机器学习是人工智能的一个分支"},
{"问题": "深度学习的特点?", "答案": "深度学习使用多层神经网络"}
]
def format_examples(examples):
return "\n".join([f"Q: {ex['问题']}\nA: {ex['答案']}" for ex in examples])
qa_template = PromptTemplate(
input_variables=["examples", "question"],
template="参考以下示例:\n{examples}\n\n现在请回答:{question}"
)
策略2:条件格式化
根据不同条件生成不同的模板结构
def create_adaptive_template(difficulty_level):
"""根据难度级别创建不同的模板"""
if difficulty_level == "初级":
return PromptTemplate(
input_variables=["question"],
template="请用简单易懂的语言回答:{question}\n要求:避免专业术语,多用比喻"
)
elif difficulty_level == "高级":
return PromptTemplate(
input_variables=["question"],
template="请从技术角度深入分析:{question}\n要求:包含原理解释和实现细节"
)
在复杂应用中,单一模板往往无法满足需求:
策略1:字符串级别组合
# 定义可复用的模板片段
ROLE_PROMPT = "你是一位{role},具有{expertise}的专业能力。"
TASK_PROMPT = "请完成以下任务:{task}"
FORMAT_PROMPT = "输出格式要求:{format}"
# 组合成完整模板
combined_template = PromptTemplate(
input_variables=["role", "expertise", "task", "format"],
template=f"{ROLE_PROMPT}\n\n{TASK_PROMPT}\n\n{FORMAT_PROMPT}"
)
策略2:模板对象组合
class TemplateBuilder:
def __init__(self):
self.components = []
self.variables = set()
def add_component(self, template_str, variables):
self.components.append(template_str)
self.variables.update(variables)
def build(self):
combined_template = "\n\n".join(self.components)
return PromptTemplate(
input_variables=list(self.variables),
template=combined_template
)
# 使用构建器
builder = TemplateBuilder()
builder.add_component("你是{role}", ["role"])
builder.add_component("任务:{task}", ["task"])
template = builder.build()
通过继承可以创建具有共同基础结构但细节不同的模板族:
class BasePromptTemplate:
def __init__(self, role, task_type):
self.role = role
self.task_type = task_type
def get_base_template(self):
return f"你是{self.role},专门处理{self.task_type}类任务。"
def create_template(self, specific_instruction):
base = self.get_base_template()
return PromptTemplate(
input_variables=["input"],
template=f"{base}\n\n{specific_instruction}\n\n输入:{{input}}"
)
# 创建特定类型的模板
code_reviewer = BasePromptTemplate("代码审查专家", "代码质量评估")
code_template = code_reviewer.create_template("请分析以下代码的质量并提出改进建议:")
Few-shot Learning(少样本学习)是一种通过提供少量示例来引导模型理解任务的技术:
核心原理:
适用场景:
策略1:代表性示例
选择能够覆盖主要情况的典型示例
# 情感分析的代表性示例
sentiment_examples = [
{"text": "这个产品质量很好,我很满意", "sentiment": "正面"},
{"text": "服务态度太差了,很失望", "sentiment": "负面"},
{"text": "价格还可以,没什么特别的", "sentiment": "中性"},
{"text": "功能不错但价格偏贵", "sentiment": "混合"}
]
策略2:边界案例示例
包含容易混淆或特殊情况的示例
# 包含边界案例的示例
boundary_examples = [
{"text": "还行吧", "sentiment": "中性"}, # 模糊表达
{"text": "不是不好", "sentiment": "正面"}, # 双重否定
{"text": "简直了", "sentiment": "需要上下文"}, # 语境依赖
]
from langchain.prompts.example_selector import LengthBasedExampleSelector
# 创建示例选择器
example_selector = LengthBasedExampleSelector(
examples=sentiment_examples,
example_prompt=PromptTemplate(
input_variables=["text", "sentiment"],
template="输入: {text}\n输出: {sentiment}"
),
max_length=1000 # 控制总长度
)
# 创建动态Few-shot模板
dynamic_template = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=PromptTemplate(
input_variables=["text", "sentiment"],
template="输入: {text}\n输出: {sentiment}"
),
prefix="以下是情感分析的示例:",
suffix="输入: {input}\n输出:",
input_variables=["input"]
)
与单轮问答不同,对话系统需要处理:
SystemMessage(系统消息)
HumanMessage(用户消息)
AIMessage(AI消息)
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
# 专业咨询对话模板
consultation_template = ChatPromptTemplate.from_messages([
("system", """你是一位{domain}领域的专业顾问,具有{experience}年经验。
你的特点:
- 专业知识丰富,能提供准确建议
- 善于倾听,理解客户真实需求
- 回答简洁明了,重点突出
- 必要时会询问更多细节
请始终保持专业和友好的态度。"""),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}")
])
# 使用示例
messages = consultation_template.format_messages(
domain="软件架构",
experience="10",
chat_history=[],
input="我想了解微服务架构的优缺点"
)
from langchain_community.chat_models import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
import json
class SmartAssistant:
def __init__(self, model_name="deepseek-r1:1.5b"):
self.model = ChatOllama(model=model_name)
self.templates = self._init_templates()
def _init_templates(self):
return {
"analyze": ChatPromptTemplate.from_messages([
("system", "你是数据分析专家,擅长从文本中提取关键信息。"),
("human", "请分析以下内容:{content}\n分析角度:{aspect}")
]),
"summarize": ChatPromptTemplate.from_messages([
("system", "你是内容总结专家,能够提取核心要点。"),
("human", "请将以下内容总结为{length}字以内:{content}")
]),
"translate": ChatPromptTemplate.from_messages([
("system", "你是专业翻译,确保翻译准确且符合目标语言习惯。"),
("human", "请将以下{source_lang}翻译为{target_lang}:{text}")
])
}
def process(self, task_type, **kwargs):
if task_type not in self.templates:
raise ValueError(f"不支持的任务类型: {task_type}")
template = self.templates[task_type]
messages = template.format_messages(**kwargs)
return self.model.invoke(messages)
# 使用示例
assistant = SmartAssistant()
# 文本分析
result = assistant.process(
"analyze",
content="今天的销售数据显示,产品A销量增长30%,但产品B下降了15%",
aspect="销售趋势"
)
# 内容总结
summary = assistant.process(
"summarize",
content="长篇文章内容...",
length="100"
)
class RobustAssistant(SmartAssistant):
def __init__(self, model_name="deepseek-r1:1.5b", max_retries=3):
super().__init__(model_name)
self.max_retries = max_retries
def process_with_retry(self, task_type, **kwargs):
for attempt in range(self.max_retries):
try:
return self.process(task_type, **kwargs)
except Exception as e:
if attempt == self.max_retries - 1:
raise e
print(f"尝试 {attempt + 1} 失败,重试中...")
def validate_input(self, task_type, **kwargs):
"""输入验证"""
required_params = {
"analyze": ["content", "aspect"],
"summarize": ["content", "length"],
"translate": ["text", "source_lang", "target_lang"]
}
if task_type in required_params:
for param in required_params[task_type]:
if param not in kwargs:
raise ValueError(f"缺少必需参数: {param}")