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

LLM 프롬프트 규칙을 두 번 고쳤는데, 정작 노트를 나누지 말았어야 했다

Read in English →

고치라는 지시부터, 다시 봐야 했다 · 6/8편

만들고 있는 Obsidian 플러그인은 기사 한 편을 넣으면 LLM이 그 안의 개념·인물·자료를 각각 별도 노트로 나눠 위키에 저장한다(ingest). 같은 원문에서 함께 만들어진 노트들을 여기서는 “형제 노트”라고 부른다. 이 글은 형제 노트 하나가 자기 내용 없이 링크만 남기고 텅 비던 버그를 프롬프트 규칙으로 두 번 고친 이야기다.

5편에서 사후 복구 방식을 두 번 제안했다가 두 번 다 정정당한 이야기를 다뤘다. 이번 편도 비슷하다 — 이번엔 정정이 한 번이 아니라, 원문을 다시 열어보고 나서야 겨냥한 자리 자체가 틀렸다는 걸 알았다.

노트 하나가 링크만 남기고 텅 비었다 — 중복 방지 프롬프트의 부작용

형제 노트끼리 같은 문단을 그대로 베끼는 버그를 임베딩+LLM 검증 파이프라인으로 잡은 뒤, 반대쪽 증상이 나타났다. MIT의 온라인 강좌 13개를 나열한 원문을 ingest한 결과에서, “AI and Algorithms”라는 강좌를 다루는 노트를 열어보니 본문에는 다른 노트를 가리키는 문장만 있었다. 세 번째 재현의 실제 결과 중 두 문장이다.

“AI and Algorithms situates [[Introduction to Machine Learning]] within the broader context of artificial intelligence and algorithms.”

“This resource is included in the [[wiki/2026/09/WeekOf14/Foundational AI Courses and Resources from MIT|Foundational AI Courses and Resources from MIT]] collection.”

자기가 무슨 강좌인지에 대한 설명은 한 마디도 없이, 전부 다른 노트로 떠넘기고 있었다. 같은 원문을 세 번 독립적으로 다시 ingest해봐도 이 노트만은 매번 똑같이 비어 있었다. 우연이 아니라 이 특정 쌍에서 결정적으로 재현되는 패턴이었다.

원인은 바로 전 라운드에 넣은 규칙이었다. 형제 노트 간 중복을 막으려고, 같은 사실이 여러 형제 노트와 관련되면 그 사실이 가장 직접적으로 속하는 노트 하나에만 쓰고 나머지는 링크로 가리키며 존재만 언급하게 하는 규칙을 넣어뒀는데, 이번엔 그 반대쪽 극단으로 튀어서 노트 하나를 통째로 비워버린 것이다.

1차 수정: “자기 정의는 반드시 남겨라” — 프롬프트에 반례 넣기

규칙에 단서를 하나 더 달았다. 중복 금지는 형제 노트와 실제로 겹치는 그 사실 하나에만 적용되는 것이고, 노트 자신이 무엇을 다루는 문서인지에 대한 최소한의 자기 정의까지 링크로 떠넘기라는 뜻은 아니라는 내용이었다. 그리고 이 정확한 강좌 쌍을 반례로 예시에 박아 넣었다.

같은 원문으로 다시 ingest를 두 번 돌렸다. 결과는 반반이었다. 한 번은 노트 요약 줄에 자기 설명이 들어갔다. 그런데 다음 번엔 똑같은 강좌가 또 텅 비어서 나왔다. 가설은 반은 맞고 반은 틀렸다 — “노트가 비면 안 된다”는 맞았지만, “그러니 다른 정의를 채워 넣으면 된다”는 틀렸다.

원문을 다시 열어보고 나서야 알았다

왜 절반은 여전히 실패하는지 이해가 안 가서, 원문으로 돌아가 그 강좌 두 개의 설명을 나란히 놓고 봤다.

AI and Algorithms: “Get an introduction to principles, algorithms, and applications of machine learning.”

Introduction to Machine Learning: “Get to know the principles, algorithms, and applications of machine learning.”

거의 같은 문장이었다. 모델이 규칙을 잘못 적용한 게 아니라, 원문 자체가 두 강좌에 사실상 똑같은 한 줄 설명을 붙여놓은 것이었다. “자기만의 정의를 반드시 써라”고 아무리 못 박아도, 애초에 “다른” 정의 자체가 원문에 없으니 모델 입장에서는 쓸 게 없었다. 내가 넣은 반례 자체가 전제부터 틀려 있었다.

돌아온 질문, “그럼 병합해야지, 링크가 왜 필요해?” — 원자적 노트 판단

이 상황을 정리해서 얘기했더니 돌아온 반응은 단순했다. 두 강좌 설명이 진짜 똑같다면, 애초에 노트를 두 개로 쪼갤 이유가 없지 않냐는 것이었다. 맞는 말이었다. 지금까지의 수정은 전부 “노트를 어떻게 쓸지”를 다루는 규칙 안에서 이루어지고 있었는데, 진짜 문제는 그보다 앞 단계 — 이 원본 하나를 몇 개의 노트로 쪼갤지 정하는 원자성 판단 단계에 있었다. 두 강좌를 별개 노트로 쪼개기로 이미 결정하고 나면, 그 뒤에 아무리 “본문을 어떻게 채울지” 규칙을 손봐도 한쪽은 구조적으로 빈 껍데기가 될 수밖에 없었다. 규칙을 아무리 다듬어도 못 이기는 싸움을, 엉뚱한 자리에서 계속하고 있었던 셈이다.

2차 수정: 쪼개는 단계에서 걸러내기 — 노트 분할 기준

원자성 판단 규칙에 새 기준을 추가했다. 두 항목이 서로 다른 URL이나 이름을 가진 별개의 자료로 보이더라도, 원문이 그 둘에 실제로 서술한 정의가 표현만 다를 뿐 실질적으로 같다면, 애초에 노트를 나누지 말고 하나로 합치라는 내용이었다. “서로 다른 실체”라는 판단을 URL이나 이름이 다르다는 사실만으로 내리지 말고, 원문이 실제로 구별되는 내용을 서술하는지로 판단하라는 조건도 같이 넣었다. 그리고 방금 그 강좌 쌍을 이번엔 “병합해야 하는 반례”로 그대로 박아 넣었다.

같은 원문으로 다시 두 번 독립적으로 ingest를 돌렸다. 이번엔 두 번 다 “AI and Algorithms and Introduction to Machine Learning”이라는 노트 하나로 합쳐져 나왔다. 본문도 텅 비지 않았다 — 왜 두 강좌를 하나로 묶었는지를 노트 스스로 설명하고 있었다.

“The source gives both resources essentially the same description: an introduction to the principles, algorithms, and applications of machine learning. Because the descriptions do not distinguish separate subject matter, they are documented together rather than as two notes with duplicated content.”

남는 생각

같은 증상을 두 번 고쳤는데, 첫 번째 수정은 절반만 통했고 두 번째 수정은 온전히 통했다. 둘의 차이는 규칙 문구를 얼마나 정교하게 썼느냐가 아니라, 그 문구를 어느 단계에 넣었느냐였다. “본문을 어떻게 채울지” 결정하는 단계에서 아무리 못을 박아도, 그보다 앞선 “애초에 몇 개로 쪼갤지” 결정 단계에서 이미 잘못된 전제가 깔려 있으면 뒤 단계의 규칙은 태생적으로 이길 수 없는 싸움을 하고 있는 셈이었다. “고치라는 지시”는 언제나 어딘가를 겨냥하고 있는데, 그 지시를 다듬는 것과 그 지시가 애초에 맞는 자리를 겨냥했는지는 다른 질문이었다. 이번엔 그 차이를 원문을 다시 열어보고 나서야 알아챘다.


Share this post:

고치라는 지시부터, 다시 봐야 했다

  1. 1. 고치라는 지시부터, 다시 봐야 했다 1편 — 죽은 주석을 고치다가, 또 틀렸다
  2. 2. 고치라는 지시부터, 다시 봐야 했다 2편 — 가설은 반은 맞고 반은 틀렸다
  3. 3. 고치라는 지시부터, 다시 봐야 했다 3편 — 고치기 전에 한 번 더 물었다
  4. 4. 고치라는 지시부터, 다시 봐야 했다 4편 — 지우라는 지시와, 어떻게 지울지는 다른 질문이었다
  5. 5. 정답은 이미 있었고, 안 쓴 쪽이 문제였다
  6. 6. LLM 프롬프트 규칙을 두 번 고쳤는데, 정작 노트를 나누지 말았어야 했다
  7. 7. LLM 언어 혼입을 잡으려 정성껏 만든 코드가, 실측해보니 한 일이 없었다
  8. 8. LLM 노트 과분할을 막을 장치를 설계하다가, 이미 있는 장치를 못 보고 있었다