🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx @anthropic-ai/skills install supercent-io/skills-template/prompt-repetition

💡 提示:需要 Node.js 和 NPM

解决的问题

LLM 被训练为因果语言模型,其中每个 token 仅能关注之前的 tokens。这导致了:

  1. 上下文-问题错位:模型在处理上下文时,还不知道后续的问题是什么
  2. 选项优先的多选题困境:当先看到选项时,无法充分理解提问的上下文
  3. 位置/索引识别困难:在长列表中,针对特定位置信息的注意力权重会减弱

提示词重复技术使第二次处理能够参考第一次处理的完整结果,从而模拟了双向注意力的部分优势


何时使用此技能

  • 使用轻量级模型时:如 claude-haiku, gemini-flash, gpt-4o-mini 等
  • 选项优先的多选题:答案选项出现在问题之前的选择题
  • 长上下文 + 问题:需要在长文本中搜索特定信息时
  • 索引/位置任务:在库存或列表中基于位置的查询
  • NPC 对话:为游戏 AI 角色保持对话一致性
  • 非推理任务:不需要使用思维链的任务

工作原理

因果注意力的局限性

[上下文] → [问题]
在处理上下文 tokens 时,无法参考后续的问题内容
当问题 tokens 出现时,上下文的注意力权重已经确定

提示词重复如何解决这个问题

[第一次处理]                [第二次处理]
上下文 → 问题        →    上下文' → 问题'
                              ↑         ↑
                         可以引用第一次处理的完整内容

在第二次重复中,模型重新处理整个第一次提示的信息,并加强对关键概念的注意力权重,从而提升性能。

注意:这并非改变模型架构以实现双向注意力,而是一种通过提示工程来缓解因果模型局限性的技术。


研究成果 (Google Research 2025)

指标 结果
显著提升 (p < 0.1) 47 / 70 个基准测试
性能下降 0 个
无显著变化 23 个
提升率 67%

最显著的提升: Gemini 2.0 Flash-Lite 在 NameIndex 任务上:21.33% → 97.33% (+76 个百分点)

测试过的模型

  • Gemini 2.0 Flash / Flash Lite
  • GPT-4o / GPT-4o-mini
  • Claude 3.7 Sonnet / Claude 3 Haiku
  • Deepseek V3

测试过的基准

  • ARC (Challenge) – 科学推理
  • OpenBookQA – 开放域问答
  • GSM8K – 数学问题
  • MMLU-Pro – 多任务语言理解
  • MATH – 数学问题求解
  • NameIndex / MiddleMatch – 自定义位置任务

应用步骤

步骤 1:确认自动应用的目标模型

提供商 自动应用的模型 排除的模型
Claude haiku 系列 opus, sonnet
Gemini flash, flash-lite pro, ultra
OpenAI gpt-4o-mini, gpt-low gpt-4o, gpt-4

步骤 2:根据任务类型确定重复次数

任务类型 关键词模式 重复次数 预期提升
选项优先的多选题 选项 A. B. C. D. 先出现 +15-40 个百分点
索引/位置任务 slot, position, index, 第N个 +50-76 个百分点
上下文 + 问题 一般性问题 +5-15 个百分点
包含思维链 step by step, think through (不应用) ~0%

步骤 3:检查 Token 限制

# 自动应用前检查上下文限制
max_context = model_context_window * 0.8  # 80% 的安全余量
if len(prompt_tokens) * repetitions > max_context:
    repetitions = max(1, int(max_context / len(prompt_tokens)))

步骤 4:提示词转换

def apply_prompt_repetition(prompt: str, times: int = 2) -> str:
    """将提示词重复指定的次数

    参数:
        prompt: 原始提示词
        times: 重复次数(默认 2)

    返回:
        重复后的提示词
    """
    if times <= 1:
        return prompt
    return "\n\n".join([prompt] * times)

实践示例

示例 1:选项优先的多选题(效果最显著)

应用前:

A. 巴黎
B. 伦敦
C. 柏林
D. 马德里

哪个城市是法国的首都?
请回复一个字母。

应用后(重复 ×2):

A. 巴黎
B. 伦敦
C. 柏林
D. 马德里

哪个城市是法国的首都?
请回复一个字母。

A. 巴黎
B. 伦敦
C. 柏林
D. 马德里

哪个城市是法国的首都?
请回复一个字母。

预期输出:

A

准确率:原始 78% → 重复后 93% (+15 个百分点)


示例 2:索引/位置任务(效果最大化)

应用前:

库存清单:
1. 铁剑
2. 皮革护甲
3. 治疗药水 (x5)
4. 魔法杖
...
25. 龙鳞
...
50. 古代地图

第 25 个槽位是什么物品?

应用后(重复 ×3):
提示词完整重复 3 次

预期输出:

龙鳞

准确率:原始 21% → 重复后 97% (+76 个百分点)


示例 3:工具调用提示处理

注意:包含工具调用指令的提示词也会被完整重复。为了简化实现和保证一致性,采用了完整重复的方法。

应用前:

使用计算器工具计算 234 * 567。
结果是多少?

应用后(重复 ×2):

使用计算器工具计算 234 * 567。
结果是多少?

使用计算器工具计算 234 * 567。
结果是多少?

研究结果表明,包含工具调用部分的完整重复同样有效。


生产级实现

自动应用转换器

"""prompt_repetition_transformer.py"""
from dataclasses import dataclass, field
from typing import Optional, Callable, List
import re

# 各模型的上下文窗口(以 token 计)
MODEL_CONTEXT_WINDOWS = {
    "claude-3-haiku": 200_000,
    "claude-haiku": 200_000,
    "gemini-flash": 1_000_000,
    "gemini-flash-lite": 1_000_000,
    "gemini-2.0-flash": 1_000_000,
    "gpt-4o-mini": 128_000,
    "gpt-low": 128_000,
}

# 自动应用的目标模型列表
AUTO_APPLY_MODELS = list(MODEL_CONTEXT_WINDOWS.keys())

# 思维链模式(应用此技能时需排除)
COT_PATTERNS = [
    r"step by step",
    r"think through",
    r"let's think",
    r"reasoning:",
    r"chain of thought",
]

# 位置/索引任务模式(需要 3 次重复)
POSITION_PATTERNS = [
    r"slot \d+",
    r"position \d+",
    r"index \d+",
    r"\d+(st|nd|rd|th)",
    r"item \d+",
    r"row \d+",
    r"column \d+",
]

@dataclass
class PromptRepetitionConfig:
    """提示词重复配置"""
    default_repetitions: int = 2
    position_repetitions: int = 3
    separator: str = "\n\n"
    max_context_ratio: float = 0.8
    applied_marker: str = "<!-- prompt-repetition-applied -->"

class PromptRepetitionTransformer:
    """为轻量级模型自动应用提示词重复的转换器"""

    def __init__(self, config: Optional[PromptRepetitionConfig] = None):
        self.config = config or PromptRepetitionConfig()

    def should_apply(self, model: str, prompt: str) -> bool:
        """判断是否自动应用"""
        # 如果已应用,则跳过
        if self.config.applied_marker in prompt:
            return False

        # 检查目标模型
        model_lower = model.lower()
        if not any(m in model_lower for m in AUTO_APPLY_MODELS):
            return False

        # 检测到思维链模式时跳过
        prompt_lower = prompt.lower()
        for pattern in COT_PATTERNS:
            if re.search(pattern, prompt_lower):
                return False

        return True

    def determine_repetitions(self, prompt: str, model: str) -> int:
        """根据任务类型确定重复次数"""
        prompt_lower = prompt.lower()

        # 检测到位置/索引模式 → 3 次重复
        for pattern in POSITION_PATTERNS:
            if re.search(pattern, prompt_lower):
                return self.config.position_repetitions

        return self.config.default_repetitions

    def estimate_tokens(self, text: str) -> int:
        """简单的 token 估算(速度优先于精度)"""
        # 大约估算 4 个字符 = 1 个 token
        return len(text) // 4

    def transform(self, prompt: str, model: str) -> str:
        """对提示词应用重复"""
        if not self.should_apply(model, prompt):
            return prompt

        repetitions = self.determine_repetitions(prompt, model)

        # 检查上下文限制
        model_lower = model.lower()
        max_tokens = 128_000  # 默认值
        for m, tokens in MODEL_CONTEXT_WINDOWS.items():
            if m in model_lower:
                max_tokens = tokens
                break

        max_allowed = int(max_tokens * self.config.max_context_ratio)
        prompt_tokens = self.estimate_tokens(prompt)

        # 如果超过 token 限制,则减少重复次数
        while prompt_tokens * repetitions > max_allowed and repetitions > 1:
            repetitions -= 1

        if repetitions <= 1:
            return prompt

        # 应用重复并添加标记
        repeated = self.config.separator.join([prompt] * repetitions)
        return f"{self.config.applied_marker}\n{repeated}"

    def wrap_llm_call(self, llm_fn: Callable, model: str) -> Callable:
        """包装 LLM 调用函数"""
        def wrapped(prompt: str, **kwargs):
            transformed = self.transform(prompt, model)
            return llm_fn(transformed, **kwargs)
        return wrapped

如何衡量效果(验证方法)

A/B 测试方法

def run_ab_test(prompts: List[str], llm_fn, model: str, ground_truth: List[str]):
    """提示词重复效果的 A/B 测试"""
    transformer = PromptRepetitionTransformer()

    results = {"baseline": [], "repeated": []}

    for prompt, expected in zip(prompts, ground_truth):
        # 基线测试
        response_a = llm_fn(prompt)
        results["baseline"].append(response_a == expected)

        # 应用重复后的测试
        repeated_prompt = transformer.transform(prompt, model)
        response_b = llm_fn(repeated_prompt)
        results["repeated"].append(response_b == expected)

    baseline_acc = sum(results["baseline"]) / len(prompts)
    repeated_acc = sum(results["repeated"]) / len(prompts)

    print(f"基线准确率:{baseline_acc:.2%}")
    print(f"重复后准确率:{repeated_acc:.2%}")
    print(f"提升:{repeated_acc - baseline_acc:+.2%}个百分点")

关键指标

指标 测量方法
准确率 比较正确答案的比例
一致性 同一提示运行 10 次的方差
Token 成本 输入 token 的增加率
延迟 比较 p50, p99 延迟

何时不使用

场景 原因
使用思维链时 推理过程本身已提供了上下文
推理模型 (opus, sonnet) 已优化,效果甚微
极长的提示词 可能超出上下文限制
已经重复过 重复应用浪费 token

成本-准确率分析

指标 基线 应用重复 变化
输入 tokens 500/请求 1000/请求 +100%
输出 tokens 100/请求 100/请求 0%
延迟 (p50) 450ms 460ms +2%
延迟 (p99) 1200ms 1250ms +4%
准确率 78% 89% +14 个百分点
每正确回答成本 $0.019 $0.020 +5%

关键洞察: 预填充阶段在 GPU 上是高度并行化的,因此输入 token 翻倍对延迟影响极小。


多代理集成

各代理的自动应用策略

代理 模型 是否应用重复 应用位置
Claude 协调器 opus/sonnet 可选
Claude 执行器 haiku 自动 skill_loader.py
Gemini 分析器 flash 自动 调用 MCP 时
OpenAI gpt-4o-mini 自动 skill_loader.py

防止重复应用

为防止在多代理流水线中重复应用:

  1. 使用标记:通过 <!-- prompt-repetition-applied --> 标记检测是否已应用
  2. 传递元数据:在代理之间传递 x-prompt-repetition-applied: true 头信息
  3. 协调器管理:Claude 协调器在调用子代理时跟踪是否已应用重复

应用模式

[Claude Sonnet] 规划(无需重复)
[Gemini Flash] 分析(自动应用 2 次重复,添加标记)
[Claude Haiku] 执行(检测到标记 → 跳过重复应用)

skill_loader.py 集成指南

推荐实现

# 添加到 skill_loader.py 的代码
from prompt_repetition_transformer import PromptRepetitionTransformer

class SkillLoader:
    def __init__(self, ...):
        # ... 现有代码 ...
        self.prompt_transformer = PromptRepetitionTransformer()

    def apply_auto_skills(self, prompt: str, model: str) -> str:
        """处理自动应用的技能"""
        # 自动应用提示词重复
        for skill in self.skills.values():
            auto_apply = skill.get('data', {}).get('auto-apply', {})
            if auto_apply.get('trigger') == 'auto':
                target_models = auto_apply.get('models', [])
                if any(m in model.lower() for m in target_models):
                    prompt = self.prompt_transformer.transform(prompt, model)

        return prompt

约束条件

强制性规则

  1. 优先轻量级模型:对 haiku, flash, mini 系列效果最显著
  2. 限制重复次数:一般任务 2 次,位置任务最多 3 次
  3. 监控上下文:注意重复可能导致上下文溢出
  4. 检查标记:必须检查标记以防止重复应用

禁止事项

  1. 禁止用填充替代:添加 . 等字符增加长度无效(根据研究)
  2. 不要与思维链结合:效果会相互抵消
  3. 不要强制应用于推理模型:它们已优化
  4. 禁止重复应用:无标记的连续应用会浪费 token

快速参考

=== 自动应用目标模型 ===
claude-3-haiku, claude-haiku
gemini-flash, gemini-flash-lite, gemini-2.0-flash
gpt-4o-mini, gpt-low

=== 重复次数 ===
一般任务:2 次
位置/索引任务(包含 slot/position/index 等关键词):3 次
包含思维链:0 次(不应用)

=== 效果(Google Research 2025) ===
提升率:67% (47/70 个基准测试)
性能下降:0 个案例
最大提升:+76 个百分点 (NameIndex)

=== 成本 ===
输入 tokens:+100%
延迟:+2% (预填充并行化)
每正确回答成本:+5%

=== 防止重复应用 ===
标记:<!-- prompt-repetition-applied -->

参考文献

📄 原始文档

完整文档(英文):

https://skills.sh/supercent-io/skills-template/prompt-repetition

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。