Prompt工程与上下文管理
掌握与AI对话的艺术:从基础到高级的Prompt设计与优化
📋 概述
Prompt工程是AI应用开发的核心技能之一。好的Prompt能够显著提升AI的输出质量、准确性和可控性。本文将系统介绍Prompt设计的原理、模式和最佳实践。
🎯 Prompt工程基础
什么是Prompt?
Prompt是给AI模型的指令或输入,它决定了模型的输出质量和方向。
基本结构:
[系统指令] + [上下文信息] + [用户问题] + [输出格式要求]
Prompt的核心要素
1. 清晰性(Clarity)
# ❌ 模糊的Prompt
"写点关于AI的东西"
# ✅ 清晰的Prompt
"写一篇800字的文章,介绍AI在医疗领域的3个主要应用场景,包括具体案例。"
2. 具体性(Specificity)
# ❌ 过于宽泛
"帮我分析这个数据"
# ✅ 具体明确
"""
请分析以下销售数据:
- 计算月度增长率
- 识别销售高峰期
- 提出3条优化建议
- 以表格和要点形式呈现
数据:[...]
"""
3. 上下文(Context)
# ❌ 缺少上下文
"这个方案可行吗?"
# ✅ 提供充分上下文
"""
背景:我们是一家电商平台,日活10万用户
目标:降低20%的客服成本
方案:使用AI客服替代50%的人工客服
限制:预算50万,3个月上线
请评估这个方案的可行性,从技术、成本、时间三个维度分析。
"""
4. 格式化(Format)
# ❌ 未指定格式
"列出AI的应用"
# ✅ 指定格式
"""
请列出AI的5个主要应用领域,按以下格式:
1. 【领域名称】
- 应用场景:
- 典型案例:
- 市场规模:
- 技术难度:⭐⭐⭐⭐⭐
"""
🔧 Prompt设计模式
1. 角色扮演模式(Role Playing)
原理:让AI扮演特定角色,提供专业视角
模板:
def role_playing_prompt(role: str, task: str) -> str:
return f"""
你是一位{role}。
{task}
请以{role}的专业角度回答。
"""
# 示例
prompt = role_playing_prompt(
role="资深Python工程师,有10年开发经验",
task="请review以下代码,指出潜在问题和优化建议"
)
实战案例:
# 技术面试官
"""
你是一位资深的技术面试官,擅长评估候选人的技术能力和解决问题的思维方式。
面试题目:设计一个分布式缓存系统
候选人回答:[...]
请评估候选人的回答,从以下维度打分(1-10分):
1. 系统设计完整性
2. 技术选型合理性
3. 可扩展性考虑
4. 容错机制设计
5. 性能优化思路
并给出具体的反馈建议。
"""
# 医疗顾问
"""
你是一位有20年临床经验的全科医生,擅长诊断常见疾病。
患者症状:
- 持续发热38.5°C(3天)
- 咳嗽有痰
- 喉咙疼痛
- 轻微头痛
请提供:
1. 可能的诊断(3个)
2. 建议的检查项目
3. 初步用药建议
4. 注意事项
注意:这只是初步建议,请强调患者需要就医确诊。
"""
2. 思维链模式(Chain of Thought, CoT)
原理:引导AI展示推理过程,提高复杂任务的准确性
基础CoT:
def basic_cot_prompt(problem: str) -> str:
return f"""
问题:{problem}
请一步一步思考:
1. 首先,分析问题的关键信息
2. 然后,列出解决步骤
3. 接着,执行每个步骤
4. 最后,给出最终答案
让我们开始:
"""
# 示例:数学问题
prompt = """
问题:一个商店原价100元的商品,先打8折,再减20元,最后又打9折,请问最终价格是多少?
请一步一步计算:
"""
# AI回答:
# 1. 原价:100元
# 2. 第一步打8折:100 × 0.8 = 80元
# 3. 第二步减20元:80 - 20 = 60元
# 4. 第三步打9折:60 × 0.9 = 54元
# 最终价格:54元
Zero-shot CoT:
# 只需在问题后加上 "让我们一步一步思考"
prompt = """
问题:如果5个人5天吃5个苹果,那么10个人10天吃多少个苹果?
让我们一步一步思考:
"""
Few-shot CoT:
prompt = """
示例1:
问题:一个班级有30个学生,其中60%是女生,女生中有一半喜欢数学。请问有多少女生喜欢数学?
思考过程:
1. 总学生数:30人
2. 女生人数:30 × 60% = 18人
3. 喜欢数学的女生:18 × 50% = 9人
答案:9人
示例2:
问题:一本书300页,小明第一天读了全书的1/3,第二天读了剩余的1/2,请问还剩多少页?
思考过程:
1. 总页数:300页
2. 第一天读:300 × 1/3 = 100页,剩余200页
3. 第二天读:200 × 1/2 = 100页,剩余100页
答案:100页
现在请解决:
问题:{your_problem}
思考过程:
"""
3. 自我一致性模式(Self-Consistency)
原理:多次生成答案,选择最一致的结果
实现:
import asyncio
from collections import Counter
class SelfConsistencyPrompt:
def __init__(self, llm, n_samples=5):
self.llm = llm
self.n_samples = n_samples
async def generate_with_consistency(self, prompt: str) -> str:
# 生成多个答案
tasks = [self.llm.generate(prompt) for _ in range(self.n_samples)]
responses = await asyncio.gather(*tasks)
# 提取最终答案(假设答案在最后一行)
answers = [r.strip().split('\n')[-1] for r in responses]
# 选择最常见的答案
answer_counts = Counter(answers)
most_common_answer = answer_counts.most_common(1)[0][0]
# 找到包含该答案的完整响应
for response in responses:
if most_common_answer in response:
return response
return responses[0]
# 使用
prompt = """
问题:公司有100名员工,平均年龄30岁。新招了10名平均年龄25岁的员工,请问现在公司员工的平均年龄是多少?
让我们一步一步计算,并在最后一行给出答案(格式:答案:XX岁):
"""
consistency = SelfConsistencyPrompt(llm, n_samples=5)
result = await consistency.generate_with_consistency(prompt)
4. 程序辅助模式(Program-Aided)
原理:让AI生成代码来解决问题,提高准确性
示例:
prompt = """
问题:计算复利投资回报。初始投资10000元,年利率8%,投资10年,每年复利一次。
请用Python代码计算:
```python
# 你的代码
然后执行代码并给出答案。 """
AI生成:
principal = 10000 # 本金
rate = 0.08 # 年利率
years = 10 # 年数
final_amount = principal * (1 + rate) ** years
profit = final_amount - principal
print(f"最终金额:{final_amount:.2f}元")
print(f"投资收益:{profit:.2f}元")
输出:
最终金额:21589.25元
投资收益:11589.25元
"""
### 5. 思维树模式(Tree of Thoughts)
**原理**:探索多个推理路径,选择最优解
**实现**:
```python
class TreeOfThoughts:
def __init__(self, llm):
self.llm = llm
def solve(self, problem: str, num_branches=3, depth=3):
"""
使用思维树方法解决问题
"""
# 第一层:生成多个初始思路
initial_prompt = f"""
问题:{problem}
请提供{num_branches}种不同的解决思路,每种思路一段话:
"""
initial_thoughts = self.llm.generate(initial_prompt)
# 评估每个思路
evaluation_prompt = f"""
以下是{num_branches}种解决思路:
{initial_thoughts}
请评估每种思路的可行性(1-10分)和理由:
"""
evaluations = self.llm.generate(evaluation_prompt)
# 选择最优思路并深入
best_thought_prompt = f"""
基于以下评估:
{evaluations}
请选择最有希望的思路,并详细展开具体步骤:
"""
detailed_solution = self.llm.generate(best_thought_prompt)
return detailed_solution
# 使用
tot = TreeOfThoughts(llm)
problem = "设计一个日活百万的社交应用,如何降低服务器成本?"
solution = tot.solve(problem)
📝 上下文管理
1. 上下文窗口
概念:模型一次能处理的最大token数量
常见模型的上下文窗口:
- GPT-3.5-Turbo:4K / 16K
- GPT-4:8K / 32K
- Claude 3:200K
- Gemini 1.5 Pro:1M
Token估算:
import tiktoken
def count_tokens(text: str, model: str = "gpt-3.5-turbo") -> int:
encoding = tiktoken.encoding_for_model(model)
return len(encoding.encode(text))
# 示例
text = "这是一段测试文本"
tokens = count_tokens(text)
print(f"Token数量:{tokens}")
2. 上下文压缩
策略1:摘要压缩
class ContextCompressor:
def __init__(self, llm, max_tokens=2000):
self.llm = llm
self.max_tokens = max_tokens
def compress(self, long_text: str) -> str:
current_tokens = count_tokens(long_text)
if current_tokens <= self.max_tokens:
return long_text
# 压缩比例
compression_ratio = self.max_tokens / current_tokens
prompt = f"""
请将以下文本压缩到原来的{compression_ratio:.0%}长度,保留核心信息:
{long_text}
压缩后的文本:
"""
compressed = self.llm.generate(prompt)
return compressed
# 使用
compressor = ContextCompressor(llm, max_tokens=1000)
compressed_text = compressor.compress(long_document)
策略2:关键信息提取
def extract_key_information(text: str, llm) -> dict:
prompt = f"""
从以下文本中提取关键信息:
{text}
请提取:
1. 主题(1句话)
2. 关键人物/实体
3. 重要事件/观点(3-5条)
4. 数据和数字
5. 结论
以JSON格式输出。
"""
response = llm.generate(prompt)
return json.loads(response)
策略3:分块处理
class ChunkedProcessor:
def __init__(self, llm, chunk_size=2000, overlap=200):
self.llm = llm
self.chunk_size = chunk_size
self.overlap = overlap
def process_long_text(self, text: str, question: str) -> str:
# 分块
chunks = self.split_text(text)
# 处理每个块
chunk_results = []
for i, chunk in enumerate(chunks):
prompt = f"""
这是长文档的第{i+1}部分:
{chunk}
问题:{question}
如果这部分包含答案,请回答;如果没有,回答"无相关信息"。
"""
result = self.llm.generate(prompt)
if "无相关信息" not in result:
chunk_results.append(result)
# 整合结果
if not chunk_results:
return "文档中未找到相关信息"
synthesis_prompt = f"""
以下是从文档不同部分提取的信息:
{chr(10).join(chunk_results)}
请整合这些信息,给出完整的答案:
"""
final_answer = self.llm.generate(synthesis_prompt)
return final_answer
def split_text(self, text: str) -> list:
words = text.split()
chunks = []
for i in range(0, len(words), self.chunk_size - self.overlap):
chunk = ' '.join(words[i:i + self.chunk_size])
chunks.append(chunk)
return chunks
3. 对话历史管理
策略1:滑动窗口
class ConversationManager:
def __init__(self, max_history=10):
self.max_history = max_history
self.messages = []
def add_message(self, role: str, content: str):
self.messages.append({
"role": role,
"content": content
})
# 保持最近的消息
if len(self.messages) > self.max_history:
# 保留系统消息
system_messages = [m for m in self.messages if m["role"] == "system"]
recent_messages = self.messages[-self.max_history:]
self.messages = system_messages + recent_messages
def get_context(self) -> list:
return self.messages
策略2:重要性筛选
class ImportanceBasedHistory:
def __init__(self, llm, max_messages=10):
self.llm = llm
self.max_messages = max_messages
self.all_messages = []
def add_message(self, role: str, content: str):
self.all_messages.append({
"role": role,
"content": content,
"importance": None
})
def get_context(self) -> list:
if len(self.all_messages) <= self.max_messages:
return self.all_messages
# 评估每条消息的重要性
for msg in self.all_messages:
if msg["importance"] is None:
msg["importance"] = self.evaluate_importance(msg)
# 排序并选择最重要的
sorted_messages = sorted(
self.all_messages,
key=lambda x: x["importance"],
reverse=True
)
important_messages = sorted_messages[:self.max_messages]
# 按时间顺序返回
important_messages.sort(key=lambda x: self.all_messages.index(x))
return important_messages
def evaluate_importance(self, message: dict) -> float:
prompt = f"""
评估以下对话消息的重要性(0-1分):
消息:{message["content"]}
评分标准:
- 包含关键信息:+0.3
- 包含决策或结论:+0.3
- 被后续对话引用:+0.2
- 纯寒暄或过渡:-0.3
只输出一个0-1之间的数字:
"""
score = float(self.llm.generate(prompt).strip())
return score
策略3:摘要保存
class SummarizedHistory:
def __init__(self, llm):
self.llm = llm
self.current_messages = []
self.summary = ""
def add_message(self, role: str, content: str):
self.current_messages.append({
"role": role,
"content": content
})
# 每10条消息,生成摘要
if len(self.current_messages) >= 10:
self.create_summary()
def create_summary(self):
conversation_text = "\n".join([
f"{m['role']}: {m['content']}"
for m in self.current_messages
])
prompt = f"""
请总结以下对话的关键信息:
{conversation_text}
摘要应包括:
1. 主要讨论的话题
2. 达成的结论或决定
3. 待解决的问题
摘要:
"""
new_summary = self.llm.generate(prompt)
# 合并到总摘要
if self.summary:
self.summary = f"{self.summary}\n\n{new_summary}"
else:
self.summary = new_summary
# 清空当前消息,只保留最近3条
self.current_messages = self.current_messages[-3:]
def get_context(self) -> str:
context_parts = []
if self.summary:
context_parts.append(f"之前的对话摘要:\n{self.summary}")
if self.current_messages:
recent_conversation = "\n".join([
f"{m['role']}: {m['content']}"
for m in self.current_messages
])
context_parts.append(f"\n当前对话:\n{recent_conversation}")
return "\n\n".join(context_parts)
🎨 高级Prompt技巧
1. 情感引导
技巧:适当的情感表达能影响AI的输出风格
# 正式场景
"""
作为一位专业的商业顾问,请严谨地分析以下商业计划...
"""
# 创意场景
"""
发挥你的想象力!让我们一起头脑风暴,想出10个超酷的产品创意...
"""
# 教学场景
"""
想象你正在教一个10岁的孩子,请用简单有趣的方式解释量子力学...
"""
2. 反面提示
技巧:明确告诉AI不要做什么
prompt = """
请写一篇关于AI伦理的文章。
要求:
✅ 提供具体案例
✅ 多角度分析
✅ 结构清晰
避免:
❌ 不要使用行业黑话
❌ 不要过度技术化
❌ 不要超过1000字
❌ 不要抄袭已有文章
"""
3. 迭代优化
技巧:通过多轮对话逐步优化
# 第一轮:初稿
prompt_1 = "写一段产品介绍"
# 第二轮:改进
prompt_2 = "这段介绍太平淡了,请加入更多卖点和情感元素"
# 第三轮:精修
prompt_3 = "很好!请再精简到100字以内,更加punchy"
4. 约束与激励
技巧:设置约束和奖励机制
prompt = """
任务:为新产品设计营销方案
约束条件:
- 预算不超过10万
- 时间周期1个月
- 目标用户是18-25岁年轻人
激励目标:
如果方案能达到以下目标,视为优秀:
- 预期触达用户 > 10万
- 转化率 > 5%
- ROI > 3
请设计3个方案,并说明哪个方案最可能达到激励目标。
"""
5. 元Prompt
技巧:让AI帮你生成更好的Prompt
meta_prompt = """
我需要一个Prompt来完成以下任务:
{task_description}
目标用户:{target_audience}
期望输出:{expected_output}
约束条件:{constraints}
请帮我设计一个高质量的Prompt,要求:
1. 清晰具体
2. 包含必要的上下文
3. 指定输出格式
4. 包含few-shot示例(如果需要)
生成的Prompt:
"""
# 示例
task = "让AI帮我分析用户反馈"
audience = "产品经理"
output = "结构化的分析报告,包含情感分析、问题分类、优先级排序"
constraints = "需要处理中英文混合的反馈,识别具体的产品功能点"
generated_prompt = llm.generate(meta_prompt.format(
task_description=task,
target_audience=audience,
expected_output=output,
constraints=constraints
))
📊 Prompt评估与优化
1. 评估指标
class PromptEvaluator:
def __init__(self, llm):
self.llm = llm
def evaluate(self, prompt: str, test_cases: list) -> dict:
results = {
'accuracy': 0,
'relevance': 0,
'completeness': 0,
'clarity': 0,
'consistency': 0
}
for test_case in test_cases:
response = self.llm.generate(prompt.format(**test_case['input']))
# 准确性
accuracy = self.check_accuracy(response, test_case['expected'])
results['accuracy'] += accuracy
# 相关性
relevance = self.check_relevance(response, test_case['input'])
results['relevance'] += relevance
# 完整性
completeness = self.check_completeness(response, test_case['requirements'])
results['completeness'] += completeness
# 清晰度
clarity = self.check_clarity(response)
results['clarity'] += clarity
# 一致性(多次运行)
consistency = self.check_consistency(prompt, test_cases[0])
results['consistency'] = consistency
# 平均分
n = len(test_cases)
for key in results:
if key != 'consistency':
results[key] /= n
return results
def check_accuracy(self, response: str, expected: str) -> float:
# 使用AI评估
eval_prompt = f"""
回答:{response}
期望:{expected}
评估回答的准确性(0-1分):
"""
score = float(self.llm.generate(eval_prompt))
return score
2. A/B测试
class PromptABTest:
def __init__(self, llm):
self.llm = llm
def compare(self, prompt_a: str, prompt_b: str, test_cases: list) -> dict:
results_a = []
results_b = []
for test_case in test_cases:
# 测试Prompt A
response_a = self.llm.generate(prompt_a.format(**test_case))
score_a = self.evaluate_response(response_a, test_case)
results_a.append(score_a)
# 测试Prompt B
response_b = self.llm.generate(prompt_b.format(**test_case))
score_b = self.evaluate_response(response_b, test_case)
results_b.append(score_b)
# 统计分析
import numpy as np
mean_a = np.mean(results_a)
mean_b = np.mean(results_b)
# 简单的显著性检验
from scipy import stats
t_stat, p_value = stats.ttest_ind(results_a, results_b)
return {
'prompt_a_avg': mean_a,
'prompt_b_avg': mean_b,
'winner': 'A' if mean_a > mean_b else 'B',
'improvement': abs(mean_a - mean_b) / min(mean_a, mean_b),
'p_value': p_value,
'significant': p_value < 0.05
}
3. 自动优化
class PromptOptimizer:
def __init__(self, llm):
self.llm = llm
def optimize(self, initial_prompt: str, test_cases: list, iterations=5):
current_prompt = initial_prompt
best_score = 0
best_prompt = initial_prompt
for i in range(iterations):
# 评估当前prompt
score = self.evaluate(current_prompt, test_cases)
if score > best_score:
best_score = score
best_prompt = current_prompt
# 生成改进建议
improvement_prompt = f"""
当前Prompt:
{current_prompt}
测试结果:
- 平均得分:{score}
- 主要问题:[从测试用例分析]
请提供3个改进建议,并生成优化后的Prompt。
优化后的Prompt:
"""
improved_prompt = self.llm.generate(improvement_prompt)
current_prompt = improved_prompt
return {
'best_prompt': best_prompt,
'best_score': best_score,
'iterations': iterations
}
💡 最佳实践总结
Do's ✅
- 明确具体:清楚说明期望的输出
- 提供上下文:给足够的背景信息
- 使用示例:Few-shot提升效果
- 指定格式:明确输出格式要求
- 迭代优化:测试和改进Prompt
- 角色设定:让AI扮演合适的角色
- 分步推理:复杂任务使用CoT
- 设置约束:明确不要什么
Don'ts ❌
- 模糊不清:避免模棱两可的表达
- 过度复杂:一次性要求太多
- 缺少上下文:信息不足
- 忽略格式:没有结构化输出
- 一成不变:不测试不优化
- 忽视token限制:超出上下文窗口
- 缺少验证:不检查输出质量
- 滥用情感:不当的情感引导
🎓 实战案例
案例1:代码Review助手
CODE_REVIEW_PROMPT = """
你是一位资深的{language}工程师,有15年开发经验。
请review以下代码:
```{language}
{code}
请从以下维度分析:
代码质量(1-10分)
- 可读性
- 可维护性
- 代码规范
潜在问题
- Bug风险
- 性能问题
- 安全隐患
优化建议
- 具体改进代码
- 解释优化理由
最佳实践
- 是否遵循最佳实践
- 推荐的设计模式
格式要求:
- 使用Markdown格式
- 代码示例使用代码块
- 每个问题给出严重程度(🔴严重/🟡中等/🟢轻微)
开始review: """
使用
review = llm.generate(CODE_REVIEW_PROMPT.format( language="Python", code=user_code ))
### 案例2:智能客服
```python
CUSTOMER_SERVICE_PROMPT = """
你是{company_name}的客服代表,友好、专业、高效。
公司信息:
- 主营业务:{business}
- 服务时间:{service_hours}
- 退换货政策:{return_policy}
常见问题库:
{faq}
对话历史:
{chat_history}
客户最新问题:
{customer_question}
请回答客户问题,注意:
1. 语气友好亲切
2. 如果问题在FAQ中,直接回答
3. 如果需要人工处理,引导转人工
4. 必要时询问补充信息
5. 回答要具体,避免模糊
你的回复:
"""
案例3:文档问答系统
QA_WITH_CONTEXT_PROMPT = """
基于以下文档内容回答问题。
文档内容:
\"\"\"
{context}
\"\"\"
问题:{question}
回答要求:
1. 只基于文档内容回答
2. 如果文档中没有相关信息,明确说明"文档中未找到相关信息"
3. 引用具体的段落或章节
4. 提供简洁但完整的答案
回答:
"""
# 使用RAG
def answer_with_rag(question: str, vector_store) -> str:
# 检索相关文档
relevant_docs = vector_store.search(question, k=3)
# 构建上下文
context = "\n\n---\n\n".join([doc.content for doc in relevant_docs])
# 生成答案
prompt = QA_WITH_CONTEXT_PROMPT.format(
context=context,
question=question
)
answer = llm.generate(prompt)
# 附加来源
sources = [doc.metadata['source'] for doc in relevant_docs]
answer += f"\n\n来源:{', '.join(sources)}"
return answer
📚 参考资源
学习资源
- OpenAI Prompt Engineering Guide
- Anthropic Prompt Engineering
- Learn Prompting (learnprompting.org)
- Prompt Engineering Guide (promptingguide.ai)
工具推荐
- ChatGPT Playground
- Claude.ai
- PromptPerfect
- LangChain PromptTemplate
社区
- r/PromptEngineering
- PromptHub
- ShareGPT
🔗 相关文章
最后更新:2024年12月22日