6장까지의 모든 기법은 한 번 달리고 멈추는 파이프라인이었다. 질의가 오면 회수하고, 순위를 고치고, 답을 지어낸다. 그 사이 어디에도 자기가 잘못 찾았음을 알아차릴 자리가 없다. 7장이 더하는 것은 기법이 아니라 태도다. 회수한 것을 곧바로 내놓지 않고 잠시 멈추어 되묻는 자리, 곧 성찰의 계층이다.
한 B2B 소프트웨어 회사의 고객지원 팀이 정례 점검을 했다. AI 지원 어시스턴트는 아홉 달째 가동 중이었고 주당 1차 티켓 3,000건가량을 처리하고 있었다. 잘 돌아가고 있었다. 고객 만족도는 사람만으로 지원하던 시절보다 높았고 에스컬레이션 비율은 낮았다. 경영진은 이 프로젝트를 분명한 성공으로 여겼다.
점검은 지난 분기에서 무작위로 뽑은 종결 티켓 백 건을 선임 지원 엔지니어가 손으로 읽는 것으로 시작되었다. 그 가운데 스물세 건이 실질적으로 틀린 답이거나, 고객의 제품 등급에 해당하지 않는 문서에 근거한 답을 담고 있었다. 스물세 건 모두에서 어시스턴트는 자신 있게 답했다. 답을 믿은 고객들은 조용히 받아들였고, 일곱 건에서는 그 조언을 따랐다가 문제를 더 키운 뒤에야 사람에게 넘어왔다.
실패의 결이 인상적이다. 스물세 건 전부에서 검색 시스템은 고객의 질문과 주제가 관련된 문서를 돌려주었다. 다만 그 문서에 답이 들어 있지 않았다. 청크들은 비슷한 기능, 비슷한 오류 코드, 비슷한 작업 흐름을 이야기하고 있었으나 다른 제품 버전, 다른 배포 구성, 다른 고객 등급의 것이었다. 벡터 검색과 하이브리드 융합과 재순위화 — 이 책 2부의 모든 기법 — 은 제 일을 옳게 해냈다. 말뭉치에서 가장 유사한 내용을 찾아 온 것이다.
겉보기에는 관련되고 실은 무관한 맥락을 받은 언어 모델은 언어 모델이 하는 일을 했다. 자신 있는 답을 합성한 것이다. 모델에게는 회수된 청크가 사용자에게 필요한 것을 담고 있지 않다는 사실을 알아볼 방법이 없었다. 주제의 유사함과 답의 존재함 사이의 간극을 알아보도록 훈련된 적이 없었기 때문이다. 그리고 지원 워크플로에도 그 간극을 감지할 기제가 없었다. 사용자는 답을 받았고, 답은 그럴듯했고, 티켓은 닫혔다.
세 주 뒤 팀이 마침내 손을 댄 곳은 검색이 아니었다. 검색은 이미 좋았다. 처방은 순수 검색 아키텍처에 없는 단계를 하나 더하는 것이었다 — 회수를 마친 뒤, 회수한 증거가 사용자의 질문에 실제로 답을 담고 있는가를 스스로 묻는 자기평가의 자리다. 담고 있다면 생성으로 나아가고, 담고 있지 않다면 다른 전략으로 다시 찾거나, 사람에게 넘기거나, 부족한 증거로 지어내는 대신 답하기를 거부한다.
이것이 이 장이 다루는 전환이다. 결정론적 파이프라인으로서의 검색에서, 스스로를 들여다보고 고쳐 나가는 과정으로서의 검색으로. RAG를 에이전틱 RAG로 만드는 것은 더 좋은 모델이 아니라 이 되묻는 자리다. 이 장을 다 읽고 나면 스물세 건의 오답은 검색의 실패가 아니라 아키텍처의 실패로 보일 것이다. 성찰 계층을 두지 않은 실패다. 확신에 차서 틀리는 시스템과 겸손하되 옳은 시스템을 가르는 것이 여기서 다루는 패턴들이며, 고위험 도메인에서 그 차이는 피한 규제 위반, 지킨 고객의 신뢰, 일어나지 않은 사고로 계량된다.
이 책이 지금까지 살펴본 모든 검색 아키텍처 — 벡터 검색, 하이브리드 융합, 재순위화, 질의 변환, GraphRAG — 는 하나의 구조적 성질을 공유한다. 검색 단계가 한 번만 돈다는 것이다. 질의가 오면 시스템이 후보를 가져오고, 필요하면 순위를 고치고, 상위 k개를 언어 모델에 넘기고, 생성이 진행된다. 시스템이 자기 검색이 실패했음을 알아차리고 다른 무엇을 하도록 마련된 자리는 없다. 이것이 정적 검색을 정의하는 성질이며, 지원 플랫폼의 스물세 건은 그 성질의 직접적 귀결이었다.
정적 검색은 충분히 오랫동안 충분히 잘 통했고, 그래서 많은 팀이 이 한계를 알아차리기를 그만두었다. 캐스케이드는 정교하다. 후보 집합은 넉넉하다. 재순위화는 훌륭하다. 개발 중에 재는 모든 지표 — 검색 재현율, 순위 정밀도, 벤치마크 질의에서의 생성 충실도 — 로 시스템은 잘 작동한다. 그러나 지표는 검색이 성공한 질의들에서 측정된 것이다. 실패 양식이 같은 지표에 보이지 않는 까닭은, 실패 양식이 바로 검색 실패를 감지할 기제의 부재 그 자체이기 때문이다. 자기 눈으로 자기 눈을 보지 못하는 것과 같다.
정적 검색이 할 수 없는 일을 헤아려 보자. 상위 k개의 청크가 주제는 비슷하나 맥락이 어긋난다는 것 — 다른 제품 버전, 다른 관할, 다른 시기의 것이라는 것 — 을 알아보지 못한다. 회수된 증거가 관련은 되지만 확정적 답을 받치기에는 불충분하다는 것, 곧 필요한 정보의 절반만 가졌다는 것을 알아보지 못한다. 첫 시도가 쓸모없는 결과를 낼 때 다른 질의로 다시 찾기로 결정하지 못한다. 모호한 질의를 사람 검토자에게 올리지 못한다. 그리고 어떤 의미로도 답하기를 거부하지 못한다. 언어 모델은 언제나 무언가를 내놓을 것이고, 그 무언가는 증거가 받치든 받치지 않든 자신 있게 들릴 것이다.
아키텍처적 처방은 검색과 생성 사이에 성찰 계층을 두는 것이다. 회수한 뒤 생성하기 전에, 시스템이 회수된 증거가 적절한지를 명시적으로 평가한다. 적절하면 생성으로 나아간다. 적절하지 않으면 다른 행동을 택한다 — 다른 전략으로 다시 찾기, 질의를 쪼개어 각각 찾기, 사람에게 올리기, 답하기를 거부하기. 성찰 계층은 파이프라인을 판단하는 시스템으로 바꾸는 것이다. 에이전틱 RAG를 정의하는 성질이 여기 있고, 이 장의 시스템들을 앞의 모든 것과 가르는 전환이 여기 있다.
성찰을 더하는 비용은 실재한다. 성찰 단계마다 언어 모델 호출(모델 자신이 성찰을 수행하는 구현)이나 학습된 분류기(관련성 평가만을 위해 훈련된 소형 모델)가 필요하다. 어느 쪽이든 질의당 비용이 오르고 지연 예산이 늘어난다. 프로덕션급 자기교정 시스템은 통상 정적 대응물의 질의당 비용 2~4배와 그에 비례하는 지연 증가를 안는다. 특정 응용에 대한 물음은 그 비용이 그것이 막아 주는 실패로 정당화되는가다. 오답이 그저 불편할 뿐인 응용 — 사내 검색 도구, 가벼운 콘텐츠 탐색, 저위험 추천 — 이라면 정적 검색이 옳은 거래일 수 있다. 오답이 실제 해를 끼치는 응용 — 의료, 법률 조언, 금융 컴플라이언스, 규제 환경의 고객 대면 지원 — 이라면 자기교정은 좀처럼 선택 사항이 아니다. 규율은 어느 경우인지 알아보고 아키텍처 투자를 그에 맞게 정하는 것이다. 단순하다는 이유로 정적 검색을 기본값으로 두지 않고, 엄격하다는 이유로 최대치의 성찰을 기본값으로 두지도 않는 일이다.
정적 검색 — 질의 → 회수 → 재순위화 → 생성. 파이프라인은 질의마다 한 번 돌며, 검색 실패를 알아보거나 그로부터 회복할 자리가 없다.
에이전틱 검색 — 질의 → 회수 → 성찰 → (다시 찾기, 쪼개기, 사람에게 올리기, 거부하기, 또는 생성). 성찰 단계가 검색의 성공 여부를 명시적으로 평가해 시스템을 알맞은 다음 행동으로 인도한다. 시스템은 반복할 수 있고, 전략을 바꿀 수 있고, 답하지 않기로 결정할 수 있다.
Self-RAG는 2023년 워싱턴 대학과 앨런 인공지능연구소의 연구자들이 내놓은, 자기교정 RAG 패턴을 처음으로 형식화한 주요 논문이다. 이 기법은 언어 모델이 생성 중에 특정한 성찰 토큰을 내도록 훈련한다. 검색 품질과 답변 근거에 대한 스스로의 판정을 표지로 남기게 하는 것이다. 그 토큰들이 이후 결정의 바탕이 된다 — 계속 생성할지, 다시 찾을지, 멈출지.
Self-RAG 프로토콜을 정의하는 성찰 토큰은 넷이다.
생성 전에 나오며, 애초에 검색이 필요한가를 말한다. 많은 질의 — 일반 상식, 단순 계산, 널리 알려진 사실 — 에서 모델은 자기 파라미터만으로 답할 수 있고 검색은 잡음만 더한다. 찾지 않기로 결정하는 것도 하나의 판단이다.
회수된 청크마다 나오며, 그 청크가 질의에 관련되는가를 말한다. 관련성 검사를 통과하지 못한 청크는 생성 맥락에서 제외된다.
모델이 답변의 각 조각을 생성할 때 나오며, 그 조각이 관련된 회수 청크에 의해 받쳐지는가를 말한다. 받쳐지지 않는 조각은 표시하거나 덜어 낼 수 있다.
마지막에 나오며, 생성된 답이 전체적으로 얼마나 쓸모 있는가를 요약한다.
실무에서 Self-RAG는 두 형태로 구현된다. 하나는 원 논문이 서술한 미세조정 형태로, 성찰 토큰을 본래부터 내도록 특정 모델을 훈련한다. 품질이 가장 높지만 미세조정 역량과 레이블된 훈련 집합이 필요하다. 다른 하나는 오늘의 프로덕션에서 더 흔한 프롬프트 형태로, 범용 모델에게 프롬프트로 같은 판정을 내도록 요청한다. 정확도는 낮지만 배포가 극적으로 쉽고, 특별한 훈련이 필요 없으며, 대부분의 팀이 이미 쓰는 프런티어 모델로 돌아간다.
프로덕션 구현은 대개 전체 프로토콜의 단순화된 판을 따른다. 네 종류의 토큰을 내는 대신 두 단계의 프롬프트 방식을 쓴다. 첫째, 회수된 각 청크의 실제 관련성을 채점하는 관련성 평가 — 흔히 주 생성 모델보다 작고 빠른 모델을 쓴다. 둘째, 관련성 여과를 살아남은 청크들이 생성된 답을 받치는지 확인하는 근거 평가. 이 단순화된 판이 구현 복잡성의 일부만으로 Self-RAG의 가치 대부분을 담아낸다.
# Self-RAG 방식의 관련성·근거 평가 from typing import List, Tuple RELEVANCE_PROMPT = """Assess whether this document chunk is directly relevant to the user's question. A chunk is relevant only if it contains information that helps answer the question — topical similarity is not enough. Question: {query} Chunk: {chunk_text} Respond with strict JSON: relevant""" SUPPORT_PROMPT = """Assess whether this answer is supported by the retrieved chunks. An answer is supported only if every factual claim can be traced to one or more chunks. Question: {query} Answer: {answer} Retrieved chunks: {chunks} Respond with strict JSON: supported""" def self_rag_retrieve_and_assess(query, retriever, llm) -> Tuple[List, bool]: # 1. 표준 검색 candidates = retriever.search(query, k=20) # 2. 관련성 여과 — 실제로 도움이 되는 청크만 남긴다 relevant = [] for chunk in candidates: result = llm.complete(RELEVANCE_PROMPT.format( query=query, chunk_text=chunk.text), response_format='json') if json.loads(result)['relevant']: relevant.append(chunk) # 3. 답할 만큼 가졌는지 판정한다 has_sufficient_evidence = len(relevant) >= 2 return relevant, has_sufficient_evidence
가장 결정적인 단계는 관련성 평가다. 앞서 본 스물세 건은 제대로 조율된 관련성 여과라면 모두 걸러졌을 것이다. 시스템이 회수하던 청크들은 주제가 관련되었을 뿐 고객이 필요로 한 답을 담고 있지 않았다. "이 청크가 사용자의 질문에 답하는 정보를 담고 있는가, 아니면 그저 같은 주제에 관한 것인가"라는 명시적 물음을 던지는 검사는 그 청크들을 무관하다고 표시했을 것이고, 시스템은 불충분한 증거로 합성하는 대신 답하기를 거부했을 것이다.
거래는 관련성 검사 자체의 정밀도와 재현율 사이에 있다. 엄격한 여과는 오답을 줄이지만 도움이 되었을 답도 줄인다 — 도울 수 있었던 경우에도 시스템이 거부한다. 느슨한 여과는 더 많은 청크를 남기지만, 지원 플랫폼의 실패를 낳은 그 '주제는 비슷하나 실은 무관한' 내용을 통과시킨다. 알맞은 보정은 거짓 부정(도울 수 있었는데 거부한 것)의 비용과 거짓 긍정(틀린 답을 준 것)의 비용을 견주어 정해진다. 프로덕션은 이 거래를 레이블된 평가 집합에 대해 명시적으로 조율하며, 고위험 응용에서는 통상 더 엄격한 문턱을 둔다.
2024년 초에 제시된 Corrective RAG(CRAG)는 검색이 부적절하다고 판정될 때의 명시적 회복 행동으로 Self-RAG의 접근을 확장한다. Self-RAG가 주로 나쁜 청크를 생성 맥락에서 걸러 내는 데 그친다면, CRAG는 걸러 낸 뒤 시스템에 증거가 부족하게 남았을 때 무엇을 할지 결정한다. 성찰이 판정에서 멈추지 않고 행동으로 이어지는 것이다. 평가 단계는 세 판정 가운데 하나를 내린다.
CRAG 프로토콜의 중심 기여는 검색 품질에 관한 결정을 암묵적 문턱이 아니라 일급 아키텍처 관심사로 대접한 것이다. 판정 — 확신, 모호, 오류 — 은 명시적이고, 기록되고, 운영에 보인다. 취해지는 행동은 조용한 실패가 아니라 판정에 의해 결정된다. 시스템이 답하기를 거부하거나 다른 출처로 물러날 때, 사용자(또는 상류 애플리케이션)는 자신 있으면서 틀린 답이 아니라 구조화된 신호를 받는다.
CRAG 구현은 통상 온전한 언어 모델 호출 대신 작은 분류기 — 확신·모호·오류로 레이블된 검색 예제로 훈련된 학습 모델 — 를 쓴다. 분류기는 빠르고(수백 밀리초가 아니라 수 밀리초), 싸고(모델 호출보다 몇 자릿수), 문턱 거동이 결정론적이다. 대가는 그 분류기를 해당 도메인에 맞게 훈련해야 한다는 것이다. 기성 분류기는 일반 영어에 보정되어 있어 전문 콘텐츠에서 부진한 경향이 있다.
관련성 신호가 참으로 모호할 때 — 분명히 충분하지도, 분명히 불충분하지도 않을 때 — 고위험 응용의 기본 행동은 답하기가 아니라 거부하기여야 한다. 의료·법률 조언·금융 안내에서 거부의 비용은 사용자가 에스컬레이션해야 하는 번거로움이고, 자신 있게 틀린 답의 비용은 잠재적으로 심각한 해악이다.
규제 도메인의 프로덕션 시스템은 흔히 보수적 문턱으로 설정된다. 도움됨을 조금 잃는 대신 확신에 찬 오답을 의미 있게 줄이는 거래다. 이것이 시스템을 응용의 실제 위험 성격에 맞추는 설정이다.
어떤 질의는 캐스케이드를 아무리 잘 조율해도 단 한 번의 검색으로 답할 수 없다. 6장의 자산운용사 질의 — 이사가 FCA 제재 회사의 이사회에서도 일한 포트폴리오 기업을 찾으라 — 가 한 예다. "Z가 설정되었을 때 X가 Y와 다르게 거동하는 이유는" 같은 고객지원 질의가 또 하나다. 이런 질의에는 공통의 구조가 있다. 답이 말뭉치의 서로 다른 곳에 사는 정보의 결합을 요구하며, 어느 한 번의 검색도 그것을 모두 내놓지 못한다.
멀티홉 분해가 이를 다루는 패턴이다. 사용자 질의를 하나의 검색 표적으로 다루는 대신, 시스템은 그것을 각각 독립적으로 회수 가능한 하위 질의의 연속으로 쪼개고, 합쳐진 결과에서 답을 종합한다. 분해는 언어 모델이 수행한다 — 통상 생성에 쓰는 것과 같은 모델이되 더 작은 모델로도 족하다. 모델에 원래 질의를 주고, 그 답들이 함께라면 원 질의에 답이 될 하위 질의 목록을 만들게 한다. 지배적인 분해 전략은 둘이다.
서로 의존하지 않는 하위 질의들을 만들어 동시에 회수한다. 순차 실행보다 지연이 극적으로 줄어드는 것이 운영상의 이점이다. 자산운용사 질의가 병렬형이다 — 포트폴리오 기업을 식별하고, FCA 제재 회사를 식별하고, 이사회 구성을 식별한 뒤, 교집합을 낸다.
어려운 대목은 종합이다. 독립적 결과들을 조리 있는 답으로 합쳐야 하고, 이는 보통 합쳐진 결과가 하나의 컨텍스트 창에 들어가야 함을 뜻한다. 결과 집합이 큰 질의 — 포트폴리오 기업이 많고 규제 조치가 많은 — 에서는 이것이 구속 제약이 된다.
모델이 각 하위 질문에 옳게 답하고도 그것들을 틀리게 합칠 수 있다. 그래서 원 질의의 의도에 대한 출력 검증이 투자할 가치가 있는 규율이다.
각 하위 질의가 앞 단계의 결과에 의존하는 사슬을 만든다. 더 강력하고 더 어려운 패턴이다. "API 계약이 버전 3과 4 사이에 무엇이 바뀌었고, 그것이 우리 SDK에 어떤 영향을 주었나" 같은 질의가 순차형이다 — 먼저 API 변경을 찾고, 변경마다 SDK 영향을 찾는다.
표준 구현은 계획 단계(하위 질의 연속을 만드는 모델 호출), 실행 루프(하위 질의마다 회수하고 관련 정보를 추출), 종합 단계(누적된 정보를 최종 답으로 결합)로 이루어진다.
오류가 사슬을 타고 겹쳐 붇는다. 첫 하위 질의가 틀리거나 불충분한 정보를 내면 그에 의존하는 이후 질의들이 모두 표적을 벗는다. 그래서 프로덕션은 하위 질의마다 중간 성찰을 넣는다 — 계속할 만큼 충분한지 확인하고, 아니면 표현을 바꿔 재시도하거나 계획 전체를 고친다. 분해와 성찰의 결합이 복잡한 질의를 믿음직하게 답할 수 있게 만든다.
# 병렬 멀티홉 분해와 종합 DECOMPOSE_PROMPT = """Break this question into 2-5 independent sub-questions. Each sub-question must be answerable by retrieval from the corpus on its own. Together they should provide everything needed to answer the original question. Original question: {query} Return strict JSON: subqueries""" SYNTHESIS_PROMPT = """Answer the original question using the retrieved evidence for each sub-question. Cite which sub-question's evidence supports each claim. If the combined evidence is insufficient, say so explicitly rather than guessing. Original question: {query} Sub-question results: {subquery_results} """ def multi_hop_answer(query, retriever, llm): plan = json.loads(llm.complete(DECOMPOSE_PROMPT.format(query=query))) # 하위 질의마다 병렬로 회수한다 with ThreadPoolExecutor(max_workers=len(plan['subqueries'])) as pool: futures = {sq: pool.submit(retriever.search, sq, k=10) for sq in plan['subqueries']} results = {sq: f.result() for sq, f in futures.items()} # 하나의 답으로 종합한다 formatted = '\n'.join(f'Q: {sq}\nEvidence: {chunks}' for sq, chunks in results.items()) return llm.complete(SYNTHESIS_PROMPT.format( query=query, subquery_results=formatted))
이 장에서 살핀 패턴들 — Self-RAG의 성찰, CRAG의 교정 행동, 멀티홉 분해 — 은 하나의 구조적 성질을 공유한다. 전에는 한 번만 지나던 파이프라인에 반복을 들여온다는 것이다. 반복은 강력한 만큼 위험하다. 잘 설계된 에이전틱 루프는 고위험 응용이 의지하는 엄정한 자기교정을 낳는다. 잘못 설계된 루프는 폭주하는 비용과 무한한 지연, 프로덕션의 신뢰성을 무너뜨리는 무한 반복 실패를 낳는다. 이 절의 기술은 끝나는 루프, 명시적 예산 안에서 도는 루프, 실패할 때 우아하게 회복하는 루프를 설계하는 일이다.
모든 에이전틱 루프에는 명시적 종료 조건이 있어야 한다. 루프를 짓기 전에 설계해 두는 것이지, 잘못된 뒤에 발견하는 것이 아니다. 반드시 있어야 할 조건은 셋이다.
시스템이 질의에 답할 만큼 증거를 모았을 때 루프가 끝난다. 통상 성찰 단계가 '확신' 판정을 돌려주는 것으로 감지한다.
할당된 자원을 다 썼을 때 루프가 끝난다. 반복 횟수(통상 2~5회), 언어 모델 호출 수(단단한 상한), 경과 시간(지연 예산), 비용(재정 예산) 가운데 무엇으로 재든 마찬가지다.
여러 전략을 시도했으나 어느 것도 충분한 증거를 내지 못했을 때, 루프는 명시적 거부와 함께 끝난다.
이 조건들의 상대적 무게는 응용에 달렸다. 고객지원 시스템은 흔히 지연에 큰 무게를 둔다 — 30초짜리 반복 루프는 채팅 인터페이스에서 쓸 수 없다 — 그리고 적당한 거부율을 신속함의 대가로 받아들인다. 컴플라이언스 시스템은 흔히 증거에 큰 무게를 둔다 — 옳은 답을 위한 긴 기다림이 빠르지만 근거 없는 답보다 낫다 — 그리고 더 긴 반복을 견딘다. 규율은 프레임워크의 기본 거동에서 무게가 암묵적으로 떠오르게 두지 않고, 응용의 실제 위험 성격에 근거해 의도적으로 정하는 것이다.
에이전틱 시스템을 한 해 넘게 운영해 본 팀들은 응용 부류마다 비슷한 설정으로 수렴한다 — 고처리량 소비자 응용에는 짧은 지연 예산과 적극적인 거부 문턱, 저처리량 고위험 응용에는 더 긴 예산과 엄격한 증거 문턱. 다만 그 수렴은 원리에 따른 설계보다 고통스러운 운영 경험을 통해 일어난다. 이미 그 운영 비용을 치른 팀의 수렴된 설정을 빌려 오는 것이, 첫 에이전틱 RAG를 출시하는 팀에게 열린 가장 지렛대 큰 선택의 하나다.
에이전틱 시스템의 예산은 부드러워서는 안 되고 단단해야 한다. 반복 예산을 넘긴 루프는 경고를 남기고 계속하는 것이 아니라 명시적 거부나 에스컬레이션과 함께 끝나야 한다. 비용 예산을 넘긴 루프는 조용히 지출을 더하는 것이 아니라 실패해야 한다. 부드러운 예산의 실패 양식이 겹쳐 붇기 때문이다. 예산을 조금 넘긴 루프가 하루 수천 질의에 걸쳐 반복되면 큰 비용 사고가 된다. 이따금 30초 대신 2분을 도는 루프도 충분히 많은 사용자가 만나면 신뢰성 사고가 된다.
프로덕션 에이전틱 시스템은 예산 강제를 루프 로직 자신에게 기대하지 않고 오케스트레이션 계층에서 구현한다. 오케스트레이터가 반복·호출·시간·비용을 추적하고, 어느 예산이든 고갈되면 루프를 깔끔하게 끊는다. 이 분리가 중요한 까닭은 루프 로직 — 프롬프트, 성찰 단계, 분해 — 은 과업에 집중해야 하기 때문이다. 예산 강제를 과업 로직에 섞으면 복잡하고 부서지기 쉬운 코드가 나온다. 떼어 두면 더 명료한 과업 로직과 더 믿음직한 예산 강제를 함께 얻는다.
거부는 이 장의 패턴들이 끝내 의지하는 회복 기제다. 검색 전략을 다 써도 충분한 증거를 찾지 못했을 때 옳은 행동은 물러서는 것이다 — 믿음직하게 답할 수 없다고 사용자에게 말하고, 에스컬레이션이나 다른 출처, 질의 재구성을 권하는 것. 역설적으로 이것이 공학하기에 가장 어려운 거동의 하나다. 언어 모델이 훈련받은 모든 것에 거스르기 때문이다. 부분적 증거로 컨텍스트 창이 채워진 모델의 기본 거동은 그 증거로 자신 있는 답을 내는 것이며, 아키텍처의 일은 명시적 거부 로직으로 그 기본값을 덮어쓰는 것이다.
프로덕션의 거부는 자유 문장이 아니라 구조화되어 있다. 언어 모델이 제 나름의 말로 거부를 짓게 두는 대신, 시스템은 구조화된 거부를 낸다 — 특정 응답 코드, 특정 메시지 템플릿, 무엇을 시도했고 각 시도가 왜 실패했는지 설명하는 메타데이터. 이 구조화된 형태가 상류 애플리케이션이 거부를 의도적으로 다루게 한다. 모호한 텍스트 응답으로 취급하는 것이 아니라, 사람에게 올리고, 재구성을 제안하고, 분석을 위해 기록하는 것이다. 규율은 거부를 성공한 답과 같은 공학적 주의를 받는 시스템의 일급 출력으로 대접하는 것이다.
에이전틱 시스템의 가장 위험한 실패 양식은 경계 없는 루프다. 성찰 단계가 증거를 부적절하다 판정하고, 시스템이 재시도하고, 재시도가 같은 결과를 내고, 성찰이 다시 부적절하다 판정하고, 루프가 되풀이된다 — 때로는 끝없이.
경계 없는 반복은 비용 사고(질의 하나가 센트가 아니라 달러를 쓴다), 지연 사고(질의가 초가 아니라 분을 쓴다), 신뢰성 사고(소수의 사용자가 동시에 이 루프를 촉발하면 시스템 전체가 응답하지 않는다)를 낳는다. 반복 예산은 선택이 아니다. 그것 없이는 에이전틱 시스템이 프로덕션에서 안전하게 돌 수 없는 구조적 안전장치다.
초기 자기교정 구현 가운데 많은 것이 성찰 단계는 더하면서 시스템에 의미 있는 대안 행동을 갖추어 주지 않는다. 성찰이 증거가 불충분함을 식별하는데도, 회복 경로가 설계되지 않았기에 시스템은 그대로 생성으로 나아간다. 성찰은 순수한 부담 — 품질 이득 없는 추가 지연과 비용 — 이 된다.
처방 — 회복 행동을 성찰보다 먼저 설계하라. 성찰의 결과에 따라 시스템이 취할 수 있는 서로 다른 행동이 적어도 둘 없다면, 그 성찰 단계는 아직 쓸모가 없다.
성찰 단계의 확신 문턱을 설정하는 팀들은 그것을 예사로 너무 낮게 잡는다. 질의와 느슨하게 관련될 뿐인 증거를 시스템이 '확신'이라 선언하게 된다. 그러면 성찰 단계는 돌지만 회복 행동은 좀처럼 발동하지 않는 시스템이 되어, 정적 검색의 실패 양식을 더 높은 비용으로 되풀이한다.
처방 — 직관이 아니라 레이블된 평가 집합에 대해 문턱을 보정하라. 팀이 합리적이라 여기는 문턱은 거의 언제나 너무 느슨하다. 재어 보아야 한다.
멀티홉 분해는 통할 때 강력하고 통하지 않을 때 조용히 틀린다. 시스템이 각 하위 질문에 옳게 답하고도 답들을 틀리게 합칠 수 있다 — 평균 내서는 안 될 사례들을 평균 내고, 비슷하나 구별되는 엔티티를 뭉개고, 하위 답들의 무게를 오해를 낳는 방식으로 매기는 것이다.
처방 — 프로덕션 멀티홉은 최종 종합을 원 질의 의도에 대해 검증한다. 종합된 답이 회수된 증거에서 끌어왔는지만이 아니라, 물어진 것에 실제로 답하는지를 명시적으로 확인하는 일이다. 이 검증이 없다면 멀티홉은 단일 검색보다 빠르게 틀린 답에 도달할 뿐이다.
정적 검색 파이프라인은 자기 실패로부터 회복하지 못한다. 아키텍처적 처방이자 에이전틱 RAG를 정의하는 성질은 성찰 계층이다. 검색과 생성 사이에 놓여 검색의 성공 여부를 평가하고 시스템을 알맞은 다음 행동으로 인도하는 명시적 단계다.
Self-RAG는 관련성·근거·효용의 명시적 판정으로 성찰 패턴을 형식화한다. 원 논문의 미세조정 형태보다 프로덕션에서 흔한 단순화된 프롬프트 형태가, 구현 복잡성의 일부만으로 가치 대부분을 담는다. 관련성 평가가 가장 결정적인 단계이니, 레이블된 데이터에 대해 명시적으로 조율할 일이다.
Corrective RAG는 성찰 패턴을 명시적 회복 행동으로 확장한다. 확신은 생성으로, 모호는 확장으로, 오류는 대안 출처나 거부로. 판정과 행동을 짝지은 이 구조가 성찰을 부담에서 쓸모로 바꾸는 전환이다.
멀티홉 분해는 어느 한 번의 검색으로도 답할 수 없는 질의를 다룬다. 병렬 분해는 독립적 하위 질의를 동시에 실행하고, 순차 분해는 의존하는 하위 질의를 중간 성찰과 함께 사슬로 잇는다. 두 패턴 모두 합쳐진 답이 실제로 원 질의를 겨누는지 확인하는 명시적 종합 검증을 요구한다.
모든 에이전틱 루프에는 명시적 종료 조건, 단단한 예산 강제, 구조화된 거부가 있어야 한다. 경계 없는 반복이 에이전틱 시스템의 지배적 실패 양식이니, 반복·시간·비용 예산은 협상의 여지가 없다. 거부는 퇴락한 실패 사례가 아니라 시스템의 일급 출력이다.
위 문헌 목록은 원서 7장의 Further Reading을 그대로 옮긴 것이다. 서지 사항의 최종 확인은 원 출처를 통해 하는 것이 옳다.
8장은 멀티 에이전트 RAG로 3부를 닫는다. 어느 한 에이전트도 홀로 감당할 수 없는 질의에 답하기 위해 여러 전문 검색 에이전트가 협력하는 아키텍처다. 이 장에서 세운 성찰과 분해의 패턴이 그 기층이 되고, 멀티 에이전트 오케스트레이션이 개별 에이전틱 검색기들을 협력하는 전문가의 체계로 만드는 조정 계층을 더한다. 8장을 마치면 3부의 에이전틱 스택이 온전히 제자리를 잡고, 4부의 프로덕션 공학 규율이 시작된다.
돌아보건대 이 장이 더한 것은 하나의 태도였다. 회수한 것을 곧바로 옳다 여기지 않는 태도, 모르는 것을 모른다고 말할 수 있는 자리를 시스템 안에 두는 태도다. 자신을 비추어 보는 거울을 하나 안에 들이는 일이 여기까지였다면, 다음 장은 여럿이 서로를 비추는 자리를 만드는 일이다. 홀로 서는 나무가 아니라 더불어 서는 숲의 이야기다.