Node.js Evidence Lifecycles: 문서 챗봇 답변 오류를 위한 RAG 환각 방지 5가지 해결책
요약
RAG 기반 챗봇의 환각 현상은 오래되거나 상충되는 증거(evidence)를 받을 때 발생하며, 단순히 임베딩이나 컨텍스트 창을 늘리는 것만으로는 해결하기 어렵습니다. 대신 버전 관리되는 증거 파이프라인 구축과 '증거 계약'을 통해 검색된 정보를 시스템적으로 검증하는 것이 중요합니다.
핵심 포인트
- RAG 환각은 오래되거나 상충되는 증거에서 발생하며, 단순한 임베딩 개선으로 해결 불가.
- 버전 관리되는 증거 파이프라인 구축이 핵심이며, 고정된 평가 세트로 재실행해야 함.
- 증거 계약(evidence contract)을 소유하고 모델 제공업체를 어댑터로 만드는 것이 권장됨.
- 인덱싱 단위에는 `repositoryId`, `revision` 등 안정적인 소스 좌표를 포함하여 추적 가능성을 확보해야 함.
간단히 말해, ask-your-docs 챗봇이 오래되거나 불완전하거나 상충되는 증거(evidence)를 받을 경우 RAG 환각은 지속됩니다. 따라서 좋은 임베딩(embeddings)과 더 큰 컨텍스트 창(context window)을 사용해도 여전히 잘못된 답변을 생성할 수 있습니다. 코드 변경 사항을 검토하는 에듀테크 어시스턴트의 경우, 실질적인 해결책은 버전 관리되는 증거 파이프라인(versioned evidence pipeline)입니다. 즉, 코스와 리포지토리 개정판을 고정하고, 요구사항과 변경된 코드를 별도로 검색하며, 약한 증거는 거부하고, 작은 발견 스키마(finding schema)를 검증하며, 출시 전에 고정된 평가 세트(fixed evaluation set)로 재실행하는 것입니다.
| 선택지 | 잘못된 답변 위험도 | 제공업체 이식성 | 운영 부담 |
|---|---|---|---|
| 가장 가까운 청크를 생성에 직접 전송 | 개정판이나 문서 유형이 충돌할 때 높음 | 프롬프트가 단일 제공업체의 응답 형태에 의존하는 경우 낮음 | 낮음 |
권장 사항: Node.js에서 증거 계약(evidence contract)을 소유하고 모델 제공업체를 어댑터(adapter)로 만드세요. 이는 단일 프롬프트를 사용하는 것보다 더 많은 엔지니어링 시간을 필요로 하지만, 1인 SaaS에서 귀중한 자원—주간 제품 출시에 투입되어야 할 시간이지 그럴듯한 발견 사항을 수동으로 검토하는 시간이 아닙니다—을 보호해 줍니다.
1. RAG 기반 ask-your-docs 챗봇이 잘못된 답변을 하는 이유는 무엇인가요?
임베딩은 '어떤 인덱싱된 구절들이 질의와 관련성이 높은가?'라는 좁은 질문에 답합니다. 하지만 코드 검토 어시스턴트는 더 어려운 답변, 즉 '어떤 구절들이 이 정확한 변경 사항, 리포지토리 개정판, 과제, 언어 및 정책 버전에 대한 권위적인 정보인가?'를 필요로 합니다.
이들은 서로 다른 작업입니다.
학습자가 수정 버전 8f21c4a에서 gradeSubmission()을 변경했다고 상상해 봅시다. 인덱스에는 현재 루브릭, 지난 학기 루브릭, 강사 예외 사항, 생성된 API 문서, 그리고 구식 동작을 인용한 토론 내용이 포함되어 있습니다. 의미적으로 유사한 청크라도 권위나 유효한 수정 버전이 잘못되었다면 무관할 수 있습니다. 컨텍스트 창(context window)을 늘리는 것은 상황을 더 악화시킬 수 있습니다. 두 규칙 모두 이제 적합해지므로, 생성 과정은 더 많은 진실보다는 더 많은 모순을 받게 됩니다. 저의 원칙은 간단합니다. 신선도(freshness)는 유사성 힌트가 아니라 강력한 필터여야 합니다. 인덱싱되는 모든 단위에는 repositoryId, revision, documentKind, effectiveFrom, supersedesId와 같은 필드와 안정적인 소스 좌표를 포함해야 합니다. “핸드북 어딘가에서” 인용하는 발견 사항은 검토할 수 없습니다. 파일, 심볼, 루브릭 항목, 그리고 불변의 콘텐츠 다이제스트(content digest)에 연결된 것이야말로 그렇습니다. 저는 약간 더 단순한 인제스션 작업(ingestion job)을 위해 그 추적 가능성(traceability)을 포기하지 않을 것입니다. 왜냐하면 나중에 디버깅 비용은 다음 기능을 출시하려는 동일한 사람에게 돌아가기 때문입니다.
버전이 우선입니다.
이는 디버깅 질문 자체를 바꿉니다. 단지 “상위 5개 청크에 올바른 것이 있었나?”라고 묻는 것을 멈추세요. 대신, “검토된 수정 버전(reviewed revision)에 대해 모든 적격 청크가 유효했는지, 그리고 구 버전 규칙이 인제스션 과정에서 살아남았는지?”를 물어보세요. 두 번째 질문은 임베딩 교체나 더 큰 창 크기로는 잡을 수 없는 종류의 실패 사례들을 포착합니다.
2. 검색(retrieval)을 시스템이 검증할 수 있는 주장(claims)으로 분리하기
차이점(diff)과 루브릭은 서로 다른 역할을 합니다. 차이점은 무엇이 변경되었는지 설명합니다. 루브릭은 무엇이 참이어야 하는지 정의합니다. 이 둘을 하나의 벡터 쿼리로 혼합하면 편리한 텍스트 묶음(bag of text)이 생성되지만, 모델이 추론해야 할 때 그 구분을 지워버립니다.
두 개의 검색 경로를 사용하세요. 첫 번째 경로는 변경된 파일, 주변 심볼, 테스트, 그리고 고정된 기본 수정 버전으로부터 코드 증거를 해결합니다. 두 번째 경로는 활성 과제 루브릭(assignment rubric)과 적용 가능한 강사 규칙으로부터 정책 증거를 해결합니다. 이 둘은 각각의 경로가 메타데이터 필터를 통과한 후에만 결합하세요. 이는 의도적으로 지루한 인프라입니다. 지루함이 배포됩니다.
조인(join)은 “새 브랜치는 미평가 상태를 반환할 수 있다”와 같은 명시적인 주장 후보군을 코드 좌표 및 해당 상태를 무효화하는 루브릭 조항과 쌍으로 생성해야 합니다. 어느 한쪽이라도 누락된 경우, 아직 발견된 사항(finding)은 없습니다. 단지 검색 단서(search lead)만 있을 뿐입니다.
청크 경계가 여기서 중요하지만, 고정 토큰 수는 둔감한 기본값입니다. 함수의 시그니처는 유지하고, 루브릭 요구사항과 그 예외를 유지하며, 부모 제목은 메타데이터로 보존해야 합니다. 오버랩(overlap)은 경계 케이스에 도움이 될 수 있지만, 과도한 오버랩은 증거를 중복시키고 여러 검색된 청크가 독립적인 지원처럼 보이게 할 수 있습니다. 생성 전에 소스 식별자 및 콘텐츠 다이제스트로 중복 제거해야 합니다.
주간 릴리스 주기라면, 유지 관리되는 파서(parser)가 이미 존재하는 곳은 파싱을 아웃소싱하고 도메인 규칙은 애플리케이션 코드에 보관하는 것이 좋겠습니다. 차별화 요소는 마크다운(Markdown) 분할이 아닙니다. “늦은 제출 예외”가 일반 기한을 특정 명명된 과제 코호트(cohort)에 대해서만 무효화한다는 것을 아는 것입니다.
3. 산문 요청 전에 증거 게이트(Gate evidence)하기
유사도 점수(Similarity scores)는 보정된 진리 확률이 아닙니다. 블로그 게시물에 보편적인 절단점(universal cutoff)을 인쇄하고 그것이 임베딩 모델, 코퍼스, 거리 함수 전반에 걸쳐 적용된다고 착각하지 마십시오. 자체 코퍼스의 레이블링된 쿼리에서 임계값(thresholds)을 선택한 다음, 그 임계값을 리트리버와 함께 버전 관리해야 합니다.
게이트는 여전히 결정론적 규칙이 필요합니다. 초기 구현을 위한 간결한 계약은 다음과 같습니다:
type Evidence = {
sourceId: string;
digest: string;
...
minimumScore는 마법의 숫자가 아니라 평가에서 파생된 설정값입니다. 개정(revision) 동등성 검사(equality checks)가 유사도의 또 다른 소수점보다 더 중요합니다. 만약 admitEvidence가 null을 반환한다면, 올바른 응답은 타입이 지정된 insufficient_evidence 결과여야 합니다. 생성기에게 즉흥적으로 꾸며내라고 요청하지 마십시오.
해당 거부 경로는 제품의 동작 방식이므로 의도적으로 설계해야 합니다. 누락된 루브릭을 요청하거나, 인덱싱을 기다리거나, 변경 사항을 인간 검토로 라우팅할 수 있습니다. OWASP는 LLM 애플리케이션에 대한 가이드라인에서 과도한 에이전시(agency)와 과도한 의존성을 위험 영역으로 다루며, 권한 부여 및 결과적인 동작을 생성된 산문 밖으로 유지하는 것이 동일한 방어 경계를 따릅니다.
4. 모든 발견 사항이 스스로 증명하도록 하라
자유 형식의 검토 텍스트는 검색 결함을 숨깁니다. 타이핑된 결과는 이를 노출합니다.
각 발견 사항에 코드 위치, 위반 규칙, 지원 소스 식별자 및 애플리케이션에서 정의한 신뢰도 카테고리를 명시하도록 요구하십시오. 그런 다음 풀 리퀘스트나 학습자 대시보드에 도달하기 전에 객체를 검증해야 합니다. JSON Schema는 유용합니다. 왜냐하면 검증이 모델 외부에서 이루어지며 제공업체별 SDK에 의존하지 않기 때문입니다.
type Finding = {
summary: string;
severity: "info" | "warning" | "error";
...
두 개의 증거 식별자를 요구하는 것은 이 예시에서 애플리케이션 정책일 뿐, 보편적인 법칙은 아닙니다. 하나는 코드에, 다른 하나는 규칙에 연결되어야 합니다. 프로덕션 환경에서는 멤버십뿐만 아니라 그러한 종류의 식별자도 검증해야 합니다. 또한 인용된 스팬(span)이 실제로 저장된 로케이터에서 발생했는지 확인하십시오. 구문적으로 유효한 인용이라도 주장을 뒷받침하지 않는 증거를 가리킬 수 있습니다.
이식 가능한 경계는 작게 유지하십시오: 입력 메시지, 타이핑된 결과, 그리고 그 옆에 사용 및 타이밍 메타데이터만 포함합니다. 제공업체별 도구 호출(tool calls), 토큰 계정(token accounting), 안전 필드(safety fields) 및 재시도 의미론(retry semantics)은 어댑터 내부에 속해야 합니다. 핵심 검토 서비스는 어떤 SDK가 후보 객체를 생성했는지 알 필요가 없습니다.
이식성에는 한계가 있습니다. 서로 다른 모델이 동일한 증거를 다르게 해석할 수 있으므로, 어댑터를 교체하는 것이 동등한 동작의 증거가 아닙니다. 제공업체나 모델 변경을 승격하기 전에 동일한 평가를 실행하십시오.
5. 프롬프트뿐만 아니라 검색 시스템 자체를 출시하라
문서 기반 질의응답(ask-your-docs) 시스템은 최소한 네 가지 독립적으로 변경되는 아티팩트를 가집니다: 원본 문서, 청킹기 및 메타데이터 추출기, 검색 구성, 그리고 생성 구성입니다. 모든 추적 기록에 이들의 버전을 기록해야 합니다. 이 튜플이 없으면 인덱스가 변경된 후 잘못된 답변을 재현할 수 없습니다.
'황금(golden)' 문구를 지어내지 않고 실제 도메인 형태로부터 작은 회귀 테스트 세트를 구축하십시오. 각 케이스는 고정된 차이점(pinned diff), 활성 규칙, 예상 증거 위치 지정자(expected evidence locators), 허용되는 발견 카테고리, 그리고 반드시 기피해야 하는 명시적 사례를 포함해야 합니다. 적대적 사례도 포함시키십시오: 더 나은 어휘 중첩을 가진 구식 평가 기준표, 함수 이름을 공유하는 두 개의 과제, 삭제된 테스트, 그리고 신뢰할 수 없는 원본 텍스트 내에 삽입된 정책 발췌문 등입니다. OWASP는 프롬프트 주입(prompt injection)을 핵심 LLM 애플리케이션 위험으로 식별하므로, 검색된 콘텐츠는 지침이 아닌 데이터로 취급되어야 합니다.
각 단계를 개별적으로 측정하십시오. 검색 재현율(Retrieval recall)은 필요한 증거가 파이프라인을 통과했는지 여부를 묻습니다. 인용 정밀도(Citation precision)는 인용된 자료가 발견을 뒷받침하는지 여부를 묻습니다. 스키마 유효성(Schema validity)은 다운스트림 코드가 결과를 안전하게 구문 분석할 수 있는지 여부를 묻습니다. 기피 테스트(Abstention tests)는 누락되거나 상충되는 증거가 출판을 막는지 여부를 묻습니다. 단일 '답변 품질' 점수는 어떤 구성 요소를 수정해야 하는지 알려줄 수 없습니다.
만약 한 사람이 유지할 수 있는 수준이라면, 30개에서 50개의 신중하게 검토된 케이스로 시작하십시오. 그 숫자는 통계적 보장이 아니라 워크플로우 선택입니다. 새로운 실패 형태가 나타날 때마다 사례를 추가하십시오. 문서가 재인덱싱되거나, 검색 로직이 변경되거나, 프롬프트가 변경되거나, 제공업체 어댑터(provider adapter)가 변경될 때 이 세트를 실행하십시오. 결정론적 실패에 대해서는 출판을 차단하고, 출시 전에 의미론적 차이를 검토하십시오.
이는 시간당 수익에 대한 결정입니다: 재현 가능한 증거에 노력을 한 번 투자하여 불투명한 챗봇 출력물을 반복적으로 검사하는 것을 피하십시오. 매주 배포하되, 인덱스, 검색기(retriever), 생성기를 하나의 테스트된 출시 단위로 홍보하십시오. 더 큰 컨텍스트는 입력 예산입니다. 그것은 정확성 메커니즘이 아닙니다.
출처
다음은 참고 자료 목록입니다:
- https://owasp.org/www-project-top-10-for-large-language-model-applications/
- https://owasp.org/www-project-top-10-for-large-language-model-applications/LLM01_2025-Prompt_Injection/
- https://owasp.org/www-project-top-10-for-large-language-model-applications/LLM06_2025-Excessive_Agency/
- https://json-schema.org/draft/2020-12/json-schema-core
- https://www.rfc-editor.org/rfc/rfc8785
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기