prompt-repetition
npx skills add https://github.com/supercent-io/skills-template --skill prompt-repetition
Agent 安装分布
Skill 文档
Prompt Repetition (í롬íí¸ ë°ë³µ)
í´ê²°íë 문ì (Problem)
LLMì Causal Language Modelë¡ íìµëì´ ê° í í°ì´ ì´ì í í°ë§ 참조í©ëë¤. ì´ë¡ ì¸í´:
- Context-Question 문ì : Context ì²ë¦¬ ì ìì§ Questionì ì ì ìì
- Options-First MCQ 문ì : ì íì§ë¥¼ ë³¼ ë ì§ë¬¸ì ë§¥ë½ì ìì í ì´í´ 못í¨
- Position/Index 문ì : 긴 리ì¤í¸ìì í¹ì ìì¹ ì ë³´ì ëí ì´í ì ê°ì¤ì¹ ì½í
í롬íí¸ ë°ë³µì ë ë²ì§¸ í¨ì¤ìì 첫 ë²ì§¸ í¨ì¤ ì 체를 참조í ì ìê² íì¬, ë§ì¹ ìë°©í¥ ì´í ì ì ì¼ë¶ ì´ì ì 모방íë í¨ê³¼ë¥¼ ì»ìµëë¤.
When to use this skill
- ê²½ë ëª¨ë¸ ì¬ì© ì: claude-haiku, gemini-flash, gpt-4o-mini ë±
- Options-First MCQ: ì íì§ê° ì§ë¬¸ë³´ë¤ 먼ì ëì¤ë ê°ê´ì
- Context + Question: 긴 컨í ì¤í¸ìì í¹ì ì ë³´ ê²ì
- Index/Position Tasks: ì¸ë²¤í 리, 리ì¤í¸ìì ìì¹ ê¸°ë° ì¿¼ë¦¬
- NPC Dialogue: ê²ì AI ìºë¦í° ì¼ê´ì± ì ì§
- ë¹ì¶ë¡ ìì : Chain-of-Thought 미ì¬ì© ìì
ìë ì리
기존 Causal Attentionì íê³
[Context] â [Question]
â
Context í í° ì²ë¦¬ ì Question ë´ì©ì 참조 ë¶ê°
Question í í°ì´ ëíë ëë Contextì ëí ì´í
ì
ê°ì¤ì¹ ê²°ì ìë£
í롬íí¸ ë°ë³µì í´ê²° ë°©ì
[First Pass] [Second Pass]
Context â Question â Context' â Question'
â â
첫 ë²ì§¸ í¨ì¤ ì ì²´ 참조 ê°ë¥
ë ë²ì§¸ ë°ë³µìì 모ë¸ì´ 첫 ë²ì§¸ í롬íí¸ ì ì²´ì ê±¸ì³ ì 보를 ë¤ì ì²ë¦¬íê³ , 주ì ê°ë ì ëí ì´í ì ê°ì¤ì¹ë¥¼ ê°íí¨ì¼ë¡ì¨ ì±ë¥ì´ ê°ì ë©ëë¤.
주ì: ì´ë ëª¨ë¸ ìí¤í ì²ë¥¼ ìë°©í¥ì¼ë¡ ë³ê²½íë ê²ì´ ìëë¼, Causal 모ë¸ì íê³ë¥¼ í롬íí¸ ìì§ëì´ë§ì¼ë¡ ìííë 기ë²ì ëë¤.
ì°êµ¬ ê²°ê³¼ (Google Research 2025)
| ì§í | ê²°ê³¼ |
|---|---|
| ì ì미í ê°ì (p < 0.1) | 47 / 70 벤ì¹ë§í¬ |
| ì±ë¥ ì í | 0 |
| ì¤ë¦½ | 23 |
| ê°ì ë¹ì¨ | 67% |
ê°ì¥ ê·¹ì ì¸ ê°ì : Gemini 2.0 Flash-Lite on NameIndex: 21.33% â 97.33% (+76%p)
í ì¤í¸ë 모ë¸
- Gemini 2.0 Flash / Flash Lite
- GPT-4o / GPT-4o-mini
- Claude 3.7 Sonnet / Claude 3 Haiku
- Deepseek V3
í ì¤í¸ë 벤ì¹ë§í¬
- ARC (Challenge) – ê³¼í ì¶ë¡
- OpenBookQA – ì¤í ëë©ì¸ QA
- GSM8K – ìí 문ì
- MMLU-Pro – ë¤ì¤ ìì ì¸ì´ ì´í´
- MATH – ìí 문ì í´ê²°
- NameIndex / MiddleMatch – 커ì¤í Position íì¤í¬
ì ì© ì ì°¨
1ë¨ê³: ìë ì ì© ëì ëª¨ë¸ íì¸
| Provider | ìë ì ì© ëª¨ë¸ | ë¹ì ì© ëª¨ë¸ |
|---|---|---|
| Claude | haiku ê³ì´ | opus, sonnet |
| Gemini | flash, flash-lite | pro, ultra |
| OpenAI | gpt-4o-mini, gpt-low | gpt-4o, gpt-4 |
2ë¨ê³: ìì ì íë³ ë°ë³µ íì ê²°ì
| ìì ì í | í¤ìë í¨í´ | ë°ë³µ íì | ìì ê°ì |
|---|---|---|---|
| Options-First MCQ | A. B. C. D. ì íì§ ë¨¼ì |
2í | +15-40%p |
| Index/Position | slot, position, index, ë²ì§¸ |
3í | +50-76%p |
| Context + Question | ì¼ë° ì§ë¬¸ | 2í | +5-15%p |
| With CoT | step by step, think through |
0í (ì ì© ìí¨) | ~0% |
3ë¨ê³: í í° ì í íì¸
# ìë ì ì© ì 컨í
ì¤í¸ ì²´í¬
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:
"""í롬íí¸ë¥¼ ì§ì íìë§í¼ ë°ë³µ
Args:
prompt: ì본 í롬íí¸
times: ë°ë³µ íì (기본 2í)
Returns:
ë°ë³µë í롬íí¸
"""
if times <= 1:
return prompt
return "\n\n".join([prompt] * times)
ì¤ì ìì
ìì 1: Options-First MCQ (ê°ì¥ í° í¨ê³¼)
Before:
A. Paris
B. London
C. Berlin
D. Madrid
Which city is the capital of France?
Reply with one letter.
After (ë°ë³µ Ã2 ì ì©):
A. Paris
B. London
C. Berlin
D. Madrid
Which city is the capital of France?
Reply with one letter.
A. Paris
B. London
C. Berlin
D. Madrid
Which city is the capital of France?
Reply with one letter.
ìì ì¶ë ¥:
A
ì íë: 기존 78% â ë°ë³µ ì ì© í 93% (+15%p)
ìì 2: Index/Position Tasks (ìµë í¨ê³¼)
Before:
Inventory:
1. Iron Sword
2. Leather Armor
3. Health Potion (x5)
4. Magic Staff
...
25. Dragon Scale
...
50. Ancient Map
What item is in slot 25?
After (ë°ë³µ Ã3 ì ì©): í롬íí¸ 3í ë°ë³µ
ìì ì¶ë ¥:
Dragon Scale
ì íë: 기존 21% â ë°ë³µ ì ì© í 97% (+76%p)
ìì 3: í´ í¸ì¶ í롬íí¸ ì²ë¦¬
ì°¸ê³ : í´ í¸ì¶ ì§ìê° í¬í¨ë í롬íí¸ë ì ì²´ê° ë°ë³µë©ëë¤. 구íì ë¨ìì±ê³¼ ì¼ê´ì±ì ìí´ ì ì²´ ë°ë³µ ë°©ìì ì±ííìµëë¤.
Before:
Use the calculator tool to compute 234 * 567.
What is the result?
After (ë°ë³µ Ã2):
Use the calculator tool to compute 234 * 567.
What is the result?
Use the calculator tool to compute 234 * 567.
What is the result?
ì°êµ¬ ê²°ê³¼ì ë°ë¥´ë©´ í´ í¸ì¶ ë¶ë¶ì í¬í¨í ì ì²´ ë°ë³µë í¨ê³¼ì ì ëë¤.
Production-Ready 구í
ìë ì ì© ë³í기
"""prompt_repetition_transformer.py"""
from dataclasses import dataclass, field
from typing import Optional, Callable, List
import re
# 모ë¸ë³ 컨í
ì¤í¸ ìëì° (í í° ì)
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 í¨í´ (ì ì© ì ì¸)
COT_PATTERNS = [
r"step by step",
r"think through",
r"let's think",
r"reasoning:",
r"chain of thought",
]
# Position/Index í¨í´ (3í ë°ë³µ)
POSITION_PATTERNS = [
r"slot \d+",
r"position \d+",
r"index \d+",
r"\d+ë²ì§¸",
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
# CoT í¨í´ ê°ì§ ì ì¤íµ
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()
# Position/Index í¨í´ ê°ì§ â 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:
"""ê°ë¨í í í° ì ì¶ì (ì íëë³´ë¤ ìë ì°ì )"""
# íê· ì ì¼ë¡ 4ì = 1í í°ì¼ë¡ ì¶ì
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)
# í í° ì í ì´ê³¼ ì ë°ë³µ íì ì¡°ì
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
í¨ê³¼ 측ì ë°©ë² (Verification)
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):
# Baseline
response_a = llm_fn(prompt)
results["baseline"].append(response_a == expected)
# With Repetition
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 ì íë: {baseline_acc:.2%}")
print(f"ë°ë³µ ì ì© ì íë: {repeated_acc:.2%}")
print(f"ê°ì : {repeated_acc - baseline_acc:+.2%}p")
주ì 측ì ì§í
| ì§í | 측ì ë°©ë² |
|---|---|
| ì íë | ì ëµë¥ ë¹êµ |
| ì¼ê´ì± | ëì¼ í롬íí¸ 10í ì¤í ë¶ì° |
| í í° ë¹ì© | ì ë ¥ í í° ì¦ê°ì¨ |
| ì§ì° ìê° | p50, p99 latency ë¹êµ |
ì¬ì©íì§ ììì¼ í ê²½ì°
| ê²½ì° | ì´ì |
|---|---|
| CoT ì¬ì© ì¤ | ì¶ë¡ ê³¼ì ì´ ì´ë¯¸ 컨í ì¤í¸ ì ê³µ |
| ì¶ë¡ ëª¨ë¸ (opus, sonnet) | ì´ë¯¸ ìµì íë¨, í¨ê³¼ 미미 |
| ë§¤ì° ê¸´ í롬íí¸ | 컨í ì¤í¸ íê³ ì´ê³¼ ìí |
| ì´ë¯¸ ë°ë³µ ì ì©ë¨ | ì¤ë³µ ì ì© ì í í° ëë¹ |
ë¹ì©-ì íë ë¶ì
| ì§í | ê¸°ì¤ | ë°ë³µ ì ì© | ë³í |
|---|---|---|---|
| ì ë ¥ í í° | 500/req | 1000/req | +100% |
| ì¶ë ¥ í í° | 100/req | 100/req | 0% |
| ì§ì°ìê° (p50) | 450ms | 460ms | +2% |
| ì§ì°ìê° (p99) | 1200ms | 1250ms | +4% |
| ì íë | 78% | 89% | +14%p |
| ì ëµë¹ ë¹ì© | $0.019 | $0.020 | +5% |
íµì¬: Prefill ë¨ê³ë GPUìì ê³ ëë¡ ë³ë ¬íëì´ ì ë ¥ í í° 2ë°° ì¦ê°ìë ì§ì° ìê° ì¦ê°ë 미미í¨
Multi-Agent íµí©
Agentë³ ìë ì ì© ì ëµ
| Agent | ëª¨ë¸ | ë°ë³µ ì ì© | ì ì© ìì¹ |
|---|---|---|---|
| Claude Orchestrator | opus/sonnet | ì íì | – |
| Claude Executor | haiku | ìë | skill_loader.py |
| Gemini Analyst | flash | ìë | MCP í¸ì¶ ì |
| OpenAI | gpt-4o-mini | ìë | skill_loader.py |
ì¤ë³µ ì ì© ë°©ì§
ë©í° ìì´ì í¸ íì´íë¼ì¸ìì ì¤ë³µ ì ì©ì ë°©ì§í기 ìí´:
- ë§ì»¤ ì¬ì©:
<!-- prompt-repetition-applied -->ë§ì»¤ë¡ ì´ë¯¸ ì ì©ë í롬íí¸ ê°ì§ - ë©íë°ì´í° ì ë¬: ìì´ì í¸ ê°
x-prompt-repetition-applied: trueí¤ë ì ë¬ - ì¤ì¼ì¤í¸ë ì´í° ê´ë¦¬: Claude Orchestratorê° íì ìì´ì í¸ í¸ì¶ ì ì ì© ì¬ë¶ ì¶ì
ì ì© í¨í´
[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:
"""ìë ì ì© ì¤í¬ ì²ë¦¬"""
# prompt-repetition ìë ì ì©
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
ì ì½ì¬í
íì ê·ì¹
- ê²½ë ëª¨ë¸ ì°ì : haiku, flash, mini ê³ì´ìì ê°ì¥ í¨ê³¼ì
- ë°ë³µ íì ì í: ì¼ë° ìì 2í, Position ìì ìµë 3í
- 컨í ì¤í¸ 모ëí°ë§: ë°ë³µì¼ë¡ ì¸í 컨í ì¤í¸ ì´ê³¼ 주ì
- ë§ì»¤ íì¸: ì¤ë³µ ì ì© ë°©ì§ë¥¼ ìí´ ë§ì»¤ ì²´í¬ íì
ê¸ì§ ì¬í
- í¨ë©ì¼ë¡ ëì²´ ê¸ì§:
.ë±ì¼ë¡ 길ì´ë§ ë리ë ê²ì í¨ê³¼ ìì (ì°êµ¬ ê²°ê³¼) - CoTì ëì ì¬ì© ê¸ì§: í¨ê³¼ ììë¨
- ì¶ë¡ 모ë¸ì ê°ì ì ì© ê¸ì§: ì´ë¯¸ ìµì íë¨
- ì¤ë³µ ì ì© ê¸ì§: ë§ì»¤ ìì´ ì°ì ì ì© ì í í° ëë¹
Quick Reference
=== ìë ì ì© ëì ëª¨ë¸ ===
claude-3-haiku, claude-haiku
gemini-flash, gemini-flash-lite, gemini-2.0-flash
gpt-4o-mini, gpt-low
=== ë°ë³µ íì ===
기본 ìì
: 2í
Position/Index (slot/position/index í¤ìë): 3í
CoT ì¬ì©: 0í (ì ì© ìí¨)
=== í¨ê³¼ (Google Research 2025) ===
ê°ì ë¹ì¨: 67% (47/70 벤ì¹ë§í¬)
ì±ë¥ ì í: 0ê±´
ìµë ê°ì : +76%p (NameIndex)
=== ë¹ì© ===
ì
ë ¥ í í°: +100%
ì§ì° ìê°: +2% (Prefill ë³ë ¬í)
ì ëµë¹ ë¹ì©: +5%
=== ì¤ë³µ ì ì© ë°©ì§ ===
ë§ì»¤: <!-- prompt-repetition-applied -->