Skip to content
게으른 엔지니어의 기술 블로그
Go back

LLM 요약에서 한 번은 사라지고, 두 번은 살아남았다

Read in English →

확신을 실측 앞에 세워봤다 · 11/11편

만들고 있는 Obsidian 플러그인은 새 원본 문서를 넣으면 AI가 읽고 요약해서 위키 노트로 만들어준다 — 이 요약 명령이 /ingest다. 이 /ingest가 원문을 요약할 때, 사실관계(인용문, 수치)는 정확한데 “왜 그런가”에 대한 설명만 원문과 다르게 바뀌는 버그가 있었다. 같은 원문(전략에 관한 아티클), 같은 문단(다트 비유)에서 세 번 연속 반복됐다 — 처음엔 반대 의미로 바뀌었고(“정밀한 목표가 유용하다”), 이후 두 번은 아예 통째로 사라졌다. 모델을 gpt-5.6에서 gpt-6으로 올려도 그대로였다. 10편에서도 그럴듯한 원인을 실제로 검증해보니 아니었던 적이 있어서, 이번에도 같은 방식으로 접근했다.

문법이 문제인 줄 알았다 (원문 문법 오류 A/B 테스트)

문제의 문장을 다시 읽어보니 원문 자체에 진짜 문법 오류가 있었다(“but in the game of life it as an apt rule” — it is가 맞다). 문장 구조도 이중으로 꼬여 있었다 — “불스아이는 다트에서 최고점도 아닌데, 그게 인생에선 오히려 맞는 룰이다, 왜냐면 아무것도 안 가르쳐주니까.” 그럴듯한 원인이었다.

원문 사본에서 그 문법 오류 한 곳만 고치고(나머지는 전혀 안 건드림), 원본은 5번(시험 실행 1번 포함), 수정본은 4번 실제 ingest에 태웠다. 결과: 9번 전부 똑같이 누락됐다. 문법은 원인이 아니었다.

반직관적인 내용이 원인이라고 생각했다가, 바로 접었다

문법을 반증하자마자 “그럼 남은 건 이거지” 싶었다 — 이 문장이 담은 주장 자체가 반직관적이다(정밀함이 오히려 나쁘다는, 이 장르 콘텐츠의 흔한 통념과 정반대인 주장). 그렇게 기록까지 남겼다 — “소거법으로 남은 유력 가설.”

틀린 논리였다. 가설 하나를 반증했다고 다른 가설이 유력해지는 게 아니다. 곧바로 철회했다.

다른 소스로 직접 검증해봤다 (대조군 실험)

반직관적인 내용 자체가 원인인지 확인하려고, 완전히 다른 원문에서 훨씬 더 노골적으로 반직관적인 주장을 찾았다 — “게임이론이 설명하는, 똑똑한 사람이 못 이기는 이유”라는 기사, “열심히 할수록 오히려 더 잃는다”는 주장이다. 이걸 5라운드 ingest에 태웠더니, 전부 정확하게 보존됐다.

반직관적인 내용만으로는 이 버그가 안 생긴다는 뜻이었다.

두 문단을 나란히 놓고 보니 — 반복 횟수가 달랐다

다트 문단은 핵심 주장이 딱 한 문장, 한 번만 나온다. 게임이론 기사는 같은 문장(“Effort spent inside a rigged game gets absorbed by the game.”)을 볼드체로 두 번, 각각 구체적인 일화(달러 경매, 교통체증)로 뒷받침하며 반복한다.

이 차이를 직접 조작해봤다. 다트 문단 뒤에 짧은 문장 하나를 추가하는 실험을 두 갈래로 나눴다 — 하나는 같은 주장을 한 번 더 반복하는 문장, 하나는 관련 없는 그럴듯한 문장(플라시보). 결과: 반복 없는 기준선은 0/5, 플라시보는 1/8, 같은 주장을 반복한 쪽은 5/8까지 올라갔다. 단순히 문단이 길어져서가 아니라, 같은 주장이 반복된 것 자체가 레버였다.

마지막으로 반대 방향도 확인했다 — 같은 글, 같은 구조 안에서 완전히 평범한 주장(“장군은 행동 전에 정찰을 보낸다”)을 딱 한 번만 언급한 문장을 찾아 8라운드 돌려봤다. 8/8 전부 살아남았다.

세 개 모델에서 똑같이 재현됐다 — gpt-5.6-luna부터 gpt-6-sol까지

gpt-5.6-luna, gpt-6-luna, gpt-6-sol — 세 모델 전부에서 같은 패턴이 똑같이 나왔다. 모델을 새로 바꿔도 안 고쳐지는 이유였다.

탐지하고 고쳐보는 것까지는 됐다 — 다만 아직 코드엔 안 넣었다

이 정도로 원인이 좁혀지자, 고치는 방법도 자연스럽게 나왔다 — 누락·대체를 감지하는 좁은 검증 콜 하나, 걸리면 그 주장을 한 번 더 명시적으로 넣도록 고치는 좁은 수리 콜 하나. 5라운드 테스트해보니 감지는 5/5, 실제로 수리가 적용된 라운드는 전부(3/3) 성공적으로 복구됐다.

그런데도 코드에는 아직 안 넣었다. 지금까지 이 패턴이 확인된 원문은 딱 하나다. 프로덕션에 상시 콜을 하나 더 붙일 만큼 넓은 문제인지 아직 모른다. 대신 앞으로 매 ingest 라운드마다 이 패턴(반직관적이고 단 한 번만 언급된 주장)이 얼마나 자주 나오는지를 계속 세어보기로 했다 — 사례가 쌓이면 그때 구현을 다시 판단한다.

덧붙임: 그 뒤 실제 테스트마다 이 패턴을 세어 왔다. 10월 2023일 다섯 번의 실행(원문 여섯 개짜리 두 묶음)에서, 상식과 어긋나고 한 번만 나온 주장 1012개 중 3~6개가 매번 빠졌다. 인과를 바꿔 쓴 경우는 없었다. 한 원문만의 문제가 아니라는 근거가 쌓이는 중이지만, 아직 코드에는 넣지 않았다.

남는 생각

가설 하나를 반증한 순간, 남은 가설이 저절로 맞는 것처럼 느껴졌다. 그 착각을 실제로 저질렀고, 지적받고 나서야 알아챘다. 증명되지 않은 걸 증명된 것처럼 다루지 않으려면, “이것만 남았다”는 문장 자체를 의심해야 했다. 다행히 그다음에 진짜로 대조군을 만들어서 갈라봤고, 원인은 반직관적인 내용도 아니고 반복 부족도 아니고 그 둘의 조합이었다. 소거법 으로 그럴듯하게 들리는 설명과, 대조군으로 실제로 갈라낸 설명은 전혀 다른 무게를 가진다.


Share this post:

확신을 실측 앞에 세워봤다

  1. 1. 확신을 실측 앞에 세워봤다 1편 — 반례는 어휘만 가르쳤다
  2. 2. 확신을 실측 앞에 세워봤다 2편 — 하나만 보고 두 번 틀렸다
  3. 3. 확신을 실측 앞에 세워봤다 3편 — 닫은 지 몇 시간 만에, 내가 다시 열었다
  4. 4. 확신을 실측 앞에 세워봤다 4편 — 끊어진 링크는 잡아주는데, 안 끊어진 채 엉뚱한 곳을 가리키는 링크는 못 잡았다
  5. 5. 확신을 실측 앞에 세워봤다 5편 — 왜 관련있다고 생각했냐고 물으니, 답을 못했다
  6. 6. 확신을 실측 앞에 세워봤다 6편 — 실사용에서 못 봤다는 말 한마디가, 가설 두 개를 무너뜨렸다
  7. 7. 확신을 실측 앞에 세워봤다 7편 — 후보 두 개를 따로 넣어보니, 둘 다 효과가 없었다
  8. 8. 확신을 실측 앞에 세워봤다 8편 — 격리할수록 좋아진다는 것도 절반만 맞았다
  9. 9. 확신을 실측 앞에 세워봤다 9편 — 답은 두 문서 안이 아니라, 밖에 있었다
  10. 10. LLM 병합 프롬프트에서 규칙 하나가 빠진 걸 찾았는데, 채워도 똑같았다
  11. 11. LLM 요약에서 한 번은 사라지고, 두 번은 살아남았다