🧠AI Prompt 与上下文

Prompt调试与迭代

难度:⭐ | 高频指数:🔥🔥🔥 | 应用岗相关度:★★★

面试回答

常见问法

  • “Prompt 不好使的时候你怎么调?”
  • “你有没有系统化的 Prompt 调试方法?”
  • “怎么做 Prompt 的版本管理和 A/B 测试?“

回答

Prompt 调试不是瞎试,而是有系统方法的。核心思路是:先诊断问题类型,再针对性调整,最后用评测验证效果

# Prompt调试系统化框架
class PromptDebugger:
    """
    Prompt调试四步法:
    1. 诊断问题类型
    2. 定位原因
    3. 针对性修改
    4. 评测验证
    """
    
    def __init__(self, llm_client, eval_dataset):
        self.llm = llm_client
        self.eval_dataset = eval_dataset
        self.prompt_versions = []
    
    def diagnose(self, prompt, bad_outputs):
        """
        诊断Prompt问题类型
        
        常见问题分类:
        - 输出不稳定:同一输入多次输出差异大
        - 格式不对:不按要求的格式输出
        - 幻觉:编造不存在的信息
        - 拒绝回答:该回答的不回答
        - 答非所问:回答和问题不相关
        - 信息遗漏:回答不完整
        """
        issues = []
        
        for output in bad_outputs:
            # 检查格式问题
            if not self.check_format(output):
                issues.append({
                    'type': 'format_error',
                    'description': '输出格式不符合要求',
                    'example': output[:200]
                })
            
            # 检查幻觉
            if self.detect_hallucination(output):
                issues.append({
                    'type': 'hallucination',
                    'description': '包含编造的信息',
                    'example': output[:200]
                })
            
            # 检查拒绝回答
            if self.detect_refusal(output):
                issues.append({
                    'type': 'refusal',
                    'description': '不必要的拒绝回答',
                    'example': output[:200]
                })
            
            # 检查答非所问
            if self.detect_irrelevant(output):
                issues.append({
                    'type': 'irrelevant',
                    'description': '回答与问题不相关',
                    'example': output[:200]
                })
        
        return {
            'issues': issues,
            'primary_issue': self.identify_primary_issue(issues),
            'suggested_fixes': self.suggest_fixes(issues)
        }
    
    def suggest_fixes(self, issues):
        """根据问题类型建议修复方案"""
        fixes = {
            'format_error': [
                "添加明确的输出格式示例",
                "使用 JSON schema 约束",
                "在 prompt 末尾重复格式要求",
            ],
            'hallucination': [
                "添加'如果不确定请说不知道'的约束",
                "要求标注信息来源",
                "降低 temperature 参数",
            ],
            'refusal': [
                "放宽安全约束的措辞",
                "明确说明这是合法的使用场景",
                "调整 system prompt 的角色定义",
            ],
            'irrelevant': [
                "在 prompt 开头强调任务目标",
                "添加 CoT(思维链)引导",
                "拆分复杂 prompt 为多步",
            ],
            'unstable': [
                "降低 temperature(0.1-0.3)",
                "添加更多约束条件",
                "使用 few-shot 示例固定输出模式",
            ],
            'incomplete': [
                "明确列出需要包含的要素",
                "使用 checklist 格式要求",
                "添加'请确保覆盖以下方面'的提示",
            ]
        }
        
        suggested = []
        for issue in issues:
            issue_type = issue['type']
            if issue_type in fixes:
                suggested.extend(fixes[issue_type])
        
        return list(set(suggested))  # 去重


# 常见问题的调试技巧
class PromptFixStrategies:
    """针对不同问题的修复策略"""
    
    def fix_unstable_output(self, original_prompt):
        """修复输出不稳定"""
        fixes = [
            # 1. 降低温度
            {"param": "temperature", "value": 0.1},
            
            # 2. 添加格式约束
            {"action": "append", "content": "\n\n请严格按照以下格式输出,不要添加额外内容:"},
            
            # 3. 添加 few-shot
            {"action": "add_examples", "count": 3},
        ]
        return fixes
    
    def fix_format_error(self, original_prompt):
        """修复格式问题"""
        # 策略:在prompt末尾重复格式要求 + 给出正反例
        improved = original_prompt + """

## 输出格式(重要!)
必须输出合法的JSON,格式如下:
```json
{
    "field1": "value1",
    "field2": "value2"
}

错误示例(不要这样输出):

  • 不要在JSON前后加解释文字

  • 不要使用markdown代码块以外的格式

  • 不要省略必需字段 """ return improved

    def fix_hallucination(self, original_prompt): """修复幻觉问题""" # 策略:添加约束 + 要求引用 constraint = """

重要约束

  1. 只基于提供的资料回答,不要编造信息

  2. 如果资料中没有相关信息,请明确说”根据提供的资料无法回答”

  3. 每个事实陈述都要标注来源编号

  4. 不确定的信息用”可能”、“大约”等词修饰 """ return original_prompt + constraint

    def fix_with_cot(self, original_prompt): """添加思维链(CoT)""" cot_instruction = """

请按以下步骤思考:

  1. 首先理解问题的核心是什么
  2. 然后从提供的信息中找到相关内容
  3. 最后组织答案

让我们一步步来: """ return original_prompt + cot_instruction

def split_complex_prompt(self, complex_prompt):
    """拆分复杂Prompt为多步"""
    # 复杂任务拆成多个简单步骤
    steps = [
        {
            'step': 1,
            'prompt': "从以下文本中提取所有关键实体(人名、地名、组织名)",
            'output_format': "JSON列表"
        },
        {
            'step': 2,
            'prompt': "基于提取的实体,分析它们之间的关系",
            'input': "上一步的输出",
            'output_format': "关系三元组"
        },
        {
            'step': 3,
            'prompt': "基于实体和关系,生成结构化摘要",
            'input': "前两步的输出",
            'output_format': "结构化报告"
        }
    ]
    return steps

### 追问

**怎么做 Prompt 的 A/B 测试?**

```python
class PromptABTest:
    """Prompt A/B测试框架"""
    
    def __init__(self, eval_dataset, metrics):
        self.eval_dataset = eval_dataset
        self.metrics = metrics
    
    def run_ab_test(self, prompt_a, prompt_b, sample_size=50):
        """
        A/B测试两个Prompt版本
        
        1. 在相同数据集上运行两个版本
        2. 计算各维度指标
        3. 统计显著性检验
        4. 给出结论
        """
        results_a = []
        results_b = []
        
        # 随机选择测试样本
        test_samples = random.sample(self.eval_dataset, sample_size)
        
        for sample in test_samples:
            # 版本A
            output_a = self.run_prompt(prompt_a, sample['input'])
            score_a = self.evaluate(output_a, sample['expected'])
            results_a.append(score_a)
            
            # 版本B
            output_b = self.run_prompt(prompt_b, sample['input'])
            score_b = self.evaluate(output_b, sample['expected'])
            results_b.append(score_b)
        
        # 统计分析
        comparison = self.compare_results(results_a, results_b)
        
        return {
            'prompt_a_avg': sum(results_a) / len(results_a),
            'prompt_b_avg': sum(results_b) / len(results_b),
            'winner': 'A' if comparison['a_better'] else 'B',
            'confidence': comparison['confidence'],
            'significant': comparison['confidence'] > 0.95,
            'details': comparison
        }
    
    def compare_results(self, results_a, results_b):
        """统计比较"""
        import numpy as np
        
        a_mean = np.mean(results_a)
        b_mean = np.mean(results_b)
        
        # 简单的t检验
        from scipy import stats
        t_stat, p_value = stats.ttest_ind(results_a, results_b)
        
        return {
            'a_better': a_mean > b_mean,
            'difference': abs(a_mean - b_mean),
            'confidence': 1 - p_value,
            'a_mean': a_mean,
            'b_mean': b_mean
        }

原理展开

Prompt 版本管理

class PromptVersionManager:
    """
    Prompt版本管理
    
    记录每个版本的:
    - Prompt内容
    - 修改原因
    - 评测结果
    - 适用场景
    """
    
    def __init__(self, storage_path):
        self.storage_path = storage_path
        self.versions = []
    
    def save_version(self, prompt_content, metadata):
        """保存新版本"""
        version = {
            'version': f"v{len(self.versions) + 1}",
            'content': prompt_content,
            'created_at': time.time(),
            'author': metadata.get('author', 'unknown'),
            'change_reason': metadata.get('reason', ''),
            'eval_results': metadata.get('eval_results', {}),
            'notes': metadata.get('notes', ''),
            'status': 'draft'  # draft / active / deprecated
        }
        
        self.versions.append(version)
        return version['version']
    
    def compare_versions(self, version_a, version_b):
        """对比两个版本"""
        va = self.get_version(version_a)
        vb = self.get_version(version_b)
        
        return {
            'content_diff': self.diff_content(va['content'], vb['content']),
            'eval_comparison': self.compare_evals(
                va['eval_results'], vb['eval_results']
            ),
            'recommendation': self.recommend(va, vb)
        }
    
    def get_changelog(self):
        """获取变更日志"""
        changelog = []
        for v in self.versions:
            changelog.append({
                'version': v['version'],
                'date': v['created_at'],
                'reason': v['change_reason'],
                'accuracy': v['eval_results'].get('accuracy', 'N/A'),
                'status': v['status']
            })
        return changelog


# 实际案例:一个Prompt从v1到v5的迭代过程
PROMPT_ITERATION_EXAMPLE = """
=== 任务:从用户反馈中提取情感和关键问题 ===

--- v1(初版,问题:输出不稳定,格式混乱)---
"分析以下用户反馈,提取情感和问题。"

问题诊断:太模糊,没有格式约束

--- v2(加格式约束,问题:有时还是不输出JSON)---
"分析以下用户反馈,提取情感和问题。输出JSON格式。"

问题诊断:格式要求不够具体

--- v3(加schema和示例,问题:幻觉,编造不存在的问题)---
"分析以下用户反馈,提取情感和关键问题。

输出格式:
{
    "sentiment": "positive/negative/neutral",
    "issues": ["问题1", "问题2"],
    "severity": "high/medium/low"
}

示例:
输入:'这个产品太难用了,按钮找不到'
输出:{"sentiment": "negative", "issues": ["界面不友好", "按钮难找"], "severity": "medium"}"

问题诊断:模型会编造反馈中没提到的问题

--- v4(加约束防幻觉,问题:部分边界case处理不好)---
"分析以下用户反馈,提取情感和关键问题。

重要:只提取反馈中明确提到的问题,不要推测或编造。
如果反馈内容不清晰,issues字段返回空数组。

输出格式:
{
    "sentiment": "positive/negative/neutral",
    "issues": ["只写反馈中明确提到的问题"],
    "severity": "high/medium/low"
}

示例:..."

问题诊断:空反馈和多语言混合时处理不好

--- v5(最终版,加边界处理)---
"你是一个用户反馈分析助手。

任务:从用户反馈中提取情感倾向和具体问题。

规则:
1. sentiment只能是 positive/negative/neutral 之一
2. issues只写反馈中明确提到的问题,不推测
3. 如果反馈为空或无法理解,返回 {"sentiment": "neutral", "issues": [], "severity": "low"}
4. 如果反馈包含多个问题,按严重程度排序

输出格式:
{
    "sentiment": "positive/negative/neutral",
    "issues": ["问题1", "问题2"],
    "severity": "high/medium/low"
}

示例1(负面):
输入:'登录总是失败,试了三次都不行'
输出:{"sentiment": "negative", "issues": ["登录失败"], "severity": "high"}

示例2(正面):
输入:'新版本速度快了很多,赞'
输出:{"sentiment": "positive", "issues": [], "severity": "low"}

示例3(模糊):
输入:'还行吧'
输出:{"sentiment": "neutral", "issues": [], "severity": "low"}

现在分析以下反馈:
{user_feedback}"

评测结果:准确率从v1的62%提升到v5的91%
"""

调试流程总结

# 系统化调试流程
DEBUG_WORKFLOW = {
    "step1_reproduce": {
        "description": "复现问题",
        "actions": [
            "收集bad case(至少5-10个)",
            "分类问题类型",
            "确认是Prompt问题还是其他环节问题"
        ]
    },
    "step2_diagnose": {
        "description": "诊断根因",
        "actions": [
            "是格式问题?→ 加格式约束和示例",
            "是幻觉?→ 加事实约束和引用要求",
            "是不稳定?→ 降温度、加few-shot",
            "是答非所问?→ 加CoT、拆分prompt",
            "是拒绝回答?→ 调整角色定义和约束措辞"
        ]
    },
    "step3_fix": {
        "description": "针对性修改",
        "actions": [
            "每次只改一个变量",
            "保留旧版本做对比",
            "先在bad case上验证"
        ]
    },
    "step4_validate": {
        "description": "评测验证",
        "actions": [
            "在完整评测集上跑",
            "确认bad case修复了",
            "确认没有引入新问题(回归)",
            "记录版本和结果"
        ]
    }
}

易错点

  • 没有系统方法,靠直觉瞎改 Prompt
  • 每次改多个变量,无法判断哪个改动有效
  • 只在 bad case 上验证,不做全量回归
  • 不记录版本,改来改去回不到之前的好版本
  • 把所有问题都归结为 Prompt 问题(可能是检索或数据问题)

记忆技巧

记住 Prompt 调试的”四步法 + 五类问题”:

四步法: 复现 → 诊断 → 修改 → 验证

五类常见问题及对策:

  1. 输出不稳定 → 降温度 + few-shot
  2. 格式不对 → 加 schema + 正反例
  3. 幻觉 → 加约束 + 要求引用
  4. 答非所问 → 加 CoT + 拆分
  5. 拒绝回答 → 调角色定义

面试速答版

  • Prompt 调试不是瞎试,系统方法是:复现问题 → 诊断类型 → 针对性修改 → 评测验证
  • 五类常见问题:不稳定(降温度)、格式错(加schema)、幻觉(加约束)、答非所问(加CoT)、拒绝(调角色)
  • 关键原则:每次只改一个变量,保留旧版本做对比,在完整评测集上回归
  • A/B 测试方法:相同数据集跑两个版本,统计显著性检验后再决定上线
  • 版本管理:记录每个版本的内容、修改原因、评测结果,能随时回滚
  • 常见坑:靠直觉改、改多个变量、只看 bad case 不做回归、不记录版本
  • 一句话最佳实践:先确认是不是 Prompt 的问题,再系统化调试,用数据说话
Related · Prompt 与上下文