在 LangChain 框架中,Prompt(提示词)是与大语言模型(LLM)交互的核心桥梁。精心设计的提示词可以显著提升模型的输出质量和准确性。本章将深入探讨 LangChain 中的提示词工程、PromptTemplate 的使用、Few-shot Prompting 技术以及动态提示词的管理方法。
提示词工程(Prompt Engineering)是指通过设计和优化输入提示词,引导大语言模型生成高质量、符合预期的输出内容的技术。它是与大语言模型交互的艺术和科学。
提示词工程的重要性:
一个完整的提示词通常包含以下几个部分:
1. 指令(Instruction) 告诉模型需要执行什么任务。这是最核心的部分。
instruction = "请用简洁的语言总结以下文章的主要内容:"
2. 上下文(Context) 提供完成任务所需的背景信息。
context = """ 这篇文章发布于2024年,作者是人工智能领域的专家。 目标读者是技术初学者,因此需要使用通俗易懂的语言。 """
3. 输入数据(Input Data) 模型需要处理的具体内容。
input_data = """ 人工智能(AI)正在改变我们的生活方式... [文章内容] """
4. 输出指示(Output Indicator) 明确说明期望的输出格式。
output_indicator = """ 请输出: 1. 核心观点(50字以内) 2. 三个关键要点 3. 结论 """
完整的提示词示例:
full_prompt = f""" {instruction} {context} 文章: {input_data} {output_indicator} """
原则一:清晰明确
提示词应该清楚地表达你想要什么。模糊的要求会导致模糊的答案。
# ❌ 不好的示例 bad_prompt = "写点东西关于苹果" # ✅ 好的示例 good_prompt = """ 请写一篇200字的产品描述,介绍 iPhone 15 的主要特点: - 钛金属设计 - A17 Pro 芯片 - 专业级摄像系统 语气要求:专业、吸引人、面向科技爱好者 """
原则二:提供上下文
模型不知道你知道什么。提供足够的背景信息可以帮助模型更好地理解任务。
# ❌ 缺乏上下文 no_context = "分析这个数据" # ✅ 提供上下文 with_context = """ 背景:你是一位数据分析专家,正在为一家电商公司工作。 数据:2024年第一季度销售数据 - 总销售额:1000万元 - 订单数量:5000单 - 退货率:5% 请分析这些数据,并给出改进建议。 """
原则三:指定输出格式
如果你想要特定格式的输出,一定要在提示词中明确说明。
format_prompt = """ 请根据以下客户反馈,生成一份报告。 反馈内容: "产品很好用,但是配送太慢了,希望改进物流服务。" 输出格式(JSON): {{ "sentiment": "正面/负面/中性", "category": "产品/物流/服务/其他", "key_points": ["要点1", "要点2"], "urgency": "高/中/低" }} """
原则四:使用分隔符
使用清晰的分隔符(如###、—、“”“)来区分提示词的不同部分。
structured_prompt = """ ### 指令 总结以下文章的主要观点。 ### 文章 """ {article_content} """ ### 要求 - 不超过100字 - 使用 bullet points - 突出关键数据 """
原则五:给出示例(Few-shot)
当任务比较复杂或格式要求严格时,提供示例是最好的方式。
few_shot_prompt = """ 将以下描述转换为结构化数据。 示例1: 输入:张三,25岁,软件工程师,北京 输出:{{"name": "张三", "age": 25, "job": "软件工程师", "city": "北京"}} 示例2: 输入:李四,30岁,产品经理,上海 输出:{{"name": "李四", "age": 30, "job": "产品经理", "city": "上海"}} 现在请处理: 输入:王五,28岁,数据分析师,深圳 输出: """
模式一:角色扮演(Role Prompting)
让模型扮演特定角色,以获得更专业的回答。
role_prompt = """ 你是一位经验丰富的心理咨询师,拥有15年的临床经验。 一位来访者说:"我最近工作压力很大,晚上睡不着,不知道该怎么办。" 请给出专业的建议,注意: 1. 语气温和、同理心强 2. 提供具体可行的建议 3. 如果情况严重,建议寻求专业帮助 """
模式二:思维链(Chain-of-Thought)
引导模型逐步思考,而不是直接给出答案。
cot_prompt = """ 问题:一个农场有鸡和兔子,一共有35个头,94只脚。鸡和兔子各有多少只? 请按以下步骤思考并回答: 1. 设鸡的数量为x,兔子的数量为y 2. 根据头的数量列出方程 3. 根据脚的数量列出方程 4. 解方程组 5. 验证答案 详细展示你的思考过程。 """
模式三:零样本思维链(Zero-shot CoT)
即使没有示例,也可以通过简单的指令引导模型逐步思考。
zero_shot_cot = """ 问题:如果5台机器5分钟生产5个零件,那么100台机器生产100个零件需要多少分钟? 让我们一步一步思考: """
模式四:自洽性检查(Self-Consistency)
让模型从多个角度思考问题,然后选择最一致的答案。
self_consistency_prompt = """ 问题:解释为什么天空是蓝色的。 请从以下三个角度分别解释,然后综合得出最准确的答案: 1. 物理学角度(光的散射) 2. 生物学角度(人眼感知) 3. 大气科学角度(大气成分) 最后,整合以上观点,给出简洁准确的解释。 """
PromptTemplate 是 LangChain 中用于创建和管理提示词的核心组件。它允许你定义带有变量的模板,并在运行时动态填充这些变量。
为什么使用 PromptTemplate?
安装和导入:
# 安装依赖 # pip install langchain from langchain.prompts import PromptTemplate
创建基础模板:
from langchain.prompts import PromptTemplate # 定义一个简单的模板 template = "请用{style}的风格,写一段关于{topic}的描述,大约{length}字。" # 创建 PromptTemplate 对象 prompt_template = PromptTemplate( input_variables=["style", "topic", "length"], template=template ) # 查看模板结构 print(prompt_template.input_variables) # ['style', 'topic', 'length']
格式化模板:
# 方式1:使用 format 方法 prompt = prompt_template.format( style="幽默", topic="人工智能", length=100 ) print(prompt) # 输出:请用幽默的风格,写一段关于人工智能的描述,大约100字。 # 方式2:使用 format_prompt 方法(返回 PromptValue 对象) prompt_value = prompt_template.format_prompt( style="专业", topic="区块链", length=200 ) print(prompt_value.to_string())
部分变量(Partial Variables)
有时你希望预先填充部分变量,创建一个”半成品“模板。
from langchain.prompts import PromptTemplate # 定义完整模板 full_template = PromptTemplate( template="你是一位{role},请用{language}回答:{question}", input_variables=["role", "language", "question"] ) # 部分填充:预先设定角色 partial_template = full_template.partial(role="Python专家") # 使用时只需提供剩余变量 prompt1 = partial_template.format( language="中文", question="什么是装饰器?" ) print(prompt1) # 输出:你是一位Python专家,请用中文回答:什么是装饰器? # 可以再次部分填充 chinese_template = partial_template.partial(language="中文") prompt2 = chinese_template.format(question="解释列表推导式") print(prompt2)
使用函数作为部分变量:
from datetime import datetime def get_current_date(): return datetime.now().strftime("%Y年%m月%d日") template_with_date = PromptTemplate( template="今天是{date},请根据以下信息生成报告:{content}", input_variables=["content"], partial_variables={"date": get_current_date} ) prompt = template_with_date.format(content="销售数据...") print(prompt) # 输出:今天是2024年01月15日,请根据以下信息生成报告:销售数据...
PromptTemplate 会自动验证输入变量,确保所有必需变量都已提供。
from langchain.prompts import PromptTemplate # 定义模板 template = PromptTemplate( template="你好{name},欢迎{action}!", input_variables=["name", "action"] ) # ✅ 正确:提供所有变量 try: prompt = template.format(name="张三", action="加入我们") print("成功:", prompt) except Exception as e: print("错误:", e) # ❌ 错误:缺少变量 try: prompt = template.format(name="张三") # 缺少 action except KeyError as e: print(f"缺少变量: {e}")
有时输入变量需要特殊的处理,你可以自定义输入变量的解析方式。
from langchain.prompts import PromptTemplate from langchain.prompts.base import StringPromptValue class MyPromptTemplate(PromptTemplate): def format(self, **kwargs) -> str: # 自定义格式化逻辑 if "name" in kwargs: kwargs["name"] = kwargs["name"].upper() return super().format(**kwargs) template = MyPromptTemplate( template="尊敬的{name},{message}", input_variables=["name", "message"] ) prompt = template.format(name="alice", message="欢迎光临") print(prompt) # 尊敬的ALICE,欢迎光临
Few-shot Prompting(少样本提示)是一种通过提供少量示例来指导模型完成任务的技术。它特别适用于:
from langchain.prompts import FewShotPromptTemplate, PromptTemplate # 定义示例 examples = [ { "input": "今天天气真好,我想去公园散步。", "output": "积极" }, { "input": "这部电影太糟糕了,完全浪费时间。", "output": "消极" }, { "input": "会议定在下午三点。", "output": "中性" } ] # 定义示例的格式 example_template = """ 文本:{input} 情感:{output} """ example_prompt = PromptTemplate( template=example_template, input_variables=["input", "output"] ) # 创建 FewShotPromptTemplate few_shot_prompt = FewShotPromptTemplate( examples=examples, example_prompt=example_prompt, prefix="请判断以下文本的情感倾向(积极/消极/中性):", suffix="\n文本:{input}\n情感:", input_variables=["input"], example_separator="\n---\n" ) # 生成提示词 prompt = few_shot_prompt.format(input="这家餐厅的饭菜真好吃!") print(prompt)
输出示例:
请判断以下文本的情感倾向(积极/消极/中性): 文本:今天天气真好,我想去公园散步。 情感:积极 --- 文本:这部电影太糟糕了,完全浪费时间。 情感:消极 --- 文本:会议定在下午三点。 情感:中性 --- 文本:这家餐厅的饭菜真好吃! 情感:
当示例很多时,你可能只想选择最相关的几个示例。LangChain 提供了多种示例选择器。
长度限制选择器:
from langchain.prompts import FewShotPromptTemplate from langchain.prompts.example_selector import LengthBasedExampleSelector examples = [ {"input": "happy", "output": "sad"}, {"input": "tall", "output": "short"}, {"input": "energetic", "output": "lethargic"}, {"input": "sunny", "output": "gloomy"}, {"input": "windy", "output": "calm"}, ] example_prompt = PromptTemplate( template="输入: {input}\n输出: {output}", input_variables=["input", "output"] ) # 根据长度选择示例 example_selector = LengthBasedExampleSelector( examples=examples, example_prompt=example_prompt, max_length=100 # 最大长度限制 ) dynamic_prompt = FewShotPromptTemplate( example_selector=example_selector, example_prompt=example_prompt, prefix="请找出以下单词的反义词:", suffix="输入: {input}\n输出:", input_variables=["input"] ) # 输入越长,选择的示例越少 short_prompt = dynamic_prompt.format(input="big") print("短输入的提示词长度:", len(short_prompt)) long_prompt = dynamic_prompt.format(input="这是一个非常长的输入,包含很多字符...") print("长输入的提示词长度:", len(long_prompt))
语义相似度选择器:
from langchain.prompts import FewShotPromptTemplate from langchain.prompts.example_selector import SemanticSimilarityExampleSelector from langchain.embeddings import OpenAIEmbeddings from langchain.vectorstores import Chroma examples = [ {"question": "谁活了最长?", "answer": "艾德加多·阿尔瓦伦加活了138年。"}, {"question": "2023年谁是美国总统?", "answer": "乔·拜登是2023年的美国总统。"}, {"question": "《呼啸山庄》的作者是谁?", "answer": "艾米莉·勃朗特是《呼啸山庄》的作者。"}, {"question": "谁发明了相对论?", "answer": "阿尔伯特·爱因斯坦发明了相对论。"}, {"question": "《哈利·波特》的作者是谁?", "answer": "J.K.罗琳是《哈利·波特》的作者。"}, ] example_prompt = PromptTemplate( template="问题: {question}\n答案: {answer}", input_variables=["question", "answer"] ) # 使用语义相似度选择器 example_selector = SemanticSimilarityExampleSelector.from_examples( examples, OpenAIEmbeddings(), Chroma, k=2 # 选择最相似的2个示例 ) similar_prompt = FewShotPromptTemplate( example_selector=example_selector, example_prompt=example_prompt, prefix="请根据示例回答以下问题:", suffix="问题: {input}\n答案:", input_variables=["input"] ) # 输入与示例相关的问题 prompt = similar_prompt.format(input="《指环王》是谁写的?") print(prompt) # 可能会选择《哈利·波特》和《呼啸山庄》相关的示例
选择合适的示例数量:
# 通常 3-5 个示例效果最好 # 太多示例可能导致: # 1. Token 消耗增加 # 2. 上下文窗口限制 # 3. 模型注意力分散 # 平衡策略 examples = [ # 示例1:展示基本格式 {...}, # 示例2:展示边界情况 {...}, # 示例3:展示复杂场景 {...}, ]
示例的质量要求:
# ✅ 好的示例特点: # 1. 清晰明确 # 2. 覆盖不同场景 # 3. 格式一致 # 4. 输入输出相关 good_examples = [ { "instruction": "总结以下文章", "input": "[一篇500字的文章]", "output": "[简洁的50字总结]" }, { "instruction": "提取关键信息", "input": "[同样的文章]", "output": "[关键数据列表]" } ] # ❌ 避免: # 1. 示例之间矛盾 # 2. 格式不一致 # 3. 示例与任务不相关
在实际应用中,你可能需要组合多个提示词模板来构建复杂的工作流。
使用 PipelinePromptTemplate:
from langchain.prompts import PipelinePromptTemplate, PromptTemplate # 定义各个阶段的模板 introduction_template = """你是一个{role}。 你的任务是:{task} """ introduction_prompt = PromptTemplate( template=introduction_template, input_variables=["role", "task"] ) example_template = """以下是几个示例: {examples} """ example_prompt = PromptTemplate( template=example_template, input_variables=["examples"] ) question_template = """现在请回答以下问题: {question} """ question_prompt = PromptTemplate( template=question_template, input_variables=["question"] ) # 组合成完整的 pipeline full_template = """{introduction} {example} {question}""" full_prompt = PromptTemplate( template=full_template, input_variables=["introduction", "example", "question"] ) # 创建 pipeline pipeline_prompt = PipelinePromptTemplate( final_prompt=full_prompt, pipeline_prompts=[ ("introduction", introduction_prompt), ("example", example_prompt), ("question", question_prompt) ] ) # 使用 pipeline result = pipeline_prompt.format( role="数据分析师", task="分析销售数据并给出建议", examples="示例1: ...\n示例2: ...", question="Q1季度的销售额下降了10%,可能是什么原因?" ) print(result)
对于聊天模型,LangChain 提供了专门的 ChatPromptTemplate,可以定义不同角色的消息。
from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate # 系统消息模板 system_template = """你是一个{role}助手。 你的专长领域是:{expertise} 回答时请遵循以下规则: {rules} """ system_message_prompt = SystemMessagePromptTemplate.from_template(system_template) # 人类消息模板 human_template = "{user_input}" human_message_prompt = HumanMessagePromptTemplate.from_template(human_template) # 组合成聊天提示词 chat_prompt = ChatPromptTemplate.from_messages([ system_message_prompt, human_message_prompt ]) # 格式化 messages = chat_prompt.format_prompt( role="编程", expertise="Python 和数据分析", rules="1. 代码必须可运行\n2. 添加详细注释", user_input="写一个计算斐波那契数列的函数" ).to_messages() for message in messages: print(f"{message.type}: {message.content}")
输出:
system: 你是一个编程助手。 你的专长领域是:Python 和数据分析 回答时请遵循以下规则: 1. 代码必须可运行 2. 添加详细注释 human: 写一个计算斐波那契数列的函数
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.schema import HumanMessage, AIMessage # 创建包含对话历史的模板 chat_prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个有帮助的助手。"), MessagesPlaceholder(variable_name="history"), # 占位符,用于插入对话历史 ("human", "{input}") ]) # 模拟对话历史 history = [ HumanMessage(content="你好"), AIMessage(content="你好!有什么我可以帮助你的吗?"), HumanMessage(content="我想了解 Python"), AIMessage(content="Python 是一门很棒的编程语言...") ] # 格式化 messages = chat_prompt.format_prompt( history=history, input="如何安装 Python?" ).to_messages() for msg in messages: print(f"{msg.type}: {msg.content}")
使用配置文件管理提示词:
# prompts.yaml # prompts_config.yaml greeting: template: "你好{name},欢迎{action}!" input_variables: ["name", "action"] summarization: template: | 请总结以下内容: {content} 要求: - {style} - 大约{length}字 input_variables: ["content", "style", "length"]
import yaml from langchain.prompts import load_prompt # 加载 YAML 配置 with open("prompts_config.yaml", "r", encoding="utf-8") as f: config = yaml.safe_load(f) # 动态创建模板 templates = {} for name, cfg in config.items(): templates[name] = PromptTemplate( template=cfg["template"], input_variables=cfg["input_variables"] ) # 使用 greeting_prompt = templates["greeting"] print(greeting_prompt.format(name="张三", action="访问"))
版本控制提示词:
from dataclasses import dataclass from datetime import datetime import json @dataclass class PromptVersion: version: str template: str variables: list description: str created_at: str performance_score: float = 0.0 class PromptRegistry: def __init__(self): self.prompts = {} def register(self, name: str, version: PromptVersion): if name not in self.prompts: self.prompts[name] = [] self.prompts[name].append(version) def get_latest(self, name: str): if name in self.prompts and self.prompts[name]: return sorted(self.prompts[name], key=lambda x: x.version)[-1] return None def save(self, filepath: str): data = {} for name, versions in self.prompts.items(): data[name] = [ { "version": v.version, "template": v.template, "variables": v.variables, "description": v.description, "created_at": v.created_at, "performance_score": v.performance_score } for v in versions ] with open(filepath, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) # 使用示例 registry = PromptRegistry() v1 = PromptVersion( version="1.0.0", template="总结:{content}", variables=["content"], description="基础总结模板", created_at=datetime.now().isoformat(), performance_score=0.85 ) registry.register("summarization", v1) registry.save("prompt_registry.json")
根据输入动态调整提示词内容。
from langchain.prompts import PromptTemplate from typing import Optional def create_conditional_prompt( content: str, audience: str = "general", include_examples: bool = True ) -> str: """根据受众和选项创建条件提示词""" # 基础模板 base = "请对以下内容进行解释:\n\n{content}" # 根据受众调整 audience_instructions = { "general": "使用通俗易懂的语言,避免专业术语。", "technical": "可以使用专业术语,提供技术细节。", "executive": "重点关注商业价值和高层次概念。", "beginner": "从最基础的概念开始,逐步深入。" } instruction = audience_instructions.get(audience, audience_instructions["general"]) # 条件添加示例 example_section = "" if include_examples: example_section = """ 请提供具体的例子帮助理解。 示例格式: - 场景描述 - 具体应用 - 预期结果""" template = f"""{base} 受众:{audience} 要求:{instruction}{example_section} """ return template.format(content=content) # 使用示例 prompt_general = create_conditional_prompt( content="区块链是一种分布式账本技术...", audience="beginner", include_examples=True ) print("初学者版本:") print(prompt_general) prompt_technical = create_conditional_prompt( content="区块链是一种分布式账本技术...", audience="technical", include_examples=False ) print("\n技术版本:") print(prompt_technical)
class PromptBuilder: """动态提示词构建器""" def __init__(self): self.sections = [] self.variables = set() def add_instruction(self, text: str): """添加指令部分""" self.sections.append(("指令", text)) return self def add_context(self, text: str, **vars): """添加上下文部分""" self.sections.append(("上下文", text)) self.variables.update(vars.keys()) return self def add_constraints(self, constraints: list): """添加约束条件""" constraint_text = "约束条件:\n" + "\n".join(f"- {c}" for c in constraints) self.sections.append(("约束", constraint_text)) return self def add_output_format(self, format_spec: str): """添加输出格式说明""" self.sections.append(("输出格式", format_spec)) return self def build(self) -> str: """构建最终提示词""" parts = [] for section_type, content in self.sections: parts.append(f"### {section_type}\n{content}") return "\n\n".join(parts) # 使用示例 builder = PromptBuilder() prompt = (builder .add_instruction("请分析以下用户反馈并提供改进建议。") .add_context( "用户反馈:{feedback}\n产品类型:{product_type}", feedback="", product_type="" ) .add_constraints([ "分析必须客观", "建议必须可行", "考虑用户情绪" ]) .add_output_format(""" JSON格式: { "sentiment": "正面/负面/中性", "issues": ["问题1", "问题2"], "suggestions": ["建议1", "建议2"] } """) .build()) print(prompt)
根据查询动态选择最相关的示例。
from typing import List, Dict import numpy as np class DynamicExampleSelector: """动态示例选择器""" def __init__(self, examples: List[Dict], embeddings_model=None): self.examples = examples self.embeddings = embeddings_model self.example_embeddings = None if embeddings_model: # 预计算示例的嵌入向量 texts = [ex["input"] for ex in examples] self.example_embeddings = embeddings_model.embed_documents(texts) def select_by_similarity(self, query: str, k: int = 3) -> List[Dict]: """基于相似度选择示例""" if not self.embeddings or not self.example_embeddings: # 如果没有嵌入模型,随机选择 import random return random.sample(self.examples, min(k, len(self.examples))) # 计算查询的嵌入向量 query_embedding = self.embeddings.embed_query(query) # 计算相似度 similarities = [ np.dot(query_embedding, ex_emb) / (np.linalg.norm(query_embedding) * np.linalg.norm(ex_emb)) for ex_emb in self.example_embeddings ] # 选择最相似的 k 个 top_k_indices = np.argsort(similarities)[-k:][::-1] return [self.examples[i] for i in top_k_indices] def select_by_category(self, category: str) -> List[Dict]: """基于类别选择示例""" return [ex for ex in self.examples if ex.get("category") == category] def create_few_shot_prompt( self, query: str, k: int = 3, template: str = "输入: {input}\n输出: {output}\n---" ) -> str: """创建 few-shot 提示词""" selected = self.select_by_similarity(query, k) example_texts = [] for ex in selected: example_texts.append(template.format(**ex)) return "\n".join(example_texts) + f"\n输入: {query}\n输出:" # 使用示例 examples = [ {"input": "天气怎么样?", "output": "询问天气", "category": "weather"}, {"input": "今天会下雨吗?", "output": "询问天气", "category": "weather"}, {"input": "附近有什么餐厅?", "output": "询问餐厅", "category": "food"}, {"input": "推荐一家好吃的火锅店", "output": "询问餐厅", "category": "food"}, {"input": "怎么去机场?", "output": "询问路线", "category": "navigation"}, ] selector = DynamicExampleSelector(examples) prompt = selector.create_few_shot_prompt("明天需要带伞吗?", k=2) print(prompt)
根据上下文窗口自动调整提示词长度。
from langchain.prompts import PromptTemplate class AdaptivePromptTemplate: """自适应提示词模板""" def __init__( self, base_template: str, max_tokens: int = 2000, tokenizer=None ): self.base_template = base_template self.max_tokens = max_tokens self.tokenizer = tokenizer def estimate_tokens(self, text: str) -> int: """估计 token 数量""" if self.tokenizer: return len(self.tokenizer.encode(text)) # 简单估计:中文字符约1个token,英文单词约1.3个token return len(text) // 2 def format_adaptive( self, **kwargs ) -> str: """自适应格式化,确保不超过最大 token 数""" # 尝试完整格式化 prompt = self.base_template.format(**kwargs) tokens = self.estimate_tokens(prompt) if tokens <= self.max_tokens: return prompt # 需要压缩内容 compression_ratio = self.max_tokens / tokens * 0.9 # 留一些余量 compressed_kwargs = {} for key, value in kwargs.items(): if isinstance(value, str) and len(value) > 100: # 截断长文本 keep_length = int(len(value) * compression_ratio) compressed_kwargs[key] = value[:keep_length] + "... [内容已截断]" else: compressed_kwargs[key] = value return self.base_template.format(**compressed_kwargs) # 使用示例 template = """请分析以下长篇文档: 文档内容: {document} 分析要求: {requirements} 输出格式: {format} """ adaptive = AdaptivePromptTemplate(template, max_tokens=1000) long_document = "这是一篇非常长的文档..." * 500 # 模拟长文档 result = adaptive.format_adaptive( document=long_document, requirements="提取关键信息", format="JSON格式" ) print(f"生成的提示词长度: {len(result)}")
根据模型反馈实时调整提示词。
class PromptOptimizer: """提示词优化器""" def __init__(self, llm): self.llm = llm self.history = [] def optimize_prompt( self, original_prompt: str, target_output: str = None, feedback: str = None ) -> str: """基于反馈优化提示词""" optimization_instruction = f""" 你是一位提示词工程专家。请优化以下提示词,使其产生更好的结果。 原始提示词: {original_prompt} """ if target_output: optimization_instruction += f""" 目标输出示例: {target_output} """ if feedback: optimization_instruction += f""" 当前问题反馈: {feedback} """ optimization_instruction += """ 请提供优化后的提示词,并说明: 1. 改进了哪些方面 2. 为什么这些改进会产生更好的结果 3. 优化后的完整提示词 优化后的提示词: """ optimized = self.llm.predict(optimization_instruction) return optimized def iterative_improvement( self, base_prompt: str, test_cases: list, iterations: int = 3 ) -> str: """通过多次迭代改进提示词""" current_prompt = base_prompt for i in range(iterations): print(f"\n=== 迭代 {i+1}/{iterations} ===") # 在当前提示词上测试 results = [] for test in test_cases: result = self.llm.predict(current_prompt.format(**test["input"])) results.append({ "input": test["input"], "expected": test["expected"], "actual": result }) # 分析结果 feedback = self._analyze_results(results) print(f"反馈: {feedback}") # 优化提示词 if i < iterations - 1: # 最后一次不需要优化 current_prompt = self.optimize_prompt( current_prompt, feedback=feedback ) print(f"优化后的提示词预览: {current_prompt[:200]}...") return current_prompt def _analyze_results(self, results: list) -> str: """分析测试结果并生成反馈""" correct = sum(1 for r in results if r["expected"] in r["actual"]) total = len(results) feedback = f"准确率: {correct}/{total}\n" for i, result in enumerate(results): if result["expected"] not in result["actual"]: feedback += f"\n测试用例 {i+1} 失败:" feedback += f"\n 输入: {result['input']}" feedback += f"\n 期望: {result['expected']}" feedback += f"\n 实际: {result['actual'][:100]}..." return feedback # 使用示例(伪代码) """ from langchain.llms import OpenAI llm = OpenAI() optimizer = PromptOptimizer(llm) test_cases = [ {"input": {"text": "今天天气很好"}, "expected": "积极"}, {"input": {"text": "这部电影太糟糕了"}, "expected": "消极"}, ] final_prompt = optimizer.iterative_improvement( base_prompt="分析文本情感:{text}", test_cases=test_cases, iterations=3 ) """
本章深入探讨了 LangChain 中的提示词工程,涵盖了以下核心内容:
提示词工程基础:
PromptTemplate 详解:
Few-shot Prompting:
Prompt 组合与管理:
动态提示词:
掌握这些提示词技术,将帮助你构建更高质量、更可控的 LLM 应用。在实际项目中,建议:
在下一章中,我们将学习 LangChain 的 Chains 组件,了解如何将多个操作串联起来构建复杂的工作流。
1. 基础练习:创建一个 PromptTemplate,用于生成产品描述。模板应包含产品名称、特点列表、目标受众等变量。
2. 进阶练习:实现一个 Few-shot 情感分析提示词,包含5个示例,并使用长度限制选择器。
3. 综合项目:设计一个动态提示词系统,能够根据用户输入的复杂度自动选择不同数量和类型的示例。