Prompt工程深度解析:从Few-Shot到Chain-of-Thought的推理增强技术全流程
Prompt工程深度解析:从Few-Shot到Chain-of-Thought的推理增强技术全流程
一、引言:Prompt是大模型时代的编程语言
在大模型时代,Prompt(提示)扮演着类似编程语言的角色——通过自然语言指令控制模型行为。同一个模型,不同的Prompt可以产生截然不同的输出质量。Prompt工程(Prompt Engineering)是研究如何设计有效Prompt以激发模型最大能力的实践学科。从简单的指令到复杂的思维链(Chain-of-Thought),从单轮提示到自洽性推理,Prompt工程的发展深刻影响着大模型的应用效果。本文将系统解析Prompt工程的核心技术:Zero-Shot、Few-Shot、Chain-of-Thought、Self-Consistency、Tree of Thoughts等,并提供完整的Python实现和实验对比。
二、Prompt工程基础
Prompt的基本结构包括:角色设定(Role)、任务描述(Task)、上下文信息(Context)、示例(Examples)、约束条件(Constraints)和输出格式(Format)。好的Prompt应当明确、具体、结构化。
import json
import re
from typing import List, Dict, Any, Optional, Tuple
from dataclasses import dataclass, field
@dataclass
class PromptTemplate:
"""Prompt模板"""
name: str
template: str
input_variables: List[str] = field(default_factory=list)
def format(self, **kwargs) -> str:
return self.template.format(**kwargs)
class PromptEngineer:
"""Prompt工程师"""
@staticmethod
def zero_shot(task: str, instruction: str = "") -> str:
"""Zero-Shot提示"""
prompt = f"""{instruction}
Task: {task}
Answer:"""
return prompt
@staticmethod
def few_shot(task: str, examples: List[Dict[str, str]],
instruction: str = "") -> str:
"""Few-Shot提示"""
prompt = instruction + "\n\n" if instruction else ""
for ex in examples:
prompt += f"Input: {ex['input']}\nOutput: {ex['output']}\n\n"
prompt += f"Input: {task}\nOutput:"
return prompt
@staticmethod
def chain_of_thought(task: str, examples: List[Dict[str, str]] = None,
instruction: str = "") -> str:
"""思维链提示"""
prompt = instruction + "\n\n" if instruction else ""
prompt += "Let's think step by step.\n\n"
if examples:
for ex in examples:
prompt += f"Question: {ex['question']}\n"
prompt += f"Reasoning: {ex['reasoning']}\n"
prompt += f"Answer: {ex['answer']}\n\n"
prompt += f"Question: {task}\nReasoning:"
return prompt
@staticmethod
def self_consistency(task: str, n_samples: int = 5,
examples: List[Dict] = None) -> List[str]:
"""自洽性提示:生成多个推理路径"""
prompts = []
for i in range(n_samples):
prompt = f"Approach {i+1}:\n"
if examples:
ex = examples[i % len(examples)]
prompt += f"Example: {ex.get('reasoning', '')}\n"
prompt += f"Question: {task}\nLet's think step by step.\n"
prompts.append(prompt)
return prompts
@staticmethod
def tree_of_thoughts(problem: str, n_branches: int = 3,
max_depth: int = 3) -> str:
"""思维树提示"""
prompt = f"""Problem: {problem}
Generate {n_branches} different approaches to solve this problem.
For each approach, follow this format:
Approach X: [description]
- Step 1: [reasoning]
- Step 2: [reasoning]
- Evaluation: [score 0-10]
- Continue/Prune: [decision]
After exploring all approaches, select the best one and provide the final answer.
"""
return prompt
@staticmethod
def role_play(role: str, task: str,
expertise: str = "") -> str:
"""角色扮演提示"""
prompt = f"""You are a {role}.
{f"Your expertise: {expertise}" if expertise else ""}
Task: {task}
Please respond based on your role and expertise."""
return prompt
@staticmethod
def structured_output(task: str, schema: Dict[str, Any]) -> str:
"""结构化输出提示"""
schema_str = json.dumps(schema, indent=2, ensure_ascii=False)
prompt = f"""Task: {task}
Please provide the answer in the following JSON format:
{schema_str}
Output:"""
return prompt
@staticmethod
def react_prompt(question: str, tools: List[str]) -> str:
"""ReAct提示"""
tool_desc = '\n'.join([f"- {t}" for t in tools])
prompt = f"""Answer the following question using the available tools.
Available tools:
{tool_desc}
Format:
Thought: [reasoning about what to do]
Action: [tool name]
Action Input: [input for the tool]
Observation: [tool result]
... (repeat as needed)
Final Answer: [answer]
Question: {question}
Thought:"""
return prompt
class MockLLM:
"""模拟LLM用于演示"""
def __init__(self):
self.responses = {}
def set_response(self, prompt_pattern: str, response: str):
self.responses[prompt_pattern] = response
def generate(self, prompt: str, temperature: float = 0.7) -> str:
# 模拟不同Prompt产生不同效果
if "step by step" in prompt.lower():
return "Step 1: 分析问题要素\nStep 2: 确定计算方法\nStep 3: 执行计算\nAnswer: 42"
elif "JSON" in prompt:
return '{"answer": "42", "confidence": 0.95}'
elif "Approach" in prompt:
return "Approach 1: 直接计算 -> Answer: 42\nApproach 2: 分步推导 -> Answer: 42"
elif "Thought:" in prompt:
return " I need to calculate this.\nAction: calculator\nFinal Answer: 42"
else:
return "42"
def test_prompts():
"""测试不同Prompt策略"""
llm = MockLLM()
engineer = PromptEngineer()
# Zero-Shot
print("=== Zero-Shot ===")
prompt = engineer.zero_shot("What is 6 * 7?", "You are a math assistant.")
response = llm.generate(prompt)
print(f"Prompt:\n{prompt}\n")
print(f"Response: {response}\n")
# Few-Shot
print("=== Few-Shot ===")
examples = [
{"input": "2 + 3", "output": "5"},
{"input": "4 * 5", "output": "20"},
]
prompt = engineer.few_shot("6 * 7", examples)
response = llm.generate(prompt)
print(f"Prompt:\n{prompt[:200]}...\n")
print(f"Response: {response}\n")
# Chain-of-Thought
print("=== Chain-of-Thought ===")
prompt = engineer.chain_of_thought(
"A train travels 60 km/h for 2 hours, then 80 km/h for 1.5 hours. Total distance?"
)
response = llm.generate(prompt)
print(f"Prompt:\n{prompt[:200]}...\n")
print(f"Response: {response}\n")
# Structured Output
print("=== Structured Output ===")
schema = {"answer": "string", "confidence": "number", "explanation": "string"}
prompt = engineer.structured_output("What is the capital of France?", schema)
response = llm.generate(prompt)
print(f"Response: {response}\n")
if __name__ == "__main__":
test_prompts()
三、高级Prompt技术
class SelfConsistency:
"""自洽性推理:生成多个推理路径,投票选择最一致的答案"""
def __init__(self, llm, n_samples: int = 5, temperature: float = 0.7):
self.llm = llm
self.n_samples = n_samples
self.temperature = temperature
def solve(self, question: str, examples: List[Dict] = None) -> Dict:
"""解决推理问题"""
engineer = PromptEngineer()
prompts = engineer.self_consistency(question, self.n_samples, examples)
# 生成多个推理路径
answers = []
reasoning_paths = []
for i, prompt in enumerate(prompts):
response = self.llm.generate(prompt, temperature=self.temperature)
# 提取答案
answer = self._extract_answer(response)
answers.append(answer)
reasoning_paths.append({
'path': i + 1,
'response': response,
'answer': answer
})
# 投票选择最一致的答案
from collections import Counter
answer_counts = Counter(answers)
best_answer, votes = answer_counts.most_common(1)[0]
return {
'answer': best_answer,
'confidence': votes / self.n_samples,
'all_answers': answers,
'reasoning_paths': reasoning_paths
}
def _extract_answer(self, response: str) -> str:
"""从响应中提取答案"""
match = re.search(r'Answer:\s*(.+?)(?:\n|$)', response)
if match:
return match.group(1).strip()
return response.strip().split('\n')[-1]
class TreeOfThoughts:
"""思维树:树形搜索推理路径"""
def __init__(self, llm, max_depth: int = 3, n_branches: int = 3):
self.llm = llm
self.max_depth = max_depth
self.n_branches = n_branches
def solve(self, problem: str) -> Dict:
"""解决复杂推理问题"""
# 生成初始想法
thoughts = self._generate_thoughts(problem, depth=0)
# 搜索最佳路径
best_path = self._search(problem, thoughts, current_path=[], depth=0)
return {
'problem': problem,
'best_path': best_path,
'solution': best_path[-1]['thought'] if best_path else None
}
def _generate_thoughts(self, context: str, depth: int) -> List[Dict]:
"""生成多个思考分支"""
prompt = f"""Context: {context}
Generate {self.n_branches} different thoughts/ideas to progress towards solving this problem.
Thought 1: [thought]
Thought 2: [thought]
Thought 3: [thought]
"""
response = self.llm.generate(prompt)
# 解析想法
thoughts = []
for match in re.finditer(r'Thought \d+:\s*(.+?)(?:\n|$)', response):
thought = match.group(1).strip()
# 评估想法质量
score = self._evaluate_thought(context, thought)
thoughts.append({
'thought': thought,
'score': score,
'depth': depth
})
return thoughts
def _evaluate_thought(self, context: str, thought: str) -> float:
"""评估想法质量"""
# 模拟评估(实际中使用LLM评估)
import random
return random.uniform(0.5, 1.0)
def _search(self, problem: str, thoughts: List[Dict],
current_path: List[Dict], depth: int) -> List[Dict]:
"""搜索最佳路径(DFS)"""
if depth >= self.max_depth or not thoughts:
return current_path
# 按分数排序
thoughts.sort(key=lambda x: x['score'], reverse=True)
# 只保留前N个
top_thoughts = thoughts[:self.n_branches]
best_path = current_path
best_score = 0
for thought in top_thoughts:
new_path = current_path + [thought]
# 如果还有深度,继续搜索
if depth + 1 < self.max_depth:
next_context = f"{problem}\nPrevious thoughts: {thought['thought']}"
next_thoughts = self._generate_thoughts(next_context, depth + 1)
path = self._search(problem, next_thoughts, new_path, depth + 1)
else:
path = new_path
# 评估路径
path_score = sum(t['score'] for t in path) / len(path) if path else 0
if path_score > best_score:
best_score = path_score
best_path = path
return best_path
class PromptOptimizer:
"""Prompt优化器"""
@staticmethod
def optimize(prompt: str, feedback: str = "") -> str:
"""根据反馈优化Prompt"""
improvements = []
# 检查是否缺少角色设定
if not re.search(r'You are|你是一个|你是', prompt):
improvements.append("添加角色设定")
# 检查是否缺少输出格式
if not re.search(r'format|格式|JSON|output', prompt, re.I):
improvements.append("指定输出格式")
# 检查是否缺少示例
if not re.search(r'Example|示例|e\.g\.', prompt):
improvements.append("添加示例")
# 检查是否缺少约束
if not re.search(r'must|should|不要|必须|不超过', prompt):
improvements.append("添加约束条件")
# 检查是否过长
if len(prompt) > 2000:
improvements.append("Prompt过长,建议精简")
return improvements
def test_advanced_prompts():
"""测试高级Prompt技术"""
llm = MockLLM()
# Self-Consistency
print("=== Self-Consistency ===")
sc = SelfConsistency(llm, n_samples=3)
result = sc.solve("What is 15 * 17?")
print(f"Answer: {result['answer']}")
print(f"Confidence: {result['confidence']:.2%}")
print(f"All answers: {result['all_answers']}")
# Tree of Thoughts
print("\n=== Tree of Thoughts ===")
tot = TreeOfThoughts(llm, max_depth=2, n_branches=2)
result = tot.solve("How to reduce carbon emissions?")
print(f"Best path length: {len(result['best_path'])}")
if result['best_path']:
print(f"Solution: {result['solution'][:100]}...")
# Prompt优化
print("\n=== Prompt Optimization ===")
prompt = "Explain machine learning."
improvements = PromptOptimizer.optimize(prompt)
print(f"原始Prompt: {prompt}")
print(f"改进建议: {improvements}")
if __name__ == "__main__":
test_advanced_prompts()
四、总结
Prompt工程通过精心设计的提示,显著提升大模型的推理和生成能力。Zero-Shot提供最简单的基线;Few-Shot通过示例引导模型理解任务格式;Chain-of-Thought激发模型的逐步推理能力;Self-Consistency通过多路径投票提升答案可靠性;Tree of Thoughts支持复杂的树形搜索。从工程实践角度,好的Prompt应当明确角色、具体描述任务、提供示例、指定输出格式、设置约束条件。随着Prompt工程与Agent技术的融合(如自动Prompt优化、Prompt-as-Program),Prompt不仅是使用大模型的技术,更成为大模型时代的核心编程范式。掌握Prompt工程,是从大模型的使用者进阶为高效开发者的必经之路。
- 点赞
- 收藏
- 关注作者
评论(0)