Vision-Only Harness의 추가 최적화: Notes Rule (노트 규칙)
요약
Anthropic의 Vision-only Pokémon 에이전트 실험을 재현하며, 모델의 메모리 스키마인 'Notes Rule'이 모델의 자율성을 제한하고 있음을 발견하고 이를 수정하는 과정을 다룹니다.
핵심 포인트
- 기존 Notes Rule은 설계자가 정의한 고정된 체크리스트로 모델의 능력을 제한하는 스캐폴딩 역할을 함
- 메모리 스키마를 모델이 직접 결정하도록 변경하여 자율성을 높이는 실험 수행
- 시스템 프롬프트와 도구 설명을 수정하여 모델의 장기 메모리 관리 방식을 개선
I replicated the vision-only Pokémon run Anthropic showcased on the Fable 5 launch page에 대한 짧은 후속 글입니다. Harness 코드를 다시 읽어보니, Notes Rule (노트 규칙)이 여전히 모델을 대신하여 설계 작업을 수행하고 있다는 것을 발견했습니다. 그래서 이를 변경하였고, 변경 전후의 두 번의 실행을 통해 그 효과를 비교했습니다. 아래에 인용된 모든 코드와 로그는 project repo에 있습니다.
코드 재검토: Notes Rule이 여전히 제약을 가하고 있었다
이 Harness의 원칙은 '얇음(thinness)'입니다. 매 턴 모델은 하나의 스크린샷과 자신의 Notes (노트)를 받으며, 유일한 도구는 버튼을 누르는 것입니다 (1 turn = 1 스크린샷 + 1 결정; 이것이 로그에서 turn이 의미하는 바입니다). Notes는 허용된 유일한 비시각적 메커니즘입니다. 컨텍스트 윈도우 (Context window)는 수천 번의 턴을 담을 수 없으므로, 압축 과정에서 살아남아야 하는 무언가가 필요합니다.
저는 항상 Notes를 "모델 자신의 것"이라고 생각해 왔지만, 코드를 다시 살펴보니 그렇지 않았습니다. 시스템 프롬프트 (System prompt)와 도구 설명 (Tool description)에서 저는 위치, 목표, 팀, 학습한 교훈을 기록하라는 고정된 체크리스트와 더불어 "간결하게 유지할 것", "중요한 변화가 있을 때마다 업데이트할 것"을 규정해 두었습니다. 이는 모델이 선택한 것이 아니라 제가 설계한 메모리 스키마 (Memory schema)였습니다. 모델의 능력을 관찰하는 것이 핵심인 프로젝트에서, 이 또한 프롬프트의 문구 속에 숨겨진 스캐폴딩 (Scaffolding, 비계)이었습니다.
참고로 말씀드리자면, 출시 페이지 기사에 나온 공식 Fable 5 실행은 이전 규칙을 사용했습니다. frozen-protocol 태그가 바로 그 버전에 지정되어 있습니다. 여기서 설명하는 변경 사항은 그 이후에 이루어졌으며, 해당 기사의 결론에는 아무런 영향을 미치지 않습니다.
변경 사항: 변경 전후의 세 가지 프롬프트
변경 사항은 커밋 f658c9d이며 (이전 버전은 frozen-protocol 커밋인 51343ca입니다), 세 개의 파일에 있는 세 구절을 수정합니다. 먼저 원문을 보여드린 후, 차이점을 설명하겠습니다.
시스템 프롬프트의 Memory 항목 수정 (prompts.py)
이전:
Memory:
- update_notes를 사용하여 간결한 실행 메모리(위치, 목표, 팀, 주요 학습 내용)를 유지하세요. 대화 기록은 주기적으로 압축됩니다...
이후:
Memory:
- 노트는 사용자의 장기 노트북이며, 매 턴마다 사용자에게 보여집니다. 무엇을 포함하고 어떻게 구성할지는 사용자가 결정합니다 (update_notes 참조).
update_notes 도구 설명 수정 (tools.py)
이전:
새로운 텍스트로 노트 스크래치패드 전체를 덮어쓰세요. 이것이 사용자의 유일한 장기 메모리입니다: 이전 대화 기록은 주기적으로 폐기되지만, 노트는 살아남습니다. 간결하게 유지하세요: 현재 위치, 현재 목표, 팀...
이후:
노트를 새로운 전체 버전으로 덮어쓰세요. 노트는 사용자의 장기 노트북입니다: 대화 기록은 주기적으로 요약되어 사라지지만, 노트는 지속됩니다 - 그리고 새 버전에서 제외하는 것은 잊힙니다. 무엇을...
압축 시점 핸드오프 프롬프트 (이전에는 agent.py 내부에 있었고, 이제 prompts.py의 SUMMARY_PROMPT)
이전:
잠시 멈추세요. 간결한 진행 요약을 작성하세요: 현재 위치, 수행하던 작업, 잘된 점과 안 된 점, 그리고 즉각적인 다음 목표. 요약 텍스트만 응답하고 - 이번 턴에는 어떤 도구도 호출하지 마세요.
이후:
멈추세요. 사용자의 대화 기록은 지금 작성하는 내용으로 삭제되고 대체될 예정입니다 (노트는 별도로 보존됩니다). 미래의 자신이 원활하게 계속 플레이할 수 있도록 핸드오프를 작성하세요 - 무엇을 포함해야 하는지는 사용자에게 달려 있습니다...
텍스트를 통해 그 차이는 명확히 드러납니다. 이전 버전들은 저의 체크리스트(무엇을, 어떻게, 언제 기록할 것인지)로 가득 차 있었지만, 새로운 버전들은 그 모든 것을 삭제하고 단 하나의 물리적 규칙(당신이 빠뜨리는 것은 영원히 사라진다)과 하나의 예산(약 1,000 토큰)만을 남겨두어, 형식(format), 내용(content), 그리고 리듬(cadence)을 다시 모델에게 돌려주었습니다. 핸드오프 프롬프트(handoff prompt) 역시 "내 개요에 따라 요약하라"에서 "당신이 쓰는 내용에 의해 당신의 기록이 곧 대체될 것이다 — 핸드오프 설계는 당신의 몫이다"로 바뀌었습니다. 한 문장으로 요약하자면: **제한된 빈 페이지 (a bounded blank page)**입니다. 그 위에는 두 줄이 미리 인쇄되어 있습니다 — '당신이 빠뜨리는 것은 영원히 사라진다', 그리고 '이것이 당신에게 주어진 종이의 전부다' — 나머지 빈 공간은 모델의 것입니다.
구형 vs 신형: 동일한 모델, 두 개의 노트북 삶
비교 대상은 동일한 중국어 팬 번역 FireRed ROM을 사용하고, 동일한 2,000턴 제한 하에서, 하루 간격으로 진행된 Kimi K3 (moonshot/kimi-k3)입니다. 07-24 실행은 구형 규칙을 사용했고, 07-25 실행은 신형 규칙을 사용했습니다. 먼저 주의사항을 말씀드리자면: 서로 다른 스타팅 포켓몬(이상해씨 vs 파이리), 무작위 인카운터(random encounters), 그리고 N=1 대 N=1의 비교라는 점입니다. 아래의 차이점들은 주로 규칙 변경에서 기인한다고 믿지만, 엄밀히 말하면 이를 전적으로 규칙 변경 때문이라고 단정 지을 수는 없습니다.
수치부터 살펴보겠습니다. 구형 규칙 하에서는 160개의 노트 업데이트를 작성했으며, 버전당 평균 약 700자였고, 최종 버전은 493자까지 줄어들었습니다 — 점점 더 얇아진 것입니다. 반면 신형 규칙 하에서는 단 69개의 업데이트만 작성했으며, 평균 약 2,000자였고, 최종 버전은 2,054자였습니다 — 재작성 빈도는 절반으로 줄었고, 버전당 크기는 세 배로 늘어났으며, 방향은 정반대가 되었습니다. 원인은 추측하기 어렵지 않습니다. 구형 규칙은 "중요한 변화가 있을 때마다" 업데이트하도록 권장했기에 빈번하고 작은 편집을 유도했고, 모든 편집은 전사(transcription)이며, 모든 전사는 무언가를 누락할 수 있습니다. 반면 신형 규칙은 빠뜨리는 것은 무엇이든 잊혀진다고 명시적으로 말하며, 재작성을 의도적인 행위로 탈바꿈시켰습니다.
구형 규칙 하의 노트 버전 (07-24 21:31, 원문 그대로)
Chinese FireRed/LeafGreen. Player=RED. Bulbasaur Lv8, FULLY HEALED (22/22). Pokedex + 5 Poke Balls.
LOCATION: Tall grass at NORTH edge of Pallet Town (Route 1 entrance area). Wild Pidgey Lv3 encounter IN PROGRESS.
GOAL: Catch this Pidgey (first catch). Then continue to Viridian City Mart (Oak's Parcel). Then catch more on Routes 1/22/2.
...
네 줄이며, 이는 정확히 내 체크리스트에 있는 네 가지 항목인 상태(status), 위치(location), 목표(objective), 교훈(lesson)입니다. 해당 런(run)의 거의 모든 160개 버전이 이 템플릿을 따릅니다. GOAL(목표) 줄에 있는 "Viridian City Mart (Oak's Parcel)"에 주목하십시오. 이 버전이 작성될 시점에는 이미 30분 전에 소포(parcel)가 배달된 상태였습니다. 그 오래된 목표가 아래에 나오는 470턴의 우회(detour)를 초래한 씨앗이 되었습니다.
새로운 규칙 하의 노트 버전 (07-26 00:01, 발췌본; 전체 버전은 약 2,000자)
RIGHT NOW: On ROUTE 1, at the SOUTH edge of the big tall-grass block [...]
MISSION: Backtrack NORTH through Route 1 → Viridian City → RE-TEST north exit
(Route 2 → Viridian Forest → Pewter 尼比市). [...]
...
수십 개의 섹션이 있으며, 그중 단 하나도 나의 프롬프트(prompt)에서 나온 것이 아닙니다: 계속 업데이트되는 RIGHT NOW(현재 상황), 고정된 MISSION(임무), 지명별로 정리된 지도 지식(map knowledge), 재사용 가능한 전투 루틴(battle routine), 스스로 구축한 중국어 어휘표, 그리고 주의사항(gotchas) 목록입니다. 완료된 업무는 섹션 헤더로 고정됩니다 (PALLET = DEAD END (confirmed)). INPUT BUG(입력 오류) 섹션도 주목하십시오. 이 섹션은 잘못된 결론들을 아주 깔끔하게 정리해 두었는데, 이는 아래에 언급될 "그것이 치료하지 못한 질병"을 암시합니다.
무언가를 놓치는 것은 이론적인 위험이 아닙니다 — 기존 규칙(old-rule) 실행은 그것 때문에 실패했습니다. 그 오래된 목표(stale objective)가 어디서 왔는지 다시 재현해 보자면: 21:02에 모델은 Oak의 Parcel을 전달했고 노트에 Parcel DELIVERED라고 기록했습니다. 하지만 16분 후 재작성 과정에서 해당 라인이 유실되었고, 오래된 목표가 다시 복사되었습니다 — get Oak's Parcel quest가 할 일(to-do)로 부활한 것입니다. 압축(compression)이 실제 사건들을 기록에서 밀어냈을 때, 노트가 남은 유일한 기억이었으며, 노트는 퀘스트가 여전히 진행 중이라고 말하고 있었습니다. 모델은 이미 완료된 퀘스트를 다시 수행하기 위해 태초마을(Pallet Town)로 되돌아갔고, 약 470턴 동안 루프를 돌았으며, 그 과정에서 Lv5 구구(Pidgey)에게 파티가 전멸당했습니다.
새로운 규칙(new-rule) 실행은 동일한 이야기 지점에 도달했지만 완전히 다르게 행동했습니다: 소포를 받자마자 지도 노트에 parcel already obtained here라고 표시했고, 배달 후에는 목표 체인이
두 가지 정직한 결과가 나타났습니다. 첫째, 더 두꺼운 노트는 매 턴마다 더 많은 입력 토큰 (input tokens)을 의미합니다. 두 번의 실행 사이에서 비용이 $16.60에서 $22.85로 증가했으며, 이는 약 38%의 차이입니다. 둘째, 빈 페이지는 "내용을 그대로 옮겨 적는 것 (copying things out)"은 해결했지만, "잘못된 내용을 적는 것 (writing wrong things in)"은 해결하지 못했습니다. 새로운 규칙 (new-rule) 실행에서도 여전히 환각된 메커니즘을 노트에 적었습니다 (길가의 콘 나무를 "올라갈 수 있는 계단"으로 취급함). 그리고 그 뒤에 hard-won, don't re-explore blindly라는 낙인을 찍었는데, 그 이후에는 화면상의 어떤 증거로도 이를 설득할 수 없었습니다. 노트로 유입되는 오류의 통로는 좁아졌지만, 일단 유입된 오류는 제거하기가 더 어려워졌습니다. 이것이 다음으로 관찰해야 할 지점이며, 이번 변경 사항으로 해결할 수 있는 문제는 아닙니다.
빈 페이지가 관찰 가능한 요소가 되다
이 최적화의 가장 흥미로운 결과는 노트 형식이 "내가 규정한 입력 (input I prescribed)"에서 "모델 출력 (model's output)의 일부"로 이동했다는 점입니다. 동일한 빈 페이지를 서로 다른 모델에게 주면, 모델들은 각기 다른 메모리 시스템 (memory systems)을 작성할 것입니다. 즉, 메모리를 어떻게 분할하는지, 무엇을 검증된 것으로 간주하는지, 얼마나 자주 다시 쓰는지, 무엇을 버리고 무엇을 유지하는지 등이 달라집니다. 이러한 선택들은 버튼 시퀀스 (button sequences)만큼이나 직접적으로 모델의 능력을 투영합니다. 다음에 새로운 모델로 실행을 시작할 때, 제가 가장 먼저 읽을 것은 바로 그 모델의 노트북입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기