Prompt 调优策略

本节目标:掌握系统化的 Prompt 调优方法,学会通过迭代优化来提升 Agent 表现。


Prompt 调优的核心思路

Prompt 调优就像调收音机——不是随便转旋钮,而是有方法地微调,直到信号清晰。核心流程是:

  1. 明确问题:Agent 在哪些任务上表现不好?
  2. 分析原因:是指令不清?上下文不够?还是格式有误?
  3. 有针对性地修改:调整 Prompt 的特定部分
  4. 对比评估:用基准测试验证是否有改善

Prompt调优迭代闭环


策略一:系统提示词优化

系统提示词(System Prompt)是 Agent 的"行为准则",对其表现影响巨大:

# ❌ 不好的系统提示词
bad_system_prompt = "你是一个助手,请帮助用户。"

# ✅ 优化后的系统提示词
good_system_prompt = """你是一名专业的 Python 技术顾问,拥有 10 年开发经验。

## 你的职责
- 回答 Python 相关的技术问题
- 提供代码示例和最佳实践建议
- 帮助调试代码问题

## 回答要求
1. **准确性优先**:不确定的内容请明确说明,不要编造
2. **代码可运行**:所有代码示例必须是可以直接运行的完整代码
3. **解释清楚**:对关键概念和代码逻辑进行解释
4. **版本明确**:涉及库或工具时,标注适用的版本号

## 回答格式
- 先用 1-2 句话直接回答问题
- 然后提供代码示例(如果适用)
- 最后补充注意事项或最佳实践

## 限制
- 只回答 Python 相关问题,其他语言请建议用户咨询专业人士
- 不要提供可能存在安全风险的代码(如 eval 用户输入)
- 回答长度控制在 500 字以内,除非问题确实需要更长的解释
"""

系统提示词的关键要素

SYSTEM_PROMPT_TEMPLATE = """
# 角色定义
你是{role_name},{role_description}。

# 核心能力
{capabilities}

# 行为准则
{behavioral_rules}

# 输出格式
{output_format}

# 限制与边界
{constraints}

# 示例(可选)
{examples}
"""

每个要素的作用:

要素作用缺失时的影响
角色定义设定 Agent 的身份和专业背景回答缺乏专业性
核心能力明确 Agent 能做什么可能超范围回答
行为准则规范回答的方式输出质量不稳定
输出格式统一回答的结构格式混乱,不便解析
限制与边界约束 Agent 不该做什么可能产生不安全的输出

策略二:Few-shot 示例优化

好的示例能显著提升 Agent 的表现:

def build_few_shot_prompt(
    task: str,
    examples: list[dict],
    user_input: str
) -> str:
    """构建 Few-shot 提示"""
    
    prompt = f"任务:{task}\n\n"
    prompt += "以下是一些示例:\n\n"
    
    for i, ex in enumerate(examples, 1):
        prompt += f"--- 示例 {i} ---\n"
        prompt += f"输入:{ex['input']}\n"
        prompt += f"输出:{ex['output']}\n"
        if "explanation" in ex:
            prompt += f"说明:{ex['explanation']}\n"
        prompt += "\n"
    
    prompt += "--- 你的任务 ---\n"
    prompt += f"输入:{user_input}\n"
    prompt += "输出:"
    
    return prompt

# 示例选择的技巧
few_shot_tips = {
    "数量": "通常 3-5 个示例效果最佳,过多反而会增加噪音",
    "多样性": "示例要覆盖不同的情况(简单/复杂/边界情况)",
    "顺序": "把最相关的示例放在最后(靠近用户输入)",
    "格式一致": "所有示例的输入输出格式要统一",
    "动态选择": "根据用户输入,动态选择最相关的示例"
}

动态示例选择

根据用户输入自动选择最相关的示例:

from langchain_openai import OpenAIEmbeddings
import numpy as np

class DynamicExampleSelector:
    """基于语义相似度动态选择示例"""
    
    def __init__(self, examples: list[dict], k: int = 3):
        self.examples = examples
        self.k = k
        self.embeddings = OpenAIEmbeddings()
        
        # 预计算所有示例的 embedding
        self.example_vectors = self.embeddings.embed_documents(
            [ex["input"] for ex in examples]
        )
    
    def select(self, query: str) -> list[dict]:
        """选择与查询最相关的 k 个示例"""
        query_vector = self.embeddings.embed_query(query)
        
        # 计算余弦相似度
        similarities = [
            np.dot(query_vector, ev) / (
                np.linalg.norm(query_vector) * np.linalg.norm(ev)
            )
            for ev in self.example_vectors
        ]
        
        # 选择 top-k
        top_indices = np.argsort(similarities)[-self.k:][::-1]
        return [self.examples[i] for i in top_indices]

策略三:A/B 测试框架

像互联网产品一样,对 Prompt 做 A/B 测试:

import random

class PromptABTest:
    """Prompt A/B 测试框架"""
    
    def __init__(self, prompts: dict[str, str], test_cases: list[dict]):
        """
        Args:
            prompts: {"A": prompt_a, "B": prompt_b, ...}
            test_cases: [{"input": "...", "expected": "..."}, ...]
        """
        self.prompts = prompts
        self.test_cases = test_cases
        self.results = {name: [] for name in prompts}
    
    def run(self, llm, judge_llm=None) -> dict:
        """运行 A/B 测试"""
        
        for case in self.test_cases:
            for name, prompt in self.prompts.items():
                # 拼接完整提示
                full_prompt = f"{prompt}\n\n用户问题:{case['input']}"
                
                # 获取回答
                response = llm.invoke(full_prompt)
                
                # 评估(如果有评审 LLM)
                score = self._evaluate(
                    case, response.content, judge_llm
                )
                
                self.results[name].append({
                    "input": case["input"],
                    "output": response.content,
                    "score": score
                })
        
        # 汇总结果
        summary = {}
        for name, results in self.results.items():
            scores = [r["score"] for r in results if r["score"] is not None]
            summary[name] = {
                "avg_score": sum(scores) / len(scores) if scores else 0,
                "total_cases": len(results),
                "scored_cases": len(scores)
            }
        
        return summary
    
    def _evaluate(self, case, response, judge_llm) -> float:
        """评估单个回答"""
        if judge_llm is None:
            return None
        
        eval_prompt = f"""对比以下回答和预期答案,给出 1-10 的评分。

问题:{case['input']}
预期:{case['expected']}
实际回答:{response}

只回复一个数字(1-10)。"""
        
        result = judge_llm.invoke(eval_prompt)
        try:
            return float(result.content.strip()) / 10
        except ValueError:
            return None

策略四:常见 Prompt 问题排查清单

当 Agent 表现不佳时,按这个清单逐一排查:

PROMPT_DEBUGGING_CHECKLIST = [
    {
        "问题": "Agent 回答太笼统、没有深度",
        "可能原因": "指令不够具体",
        "修复方法": "添加具体的角色背景和专业领域描述",
        "示例": "❌ '回答问题' → ✅ '作为有 10 年经验的后端工程师,提供带代码示例的详细解答'"
    },
    {
        "问题": "Agent 不使用工具,直接编造答案",
        "可能原因": "没有明确要求使用工具",
        "修复方法": "在系统提示中强调:'如果需要查询数据,必须使用对应的工具,不要猜测'",
        "示例": "添加规则:'任何需要实时数据的问题,都必须先使用搜索工具查询'"
    },
    {
        "问题": "Agent 输出格式不一致",
        "可能原因": "缺少明确的格式要求",
        "修复方法": "提供详细的输出格式模板和示例",
        "示例": "指定 JSON Schema 或 Markdown 模板"
    },
    {
        "问题": "Agent 重复调用同一个工具",
        "可能原因": "缺少终止条件或步骤限制",
        "修复方法": "添加最大步骤限制和终止条件说明",
        "示例": "'最多执行 5 步,如果仍未解决问题,请总结当前进展并请求用户帮助'"
    },
    {
        "问题": "Agent 回答中有明显的事实错误",
        "可能原因": "模型幻觉,或使用了过时知识",
        "修复方法": "要求 Agent 标注信息来源,并添加 '不确定时明确说明' 的规则",
        "示例": "'回答时请标注信息来源。如果你不确定某个事实,请说 \"我不确定,建议您查证\"'"
    }
]

实操案例:迭代优化一个客服 Agent

# 第 1 版 —— 基础版(问题:回答太简短,缺乏同理心)
v1_prompt = "你是客服,请回答用户问题。"

# 第 2 版 —— 添加角色细节(改善:更专业,但还是不够温暖)
v2_prompt = """你是"小慧",一名专业的客户服务代表。
你需要准确回答用户关于产品和订单的问题。"""

# 第 3 版 —— 添加行为准则(改善:更有同理心,但格式不统一)
v3_prompt = """你是"小慧",一名有 3 年经验的客户服务代表。

## 行为准则
1. 始终以友好、耐心的态度回应
2. 先表达对客户处境的理解,再提供解决方案
3. 如果问题超出你的能力范围,指引客户联系人工客服
4. 不确定的信息不要编造,承诺稍后确认"""

# 第 4 版 —— 添加格式规范和示例(当前最优版本)
v4_prompt = """你是"小慧",一名有 3 年经验的客户服务代表。

## 行为准则
1. 始终以友好、耐心的态度回应
2. 先表达理解(1句),再提供方案(要点清晰)
3. 超范围问题 → 指引人工客服
4. 不确定 → 承诺稍后确认

## 回答格式
[理解客户] → [具体方案] → [后续跟进]

## 示例
客户:我的订单三天了还没发货
小慧:完全理解您的着急,三天确实等得比较久了。我帮您查一下订单状态...
  1. 订单 #xxx 目前在仓库拣货中
  2. 预计明天发货,正常 2-3 天送达
  3. 我会持续跟进,有更新第一时间通知您
  如果有其他问题,随时联系我 😊
"""

每个版本的评估分数变化:

版本准确率满意度改进点
v10.652.1/5基线
v20.783.0/5+角色定义
v30.803.8/5+行为准则
v40.854.3/5+格式+示例

小结

策略核心要点效果
系统提示词优化角色+能力+准则+格式+限制全面提升
Few-shot 优化3-5 个多样化示例,动态选择显著提升一致性
A/B 测试数据驱动,用评分说话科学决策
问题排查清单对症下药,逐一排查快速定位问题

下一节预告:除了 Prompt 调优,成本控制也是生产环境中必须面对的问题。


下一节:16.4 成本控制与性能优化 →