Codex에게 외부 리뷰를 요청한 배경
LLM 라벨명 설계 오류가 분류 문제의 뿌리일 수 있다는 걸 처음에는 몰랐다. 글3에서 다섯 번째 파일럿(D5)부터 아홉 번째 파일럿(D9)까지 반복 실험을 했다. 결론은 하나였다. 구조를 아무리 바꿔도 성장 응원 항목을 잘못 잡아내는 문제는 줄지 않았다.
그때까지 문제라고 생각한 건 프롬프트였다. 정의를 더 좁게 쓰면 될 것 같았다. 부정 예시를 추가했다. 그런데 아홉 번째 시도(D9)에서 틀린 수가 여덟 번째 시도(D8)보다 오히려 늘었다. 여덟 편 중 두 편이 틀렸다.
거기서 멈췄다. 같은 방향으로 계속 밀어붙이는 게 맞는지 확신이 없었다.
그래서 외부에 adversarial-review(내 설계를 반대 입장에서 검토하도록 외부에 요청하는 방식)를 요청했다. Codex에게 질문 일곱 개를 보냈다.
- K-ON!과 4월은 너의 거짓말의 잘못 잡힌 원인 진단이 맞는가
- D5→D9 틀린 비율(98%→75%→62%→12%→25%)이 프롬프트 패칭의 한계인가
- 지금까지 시도하지 않은 방법이 있는가
- 거부한 옵션 중 재고해야 할 것이 있는가
질문을 보낸 게 아니라 내 설계를 반박해달라고 한 것이었다.
라벨 이름이 너무 넓어서 생긴 문제
Codex의 답변은 예상과 달랐다.
K-ON!이 계속 틀린 이유를 나는 경계를 명확히 안 그어서 생긴 문제라고 봤다. 문화 행사 규칙을 정의에 추가했는데도 K-ON!의 학교 음악 동아리를 모델이 성장 응원으로 잡아내는 건 정의를 잘못 썼기 때문이라고 생각했다.
Codex는 다르게 봤다.
“K-ON!은 경계를 명확히 안 그어서 생긴 문제만이 아니라 라벨에 붙인 이름이 원래 의도보다 넓은 쪽으로 자꾸 쏠리는 문제이기도 하다.”
라벨에 붙인 이름이 원래 의도보다 넓은 쪽으로 자꾸 쏠리는 현상이 있다. “연습,” “학교 축제,” “동아리,” “공연,” “실력 향상” 같은 단어들이 “노력으로 성장하는 청춘” 장르 패턴 근처에 있다. 모델은 내 정의를 따르는 게 아니라 애니 장르 공식에 끌려가고 있었던 것이다.
근거 문장을 시놉시스에서 먼저 찾아 인용하게 만드는 방식으로 실제 문장을 잡게 했다. K-ON! 잘못 잡힌 근거 문장은 “school-festival drawing near and Yui getting stuck with her practice”였다. 시놉시스에 실제로 있는 문장이다. 문제는 그 문장이 “규칙: 공연을 위한 연습은 False” 조건과 충돌한다는 걸 모델이 인식하지 못한 것이었다.
근거 문장이 있다고 해서 정의 조건을 충족하는 게 아니다. 그 차이를 Codex가 처음으로 명확하게 짚었다.
Codex의 제안은 이랬다. “성장 응원이라는 이름 자체가 문제다. 구조화된 경쟁의 진행 과정처럼 의미를 더 좁게 담는 이름이어야 한다.”
라벨 이름이 설계다. 이름을 잘못 지으면 모델이 아무리 좋아도 그 이름이 가리키는 방향으로 쏠려버린다.
→글3(공유 원자: codex_adversarial_output.md §2)
4월은 너의 거짓말이 드러낸 이야기 범위 문제
4월은 너의 거짓말(Shigatsu wa Kimi no Uso)은 새로운 유형의 미스매치였다.
나는 4월은 너의 거짓말에서 잘못 잡힌 원인을 지금 일어나는 일인지 과거 일인지 헷갈린 문제로 봤다. 과거 경쟁 이력이 있는 캐릭터를 현재 경쟁 중으로 잘못 읽는 문제라고 봤다.
Codex는 이것도 다르게 진단했다.
“4월은 너의 거짓말은 지금 일어나는 일인지 과거 일인지 헷갈린 문제이기도 하지만, 이야기에서 뭐가 중심이고 뭐가 배경인지 구분 못 한 문제이기도 하다.”
모델이 구분하지 못하는 다섯 가지를 Codex가 나열했다.
- 배경이나 과거 이야기
- 현재 이야기의 핵심 갈등
- 주제적 결말 방향
- 장르 맥락
- 캐릭터의 역사
4월은 너의 거짓말 시놉시스에는 “피아노 신동이 대회를 석권했다”는 과거형 문장이 있다. 모델은 이 문장을 근거로 성장 응원이 있다고 출력했다. 현재 이야기가 감정 회복과 자유로운 음악 표현에 관한 것이라는 건 읽지 못했다.
내가 내린 정의는 “시놉시스가 묘사할 때”였다. 그런데 모델은 “시놉시스에 언급됐을 때”로 해석했다. “묘사한다”와 “언급한다”의 차이가 설계에 빠져 있었다.
Codex의 결론: “경쟁 시스템이 현재 이야기의 핵심 갈등이어야 한다. 역사적 배경, 과거 사건, 트라우마 설정이면 해당 없음으로 처리해야 한다는 규칙이 필요하다.”
라벨 이름 안에 뒤섞인 두 가지
K-ON!과 4월은 너의 거짓말의 사례를 합쳐보면 하나의 구조가 나온다.
모델이 틀리는 게 아니었다. 라벨 이름이 두 가지를 뒤섞고 있었다.
- 장르 인상(성장하는 이야기처럼 느껴지는가)
- 서사 구조(구조화된 승부 시스템이 현재 이야기를 움직이는가)
성장 응원이라는 이름은 첫 번째(장르 인상)를 가리키는 것처럼 들린다. 내가 원한 건 두 번째(서사 구조)였다.
Codex가 권장한 분해 방식은 이렇다.
성장 응원 항목을 단번에 있다/없다로 묻지 말고, 선행 조건 여섯 개를 먼저 확인하라는 것이었다.
- 구조화된 경쟁이 있는가
- 공개 지표(점수·순위·승패)가 있는가
- 외재 라이벌이나 팀이 있는가
- 경쟁이 현재 이야기를 움직이는 요소인가
- 단순 훈련이나 공연이 아닌가
- 배경 이야기나 과거 사건이 아닌가
여섯 개를 전부 충족할 때만 해당한다고 판정한다. 모델한테 최종 판단을 묻는 게 아니라, 각 조건을 확인하고 코드로 계산하는 방식이다.
이건 라벨명 설계 문제와 직결됐다. 성장 응원이라는 이름 안에 이 여섯 가지가 뒤엉켜 있었기 때문에 모델이 끌려다닌 것이었다. Codex는 이걸 라벨 이름을 어떻게 짓느냐의 문제라고 불렀다. 라벨 이름이 장르 인상·서사 구조·경쟁 메커니즘을 한꺼번에 담으면 미스매치가 구조적으로 나올 수밖에 없다.
같은 파일럿 여덟 편으로 계속 실험하는 것도 문제였다. Codex의 말이다. “반복적인 프롬프트 수정으로 오염된 파일럿 세트다. 대규모 검증 세트가 필요하다.”
기준을 글로 못 박아뒀더니 미스매치가 줄었다
Codex 리뷰 이전에 이미 기준을 글로 못 박아두는 방식을 설계에 도입했다. D8에서 미스매치가 여덟 편 중 한 편(12%)으로 줄어든 이유가 여기 있었다.
기준을 글로 못 박아두는 방식의 핵심은 두 가지였다.
첫째, 작품명을 정의에 박지 않는다. K-ON!=해당 없음, 4월은 너의 거짓말=해당 없음 이런 식으로 작품명을 직접 쓰면 모델이 정답표처럼 외워버린다. 그 여덟 편에서만 작동하는 답 목록이 된다.
둘째, 추상 충돌 케이스만 정의에 박는다. “문화 행사나 공연을 위한 연습이면 False”처럼 시놉시스 텍스트만으로 판단할 수 있는 조건을 쓴다.
D8 이후 이 원칙이 맞다는 걸 Codex 리뷰가 거꾸로 확인해줬다. Codex도 같은 방향을 권장했기 때문이다. “있다/없다를 모델한테 직접 묻지 말고, 좁게 정의된 조건들을 확인하고 직접 계산하라.”
다만 D8 결과는 조건부 통과였다. 성장 응원 미스매치가 여덟 편 중 한 편으로 줄었지만, 다른 항목인 미스터리 항목이 여덟 편 중 여섯 편을 틀려 기준에 미달했다. D8 이후 해결됐다고 할 수 없다.
4단 검토가 이 과정에서 핵심이었다. D5→D7 파일럿 실패 후 학계(Arxiv 논문)·실무(Andy Bosyi 사례)·오픈소스(langextract)·내가 호출한 시스템 검증용 서브에이전트(senior-engineer) 네 단계를 거쳐서 근거 문장을 시놉시스에서 먼저 찾아 인용하게 만드는 방식과 기준을 글로 못 박아두는 방식에 도달했다. Codex 외부 리뷰는 그 이후에 왔다. 각 단계가 잡는 영역이 달랐다. 학계만 했으면 기준을 글로 못 박아두는 방식을 못 잡았을 것이다. senior-engineer만 했으면 새로운 사각지대가 생겼을 것이다.
라벨명 설계 문제는 내부 시선으로는 보이지 않았다. Codex라는 외부 시선이 들어오고 나서야 성장 응원이라는 이름 자체가 함정이라는 게 보였다.
→글9(공유 원자: ADR-fresh-005 §외부adversarial점검 구조)