跳转至

附录 E:提示词常见反模式与排错指南

在长期的提示词工程实践中,开发者们总结出了一些普遍存在的“错误做法”。我们称之为 反模式。使用反模式虽然也能让大模型输出结果,但往往会带来不稳定性、冗余或过高的成本。

本附录总结了最常见的 8 种提示词反模式,并给出了推荐的修正方案。


E.1 冗余与过度限定

反模式:在提示词中堆砌大量毫无必要的背景故事、同义词重复、或冗长的礼貌用语。

[反模式示例]
你好,亲爱的人工智能助手。我今天遇到了一点小麻烦,希望你能帮我。请你务必、一定、千万要记住,扮演一个非常有礼貌、非常专业的程序员。你知道吗,这对我特别重要,因为我要把这段代码展示给老板看……请写一个 Python 函数反转字符串。

后果:消耗额外的 Token,分散模型的注意力,并且可能触发模型在回复结尾额外加入一大段不需要的寒暄环节。

正确做法:直接切入正题,保持信息高密度。

[修正示例]
你是一个高级 Python 工程师。请写一个时间复杂度为 O(n) 的字符串反转函数。不要输出问候语和解释。

E.2 负向指令优先

反模式:花费大量篇幅告诉模型“不要做什么”,而不是“你该做什么”。

[反模式示例]
不要用第一人称,不要用长句子,不要带有感情色彩,绝对不要输出任何 markdown 格式的标题,不要写总结词。现在帮我写一份会议记录。

后果:模型(特别是较弱的模型)如果看到大量自己不该做的事情的实体描述,有时反而会受该词语触发(负面启动效应),输出被禁止的内容。

正确做法:将负向约束转化为正向的、具有操作性的指南。

[修正示例]
请用第三人称、平实的语气写一份段落式会议记录。输出纯文本(禁止任何格式符号)。

E.3 单次调用的超载

反模式:试图用一个包含十几条任务指令的巨大 Prompt 来让模型一次性完成数据提取、翻译、情感分析、打分并输出 HTML 报告。

[反模式示例]
请阅读这 10 份研报。先将它们翻译成中文,然后每一份写个 200 字摘要。另外,评估它们的情感倾向并给出 1-5 分的评分。最后将这些汇总成一个带有柱状图数据的 HTML 网页。

后果:必然导致部分指令被忽视。

正确做法:使用提示词链或 Pipeline 分步处理。


E.4 强制格式的硬换行与缩进敏感

反模式:强迫模型输出基于空格对齐的 ASCII 图表,或极难书写的特定非标格式。

[反模式示例]
请输出一个树状图,每层子节点必须缩进 4 个空格,且必须用 `|-- ` 连接。如果有多行,必须对齐。

后果:几乎 100% 会触发对齐错位。

正确做法:改用工业标准(如 JSON、YAML、Mermaid,或 Markdown List),依靠下游去解析并自行渲染视觉 UI。


E.5 缺乏退路

反模式:没有为模型提供“不知道”或“数据异常”的处理选项。

[反模式示例]
提取这段文字中的人名并输出 JSON: {"person_name": "xxx"}

(如果文字是一段风景描写呢?)

后果:模型陷入幻觉,强行编造一个名字以满足 JSON 格式。

正确做法:设计显式的逃生通路。

[修正示例]
提取文字中的人名。如果未找到任何人名,返回: {"person_name": null, "reason": "未提及人物"}

E.6 在系统提示词中附带用户请求

反模式:将应该放在 user 角色中的临时任务或动态数据硬编码进入 system 角色。

后果:System 角色被污染。当未来出现多轮对话时,底层上下文无法正确刷新,逻辑会陷入死循环。

正确做法:分离数据与指令。用 System 规定系统规则与输出格式,用 User 承载当次请求的内容数据。


E.7 盲目依赖 Few-Shot

反模式:未经筛选,随便找几条历史数据作为 Few-Shot 塞进提示词中。

后果:如果历史数据中包含由于人工失误造成的拼写错误、逻辑不一,模型会立刻学到这些“坏习惯”,反而比 Zero-Shot 表现得更差。另外,例子如果缺乏多样性,会导致模型严重过拟合于例子的类别。

正确做法:只有在发现模型难以理解格式或风格要求时才引入 Few-Shot。仔细挑选最具代表性、最高质量的“金标准”示例。


E.8 上下文污染与无差别检索

反模式:为模型提供与问题完全不相关,或者内容过于庞杂以至于淹没核心问题的参考资料,例如在使用 RAG(检索增强生成)时进行文档无脑拼接而缺乏过滤与重排策略。

后果:模型的注意力会被大量无关内容分散(容易触发 “Lost in the Middle” 遗忘现象),或被无关信息误导产生幻觉,强行建立不存在的逻辑关联。此外还会浪费大量 Token。

正确做法:精细化检索结果(使用重排策略过滤低相关段落)。同时增强提示词的防御性,例如明确声明:“如果给定的参考资料不足以回答问题,请直接回答'资料不全',禁止尝试强行关联上下文。”


小结

避免这些反模式的核心在于一句话:将模型视为一个极度聪明但记忆力只有几秒钟,且非常容易受暗示的新员工。提供清晰、结构化、分步骤的操作手册,永远好过一纸天马行空的需求单。

附录 E(扩展):提示词反模式的深度分析

在基础的反模式介绍(附录 E)之后,本补充章节提供更深层的原理分析和自查清单,帮助你在设计提示词时及早发现和避免这些问题。


E.1 反模式为什么会发生?

根本原因分析

原因 1:对模型能力的误解

反模式:假设模型能够"自己理解"复杂意图
症状:"给我写个游戏"→ 模型返回的不是用户期望的游戏

为什么发生:
- 开发者认为"游戏"是明确的概念
- 但模型不知道用户想要 2D 还是 3D、什么游戏风格等
- 模型会猜测最常见的情况(比如文本冒险游戏)

正确认识:
模型不能读心。它只能根据给定的信息生成概率最高的文本。

原因 2:认知负荷过重

反模式:在一个提示词中堆砌 10+ 条指令
症状:模型遗漏了某些指令,或输出混乱

为什么发生:
- 提示词设计者在急于完成任务
- 没有时间逐步测试和优化
- 试图用一个"万能"提示词解决所有问题

认知科学的启示:
人类短期记忆容量约 7±2 个元素。模型也有类似的限制。
超过这个限制,后续信息会被忽视或优先级降低。

原因 3:缺乏迭代测试

反模式:一次性设计提示词,无测试就投入生产
症状:上线后才发现有大量失败案例

为什么发生:
- 时间压力
- 对测试的重要性认识不足
- 没有建立标准的评估流程

教训:
提示词就像代码,需要测试。仅有好的意图是不够的。

E.2 八大反模式的深度剖析

反模式 1:冗余与过度限定

原理分析

问题症状:
❌ "尊敬的 AI 助手,我诚心诚意地请求你...请你务必..."

后果:
1. Token 浪费:礼貌词汇占用 20-30% 的上下文
2. 注意力分散:模型的"注意力"被肤浅的措辞削弱
3. 样式学习错误:模型会学习输出冗长的回复

原理

在 Transformer 模型中,每个词都会获得一定的“注意力权重”(attention weight)。

示例:
"请你一定要,务必,千万不要忘记,必须写出..."

权重分配:
- "请" → 低权重(表客气)
- "你" → 中等权重(代词)
- "一定要/务必/千万" → 中等但重复,浪费!
- "写出" → 关键动词,但权重被前面的修饰词稀释

如果简化为:
"请写出..."

权重分配:
- "请" → 低权重
- "写出" → 高权重(关键动词立即出现)

修复方案

# 反模式检测脚本

def detect_over_prompting(prompt: str) -> dict:
    """检测过度限定问题"""

    indicators = {
        "冗余词语重复": 0,
        "过度礼貌": 0,
        "不必要的背景故事": 0,
    }

    # 检测重复的强调词
    emphasis_words = [
        "务必", "必须", "一定", "千万", "重要",
        "请", "拜托", "麻烦", "谢谢"
    ]

    for word in emphasis_words:
        count = prompt.count(word)
        if count > 1:
            indicators["冗余词语重复"] += count - 1

    # 检测长度和复杂性
    sentences = prompt.split("。")
    if len(sentences) > 3 and "但" not in prompt:
        indicators["不必要的背景故事"] += len(sentences) - 3

    # 检查是否过度礼貌
    if prompt.count("请") > 2 or prompt.count("谢谢") > 0:
        indicators["过度礼貌"] += 1

    return {
        "score": sum(indicators.values()),
        "details": indicators,
        "suggestion": "建议精简冗余词汇,直接陈述核心需求"
    }


# 使用示例

bad_prompt = """尊敬的 AI 助手,我今天遇到了一个问题,
希望你能帮我。请务必、一定、千万记住...写一个 Python 函数..."""

result = detect_over_prompting(bad_prompt)
print(f"冗余度计数: {result['score']}")
print(f"建议: {result['suggestion']}")

正确做法

✓ "写一个 Python 函数,功能是..."
✓ "按照以下要求完成任务:..."
✓ 用短句、直接动词、清晰结构

反模式 2:负向指令优先

原理分析

问题症状:
❌ "不要用第一人称,不要用长句子,不要..."

为什么失败:
研究显示,模型在看到单词"不要"后,
会激活这个单词相关的概念,导致模型实际上倾向于做这些事。

这叫"文字激活效应"(Priming Effect)

心理学解释

当我们说"不要想象一只蓝色的大象"时,
人们脑海中第一反应是什么?
→ 大象!(越不让想,越会想)

LLM 有类似的倾向:
- "不要输出 Markdown" → 模型被激活"Markdown"这个概念
- 模型开始生成 Markdown 的概率反而上升

实验验证

import json

# 实验:对比两种提示词的结果

prompts = {
    "negative_instruction": """
    不要使用 markdown 格式,不要使用 # 标题,
    不要使用 ** 加粗,不要使用列表。
    请写一个关于 Python 的简介。
    """,

    "positive_instruction": """
    用纯文本格式写一个关于 Python 的简介。
    使用段落,用行号分隔不同的要点。
    """
}

def test_formatting_compliance(prompt, llm):
    """测试格式遵循率"""
    response = llm.generate(prompt)

    has_markdown = any([
        "# " in response,
        "**" in response,
        "- " in response.split("\n")[0],
        "[" in response and "](" in response
    ])

    return {
        "prompt_type": prompt,
        "has_markdown": has_markdown,
        "response_snippet": response[:100]
    }

# 结果通常显示:

# negative_instruction: has_markdown = True (40% 概率)

# positive_instruction: has_markdown = True (5% 概率)

修复方案

class InstructionFormatter:
    """指令格式优化器"""

    @staticmethod
    def convert_negative_to_positive(instruction: str) -> str:
        """将负向指令转换为正向指令"""

        conversions = {
            "不要使用": "使用",
            "避免": "确保",
            "不能": "应该",
            "千万别": "务必",
            "绝对不要": "必须"
        }

        result = instruction
        for negative, positive in conversions.items():
            if negative in instruction:
                # 找到负向指令的具体内容
                result = result.replace(
                    f"{negative} X",
                    f"{positive} 不使用 X"
                )

        return result

    @staticmethod
    def reframe_restriction(restriction: str) -> str:
        """重新表述限制条件为正向目标"""

        examples = {
            "不要太长": "控制在 100 字以内",
            "不要不清楚": "确保表达清晰",
            "不要离题": "保持话题相关",
            "不要重复": "每个点只提一次",
        }

        for restrict, positive in examples.items():
            restriction = restriction.replace(restrict, positive)

        return restriction

# 修复前后对比

before = """不要用第一人称,不要用长句子,
不要带有感情色彩,不要输出任何 markdown"""

formatter = InstructionFormatter()
after = formatter.convert_negative_to_positive(before)

print("修复前:")
print(before)
print("\n修复后:")
print(after)

反模式 3:单次调用的超载

问题分析

症状:用一个提示词完成 10+ 个任务
❌ "请阅读这 10 份财报、翻译成中文、写摘要、评分、制作 HTML..."

为什么失败:
1. Token 限制:指令堆积,留给输出的空间减少
2. 优先级混乱:模型不知道哪个任务最重要
3. 格式冲突:多个不同格式要求可能相互干扰
4. 错误级联:第一步错误会影响后续步骤

任务复杂度分析

class TaskComplexityAnalyzer:
    """任务复杂度分析器"""

    def analyze_prompt(self, prompt: str) -> dict:
        """分析提示词的任务复杂度"""

        # 统计任务数量
        task_indicators = [
            "请",
            "然后",
            "接着",
            "随后",
            "最后",
            "同时",
            "并且"
        ]

        task_count = sum(1 for indicator in task_indicators
                        if indicator in prompt)

        # 统计格式要求数量
        format_keywords = [
            "json",
            "csv",
            "表格",
            "列表",
            "段落",
            "要点",
            "代码"
        ]

        format_count = sum(1 for keyword in format_keywords
                          if keyword in prompt)

        # 计算复杂度分数
        complexity_score = task_count + format_count * 1.5

        recommendation = self._get_recommendation(complexity_score)

        return {
            "task_count": task_count,
            "format_requirements": format_count,
            "complexity_score": complexity_score,
            "recommendation": recommendation
        }

    def _get_recommendation(self, score: float) -> str:
        if score <= 2:
            return "✓ 可以单次处理"
        elif score <= 5:
            return "⚠️ 可能需要分解"
        else:
            return "❌ 强烈建议使用提示词链"

    def suggest_decomposition(self, prompt: str) -> list:
        """建议如何分解任务"""

        # 识别任务边界
        tasks = []

        task_keywords = ["请", "然后", "接着", "最后"]
        parts = prompt.split("。")

        for i, part in enumerate(parts):
            for keyword in task_keywords:
                if keyword in part:
                    tasks.append({
                        "step": i + 1,
                        "content": part.strip(),
                        "type": self._classify_task(part)
                    })
                    break

        return tasks

    def _classify_task(self, task_text: str) -> str:
        """分类任务类型"""
        if any(w in task_text for w in ["翻译", "转换", "改写"]):
            return "转换"
        elif any(w in task_text for w in ["摘要", "总结", "概括"]):
            return "摘要"
        elif any(w in task_text for w in ["分析", "评价", "评分"]):
            return "分析"
        else:
            return "其他"


# 使用示例

analyzer = TaskComplexityAnalyzer()

god_prompt = """请阅读这 10 份财报。
然后将它们翻译成中文。
接着对每一份写个 200 字摘要。
同时评估其情感倾向并打分。
最后将这些汇总成一个带柱状图的 HTML 网页。"""

analysis = analyzer.analyze_prompt(god_prompt)
print(f"复杂度: {analysis['complexity_score']}")
print(f"建议: {analysis['recommendation']}")

decomposition = analyzer.suggest_decomposition(god_prompt)
print("\n建议的分解步骤:")
for task in decomposition:
    print(f"步骤 {task['step']} ({task['type']}): {task['content'][:50]}...")

修复方案:提示词链

# 修复:使用提示词链

class FinancialReportProcessor:
    """财务报告处理器(使用链式处理)"""

    def __init__(self, llm_client):
        self.llm = llm_client
        self.results = {}

    def process_report(self, report_text: str) -> dict:
        """处理单个报告"""

        # 步骤 1: 翻译
        translation = self._translate(report_text)
        self.results["translation"] = translation

        # 步骤 2: 摘要
        summary = self._summarize(translation)
        self.results["summary"] = summary

        # 步骤 3: 分析情感和评分
        analysis = self._analyze(summary)
        self.results["analysis"] = analysis

        return self.results

    def _translate(self, text: str) -> str:
        """单独的翻译步骤"""
        prompt = f"""请将以下财务报告翻译成中文。
保持专业术语和格式。

原文:
{text}"""

        return self.llm.generate(prompt)

    def _summarize(self, text: str) -> str:
        """单独的摘要步骤"""
        prompt = f"""请用 200 字总结以下财务报告的关键要点:

{text}"""

        return self.llm.generate(prompt)

    def _analyze(self, text: str) -> dict:
        """单独的分析步骤"""
        prompt = f"""分析以下财务报告摘要:
1. 情感倾向(正面/中立/负面)
2. 风险评级(1-5 分,5 分风险最高)

摘要:
{text}

请返回 JSON 格式:
{{"sentiment": "...", "risk_score": ...}}"""

        response = self.llm.generate(prompt)
        return json.loads(response)

    def batch_process(self, reports: list) -> dict:
        """批量处理多个报告"""
        results = {}
        for i, report in enumerate(reports):
            results[f"report_{i+1}"] = self.process_report(report)

        return results


# 使用

processor = FinancialReportProcessor(llm_client)
all_results = processor.batch_process(reports)

反模式 4-8 的自查清单

反模式 4:强制格式的硬换行与缩进敏感

自查清单:

  • 是否要求模型生成基于空格对齐的 ASCII 艺术?
  • 是否强制要求特定的缩进或特殊字符模式?
  • 替代方案:使用 JSON、YAML、Markdown 等标准格式

诊断代码:

def check_rigid_formatting(prompt: str) -> bool:
    """检测是否有过于严格的格式要求"""

    rigid_patterns = [
        r"缩进.*个空格",
        r"must.*align",
        r"空格.*对齐",
        r"固定.*格式",
    ]

    return any(re.search(p, prompt) for p in rigid_patterns)

反模式 5:缺乏退路

自查清单:

  • 是否为“不确定”或“无法处理”提供了选项?
  • 是否明确告诉模型什么时候可以说“我不知道”?
  • 是否设置了错误情况下的降级方案?

诊断代码:

def check_escape_hatch(prompt: str) -> bool:
    """检查是否提供了逃生通路"""

    escape_keywords = [
        "如果找不到",
        "如果不知道",
        "如果无法",
        "返回 null",
        "return None",
        "not found",
        "unclear"
    ]

    has_escape = any(kw in prompt for kw in escape_keywords)
    return has_escape

反模式 6-8 的通用诊断框架

class AntiPatternDiagnostics:
    """反模式诊断工具"""

    def diagnose_all(self, prompt: str) -> dict:
        """全面诊断提示词中的反模式"""

        results = {
            "over_prompting": self._check_over_prompting(prompt),
            "negative_first": self._check_negative_first(prompt),
            "god_prompt": self._check_god_prompt(prompt),
            "rigid_formatting": self._check_rigid_formatting(prompt),
            "no_escape": self._check_no_escape(prompt),
            "context_pollution": self._check_context_pollution(prompt),
        }

        # 计算总体健康分数
        results["health_score"] = self._calculate_health_score(results)
        results["recommendations"] = self._generate_recommendations(results)

        return results

    def _calculate_health_score(self, results: dict) -> float:
        """计算提示词的健康分数(0-100)"""
        issues = sum(1 for k, v in results.items()
                    if k != "health_score" and v.get("severity", 0) > 0)
        return max(0, 100 - issues * 10)

    def _generate_recommendations(self, results: dict) -> list:
        """基于诊断结果生成改进建议"""
        recommendations = []

        for issue_type, issue_data in results.items():
            if issue_type == "health_score":  # 已在上一行写入,是 float 而非诊断字典
                continue
            if issue_data.get("severity", 0) > 0:
                recommendations.append({
                    "issue": issue_type,
                    "severity": issue_data["severity"],
                    "suggestion": issue_data.get("suggestion", "")
                })

        return sorted(recommendations, key=lambda x: x["severity"], reverse=True)

    def _check_over_prompting(self, prompt: str) -> dict:
        # 实现检测逻辑;返回值必须含 severity(0 表示未命中)与 suggestion,
        # 否则 _calculate_health_score / _generate_recommendations 会在 None 上取值
        return {"severity": 0, "suggestion": ""}

    def _check_negative_first(self, prompt: str) -> dict:
        # 实现检测逻辑
        return {"severity": 0, "suggestion": ""}

    # ... 其他检测方法(_check_god_prompt、_check_rigid_formatting、
    # _check_no_escape、_check_context_pollution,返回结构同上)

E.3 提示词自查清单

快速检查表

【设计阶段】
□ 是否清晰定义了任务?
□ 是否有具体的成功标准?
□ 是否考虑了边界情况?

【指令阶段】
□ 是否避免了冗余措辞?
□ 是否用正向而非负向指令?
□ 是否字数控制在合理范围(通常 < 500 字)?
□ 是否将复杂任务分解为步骤?
□ 是否明确了输出格式?

【上下文阶段】
□ 是否只包含了相关信息?
□ 是否标记了外部数据的边界?
□ 是否移除了冗余的背景故事?
□ 是否提供了足够的示例?

【安全性阶段】
□ 是否有明确的权限限制?
□ 是否有错误处理的逃生通路?
□ 是否防护了提示词注入风险?

【测试阶段】
□ 是否在 5+ 个测试用例上运行?
□ 是否测试了边界情况?
□ 是否检查了格式一致性?
□ 是否评估了成功率?

健康度评分表

指标 优秀 良好 需改进 差
简洁度 无冗余 最少冗余 有明显冗余 严重冗余
指令清晰度 一句话清楚 需读 2 遍 需读多遍 无法理解
格式合理性 使用标准格式 格式明确 格式模糊 无格式
容错能力 有 3+ 个逃口 有 1-2 个 几乎没有 完全没有
整体评分 85+ 70-84 50-69 <50

E.4 常见反模式的修复工作坊

示例:电商 ChatBot 的反模式修复

原始(反模式集中)提示词

你好亲爱的 AI 助手!我今天遇到了个问题,希望你能帮我。
请务必、一定、千万记住:你是一个电商客服。
你不要问太多问题,不要说废话,不要输出无关内容。
用户可能会问产品、价格、发货、退货等问题。

请先问用户想了解什么,然后根据以下信息:
[100 行产品数据库内容]

然后根据用户的问题:
[用户输入]

最后给出专业的、礼貌的、简洁的、准确的回答。
务必确保回答符合我们公司的服务标准。

问题诊断

检测到的反模式:
✗ 过度措辞("亲爱的"、"务必"、"千万")
✗ 负向指令优先("不要问太多问题")
✗ 指令堆积(一个提示词承载多个角色)
✗ 冗余强调("专业的、礼貌的、简洁的、准确的"重复)
✗ 过多背景信息(100 行数据库)

诊断得分: 50/100(6 项检测命中 5 项,按 100 - 命中数 × 10 计算)

修复版本

<system>
你是一个电商客服助手。

【核心任务】
回答用户关于产品、价格、发货、退货的问题。

【可用信息】
[关键产品数据 - 仅保留必要部分]

【回答原则】
1. 准确:基于产品信息回答
2. 简洁:控制在 100 字以内
3. 有帮助:直接解决用户问题

【可行的操作】
✓ 查询产品信息
✓ 解释退货政策
✓ 建议相关产品

【不可行的操作】
✗ 修改订单价格
✗ 做出超出政策的承诺
✗ 讨论非业务话题

【处理不确定情况】
如果不清楚用户的问题,请说:"我需要更多信息...才能帮助你"
如果找不到答案,请说:"我来帮你联系我们的专家"
</system>

优化前后对比

指标 原始版 修复版
字数 350 180
冗余度 高 低
清晰度 中 高
一致性 低 高
诊断分数 50 100

E.5 反模式演变:为什么今天的“最佳实践”可能是明天的“反模式”

历史视角

2022年:
"最佳实践" - 使用详细的少样本示例
原因:模型较弱,需要更多引导

2024年:
"反模式" - 过多示例会减弱模型能力
原因:现在的模型足够强,过度示例反而混淆

启示:
随着模型的进化,我们的策略也需要进化。
不要固守"我以前的最佳实践",而要不断测试和适应。

适应新模型的检查表

当升级到新模型时:

□ 重新测试所有现有提示词
□ 尝试减少示例数量(新模型可能需要更少)
□ 尝试简化指令(新模型可能能理解更复杂的意图)
□ 评估性能是否有改进
□ 更新评估标准
□ 文档化新的最佳实践

总结

反模式不仅仅是“坏的做法”,它们是学习的机会。通过理解为什么某些模式失败,我们可以设计出更好的提示词。

关键要点:

  1. 简洁优于冗长:信息密度比措辞数量更重要
  2. 正向优于负向:告诉模型做什么,而不是不做什么
  3. 分解优于堆积:复杂任务需要链式处理
  4. 清晰优于隐含:明确标记数据和指令的边界
  5. 持续测试优于一次性设计:提示词需要不断优化