본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 31. 02:05

LLM이 스스로 증거를 조작하는 것을 포착한 방법

요약

Graph RAG 파이프라인 구축 중 LLM이 존재하지 않는 인용구를 생성하는 증거 조작(Fabrication) 문제를 다룹니다. 컨텍스트 절단이 환각을 유발함을 지적하며, 인용구가 원문과 정확히 일치하는지 검증하는 엄격한 확인 절차를 해결책으로 제시합니다.

핵심 포인트

  • LLM은 텍스트 생성기이므로 인용구를 그대로 복사하지 않고 조작할 수 있음
  • 말줄임표(...)를 사용해 서로 다른 문장을 결합하는 위험한 환각 패턴 존재
  • 컨텍스트 윈도우를 위해 본문을 자르는 행위가 증거 조작을 심화시킴
  • 해결책은 모델 검증이 아닌 원문과의 정확한 부분 문자열(substring) 일치 확인

내 Graph RAG 파이프라인 뒤에 있는 언어 모델(Language Model)은 단순히 사실을 틀리는 것보다 더 나쁜 행동을 했습니다. 바로 증거를 조작(Fabricate)한 것입니다. 모델이 추출한 각 관계(Relation)에는 원문 기사에서 직접 가져왔어야 할 인용구가 포함되어 있었는데, 그 인용구 중 상당수는 실제로 작성된 적이 없는 것들이었습니다. 문장은 완벽하게 읽혔지만, 존재하지 않는 문장이었습니다.

지식 그래프(Knowledge Graph)에서 조작된 증거란 무엇을 의미하는가?

나는 무역 및 관세 뉴스에 대한 인과 관계 체인 지능 시스템인 2asy.ai를 위한 시드 지식 그래프(Seed Knowledge Graph)를 구축하고 있습니다. 그래프 내의 모든 관계와 이벤트는 증거(Evidence) 필드를 포함합니다. 즉, 해당 내용을 정당화하는 원문 문서의 정확한 문장입니다. 이 증거가 핵심입니다. 증거가 있어야 나 혹은 독자가 모델을 맹목적으로 믿는 대신, 주장이 어디에서 왔는지 역추적할 수 있기 때문입니다.

문제는 내가 언어 모델에게 원문을 인용하여 그 증거를 생성하도록 요청했다는 점입니다. 그리고 언어 모델은 텍스트 생성기(Text Generator)이지, 복사기(Copier)가 아닙니다. 원문 기사와 증거를 대조해 보았을 때, 인용구의 상당 부분이 그대로 옮겨온 것이 아니었습니다. 그것들은 유창하고 주제에 부합했지만, 지어낸 것이었습니다.

말줄임표가 결정적인 단서였다

가장 명확한 패턴은 말줄임표(...)였습니다. 모델은 기사의 완전히 다른 부분에서 두 문장을 가져온 뒤, 그 사이에 ...를 넣고 그 결과를 하나의 연속된 인용구처럼 제시했습니다. 그 경계선은 마치 일반적인 편집상의 생략처럼 보였습니다. 하지만 그렇지 않았습니다. 그것은 모델이 이미 추출하기로 결정한 관계를 뒷받침하기 위해 조작된, 서로 관련 없는 두 파편의 결합이었습니다.

이것은 매우 위험한 종류의 환각(Hallucination)입니다. 왜냐하면 실제 증거와 똑같은 형태를 띠고 있기 때문입니다. 틀린 사실은 눈에 띕니다. 하지만 사실을 의역하여 만든 조작된 인용구는, 원문으로 돌아가 글자 하나하나를 직접 찾아보기 전까지는 완전히 신뢰할 수 있는 것처럼 읽힙니다.

입력값의 길이를 자르는 것이 상황을 악화시킨 이유

저는 무해해 보이는 작업을 수행해 왔습니다. 적절한 컨텍스트 윈도우 (Context Window) 범위를 유지하기 위해 추출 전 각 기사의 본문을 수천 자로 자르는 (truncating) 작업이었습니다. 하지만 그 절단 작업이 조용히 조작 (fabrication)을 허용하고 있었습니다. 관계를 실제로 뒷받침하는 문장이 절단 지점 너머에 있을 때, 모델은 거절하지 않았습니다. 대신 모델은 누락된 텍스트가 아마도 무엇을 말했을지에 대해 자신감 있게 재구성하여 그 공백을 채웠습니다.

그래서 저는 절단 작업을 완전히 제거하고, 수집기 (collectors)를 '전체 본문 또는 건너뛰기 (full-body-or-skip)' 방식으로 전환했습니다. 즉, 파이프라인이 기사의 전체 텍스트를 가지고 있거나, 아니면 해당 문서를 아예 처리하지 않도록 한 것입니다. 누락된 문서보다 부분적인 문서가 더 위험합니다. 부분적인 문서는 여전히 출력을 생성하며, 그 출력은 완성된 것처럼 보이기 때문입니다.

해결책: 인용구를 채점하지 말고, 확인하라

해결책은 당황스러울 정도로 간단하며, 바로 그것이 핵심입니다. 커밋 (commit) 시점에, 어떤 관계가 그래프에 기록되기 전에, 저는 해당 증거 문자열 (evidence string)이 소스 문서의 정확한 부분 문자열 (substring)로 나타나는지 확인합니다. 만약 인용구가 텍스트에 문자 그대로 존재하지 않는다면, 해당 관계는 거부됩니다. 퍼지 매칭 (fuzzy matching)도 없고, 증거가 충분히 좋은지 판단하도록 요청하는 두 번째 모델도 없습니다.

이런 상황에서 본능적으로는 첫 번째 모델을 검증하기 위해 또 다른 언어 모델을 사용하려 하게 됩니다. 저는 그 본능이 대개 틀렸다고 생각합니다. 결정론적인 문자열 연산 (deterministic string operation)으로 출력을 확인할 수 있다면, 하나의 생성기 (generator)를 다른 생성기로 채점하는 대신 그 방법을 사용하십시오. 부분 문자열 테스트 (substring test)는 그럴듯한 답변을 하도록 설득할 수 없습니다. 비용이 저렴하고, 정확하며, 환각 (hallucinate)을 일으킬 수 없습니다.

이미 배포된 데이터 정리하기

가드 (guard)는 새로운 조작을 막아주지만, 이미 그래프에 자리 잡고 있는 관계들을 되돌리지는 않습니다. 그래서 저는 이미 커밋된 모든 항목에 대해 동일한 부분 문자열 확인 작업을 역으로 실행했습니다. 증거가 서로 다른 문장들로부터 짜깁기된 122개의 문서를 되돌렸고, 인용구가 소스와 단순히 일치하지 않는 수백 개의 문서를 추가로 정리했습니다. 정리 과정을 거치며 총 500개 이상의 문서가 처리되었습니다.

그 수치는 애초에 신뢰할 수 있는 생성된 증거를 확보하기 위해 지불해야 하는 실제 비용입니다. 해당 문서들은 모두 깔끔하게 작동하는 파이프라인을 통과했으며, 올바르게 보이는 결과물을 생성했습니다. 이 정제 작업의 규모는 아무도 소스(source)와 대조하여 확인하지 않을 때, 조작된 증거가 얼마나 설득력 있게 다가오는지를 보여주는 척도입니다.

교훈: 포인터(pointer)를 저장하고, 코드로 검증하라

언어 모델(Language Model)을 사용하여 텍스트에서 구조화된 주장(structured claims)을 추출하고 있다면, 모델이 제공하는 모든 인용구는 문자열 연산(string operation)을 통해 확인될 때까지 사실이 아닌 하나의 가설로 취급하십시오. 증거를 모델이 충실히 복사했을 것이라고 믿는 자유 형식의 텍스트(free text)로 저장하지 말고, 검증 가능한 형태인 스팬(span) 또는 정확한 부분 문자열(substring)로 저장하십시오.

이 모든 과정은 RTX 4090과 AMD W6800이 장착된 로컬 하드웨어에서 실행되며, 추출 작업에는 오픈 모델(open models)이 사용되었습니다. 부분 문자열 가드(substring guard)는 추가적인 모델 호출이나 클라우드 비용을 발생시키지 않습니다. 신뢰할 수 있는 그래프와, 완전한 문장으로 당신에게 조용히 거짓말을 하는 그래프 사이에는 단 몇 줄의 코드만이 존재할 뿐입니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0