사례 노트 환각 현상에 대한 나의 해결책은 이상할 정도로 지루했다: 컨텍스트를 채워 넣는 것을 멈추고 작업을 둘로 나누기
요약
노트 데이터를 실행 계획으로 변환할 때 발생하는 AI 환각 현상을 해결하기 위해, 단일 프롬프트 대신 작업을 두 단계로 분리하는 아키텍처적 접근법을 제안합니다. 1단계에서 원문 인용구를 추출하고, 2단계에서 해당 인용구에만 기반해 결과물을 생성함으로써 데이터의 근거(grounding)를 확보합니다.
핵심 포인트
- 단일 프롬프트의 과도한 작업 수행은 환각의 주요 원인임
- 더 큰 모델이나 긴 컨텍스트보다 아키텍처 개선이 효과적임
- 2단계 패턴: 원문 인용구 추출 후 이를 기반으로 결과 생성
- 데이터 추출 과정에서 증거에 대한 관리 연속성 확보 필요
나는 노트-액션 (note-to-action) 워크플로우에서 동일한 실패 모드를 계속 목격하고 있습니다:
- 상담 노트 (therapy notes) -> 실행 계획 (action plan)
- 사고 보고서 (incident report) -> 후속 조치 단계 (follow-up steps)
- 인사(HR) 사례 로그 (HR case log) -> 권장 사항 (recommendation)
- 접수 노트 (intake notes) -> 분류 (classification) + 우선순위 (priority)
모델의 출력물은 매끄럽게 들립니다.
하지만 소스 노트를 역추적해 보면 추론의 절반이 엉망이라는 사실을 깨닫게 됩니다.
항상 완전히 조작되는 것은 아닙니다. 그저... 신뢰할 수 있을 만큼 근거(grounded)가 충분하지 않을 뿐입니다.
OpenClaw를 사용하여 상담 노트를 실행 계획으로 변환하려는 사람의 r/openclaw 스레드를 읽은 후 이 문제에 다시 몰입하게 되었습니다. 문제는 고통스러울 정도로 익숙했습니다. 에이전트(agent)가 노트를 읽을 수는 있었지만, 권장 사항이 실제 증거에서 벗어나고 있었습니다.
한 답변이 스레드 전체에서 가장 좋은 해결책을 제시했습니다:
데이터 추출 (data extraction)에서의 환각 (Hallucination)은 대개 프롬프트 (prompt)가 너무 개방적이거나 컨텍스트 윈도우 (context window)가 혼잡할 때 발생합니다. 2단계 검증 프로세스를 구현해 보세요. 먼저 에이전트가 실행 항목을 뒷받침하는 노트의 원문 인용구 (raw quotes)를 추출하게 하고, 그다음 두 번째 단계에서 오직 그 인용구들에만 기반하여 실행 계획을 생성하도록 하세요.
그 답변은 지루합니다.
그것이 바로 내가 그 답변을 신뢰하는 이유입니다.
진정한 해결책은 대개 다음과 같은 것들이 아닙니다:
- 더 똑똑한 시스템 프롬프트 (system prompt)
- 더 큰 모델 (bigger model)
- 1M-토큰 컨텍스트 윈도우 (1M-token context window)
- 더 정교한 에이전트 루프 (agent loop)
진정한 해결책은 아키텍처 (architectural)에 있습니다.
작업을 둘로 나누십시오.
실제 버그: 너무 많은 일을 수행하는 하나의 프롬프트
단일 패스(single-pass) 노트-액션 프롬프트는 보통 한 번의 모델 호출 (model call)로 다음의 모든 일을 한꺼번에 수행하도록 요청합니다:
- 지저분한 노트 읽기
- 무엇이 중요한지 결정하기
- 사례 분류하기
- 누락된 컨텍스트 추론하기
- 리스크 우선순위 지정하기
- 권장 사항 생성하기
- 이유 설명하기
이것은 하나의 작업이 아닙니다.
이것은 단일 프롬프트 내부에서 열리는 위원회 회의와 같습니다.
민감한 워크플로우의 경우, 바로 이 지점에서 문제가 잘못됩니다.
만약 당신이 노트를 처리하고 후속 액션을 트리거하기 위해 OpenClaw, n8n, Make, Zapier 또는 커스텀 에이전트 스택 (custom agent stack)을 사용하고 있다면, 모델이 이 모든 단계를 한 번에 즉흥적으로 처리하게 해서는 안 됩니다.
증거에 대한 관리 연속성 (chain of custody)를 확보해야 합니다.
2단계 패턴 (The two-pass pattern)
이것이 제가 가장 먼저 출시할 버전입니다.
| 접근 방식 | 실제로 일어나는 일 |
|---|---|
| 단일 단계 노트-액션 프롬프트 (Single-pass note-to-action prompt) | 하나의 모델 호출이 추출 (extraction), 분류 (classification), 권장 사항 (recommendations) 생성을 한꺼번에 수행합니다. 프로토타입 제작은 빠르지만, 권장 사항이 노이즈가 섞인 전체 컨텍스트 (context)로부터 생성되므로 드리프트 (drift)를 포착하기 어렵습니다. |
| 2단계 근거 기반 워크플로우 (Two-pass grounded workflow) | 1단계에서 출처 참조와 함께 증거 또는 인용구를 추출합니다. 2단계에서는 승인된 증거만을 사용하여 권장 사항을 생성합니다. 감사 가능성이 더 높고, 디버깅이 쉬우며, 민감한 워크플로우에서 훨씬 안전합니다. |
1단계: 증거만 추출 (extract evidence only)
권장 사항을 요구하지 마세요.
종합 (synthesis)을 요구하지 마세요.
다음 사항을 요구하세요:
- 축자 인용 (verbatim quotes)
- 구조화된 사실 (structured facts)
- 출처 참조 (source references)
- 필요한 경우 신뢰도 또는 모호성 플래그 (confidence or ambiguity flags)
예시 스키마 (schema):
{
"evidence": [
{
...
2단계: 증거로부터 권장 사항만 생성 (generate recommendations from evidence only)
이제 모델은 훨씬 더 작은 입력을 받게 됩니다.
거대한 노트 덩어리도, 숨겨진 방해 요소도 없습니다. 오직 추출된 증거뿐입니다.
모든 권장 사항은 증거 ID (evidence IDs)를 인용해야 합니다.
{
"recommendations": [
{
...
3단계: 기권 또는 에스컬레이션 (abstain or escalate)
이것은 팀들이 건너뛰는 단계입니다.
증거가 취약하거나, 상충되거나, 불완전한 경우, 워크플로우는 다음을 반환해야 합니다:
- 증거 불충분 (insufficient evidence)
- 인간의 검토 필요 (needs human review)
- 분류 불가 (unable to classify)
이것은 실패가 아닙니다.
이것은 작동하는 안전 장치입니다.
왜 더 많은 컨텍스트를 채워 넣는 것이 종종 출력을 악화시키는가
사람들은 여전히 긴 컨텍스트 (long context)가 근거 제시 (grounding) 문제를 자동으로 해결하는 것처럼 이야기합니다.
그렇지 않습니다.
큰 컨텍스트 창 (context window)은 모델이 더 많은 텍스트를 받을 수 있음을 의미할 뿐입니다. 그것이 모델이 올바른 텍스트를 신뢰성 있게 사용할 것임을 의미하지는 않습니다.
그것이 중요한 차이점입니다.
"중간에서 길을 잃음 (Lost in the Middle)" 결과는 거대한 프롬프트가 실제 환경에서 왜 성능이 떨어지는지를 설명하는 가장 명확한 이유 중 하나입니다. 긴 컨텍스트의 중간에 묻혀 있는 관련 정보는 모델이 놓치기 더 쉽습니다.
이는 우리 중 많은 이들이 운영 환경 (production)에서 목격하는 현상과 일치합니다.
당신은 아무것도 빠뜨리지 않는 것이 더 안전하다고 느끼기 때문에 모든 노트, 모든 이전 이력, 메타데이터 (metadata), 정책 텍스트 (policy text), 그리고 거대한 지시문 블록 (instruction block)을 쑤셔 넣습니다.
하지만 이제 중요한 문장은 무관한 세부 사항들 사이에 끼어 8페이지 어딘가에 묻혀버립니다.
모델은 더 많은 텍스트를 갖게 되지만,
더 나은 근거 제시 (grounding) 능력을 갖게 되는 것은 아닙니다.
이것이 바로 실제 시스템에서 검색 (retrieval)과 범위가 지정된 증거 추출 (scoped evidence extraction)이 컨텍스트 스터핑 (context stuffing)을 계속해서 이기는 이유입니다.
긴 컨텍스트 (Long context)는 유용합니다. 다만 모든 작업에 적합한 것은 아닐 뿐입니다.
저는 긴 컨텍스트를 반대하는 것이 아닙니다.
긴 컨텍스트는 다음과 같은 경우에 훌륭합니다:
- 정책 질의응답 (policy Q&A)
- 문서와의 채팅 (chat-with-documents)
- 안정적인 코퍼스 (corpus)에 대한 반복적인 분석
- 방대한 참조 자료에 대한 캐시된 프롬프트 (cached prompts)
만약 제가 Claude나 GPT-5가 핸드북에 관한 질문에 답하기를 원한다면, 거대한 캐시된 프롬프트는 우아한 해결책이 될 수 있습니다.
하지만 제가 모델이 민감한 노트를 권장 사항으로 변환하기를 원한다면, 저는 먼저 증거 추출 (evidence extraction)을 수행하기를 원합니다.
작업이 다르면, 실패 모드 (failure mode)도 다릅니다.
OpenAI 호환 클라이언트를 이용한 실질적인 구현
이 부분이 개발자들에게 유용한 지점입니다.
만약 당신의 스택이 이미 OpenAI API와 통신하고 있다면, 앱 아키텍처 (architecture)를 다시 작성하지 않고도 보통 이 2단계 패턴 (two-pass pattern)을 구현할 수 있습니다.
가장 좋은 워크플로우 (workflow)의 변화는 실제로 배포할 수 있는 변화이기 때문에 이 점은 매우 중요합니다.
다음은 OpenAI Node SDK 형식을 사용한 최소한의 예시입니다.
1단계: 증거 추출 (evidence extraction)
import OpenAI from "openai";
const client = new OpenAI({
...
2단계: 추출된 증거만을 기반으로 한 권장 사항 (recommendations)
const extractedEvidence = extraction.output_text;
const plan = await client.responses.create({
...
몇 가지 실질적인 참고 사항:
- 두 단계 모두에 동일한 모델을 사용할 수 있습니다.
- 추출은 더 저렴한 모델로, 권장 사항은 더 강력한 모델로 라우팅 (route)할 수 있습니다.
- 단계 사이에 JSON을 검증 (validate)할 수 있습니다.
- 1단계 이후에 인간의 검토 (human review)를 삽입할 수 있습니다.
마지막 사항은 민감한 워크플로우에서 매우 중요합니다.
왜 이 패턴이 Standard Compute에 매우 잘 맞는지
이것은 토큰당 과금 (per-token pricing) 방식이 빠르게 짜증스럽게 변하는 바로 그런 종류의 워크플로우입니다.
하나의 거대한 프롬프트 (prompt)를 두 개 또는 세 개의 더 작은 호출 (call)로 나누면, 일반적으로 더 나은 신뢰성 (reliability)을 얻을 수 있습니다.
하지만 호출 횟수 (call volume) 또한 증가하게 됩니다.
기술적으로는 이것이 올바른 트레이드오프 (tradeoff)입니다. 다만 표준적인 토큰당 과금 (per-token billing) 방식에서는 재정적으로 번거로울 뿐입니다.
이 지점이 바로 에이전트 (agent) 및 자동화 팀에게 Standard Compute가 매우 합리적인 이유입니다.
다음과 같은 혜택을 얻을 수 있습니다:
- 고정된 월간 가격으로 무제한 AI 컴퓨팅 (AI compute)
- OpenAI 호환 API
- 기존 SDK 및 HTTP 클라이언트와 즉시 사용 가능
- GPT-5.4, Claude Opus 4.6, Grok 4.20 간의 동적 라우팅 (dynamic routing)
따라서 토큰을 아끼기 위해 모든 것을 하나의 거대한 호출에 쑤셔 넣으려고 노력하는 대신, 다음과 같이 설계되어야 할 방식대로 워크플로우 (workflow)를 설계할 수 있습니다:
- 추출 (extraction)을 위한 1회 통과
- 추천 (recommendation)을 위한 1회 통과
- 검증 (validation) 또는 기권 (abstention)을 위한 1회 통과 (선택 사항)
이는 특히 다음과 같은 환경에서 구축할 때 유용합니다:
- n8n
- Make
- Zapier
- OpenClaw
- 커스텀 에이전트 프레임워크 (custom agent frameworks)
정액제 컴퓨팅 (Flat-rate compute)은 행동 양식을 변화시킵니다.
사람들은 더 이상 "검증 단계를 하나 더 추가할 여유가 될까?"라고 묻지 않습니다.
대신 더 나은 질문을 하기 시작합니다:
"검증 단계를 하나 더 추가하는 것이 이 워크플로우를 더 안전하고 디버깅 (debug)하기 쉽게 만드는가?"
이것이 훨씬 더 건강한 구축 방식입니다.
로컬 또는 에이전트 기반 워크플로우를 위한 OpenClaw 설정
OpenClaw를 오케스트레이션 계층 (orchestration layer)으로 사용하는 경우, 에이전트 간의 책임 분할은 간단합니다.
기본 설정:
npm install -g openclaw@latest
openclaw onboard --install-daemon
openclaw dashboard
상태 확인 (Health checks):
openclaw status
openclaw status --all
openclaw health --json
여기서 좋은 패턴은 다음과 같습니다:
- 에이전트 1: 관련 노트/청크 (chunks) 검색
- 에이전트 2: 증거 (evidence)만 추출
- 에이전트 3: 승인된 증거로부터 추천 생성
- 에이전트 4: 증거가 불충분할 경우 에스컬레이션 (escalate)
이 방식은 한 번의 호흡에 모든 것을 처리하려는 과부하된 에이전트 하나보다 훨씬 낫습니다.
검색 (Retrieval) vs 채워넣기 (stuffing)
매우 작은 코퍼스 (corpora)의 경우, 채워넣기 (stuffing) 방식도 괜찮을 수 있습니다.
하지만 성장하는 코퍼스의 경우, 일반적으로 검색 (retrieval) 방식이 승리합니다.
| 전략 | 트레이드오프 (Tradeoff) |
|---|---|
| 컨텍스트 채워 넣기 (Context stuffing) | 작은 코퍼스 (corpora)의 경우 더 간단합니다. 하지만 프롬프트 (prompt)가 커질수록, 관련 사실들이 중간에 파묻혀 모델이 이를 올바르게 사용하기 어려워질 수 있습니다. |
| 검색 (Retrieval) + 재순위화 (reranking) | 구동 요소가 더 많지만, 확장성이 더 뛰어나며 긴 컨텍스트 (context) 내부에서 적절한 증거가 유실될 상황에서 더 강력한 성능을 발휘합니다. |
만약 추천 (recommendation) 단계가 잘못된 청크 (chunks)에서 시작된다면, 여러분이 GPT-5.4, Claude Opus 4.6, Grok 4.20, Qwen, 또는 Llama 중 무엇을 선택했는지는 중요하지 않습니다.
상류 (upstream) 단계의 증거가 틀렸거나 불완전하다면, 출력값은 여전히 빗나갈 것입니다.
그것이 바로 모델 쇼핑 (model shopping)이 종종 주의를 분산시키는 요소인 이유입니다.
아키텍처 (architecture)가 잘못되었다면, 더 나은 모델은 그저 더 유창한 실수를 내뱉을 뿐입니다.
내가 추천하는 기본 워크플로 (workflow)
노트를 의사결정으로 전환하는 무언가를 구축하고 있다면, 이것이 제가 시작점으로 삼을 기본 설정입니다:
- 가장 작으면서도 유용한 증거 세트를 검색 (Retrieve) 합니다.
- 먼저 축자 인용구 (verbatim quotes)와 구조화된 사실 (structured facts)을 추출합니다.
- 추출된 모든 항목에 출처 참조 (source references)를 첨부합니다.
- 오직 추출된 증거로부터만 추천을 생성합니다.
- 증거가 약하거나 누락된 경우 기권 (abstention)할 수 있도록 허용합니다.
- 오류의 비용이 높은 곳에는 인간의 검토 (human review)를 추가합니다.
이것은 화려하지 않습니다.
프롬프트 엔지니어링 (prompt engineering) 미인 대회에서 우승하지도 못할 것입니다.
하지만 현실과의 접촉에서도 살아남습니다.
최종 결론
모델이 사례 노트 (case notes)에 대해 환각 (hallucination)을 일으킬 때, 저의 첫 번째 질문은 더 이상 다음과 같지 않습니다:
- 모델을 바꿔야 할까?
- 컨텍스트 윈도우 (context window)를 늘려야 할까?
- 더 똑똑한 프롬프트를 작성해야 할까?
저의 첫 번째 질문은 이것입니다:
왜 우리는 거대한 프롬프트 중간에 증거를 숨겨둔 채, 단 한 번의 모델 호출 (model call)로 세 가지 일을 처리하라고 요구했는가?
그 문제를 해결한다면,
만약 당신의 스택이 이미 OpenAI 호환 클라이언트 (OpenAI-compatible client)를 사용하고 있다면, 이 패턴을 테스트하기 위한 구현 변경 사항은 매우 적을 것입니다.
그것이 아마도 이 아이디어 전체에서 가장 유용한 부분일 것입니다:
해결책은 지루합니다.
즉, 이번 주 안에 바로 배포할 수 있다는 뜻입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기