名称: 提示工程 描述: 大型语言模型提示工程技术与最佳实践综合指南
提示工程
概述
大型语言模型提示工程技术与最佳实践综合指南。
前提条件
- 对大型语言模型(LLM)的基本理解
- 熟悉AI/ML概念
- 使用AI助手或聊天机器人的经验
- 理解自然语言沟通
- 编程概念知识(用于代码生成任务)
关键概念
- 零样本提示:在不提供示例的情况下要求模型执行任务
- 少样本提示:提供示例以引导模型理解和输出
- 思维链(CoT):引导模型逐步展示其推理过程
- ReAct(推理+行动):结合推理与面向行动的提示以解决问题
- 自一致性:生成多个推理路径并达成共识
- 提示模板:带有变量替换的可重用提示模式
- 系统消息:设置AI助手的行为和个性
- 上下文管理:在令牌限制内处理长对话和文档
- 输出格式化:引导模型生成结构化、可解析的输出
- 约束与控制:明确设置模型应做和不应做的边界
- 温度:控制模型输出中的随机性(低=确定性,高=创造性)
- Top P(核采样):控制输出多样性的累积概率阈值
- 最大令牌数:控制输出的最大长度
- 停止序列:定义用于结构化输出的生成停止字符串
- 提示版本管理:管理不同版本的提示以进行测试和部署
- 反模式:避免常见的提示工程错误
- 模型特定提示:针对不同LLM提供商(GPT、Claude、Llama、Mistral)的优化策略
1. 提示设计原则
1.1 核心原则
"""
提示工程核心原则:
1. 清晰性 - 具体且无歧义
2. 上下文 - 提供相关背景信息
3. 约束 - 设置明确的边界和期望
4. 示例 - 展示,而非仅告知
5. 格式 - 指定期望的输出结构
6. 迭代 - 优化和测试提示
"""
# 结构良好的提示示例
WELL_STRUCTURED_PROMPT = """
您是一位精通Python和Web开发的高级软件工程师。
任务:
编写用户注册的REST API端点。
要求:
- 使用FastAPI框架
- 包括输入验证
- 使用bcrypt哈希密码
- 返回适当的HTTP状态码
- 处理重复电子邮件错误
上下文:
这是具有现有用户模型的更大应用程序的一部分。
用户模型字段包括:id、email、password_hash、created_at。
输出格式:
返回完整的Python代码,包括导入和类型提示。
"""
# 结构不佳的提示示例
POORLY_STRUCTURED_PROMPT = """
编写用户注册API。
"""
1.2 提示结构模板
class PromptTemplate:
"""用于构建提示的模板。"""
@staticmethod
def create_prompt(
role: str,
task: str,
context: str = None,
requirements: list = None,
examples: list = None,
output_format: str = None,
constraints: list = None
) -> str:
"""创建结构良好的提示。"""
parts = []
# 角色
parts.append(f"您是{role}。")
# 上下文
if context:
parts.append(f"
上下文:
{context}")
# 任务
parts.append(f"
任务:
{task}")
# 要求
if requirements:
parts.append("
要求:")
for req in requirements:
parts.append(f"- {req}")
# 示例
if examples:
parts.append("
示例:")
for i, example in enumerate(examples, 1):
parts.append(f"
示例 {i}:")
parts.append(example)
# 输出格式
if output_format:
parts.append(f"
输出格式:
{output_format}")
# 约束
if constraints:
parts.append("
约束:")
for constraint in constraints:
parts.append(f"- {constraint}")
return "
".join(parts)
# 使用示例
prompt = PromptTemplate.create_prompt(
role="精通机器学习的数据科学家",
task="为表格数据创建数据预处理流水线",
context="数据集包含具有缺失值和异常值的客户信息。",
requirements=[
"适当处理缺失值",
"检测和处理异常值",
"标准化数值特征",
"编码分类变量"
],
output_format="返回使用pandas和scikit-learn的Python代码",
constraints=[
"除pandas和scikit-learn外不使用外部库",
"包括类型提示",
"为函数添加文档字符串"
]
)
print(prompt)
2. 提示技术
2.1 零样本提示
"""
零样本:要求模型执行任务而不提供示例。
当任务直接且模型具有先验知识时有用。
"""
# 简单零样本提示
ZERO_SHOT_PROMPT = """
将以下电子邮件分类为垃圾邮件或非垃圾邮件:
电子邮件:"恭喜!您赢得了免费iPhone。点击此处领取您的奖品。"
分类:
"""
# 带推理的零样本提示
ZERO_SHOT_REASONING = """
分析以下客户评论的情感:
评论:"产品迅速送达且工作完美。我对购买非常满意。"
提供您的推理,然后给出最终情感标签(正面、负面、中性)。
"""
# 零样本代码生成
ZERO_SHOT_CODE = """
编写一个检查数字是否为质数的Python函数。
函数签名:def is_prime(n: int) -> bool:
"""
# 带角色的零样本提示
ZERO_SHOT_ROLE = """
作为法律助手,用简单英语总结以下合同条款:
条款:"双方同意,任何由本协议引起或相关的争议应通过按照美国仲裁协会规则的约束性仲裁解决。"
总结:
"""
2.2 少样本提示
"""
少样本:提供示例以引导模型理解。
对复杂任务或需要特定模式时有用。
"""
# 少样本分类
FEW_SHOT_CLASSIFICATION = """
将以下文本分类为正面、负面或中性。
示例1:
文本:"我喜欢这个产品!它工作得很好。"
分类:正面
示例2:
文本:"产品送达损坏且无法工作。"
分类:负面
示例3:
文本:"产品还可以,没什么特别。"
分类:中性
现在分类:
文本:"这超出了我所有预期!强烈推荐。"
分类:
"""
# 少样本代码生成
FEW_SHOT_CODE = """
编写一个在摄氏度和华氏度之间转换温度的函数。
示例1:
输入:将25°C转换为华氏度
输出:77°F
示例2:
输入:将68°F转换为摄氏度
输出:20°C
现在转换:
输入:将100°C转换为华氏度
输出:
"""
# 带思维链的少样本提示
FEW_SHOT_COT = """
逐步解决以下数学问题。
问题1:如果一件衬衫成本20美元且打25%折扣,售价是多少?
解决方案:
步骤1:计算折扣金额:$20 × 0.25 = $5
步骤2:从原价减去折扣:$20 - $5 = $15
答案:$15
问题2:商店以每件50美元购买物品并以40%加价出售。售价是多少?
解决方案:
步骤1:计算加价金额:$50 × 0.40 = $20
步骤2:将加价加到成本:$50 + $20 = $70
答案:$70
现在解决:
问题3:笔记本电脑成本800美元,有15%折扣,然后加5%税。最终价格是多少?
解决方案:
"""
# 少样本翻译
FEW_SHOT_TRANSLATION = """
将以下英语句子翻译成法语。
示例1:
英语:"Hello, how are you?"
法语:"Bonjour, comment allez-vous?"
示例2:
英语:"I would like a coffee, please."
法语:"Je voudrais un café, s'il vous plaît."
现在翻译:
英语:"Where is the train station?"
法语:
"""
2.3 思维链(CoT)
"""
思维链:引导模型展示其推理过程。
对复杂推理任务和调试有用。
"""
# 基本思维链
CHAIN_OF_THOUGHT = """
逐步解决这个问题:
农夫有鸡和牛。共有30只动物,74条腿。
农夫有多少只鸡和多少头牛?
让我们思考一下:
"""
# 带明确步骤的思维链
COT_EXPLICIT = """
分析以下商业想法是否可行。逐步提供您的推理。
商业想法:租赁奢侈手提包的订阅服务。
步骤1:识别目标市场和需求
步骤2:分析竞争格局
步骤3:评估商业模式经济性
步骤4:识别潜在风险和挑战
步骤5:提供最终推荐
分析:
"""
# 用于调试的思维链
COT_DEBUGGING = """
调试以下代码。为每个步骤解释您的思考过程。
代码:
```python
def calculate_average(numbers):
total = 0
for num in numbers:
total += num
return total / len(numbers)
该函数在空列表时失败。让我们调试: “”"
用于决策的思维链
COT_DECISION = “”" 我们是否应该将应用程序从单体架构迁移到微服务?
考虑:
- 团队规模和专业知识
- 应用程序复杂性
- 部署需求
- 可扩展性需求
- 维护开销
提供逐步分析和推荐: “”"
### 2.4 ReAct(推理+行动)
```python
"""
ReAct:结合推理与面向行动的提示。
对需要分析和执行的任务有用。
"""
# ReAct用于问题解决
REACT_PROMPT = """
您是一个可以通过思考和行动解决问题的有帮助助手。
问题:用户报告其Web应用程序在加载大型数据集时变慢。
思考1:什么可能导致性能缓慢?
行动1:识别潜在原因(数据库查询、网络、客户端渲染)
思考2:我如何诊断?
行动2:列出诊断步骤(性能分析、监控、负载测试)
思考3:我应该推荐什么解决方案?
行动3:基于诊断提出解决方案
提供您的完整分析:
"""
# ReAct用于代码审查
REACT_CODE_REVIEW = """
审查以下代码的潜在问题。
代码:
```python
def process_user_data(user_id):
user = db.query("SELECT * FROM users WHERE id = ?", user_id)
orders = db.query("SELECT * FROM orders WHERE user_id = ?", user_id)
return {"user": user, "orders": orders}
思考:存在什么安全问题? 行动:识别SQL注入漏洞
思考:存在什么性能问题? 行动:识别N+1查询问题
思考:可以进行哪些改进? 行动:建议重构和最佳实践
提供您的审查: “”"
ReAct用于故障排除
REACT_TROUBLESHOOTING = “”" 用户无法登录其账户。帮助排除此问题。
思考1:可能的原因是什么? 行动1:列出潜在原因(错误密码、账户锁定、服务器问题)
思考2:我需要什么信息? 行动2:询问澄清问题
思考3:如何解决每个原因? 行动3:提供逐步解决方案
提供您的故障排除指南: “”"
### 2.5 自一致性
```python
"""
自一致性:生成多个推理路径并达成共识。
对准确性关键且存在多种方法的任务有用。
"""
# 自一致性用于数学
SELF_CONSISTENCY_MATH = """
使用三种不同方法解决此问题,并验证它们给出相同答案。
问题:240的15%是多少?
方法1:直接计算
方法2:比例方法
方法3:小数方法
展示所有三种方法并验证答案:
"""
# 自一致性用于推理
SELF_CONSISTENCY_REASONING = """
从多个角度分析此场景并达成共识。
场景:公司正在考虑为所有员工实施远程工作。
角度1:员工福利和满意度
角度2:公司文化和协作
角度3:业务成本和生产力
角度4:客户关系和沟通
从每个角度提供分析并给出平衡结论:
"""
# 自一致性用于代码审查
SELF_CONSISTENCY_CODE = """
从三个不同角度审查此代码:安全性、性能和可维护性。
代码:
```python
def authenticate(username, password):
user = db.find_one("users", {"username": username})
if user and user["password"] == password:
return {"success": True, "token": generate_token(user)}
return {"success": False}
安全性审查: 性能审查: 可维护性审查:
整合建议: “”"
---
## 3. 提示模板
### 3.1 模板系统
```python
from typing import Dict, List
from dataclasses import dataclass
@dataclass
class PromptTemplate:
"""带有变量的可重用提示模板。"""
name: str
template: str
variables: List[str]
def format(self, **kwargs) -> str:
"""使用提供的变量格式化模板。"""
missing_vars = set(self.variables) - set(kwargs.keys())
if missing_vars:
raise ValueError(f"缺失变量:{missing_vars}")
return self.template.format(**kwargs)
# 定义模板
PROMPT_TEMPLATES = {
"code_review": PromptTemplate(
name="code_review",
template="""您是一位专家代码审查员。
审查以下{language}代码:
```{language}
{code}
关注点:
- 代码质量和风格
- 潜在错误
- 性能问题
- 安全漏洞
- 最佳实践
提供具体、可操作的反馈: “”", variables=[“language”, “code”] ),
"summarization": PromptTemplate(
name="summarization",
template="""在{max_sentences}个句子中总结以下文本。
文本: {text}
总结: “”", variables=[“text”, “max_sentences”] ),
"translation": PromptTemplate(
name="translation",
template="""将以下文本从{source_lang}翻译到{target_lang}。
文本: {text}
翻译: “”", variables=[“source_lang”, “target_lang”, “text”] ),
"extraction": PromptTemplate(
name="extraction",
template="""从文本中提取以下信息:
{fields}
文本: {text}
提取的信息(JSON格式): “”", variables=[“fields”, “text”] ) }
使用示例
code_review_prompt = PROMPT_TEMPLATES[“code_review”].format( language=“Python”, code=“def add(a, b): return a + b” )
summarization_prompt = PROMPT_TEMPLATES[“summarization”].format( text=“长文本在此…”, max_sentences=3 )
print(code_review_prompt)
### 3.2 动态提示构建
```python
class PromptBuilder:
"""基于上下文动态构建提示。"""
def __init__(self):
self.sections = []
def add_role(self, role: str):
"""添加角色定义。"""
self.sections.append(f"您是{role}。")
return self
def add_context(self, context: str):
"""添加上下文信息。"""
self.sections.append(f"
上下文:
{context}")
return self
def add_task(self, task: str):
"""添加任务描述。"""
self.sections.append(f"
任务:
{task}")
return self
def add_requirements(self, requirements: List[str]):
"""添加要求作为项目符号。"""
self.sections.append("
要求:")
for req in requirements:
self.sections.append(f"- {req}")
return self
def add_examples(self, examples: List[str]):
"""添加示例。"""
self.sections.append("
示例:")
for i, example in enumerate(examples, 1):
self.sections.append(f"
示例 {i}:
{example}")
return self
def add_constraints(self, constraints: List[str]):
"""添加约束。"""
self.sections.append("
约束:")
for constraint in constraints:
self.sections.append(f"- {constraint}")
return self
def add_output_format(self, format_spec: str):
"""添加输出格式规范。"""
self.sections.append(f"
输出格式:
{format_spec}")
return self
def build(self) -> str:
"""构建最终提示。"""
return "
".join(self.sections)
# 使用示例
prompt = (PromptBuilder()
.add_role("高级Python开发人员")
.add_context("我们正在构建任务管理应用程序的REST API。")
.add_task("创建按ID更新任务的端点。")
.add_requirements([
"使用FastAPI",
"包括输入验证",
"优雅处理不存在的任务",
"返回更新后的任务响应"
])
.add_constraints([
"不要修改其他字段",
"维护审计跟踪"
])
.add_output_format("返回包括导入的完整Python代码")
.build())
print(prompt)
4. 系统消息
4.1 系统消息模式
"""
系统消息:设置AI助手的行为和个性。
在对话开始时发送并持续存在。
"""
# 专业助手
SYSTEM_PROFESSIONAL = """
您是一位专业、有帮助的助手。提供准确、结构良好的响应。
简洁但全面。使用带有markdown的适当格式化。
如果不确定某事,承认而不是猜测。
"""
# 技术专家
SYSTEM_TECHNICAL = """
您是一位拥有15年以上经验的高级软件工程师。
提供带有最佳实践、安全考虑和性能优化的技术解决方案。
相关时包括代码示例。解释不同方法之间的权衡。
"""
# 创意作家
SYSTEM_CREATIVE = """
您是一位擅长讲故事、世界构建和角色发展的创意作家。
使用生动的描述、引人入胜的对话和引人注目的叙述。
调整风格以匹配请求的类型和语调。
"""
# 教师
SYSTEM_TEACHER = """
您是一位耐心、鼓励的教师。用示例清晰地解释概念。
将复杂主题分解为可管理的部分。检查理解程度。
根据学习者水平调整解释。
"""
# 代码审查员
SYSTEM_CODE_REVIEWER = """
您是一位细致的代码审查员。关注:
- 代码质量和可读性
- 潜在错误和边缘情况
- 性能和可扩展性
- 安全漏洞
- 遵循最佳实践
提供有建设性、具体的反馈和改进建议。
"""
# 数据分析师
SYSTEM_ANALYST = """
您是一位擅长统计分析和数据可视化的数据分析师。
准确解释数据,识别模式,并提供可操作的见解。
使用适当的统计方法并清晰地解释您的推理。
"""
# 客户服务
SYSTEM_CUSTOMER_SERVICE = """
您是一位有帮助的客户服务代表。富有同理心、耐心且以解决方案为导向。
专业地处理客户关切。必要时升级问题。
始终保持积极、专业的语调。
"""
4.2 系统消息 + 用户提示
class ConversationManager:
"""管理系统消息的对话。"""
def __init__(self, system_message: str):
self.system_message = system_message
self.conversation = [{"role": "system", "content": system_message}]
def add_user_message(self, message: str):
"""添加用户消息到对话。"""
self.conversation.append({"role": "user", "content": message})
def add_assistant_message(self, message: str):
"""添加助手消息到对话。"""
self.conversation.append({"role": "assistant", "content": message})
def get_conversation(self) -> List[Dict]:
"""获取完整对话历史。"""
return self.conversation
def reset(self):
"""重置对话,保留系统消息。"""
self.conversation = [{"role": "system", "content": self.system_message}]
# 使用示例
conversation = ConversationManager(SYSTEM_TECHNICAL)
conversation.add_user_message("如何在Python中实现REST API?")
conversation.add_assistant_message("我将帮助您实现REST API...")
conversation.add_user_message("那认证呢?")
# 获取API调用的完整对话
full_conversation = conversation.get_conversation()
5. 上下文管理
5.1 上下文窗口策略
"""
上下文窗口管理:处理长对话和文档。
不同模型有不同上下文限制(4K、8K、32K、128K令牌)。
"""
class ContextManager:
"""在令牌限制内管理上下文。"""
def __init__(self, max_tokens: int = 4000):
self.max_tokens = max_tokens
self.conversation = []
def add_message(self, role: str, content: str):
"""添加消息到对话。"""
self.conversation.append({"role": role, "content": content})
self._trim_if_needed()
def _trim_if_needed(self):
"""如果超过令牌限制则修剪对话。"""
# 估计令牌(粗略近似:1令牌 ≈ 4字符)
total_chars = sum(len(msg["content"]) for msg in self.conversation)
estimated_tokens = total_chars // 4
while estimated_tokens > self.max_tokens and len(self.conversation) > 2:
# 移除最旧的非系统消息
self.conversation.pop(1) # 保留索引0的系统消息
total_chars = sum(len(msg["content"]) for msg in self.conversation)
estimated_tokens = total_chars // 4
def get_context(self) -> List[Dict]:
"""获取当前上下文。"""
return self.conversation
# 使用示例
context = ContextManager(max_tokens=4000)
context.add_message("system", "您是一位有帮助的助手。")
context.add_message("user", "你好!")
context.add_message("assistant", "嗨!我可以怎么帮助?")
# 添加许多消息 - 会自动修剪
for i in range(100):
context.add_message("user", f"消息 {i}")
context.add_message("assistant", f"响应 {i}")
print(f"上下文长度:{len(context.get_context())} 条消息")
5.2 文档分块以处理上下文
from typing import List
class DocumentChunker:
"""为上下文窗口分块文档。"""
def __init__(self, chunk_size: int = 1000, overlap: int = 100):
self.chunk_size = chunk_size
self.overlap = overlap
def chunk_by_size(self, text: str) -> List[str]:
"""按大小分块文本。"""
chunks = []
start = 0
while start < len(text):
end = start + self.chunk_size
chunk = text[start:end]
chunks.append(chunk)
start = end - self.overlap
return chunks
def chunk_by_sentences(self, text: str, sentences_per_chunk: int = 5) -> List[str]:
"""按句子分块文本。"""
import re
sentences = re.split(r'(?<=[.!?])\s+', text)
chunks = []
for i in range(0, len(sentences), sentences_per_chunk):
chunk = ' '.join(sentences[i:i + sentences_per_chunk])
chunks.append(chunk)
return chunks
def chunk_by_paragraphs(self, text: str, paragraphs_per_chunk: int = 3) -> List[str]:
"""按段落分块文本。"""
paragraphs = text.split('
')
chunks = []
for i in range(0, len(paragraphs), paragraphs_per_chunk):
chunk = '
'.join(paragraphs[i:i + paragraphs_per_chunk])
chunks.append(chunk)
return chunks
# 使用示例
document = """
这是一个包含多个段落的文档。
每个段落包含重要信息。
我们需要分块处理此文档。
第二段继续讨论。
它提供了关于主题的更多细节。
分块有助于管理上下文窗口。
最后,第三段总结文档。
它总结了早些时候的关键点。
这种方法适用于长文本。
"""
chunker = DocumentChunker(chunk_size=200, overlap=20)
chunks = chunker.chunk_by_size(document)
print(f"创建了 {len(chunks)} 个块")
6. 输出格式化
6.1 结构化输出
"""
输出格式化:引导模型生成结构化、可解析的输出。
"""
# JSON输出
JSON_OUTPUT = """
从文本中提取以下信息并以JSON返回:
- 姓名
- 电子邮件
- 电话
- 公司
文本:
"John Smith在Acme Corp工作。您可以通过john.smith@acme.com或拨打555-123-4567联系他。"
JSON输出:
"""
# Markdown输出
MARKDOWN_OUTPUT = """
创建具有以下部分的markdown报告:
## 执行摘要
## 关键发现
## 建议
## 后续步骤
主题:"远程工作生产力研究"
报告:
"""
# 表格输出
TABLE_OUTPUT = """
创建以下编程语言的比较表:
- Python
- JavaScript
- Java
- Go
包括列:用例、性能、学习曲线、生态系统
格式化为markdown表格:
"""
# 代码块输出
CODE_OUTPUT = """
编写验证电子邮件地址的Python函数。
包括适当的正则表达式模式和错误处理。
在带有语法高亮的markdown代码块中返回代码:
"""
# 列表输出
LIST_OUTPUT = """
列出API安全的前10个最佳实践。
格式化为带有每个简要解释的编号列表:
"""
6.2 输出验证
import json
import re
class OutputValidator:
"""验证和解析模型输出。"""
@staticmethod
def extract_json(output: str) -> dict:
"""从输出中提取和解析JSON。"""
# 尝试在代码块中查找JSON
json_match = re.search(r'```json\s*(.*?)\s*```', output, re.DOTALL)
if json_match:
return json.loads(json_match.group(1))
# 尝试在没有代码块的情况下查找JSON
try:
return json.loads(output.strip())
except json.JSONDecodeError:
raise ValueError("输出中未找到有效JSON")
@staticmethod
def extract_code(output: str, language: str = None) -> str:
"""从markdown代码块中提取代码。"""
if language:
pattern = rf'```{language}\s*(.*?)\s*```'
else:
pattern = r'```\s*(.*?)\s*```'
match = re.search(pattern, output, re.DOTALL)
if match:
return match.group(1).strip()
raise ValueError("输出中未找到代码块")
@staticmethod
def extract_table(output: str) -> list:
"""从markdown表格中提取表格数据。"""
lines = output.strip().split('
')
table = []
for line in lines:
if '|' in line and not line.strip().startswith('|---'):
cells = [cell.strip() for cell in line.split('|')[1:-1]]
if cells:
table.append(cells)
return table
@staticmethod
def validate_format(output: str, expected_format: str) -> bool:
"""验证输出是否匹配期望格式。"""
if expected_format == "json":
try:
json.loads(output)
return True
except json.JSONDecodeError:
return False
elif expected_format == "code":
return "```" in output
elif expected_format == "list":
return bool(re.match(r'^\s*\d+\.', output))
return False
# 使用示例
output = """
```json
{
"name": "John Smith",
"email": "john@example.com",
"phone": "555-123-4567"
}
“”"
validator = OutputValidator() data = validator.extract_json(output) print(data)
---
## 7. 约束与控制
### 7.1 设置边界
```python
"""
约束:明确设置模型应做和不应做的边界。
"""
# 长度约束
LENGTH_CONSTRAINTS = """
在恰好3个句子中总结文章。
每个句子不应超过20个词。
文章:
[长文章文本]
总结:
"""
# 内容约束
CONTENT_CONSTRAINTS = """
向12岁孩子解释量子计算。
约束:
- 不使用技术术语
- 使用简单类比
- 保持不超过200词
- 专注于概念,而非数学
解释:
"""
# 格式约束
FORMAT_CONSTRAINTS = """
创建具有这些约束的产品描述:
- 必须包括恰好3个项目符号
- 每个项目符号必须以动词开头
- 总长度必须不超过100词
- 没有感叹号
产品:无线蓝牙耳机
描述:
"""
# 负面约束(不应做什么)
NEGATIVE_CONSTRAINTS = """
建设性地批评此代码。
约束:
- 不使用严厉语言
- 不指出风格偏好
- 不建议完全重写
- 仅关注功能问题
代码:
```python
def process(data):
result = []
for item in data:
if item:
result.append(item * 2)
return result
批评: “”"
安全约束
SAFETY_CONSTRAINTS = “”" 提供关于网络安全最佳实践的信息。 约束:
- 不提供恶意活动说明
- 不建议利用漏洞
- 仅专注于防御措施
- 如果询问攻击,解释如何预防
主题:SQL注入预防
响应: “”"
### 7.2 输出控制
```python
# 温度控制(随机性)
"""
温度:控制模型输出中的随机性。
- 低(0.0-0.3):更确定性、聚焦
- 中(0.4-0.7):创造力与连贯性的平衡
- 高(0.8-1.0):更具创造性、多样化
"""
# Top P(核采样)
"""
Top P:控制累积概率阈值。
- 较低(0.1-0.5):更聚焦、保守
- 较高(0.6-0.9):更多样化、创造性
"""
# 最大令牌数
"""
最大令牌数:控制输出的最大长度。
- 基于期望响应长度设置
- 防止过长的响应
"""
# 停止序列
"""
停止序列:定义停止生成的字符串。
- 对结构化输出有用
- 防止模型不必要地继续
"""
# 带控制的示例
OUTPUT_CONTROLS = """
写一个关于机器人学习绘画的创意故事。
控制:
- 温度:0.8(更具创造性)
- 最大令牌数:500
- 停止序列:"THE END"
故事:
"""
8. 测试提示
8.1 提示测试框架
from typing import List, Dict, Callable
from dataclasses import dataclass
@dataclass
class PromptTest:
"""提示评估的测试用例。"""
name: str
prompt: str
expected_output_type: str
validation_fn: Callable[[str], bool]
test_inputs: List[Dict]
class PromptTester:
"""系统地测试提示。"""
def __init__(self):
self.tests = []
def add_test(self, test: PromptTest):
"""添加测试用例。"""
self.tests.append(test)
def run_test(self, test: PromptTest, model_fn: Callable) -> Dict:
"""运行单个测试。"""
results = {
"name": test.name,
"passed": 0,
"failed": 0,
"errors": []
}
for input_data in test.test_inputs:
try:
# 使用输入数据格式化提示
prompt = test.prompt.format(**input_data)
# 获取模型输出
output = model_fn(prompt)
# 验证输出
if test.validation_fn(output):
results["passed"] += 1
else:
results["failed"] += 1
results["errors"].append({
"input": input_data,
"output": output,
"reason": "验证失败"
})
except Exception as e:
results["failed"] += 1
results["errors"].append({
"input": input_data,
"error": str(e)
})
return results
def run_all_tests(self, model_fn: Callable) -> List[Dict]:
"""运行所有测试。"""
return [self.run_test(test, model_fn) for test in self.tests]
# 使用示例
def validate_json_output(output: str) -> bool:
"""验证输出是否为有效JSON。"""
try:
json.loads(output)
return True
except json.JSONDecodeError:
return False
def validate_list_output(output: str) -> bool:
"""验证输出是否为编号列表。"""
return bool(re.match(r'^\s*\d+\.', output.strip()))
# 创建测试
tester = PromptTester()
# 测试1:JSON提取
test1 = PromptTest(
name="JSON提取",
prompt="从以下文本提取姓名和电子邮件:{text}
JSON:",
expected_output_type="json",
validation_fn=validate_json_output,
test_inputs=[
{"text": "联系人:John Doe,邮箱john@example.com"},
{"text": "来自Jane Smith的电子邮件jane@test.com"}
]
)
# 测试2:列表生成
test2 = PromptTest(
name="列表生成",
prompt="列出{topic}的3个好处:",
expected_output_type="list",
validation_fn=validate_list_output,
test_inputs=[
{"topic": "锻炼"},
{"topic": "冥想"}
]
)
tester.add_test(test1)
tester.add_test(test2)
# 运行测试(模拟模型函数)
def mock_model(prompt: str) -> str:
return '{"name": "John Doe", "email": "john@example.com"}'
results = tester.run_all_tests(mock_model)
for result in results:
print(f"{result['name']}:{result['passed']} 通过,{result['failed']} 失败")
8.2 A/B测试提示
class PromptABTest:
"""A/B测试不同的提示变体。"""
def __init__(self, prompt_a: str, prompt_b: str):
self.prompt_a = prompt_a
self.prompt_b = prompt_b
self.results_a = []
self.results_b = []
def test_prompt(
self,
prompt: str,
test_cases: List[Dict],
model_fn: Callable,
evaluator: Callable
) -> List[float]:
"""针对多个用例测试提示。"""
scores = []
for test_case in test_cases:
formatted_prompt = prompt.format(**test_case)
output = model_fn(formatted_prompt)
score = evaluator(output, test_case.get("expected", {}))
scores.append(score)
return scores
def run_ab_test(
self,
test_cases: List[Dict],
model_fn: Callable,
evaluator: Callable
) -> Dict:
"""运行A/B测试。"""
scores_a = self.test_prompt(self.prompt_a, test_cases, model_fn, evaluator)
scores_b = self.test_prompt(self.prompt_b, test_cases, model_fn, evaluator)
return {
"prompt_a": {
"平均分数": sum(scores_a) / len(scores_a),
"所有分数": scores_a
},
"prompt_b": {
"平均分数": sum(scores_b) / len(scores_b),
"所有分数": scores_b
},
"胜者": "A" if sum(scores_a) > sum(scores_b) else "B"
}
# 使用示例
prompt_a = "用1句话总结以下内容:{text}"
prompt_b = "提供一句话总结:{text}"
test_cases = [
{"text": "猫坐在垫子上环顾四周。"},
{"text": "Python是数据科学的流行编程语言。"}
]
def mock_model(prompt: str) -> str:
return "一个简单的总结。"
def evaluate_summary(output: str, expected: Dict) -> float:
"""评估总结质量(0-1)。"""
# 实际上,使用更复杂的评估
return 0.8
ab_test = PromptABTest(prompt_a, prompt_b)
results = ab_test.run_ab_test(test_cases, mock_model, evaluate_summary)
print(f"胜者:{results['胜者']}")
9. 提示版本管理
9.1 版本控制
from typing import Dict, List
from datetime import datetime
class PromptVersionManager:
"""管理提示版本。"""
def __init__(self):
self.versions = {}
def save_version(
self,
prompt_id: str,
version: str,
prompt: str,
description: str = None,
tags: List[str] = None
):
"""保存提示版本。"""
if prompt_id not in self.versions:
self.versions[prompt_id] = {}
self.versions[prompt_id][version] = {
"prompt": prompt,
"description": description,
"tags": tags or [],
"created_at": datetime.now().isoformat()
}
def get_version(self, prompt_id: str, version: str) -> Dict:
"""获取特定提示版本。"""
return self.versions.get(prompt_id, {}).get(version)
def get_latest(self, prompt_id: str) -> Dict:
"""获取提示的最新版本。"""
versions = self.versions.get(prompt_id, {})
if not versions:
return None
latest_version = max(versions.keys())
return versions[latest_version]
def list_versions(self, prompt_id: str) -> List[str]:
"""列出提示的所有版本。"""
return list(self.versions.get(prompt_id, {}).keys())
def compare_versions(
self,
prompt_id: str,
version_a: str,
version_b: str
) -> Dict:
"""比较两个提示版本。"""
return {
"version_a": self.get_version(prompt_id, version_a),
"version_b": self.get_version(prompt_id, version_b)
}
# 使用示例
manager = PromptVersionManager()
manager.save_version(
"code_review",
"1.0",
"审查此代码:{code}",
description="初始版本",
tags=["v1", "initial"]
)
manager.save_version(
"code_review",
"1.1",
"审查此{language}代码的安全和性能:{code}",
description="添加了语言和关注领域",
tags=["v1", "improved"]
)
manager.save_version(
"code_review",
"2.0",
"""审查以下代码:
语言:{language}
关注:{focus_areas}
```{language}
{code}
提供具体、可操作的反馈。“”", description=“带有结构化格式的完全重新设计”, tags=[“v2”, “structured”] )
获取最新版本
latest = manager.get_latest(“code_review”) print(f"最新版本:{latest[‘description’]}")
### 9.2 提示回滚
```python
class PromptRollbackManager:
"""管理提示回滚。"""
def __init__(self, version_manager: PromptVersionManager):
self.version_manager = version_manager
self.deployment_history = {}
def deploy(self, prompt_id: str, version: str, environment: str = "production"):
"""部署提示版本。"""
if prompt_id not in self.deployment_history:
self.deployment_history[prompt_id] = {}
self.deployment_history[prompt_id][environment] = {
"version": version,
"deployed_at": datetime.now().isoformat()
}
def rollback(self, prompt_id: str, environment: str = "production") -> str:
"""回滚到先前版本。"""
history = self.deployment_history.get(prompt_id, {})
if environment not in history:
raise ValueError(f"未找到{environment}的部署")
current_version = history[environment]["version"]
version_list = self.version_manager.list_versions(prompt_id)
# 查找先前版本
current_idx = version_list.index(current_version)
if current_idx == 0:
raise ValueError("没有先前版本可回滚")
previous_version = version_list[current_idx - 1]
# 部署先前版本
self.deploy(prompt_id, previous_version, environment)
return previous_version
def get_deployed_version(self, prompt_id: str, environment: str = "production") -> str:
"""获取当前部署的版本。"""
history = self.deployment_history.get(prompt_id, {})
return history.get(environment, {}).get("version")
# 使用示例
rollback_manager = PromptRollbackManager(manager)
# 部署版本2.0
rollback_manager.deploy("code_review", "2.0", "production")
# 回滚到1.1
previous = rollback_manager.rollback("code_review", "production")
print(f"回滚到:{previous}")
10. 反模式
10.1 常见错误
"""
反模式:常见的提示工程错误需避免。
"""
# 1. 太模糊
BAD_VAGUE = """
为网站编写代码。
"""
GOOD_SPECIFIC = """
编写具有以下端点的Python Flask应用程序:
- GET /api/users - 列出所有用户
- POST /api/users - 创建新用户
- GET /api/users/<id> - 按ID获取用户
使用SQLAlchemy进行数据库操作。
"""
# 2. 太多上下文
BAD_TOO_MUCH = """
[1000行不相关文本]
基于以上,法国的首都是什么?
"""
GOOD_CONCISE = """
法国的首都是什么?
"""
# 3. 冲突指令
BAD_CONFLICTING = """
写一个简短响应。
提供详细解释。
保持不超过50词。
包括所有相关细节。
"""
GOOD_CLEAR = """
在不超过50词中提供简洁解释。
"""
# 4. 缺少示例
BAD_NO_EXAMPLES = """
将以下日期转换为ISO格式。
日期:2024年1月15日
"""
GOOD_WITH_EXAMPLES = """
将日期转换为ISO格式(YYYY-MM-DD)。
示例:2024年1月1日 → 2024-01-01
示例:2024年3月15日 → 2024-03-15
转换:2024年1月15日
"""
# 5. 假设知识
BAD_ASSUME = """
修复此代码中的错误。
```python
# [不完整代码片段]
“”"
GOOD_COMPLETE = “”" 此函数应降序排序列表但不工作。
def sort_descending(items):
return sorted(items)
问题是什么?我们如何修复? “”"
6. 无输出格式
BAD_NO_FORMAT = “”" 总结此文章。 [文章文本] “”"
GOOD_WITH_FORMAT = “”" 用3个项目符号总结文章。 每个点应不超过20词。
[文章文本]
总结: “”"
7. 过度约束
BAD_OVER_CONSTRAINT = “”" 写一个关于猫的故事。 约束:
- 必须恰好100词
- 必须使用字母表中的每个字母
- 必须包括5种不同颜色
- 必须押韵
- 必须是抑扬格五音步 “”"
GOOD_REASONABLE = “”" 写一个关于猫冒险的短故事(100-150词)。 包括至少2种颜色并使其引人入胜。 “”"
8. 无角色上下文
BAD_NO_ROLE = “”" 如何保护我的API? “”"
GOOD_WITH_ROLE = “”" 作为安全专家,解释如何保护REST API。 专注于认证、授权和常见漏洞。 “”"
9. 模糊术语
BAD_AMBIGUOUS = “”" 使其更好。 “”"
GOOD_PRECISE = “”" 通过减少时间复杂度改进代码性能。 “”"
10. 模糊提示链
BAD_CHAIN = “”" 编写代码。 使其更快。 添加错误处理。 使其安全。 “”"
GOOD_SINGLE = “”" 编写一个Python函数,:
- 处理用户ID列表
- 从API获取用户数据
- 优雅处理网络错误
- 使用缓存提高性能
- 验证输入数据 “”"
---
## 11. 模型特定提示
### 11.1 GPT模型
```python
"""
GPT特定提示:优化OpenAI GPT模型。
"""
# GPT-4优化
GPT4_TIPS = """
GPT-4最佳实践:
1. 有效使用系统消息
- 设置清晰角色和行为
- 在系统消息中指定输出格式
2. 利用GPT-4的推理
- 对复杂任务使用思维链
- 请求逐步解释
3. 结构化复杂提示
- 使用清晰部分标题
- 编号要求
- 提供示例
4. GPT-4处理长上下文良好
- 可使用更长提示(最多8K令牌)
- 适合文档分析
5. 使用函数调用以获取结构化输出
- 定义清晰函数模式
- 让GPT-4选择适当函数
"""
# GPT-3.5优化
GPT35_TIPS = """
GPT-3.5最佳实践:
1. 保持提示简洁
- GPT-3.5有4K令牌限制
- 更直接和具体
2. 使用更多示例
- GPT-3.5受益于少样本
- 提供清晰模式
3. 更简单指令
- 避免复杂推理请求
- 分解复杂任务
4. 温度更关键
- 较低温度(0.3-0.5)以保持一致性
- 较高温度(0.7-0.9)以增加创造性
5. 使用结构化输出
- 明确指定JSON格式
- 对代码使用代码块
"""
# GPT-4优化示例
GPT4_OPTIMIZED = """
您是一位高级软件架构师。
任务:为电子商务平台设计微服务架构。
要求:
1. 服务分解
2. 服务间通信
3. 数据存储策略
4. 认证和授权
5. 可扩展性考虑
输出格式:
提供结构化响应,包括:
- 架构图(ASCII艺术)
- 服务列表及职责
- 技术推荐
- 潜在挑战和缓解措施
逐步思考:
"""
# GPT-3.5优化示例
GPT35_OPTIMIZED = """
为电子商务设计微服务。
所需服务:
- 产品目录
- 订单管理
- 支付处理
- 用户账户
列出每个服务,包括:
1. 主要职责
2. 所需API
3. 数据库选择
示例格式:
产品目录:
- 职责:管理产品
- API:GET /products, POST /products
- 数据库:PostgreSQL
您的设计:
"""
11.2 Claude模型
"""
Claude特定提示:优化Anthropic Claude模型。
"""
# Claude优化
CLAUDE_TIPS = """
Claude最佳实践:
1. 使用XML风格标签
- Claude对<tags>响应良好
- 用于结构和强调
2. 更对话化
- Claude比GPT更对话化
- 可使用自然语言指令
3. 利用Claude的长上下文
- Claude支持100K+令牌
- 适合文档分析
4. 使用Claude的优势
- 擅长分析和推理
- 强于遵循复杂指令
5. Claude 3能力
- Haiku:快速、成本效益高
- Sonnet:平衡性能
- Opus:最高能力
"""
# Claude优化提示
CLAUDE_OPTIMIZED = """
<任务>
分析此文档并提取关键信息。
</任务>
<上下文>
这是两方之间的法律合同。
专注于义务、截止日期和处罚。
</上下文>
<文档>
[文档文本]
</文档>
<输出格式>
以此结构提供分析:
- 涉及方
- 关键义务
- 重要截止日期
- 潜在风险
- 建议
</输出格式>
<指令>
全面但简洁。
为清晰使用项目符号。
突出任何令人担忧的条款。
</指令>
"""
11.3 其他模型
"""
其他模型:针对各种LLM提供商的提示。
"""
# Llama模型
LLAMA_TIPS = """
Llama最佳实践:
1. Llama经过指令调整
- 使用"### Instruction:"格式
- 清晰"### Response:"分隔符
2. 适合本地部署
- 可在消费者硬件上运行
- 成本低于API模型
3. 较短上下文窗口
- 通常4K-8K令牌
- 小心管理上下文
4. 能力低于GPT-4
- 更简单任务效果更好
- 更多示例有帮助
"""
# Mistral模型
MISTRAL_TIPS = """
Mistral最佳实践:
1. 规模性能强劲
- 7B模型与更大模型竞争
- 速度与质量的良好平衡
2. 擅长代码
- 强大的编码能力
- 对开发任务有用
3. 高效推理
- 快速生成
- 较低延迟
"""
# Llama格式示例
LLAMA_FORMAT = """
### Instruction:
编写计算斐波那契数列的Python函数。
### Response:
"""
# Mistral格式示例
MISTRAL_FORMAT = """
[INST]
编写计算斐波那契数列的Python函数。
包括类型提示和文档字符串。
[/INST]
"""
12. 生产模式
12.1 提示管理系统
from typing import Dict, List, Optional
from enum import Enum
class PromptEnvironment(Enum):
"""提示环境。"""
DEVELOPMENT = "development"
STAGING = "staging"
PRODUCTION = "production"
class PromptManager:
"""生产提示管理系统。"""
def __init__(self):
self.prompts = {}
self.deployments = {}
def register_prompt(
self,
prompt_id: str,
version: str,
prompt: str,
environment: PromptEnvironment = PromptEnvironment.DEVELOPMENT,
metadata: Dict = None
):
"""注册新提示版本。"""
if prompt_id not in self.prompts:
self.prompts[prompt_id] = {}
self.prompts[prompt_id][version] = {
"prompt": prompt,
"environment": environment.value,
"metadata": metadata or {},
"created_at": datetime.now().isoformat()
}
def deploy(
self,
prompt_id: str,
version: str,
environment: PromptEnvironment = PromptEnvironment.PRODUCTION
):
"""将提示版本部署到环境。"""
if prompt_id not in self.prompts:
raise ValueError(f"未找到提示 {prompt_id}")
if version not in self.prompts[prompt_id]:
raise ValueError(f"未找到{prompt_id}的版本 {version}")
env_key = f"{prompt_id}:{environment.value}"
self.deployments[env_key] = {
"version": version,
"deployed_at": datetime.now().isoformat()
}
def get_prompt(
self,
prompt_id: str,
environment: PromptEnvironment = PromptEnvironment.PRODUCTION
) -> str:
"""获取当前部署的提示。"""
env_key = f"{prompt_id}:{environment.value}"
if env_key not in self.deployments:
raise ValueError(f"{env_key}未部署提示")
version = self.deployments[env_key]["version"]
return self.prompts[prompt_id][version]["prompt"]
def get_prompt_with_fallback(
self,
prompt_id: str,
environments: List[PromptEnvironment] = None
) -> Optional[str]:
"""带环境回退获取提示。"""
environments = environments or [
PromptEnvironment.PRODUCTION,
PromptEnvironment.STAGING,
PromptEnvironment.DEVELOPMENT
]
for env in environments:
try:
return self.get_prompt(prompt_id, env)
except ValueError:
continue
return None
def list_prompts(self) -> List[Dict]:
"""列出所有注册的提示。"""
result = []
for prompt_id, versions in self.prompts.items():
for version, data in versions.items():
result.append({
"prompt_id": prompt_id,
"version": version,
"environment": data["environment"],
"metadata": data["metadata"]
})
return result
# 使用示例
manager = PromptManager()
# 注册提示
manager.register_prompt(
"code_review",
"1.0",
"审查此代码:{code}",
PromptEnvironment.DEVELOPMENT
)
manager.register_prompt(
"code_review",
"1.1",
"审查此{language}代码:{code}",
PromptEnvironment.STAGING
)
manager.register_prompt(
"code_review",
"2.0",
"审查以下代码的安全性:{code}",
PromptEnvironment.PRODUCTION
)
# 部署到生产
manager.deploy("code_review", "2.0", PromptEnvironment.PRODUCTION)
# 获取生产提示
prompt = manager.get_prompt("code_review", PromptEnvironment.PRODUCTION)
print(prompt)
12.2 提示监控
from typing import Dict, List
from dataclasses import dataclass
from datetime import datetime, timedelta
@dataclass
class PromptMetrics:
"""提示性能指标。"""
prompt_id: str
version: str
total_calls: int
total_tokens: int
avg_latency_ms: float
error_rate: float
satisfaction_score: float
class PromptMonitor:
"""监控生产中的提示性能。"""
def __init__(self):
self.metrics = {}
self.call_history = []
def record_call(
self,
prompt_id: str,
version: str,
tokens: int,
latency_ms: float,
success: bool,
satisfaction: float = None
):
"""记录提示调用。"""
key = f"{prompt_id}:{version}"
if key not in self.metrics:
self.metrics[key] = {
"prompt_id": prompt_id,
"version": version,
"total_calls": 0,
"total_tokens": 0,
"total_latency": 0,
"errors": 0,
"satisfaction_scores": []
}
metrics = self.metrics[key]
metrics["total_calls"] += 1
metrics["total_tokens"] += tokens
metrics["total_latency"] += latency_ms
if not success:
metrics["errors"] += 1
if satisfaction is not None:
metrics["satisfaction_scores"].append(satisfaction)
self.call_history.append({
"prompt_id": prompt_id,
"version": version,
"tokens": tokens,
"latency_ms": latency_ms,
"success": success,
"timestamp": datetime.now().isoformat()
})
def get_metrics(
self,
prompt_id: str,
version: str = None,
time_window: timedelta = None
) -> PromptMetrics:
"""获取提示的指标。"""
if version:
key = f"{prompt_id}:{version}"
if key not in self.metrics:
return None
metrics_data = [self.metrics[key]]
else:
# 聚合所有版本
metrics_data = [
self.metrics[k] for k in self.metrics
if k.startswith(f"{prompt_id}:")
]
if not metrics_data:
return None
# 聚合指标
total_calls = sum(m["total_calls"] for m in metrics_data)
total_tokens = sum(m["total_tokens"] for m in metrics_data)
total_latency = sum(m["total_latency"] for m in metrics_data)
total_errors = sum(m["errors"] for m in metrics_data)
all_scores = []
for m in metrics_data:
all_scores.extend(m["satisfaction_scores"])
return PromptMetrics(
prompt_id=prompt_id,
version=version or "all",
total_calls=total_calls,
total_tokens=total_tokens,
avg_latency_ms=total_latency / total_calls if total_calls else 0,
error_rate=total_errors / total_calls if total_calls else 0,
satisfaction_score=sum(all_scores) / len(all_scores) if all_scores else 0
)
def get_anomalies(self, threshold: float = 2.0) -> List[Dict]:
"""检测提示性能中的异常。"""
anomalies = []
for key, metrics in self.metrics.items():
if metrics["total_calls"] < 10:
continue
avg_latency = metrics["total_latency"] / metrics["total_calls"]
error_rate = metrics["errors"] / metrics["total_calls"]
# 检查高延迟
if avg_latency > 5000: # 5秒
anomalies.append({
"type": "高延迟",
"prompt_id": metrics["prompt_id"],
"version": metrics["version"],
"value": avg_latency
})
# 检查高错误率
if error_rate > 0.1: # 10%
anomalies.append({
"type": "高错误率",
"prompt_id": metrics["prompt_id"],
"version": metrics["version"],
"value": error_rate
})
return anomalies
# 使用示例
monitor = PromptMonitor()
# 记录一些调用
monitor.record_call("code_review", "1.0", 100, 500, True, 0.8)
monitor.record_call("code_review", "1.0", 150, 600, True, 0.9)
monitor.record_call("code_review", "1.0", 120, 400, False, 0.5)
# 获取指标
metrics = monitor.get_metrics("code_review", "1.0")
print(f"平均延迟:{metrics.avg_latency_ms:.2f}毫秒")
print(f"错误率:{metrics.error_rate:.2%}")
print(f"满意度:{metrics.satisfaction_score:.2f}")
# 检查异常
anomalies = monitor.get_anomalies()
for anomaly in anomalies:
print(f"异常:{anomaly}")
相关技能
06-ai-ml-production/llm-integration06-ai-ml-production/llm-function-calling06-ai-ml-production/llm-guardrails06-ai-ml-production/agent-patterns06-ai-ml-production/embedding-models