AI 답변이 정확한 출처 문장을 인용하거나 모른다고 인정하게 만드는 파일 포맷을 구축했습니다
요약
RAG의 신뢰성 문제를 해결하기 위해 문장 단위의 근거를 강제하는 새로운 패키지 포맷인 AIPK를 소개합니다. .aipk 파일은 지식 베이스와 검증된 클레임을 포함하며, 모델이 답변 시 반드시 출처를 인용하도록 설계되었습니다.
핵심 포인트
- AIPK는 페르소나, 지식 베이스, 검증된 클레임을 포함하는 단일 바이너리 패키지 포맷입니다.
- 문장 단위의 '주장 추출'과 '엄격한 렌더링'을 통해 모델의 환각을 방지합니다.
- aipk verify를 통해 모델 답변의 인용이 실제 근거와 일치하는지 검증합니다.
- Rust 기반의 바이너리를 통해 OpenAI 호환 API로 변환하여 다양한 백엔드에서 사용 가능합니다.
RAG (Retrieval-Augmented Generation)에는 신뢰성 문제가 있습니다. 모델은 유창하게 답변하지만 아무것도 인용하지 않으며, 사용자는 소스 문서를 수동으로 확인하지 않고서는 사실과 자신감 있는 즉흥 연기(improvisation)를 구분할 수 없습니다. 이는 모델의 크기가 작아질수록 더 악화됩니다. 작은 모델들은 공백을 그럴듯한 내용으로 채울 가능성이 더 높고, 답변을 유보(hedge)할 가능성은 더 낮기 때문입니다.
저는 이 간극을 메우기 위해 AIPK라는 패키지 포맷을 구축해 왔습니다. 모델을 더 똑똑하게 만드는 방식이 아니라, 문장 단위로 _증명 가능한 근거(provably grounded)_를 갖게 하거나, 그렇지 않다는 사실을 명시적으로 드러내게 하는 방식입니다.
이것의 실체
.aipk 파일은 페르소나(persona), RAG 지식 베이스 (청크(chunks) + 임베딩(embeddings), 외부 벡터 DB 없음), 기술(skills), 도구 정의(tool definitions), 그리고 감사 가능한 클레임(claims) 세트(기초 문서에서 추출된 원자적이고 출처가 명확한 사실적 진술)를 포함하는 단일 바이너리 패키지입니다.
aipk serve는 약 9MB 크기의 Rust 바이너리로, .aipk 파일(또는 병합된 여러 파일)을 해당 프로토콜을 지원하는 모든 백엔드(Ollama, vLLM, 클라우드 API 등) 상에서 OpenAI 호환 API로 변환해 줍니다. 기존의 채팅 UI를 이 API로 연결하면 패키지가 하나의 모델로 나타납니다. 백엔드 모델을 교체하더라도 지식 베이스, 클레임, 감사 추적(audit trail)은 변경되지 않은 채 함께 이동합니다.
느낌(vibes)이 아닌 문장 수준의 출처(provenance)
대부분의 "근거 있는 RAG (grounded RAG)" 설정은 검색(retrieval) 단계에서 멈춥니다. 즉, 몇몇 청크를 컨텍스트 윈도우(context window)에 집어넣고 모델이 그 내용에 충실하기를 바랄 뿐입니다. AIPK는 그 위에 강제 및 감사 계층을 추가합니다:
- 주장 추출 (Claims extraction). LLM 패스(pass)가 소스 문서를 읽고 원자적 사실 진술(atomic factual statements)을 추출합니다. 문장 수준의 사실 하나당 하나의 진술을 추출하며, 각 진술에는 출처 태그가 붙습니다. 이 진술들은 신뢰받기 전까지 생명 주기(
extracted → reviewed → canonical → deprecated)를 거칩니다. - 엄격한 렌더링 (Strict-render). 이 모드에서는 시스템 프롬프트(system prompt)가 모델로 하여금 사실적 문장을 작성할 때마다 그 뒤에
[claim_id]인용을 붙이도록 요구합니다. 인용이 없으면 신뢰할 수 없습니다. aipk verify. 별도의 독립적인 패스(pass)가 모델의 답변을 문장 단위로 파싱(parse)하여, 모든 인용이 정식 주장(canonical claim)으로 연결되는지 확인하고 커버리지 점수(coverage score)를 보고합니다. 즉, 답변의 사실적 문장 중 모델의 자체 권위에 기반해 주장된 것이 아니라, 실제로 패키지 내의 내용에 의해 뒷받침되는 비율이 얼마인지를 측정합니다.
이 방식은 단어 하나하나가 일치하는 인용(word-for-word quote match)을 요구하지 않습니다. 그런 방식은 취약(brittle)하기 때문입니다. 대신 실제 검토를 거친 정식 주장(canonical claim)을 가리키는 유효한 ID를 요구합니다.
벤치마크 (The benchmark)
이 방식이 단순히 형식적인 절차를 추가하는 것에 그치지 않고 실질적인 변화를 만들어내는지 확인하기 위해, 저는 모델이 사전 학습(pretraining) 지식에 의존할 수 없도록 특별히 설계된 작은 가상의 코퍼스(corpus)를 구축했습니다. 여기에는 회사 핸드북, 사고 대응 표준 운영 절차(SOP), 그리고 존재하지 않는 로봇의 제품 사양서가 포함됩니다. 총 23개의 질문을 구성했습니다: 15개는 코퍼스에서 답변 가능하며, 8개는 의도적으로 답변할 수 없게 만들었습니다.
모델: 로컬에서 실행된 llama3.2:3b. 두 가지 조건: 일반적인 RAG(vanilla RAG) vs --strict-render, 두 조건 모두 aipk verify로 점수를 산출했습니다.
| 구분 | 일반 RAG 커버리지 | strict-render 커버리지 |
|---|---|---|
| 코퍼스 내 질문 (15개) | 0.933 | 0.983 |
| ... |
코퍼스가 진정으로 답변할 수 없는 8개의 질문에 대해, 일반적인 RAG는 8번 중 7번이나 그럴듯하게 들리는 답변을 생성했습니다. 일부 근거(grounding)가 있긴 했지만, 나머지는 조용히 허구로 채워 넣었습니다. 반면, strict-render는 8개 질문 모두에 대해 답변을 단호히 거부했습니다.
하나의 구체적인 예시 (One concrete example)
벤치마크 코퍼스(benchmark corpus)는 의도적으로 합성된 것이었습니다. 더 설득력 있는 테스트는 실제 데이터였습니다. 공식 Kubernetes 문서(CC-BY 4.0, 111 MB, 35,588개 청크, 1,354개 정전적 주장(canonical claims))로 구축된 패키지를 사용하여, 존재하지 않는 kubectl 플래그인 --force-evict에 대해 질문했습니다.
일반 모드(normal mode)에서는 모델이 이를 깔끔하게 잡아내고 실제 명령어로 대체했습니다. --strict-render를 켰을 때는 솔직하게 확답을 피하며("근거가 되는 정보가 불충분함") 답변했습니다. 그러고 나서 첫 번째 플래그가 왜 가짜인지 설명하는 동안 다른 가짜 플래그를 만들어냈습니다. 인용 전용 프롬프팅(Citation-only prompting)은 모델이 허구(fiction)를 쓰는 것을 막지는 못합니다. 다만 확인했을 때 그 허구가 눈에 보이게 만들 뿐입니다:
_aipk: canonical_used=0 invalid_ids=[] coverage=0.00 uncited_sentences=4 fully_grounded=false
정전적 인용(canonical citations) 0개, 커버리지(coverage) 0. 이는 시스템이 모델의 허세를 막은 것이 아니라, 허세를 잡아내어 구조화되고 기계가 확인 가능한 방식으로 알려주었음을 의미합니다.
도그푸딩(dogfooding)을 통해 실제로 발견한 것
벤치마크와 Kubernetes 패키지를 구축하면서 합성 단위 테스트(synthetic unit tests)에서는 나타나지 않았던 실제 결함들이 드러났습니다:
- 커버리지 보고서가 누락을 통해 거짓말을 했습니다. 기존의
fully_grounded체크는 이미 인용된 주장 ID(claim IDs)가 유효한지만 확인했습니다. 따라서 인용이 전혀 없는 답변도 아무런 문제 없이 통과되었습니다. 문장 중 인용을 포함하는 비율이 얼마인지 확인하도록 수정했습니다. - 토큰 제한(token limit) 누락으로 인해 전체 요청이 중단될 수 있었습니다. 생성 길이를 제한하는 장치가 없어, 가끔 정지 토큰(stop token)을 내보내지 못하는 모델은 무한히 생성할 수 있었습니다.
--max-tokens제한과 요청 타임아웃(request timeout)을 통해 수정했습니다. - 소수점이 문장을 나누고 있었습니다. "8.4 kWh"가 조용히 두 개의 문장으로 나뉘면서 주장 추출(claim extraction)을 망가뜨렸습니다. 문장 분할을 수행하는 세 곳 모두에서 수정했습니다.
이 중 어느 것도 생소한 것은 아닙니다. 현실적인 규모로 루프를 처음부터 끝까지 실행할 때만 나타나는 종류의 버그들입니다.
사용해 보기
.aipk 파일은 독립적입니다. 파일 하나로 구성되며, 오프라인 사용이 가능하고, OpenAI 호환되는 모든 로컬 또는 클라우드 백엔드에서 작동합니다.
curl -fsSL https://aipk.dev/install.sh | sh
Repo: https://github.com/ArchDuran/aipk
Site + demo video: https://aipk.dev
BSL 1.1에 따라 소스 공개 (Source-available) — 평가용, 개인 및 소규모 팀은 무료로 사용 가능하며, 대규모 상업적 생산 용도로는 상업 라이선스 (Commercial license)가 필요합니다.
커버리지 방법론 (Coverage methodology), 클레임 생명주기 (Claim lifecycle), 또는 이 방식이 여전히 한계를 보이는 부분에 대한 피드백을 진심으로 기다립니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기