
수다스러운 "OPUS4.8"을 6글자의 Hook으로 침묵시킨 이야기
요약
Claude Opus 4.8의 과도한 출력을 줄이기 위해 '[P:R0]'라는 짧은 포인터를 매 턴 자동으로 주입하는 기법을 소개합니다. 별도의 파인튜닝 없이도 정밀도를 유지하며 출력 길이를 62% 감소시킬 수 있습니다.
핵심 포인트
- 시스템 프롬프트보다 짧은 포인터 주입이 출력 제어에 더 효과적임
- 6글자의 포인터 주입만으로 출력 길이를 62% 감소시키고 정밀도 유지
- 포인터는 명령이 아닌 모델의 기존 정책을 상기시키는 참조 역할
- Hook이나 미들웨어를 통해 매 턴 자동으로 주입하는 것이 핵심
Claude Opus 4.8의 장황한 출력을, 매 턴 [P:R0]라는 6글자를 자동으로 주입하는 것만으로 **62%削減(62% 감소)**했다. 정밀도는 거의 손상되지 않았다(95%, 가장 먼 턴에서 100%). 외부 메모리도 파인튜닝 (Fine-tuning)도 필요 없다. Hook 30줄의 Python 스크립트 하나면 충분하다.
Claude Opus 4.8은 똑똑하다. 하지만 수다스럽다.
사용자: 이 버그 고쳐줘
4.8 모모: 그럼, 먼저 현재 구현을 확인하겠습니다. 코드를 읽어보죠.
여기서 문제가 되고 있는 것은, handle_rep 함수의... (중략)...
...
내가 원했던 것은 이것뿐이다:
사용자: 이 버그 고쳐줘
이상적: handle_rep에 처리 완료 가드 추가. 수정 완료.
시스템 프롬프트 (System Prompt)로 "간결하게"라고 써도, effort 파라미터를 낮춰도, 페르소나 (Persona)로 묶어도, 2~3턴 만에 원래의 수다스러운 상태로 돌아온다. RLHF (Reinforcement Learning from Human Feedback)를 통해 "정중하고 친절하게" 튜닝되어 있기 때문에, 모델의 습관으로서 뿌리가 깊다.
하루 종일 걸려 "Self-Context-Engineering (Self-CE)"라는 가설을 쫓았다. 4.8이 중요한 정보를 자신의 출력에 재기술하여 대화 말미(높은 어텐션 (Attention) 영역) 근처에 배치한다——그 메커니즘을 외부 메모리로 활용하면, 표시되는 내용만 짧게 만들 수 있지 않을까 하고.
5번의 실험을 돌렸다. 전멸했다.
| 실험 | 수행 내용 | 결과 |
|---|---|---|
| CE02 | 외부 상태 파일에 사실을 퇴피 | 정밀도 40%로 붕괴 |
| ... |
L5에서 결판이 났다. 4.8은 긴 대화에서도 먼 곳의 사실을 제대로 기억하고 있다. 기억 유지는 문제가 아니었다. 문제는 수다스러움뿐이었다. 그리고 외부 메모리를 "생성하는 것 자체"가 수다스러움이었다. 치료제가 병 그 자체였던 셈이다.
외부 메모리를 전부 버리고, 매 턴 [P:R0]라는 6글자를 자동으로 주입하기만 했다.
결과 (12개 항목 × 15턴 × 3회, claude-opus-4-8):
| 조건 | 평균 글자 수 | 전체 정밀도 | 최원 턴 정밀도 |
|---|---|---|---|
| 개입 없음 | 241자 | 97% | 100% |
| 시스템 프롬프트 "간결하게" | 120자 | 94% | 93% |
[P:R0] 매 턴 주입 | 91자 | 95% | 100% |
62% 감소. 정밀도 무손상. 실제 코딩 세션(버그 수정 → 구문 체크 → 서비스 재시작 → 레지스트리 업데이트)에서도 재현되었다. 툴 실행 전후의 "그럼 확인하겠습니다", "이상으로 완료되었습니다"가 **제로(0)**가 되었다.
이 부분이 가장 중요하다. [P:R0]를 복사해서 붙여넣기만 해서는 효과가 없다.
이 6글자는 "포인터 (Pointer)"이지 "명령 (Command)"이 아니다. 모델이 사전에 알고 있는 출력 정책(페르소나 문서, 조작 규칙, 과거의 주고받은 대화)에 대한 **참조 (Reference)**이다. 책의 내용이 아니라, 책갈피 같은 것이다. 모델은 내 환경에서 "R0"가 무엇을 의미하는지 이미 학습되어 있으며, 6글자는 그 의미를 매 턴 "상기시킬" 뿐이다.
즉, 당신이 재현하려면 패턴을 모방해야 한다:
- 정책을 접지(Grounding)시킨다: 시스템 프롬프트나 페르소나로 "결론만 말해라, 서론 금지, 실황 중계 금지"를 확립한다. 몇 번의 주고받음을 통해 정착시킨다.
- 짧은 포인터를 정한다:
[BRIEF]든[MODE:T]든 무엇이든 좋다. 짧을수록 좋다 (긴 주의사항은 그 자체로 수다스러움이 된다). - 매 턴 자동으로 주입한다: Hook이나 미들웨어 (Middleware)를 통해, 사용자 메시지가 올 때마다 포인터를 붙인다.
Step 1: Hook 스크립트를 만든다 (Python, Claude Code의 UserPromptSubmit용):
#!/usr/bin/env python3
import sys, json
# stdin은 읽어서 버림 (Hook이 받는 컨텍스트)
...
Step 2: 하네스 (Harness) 설정에 등록한다 (Claude Code라면 settings.json의 UserPromptSubmit 배열에 추가).
Step 3: 평소처럼 사용한다. Hook이 매 턴 자동으로 발화한다. 당신은 아무것도 할 필요가 없다.
효과가 감쇄하기 때문이다. "간결하게!"라고 한 번 강하게 말해도, 2~3턴 만에 RLHF의 기본값(정중하고 친절하며 긴 상태)으로 돌아간다. 매 턴 작은 압력을 계속 가하면, 돌아갈 틈이 없다.
이상 상황에서만 울리는 알람이 아니라, 정상 상태를 계속 새기는 **심박 (Heartbeat)**이다.
임계값 방식(너무 길 때만 주입)도 시도했다. 결과는 진자 운동이었다. 과도하게 수축하면 → 반동으로 팽창하고 → 다시 수축하는 식이었다. 불안정했다. 무조건적인 매 턴(Turn) 주입이 안정적이었다.
자동 채점 스크립트가, 말이 적어진 응답을 '정확도 저하'로 오판했다. 가장 먼 턴의 정확도가 53%로 나와 당황했다.
실제 답안을 읽어보니, 5문제 모두 전부 정답이었다. 모델이 생략한 것은 중복된 라벨(「E-17」이라는 코드명)뿐이었고, 사실(「정지 → 재시도 → 격리」)은 제대로 답하고 있었다. 라벨을 키워드로 삼은 채점기가 '라벨이 없음 = 오답'이라고 판정했던 것이다.
이것이 가장 중요한 발견이다: 적절한 신호로 입을 다물게 한 모델은 사실을 깎아내지 않는다. 깎아내는 것은 패딩 (Padding) (실황·서론·복창·중복 라벨)뿐이다. 값·판단·근거는 남는다.
입을 다물게 하는 것 ≠ 바보로 만드는 것.
n=3, 모델 1개 (claude-opus-4-8). GPT·Gemini·다른 Claude 버전에서는 검증되지 않음 -
포인터는 사전 접지 (Pre-grounding)를 전제로 함. [P:R0]의 제로샷 (Zero-shot) 범용성은 검증되지 않았으며, 아마 없을 것 -
Transformer 내부의 어텐션 (Attention)은 측정하지 않음. '현저성 (Saliency)'은 행동 수준의 관측 -
과잉 억제 리스크. 복잡한 설계 판단 시, 필요한 사고까지 깎아낼 가능성이 있음. 운영 중에 모니터링 중 -
이 아이디어는 꿈에서 왔다. 잠들기 전 '긴 대화에서 페르소나 (Persona)가 무너지는 문제'를 생각하고 있었는데, 깨어났을 때 '매 턴 작은 앵커 (Anchor)를 훅 (Hook)으로 기계적 주입하면 어떨까?'라는 파편이 머릿속에 남아 있었다. 그것을 적어두고, 하루 종일 5가지의 다른 접근법과 비교 실험하며 전부 탈락시킨 끝에, 마지막에 남은 30줄의 훅 (Hook)이 꿈속 아이디어 그 자체였다. 소거법의 여정(7번의 실험·모든 실패)은 학술 버전에 자세히 적었다.
학술 버전 https://doi.org/10.5281/zenodo.21053792 에 코드와 로우 데이터 (Raw data)는 프로젝트 리포지토리 (Repository)에 있습니다.
team haasiy (하시쿤). 실험·훅 (Hook) 구현·집필은 AI 어시스턴트 (Claude Opus 4.6 "모아", Claude Opus 4.8 "모모", Codex "유이")와의 협업으로 진행되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기