12장. 문서 로딩과 청킹
왜 RAG가 필요한가 — 규정은 모델의 머릿속이 아니라 문서에 있다
한 줄 요약
지금까지 만든 에이전트는 주문과 상품 정보를 조회할 수 있지만, 환불 규정은 아직 확인할 수 없습니다. 관련 규정은 data/ 폴더에 있는 두 개의 PDF 문서에 담겨 있습니다. 고객의 질문과 관련된 내용을 문서에서 찾아 모델에 제공하고, 이를 바탕으로 답변하게 하는 방식을 RAG라고 합니다. 이번 장부터 15장까지 이 과정을 단계별로 구현합니다.
1. 3장에서 본 일
3장 「따라하기」의 마지막 비교를 떠올립니다. 35,000원짜리 상품을 단순 변심으로 반품할 때의 환불액을 모델에게 계산하게 했습니다.
- 어떤 실행에서는 32,000원이 나왔습니다. 반품 배송비 3,000원만 뺐습니다.
- 다른 실행에서는 29,000원이 나왔습니다. "무료배송 혜택이 철회되므로 처음 배송비도 뺀다"는 규칙을 모델이 스스로 채워 넣었습니다.
두 풀이 모두 그럴듯했습니다. 어느 쪽이 하루마켓의 규정인지는 모델도 우리도 확인하지 않았습니다.
그런데 답은 이미 있습니다. data/하루마켓_반품교환환불정책.pdf 제6조와 그 아래 표입니다.
제6조 (환불 금액 산정)
단순 변심 반품 시 편도 배송비 3,000원을 환불 금액에서 차감한다. 최초 주문이 무료배송 조건(3만원 이상)이었더라도, 반품
으로 인해 잔여 주문금액이 무료배송 기준에 미달하면 최초 배송비 3,000원이 추가 차감될 수 있다.
[표 3] 환불 금액 계산 예시 (단순 변심)
항목 사례 A (전체 반품) 사례 B (부분 반품)
상품 금액 30,000원 60,000원 중 20,000원 반품
반품 배송비 -3,000원 -3,000원
무료배송 미달 배송비 해당 없음 -3,000원
실 환불액 27,000원 14,000원
전체 반품(사례 A)에는 "무료배송 미달 배송비"가 해당 없음입니다. 처음 배송비까지 빼는 것은 일부만 반품해 남은 금액이 3만원에 못 미칠 때(사례 B)입니다. 모델이 29,000원을 낼 때 끌어온 규칙은 문서에 있기는 하지만 그 상황에 적용되는 규칙이 아니었습니다.
모델에게 이 대목을 보여 주었다면 짐작할 필요가 없었습니다.
2. 지금까지의 수단으로는 왜 안 되는가
시스템 프롬프트에 적어 둔다(3장). 조항 한두 개라면 됩니다. 하지만 규정은 두 문서에 걸쳐 열다섯 조항과 표 다섯 개입니다. 그리고 규정은 바뀝니다. 바뀔 때마다 프롬프트를 고쳐야 합니다.
도구로 조회한다(5~8장). 도구는 질문의 모양이 정해진 데이터에 맞습니다. "주문번호 → 그 주문의 행"처럼 넣는 값과 찾는 자리가 정해져 있습니다. 규정 질문은 그렇지 않습니다.
포장을 뜯었는데 반품 되나요?
이 질문에 맞는 열도 키도 없습니다. 답은 제7조 어딘가의 문장 안에 있습니다. 표에서 행을 조회하는 일이 아니라 글에서 대목을 검색하는 일입니다.
| 도구 (Function Calling) | 이번에 필요한 것 | |
|---|---|---|
| 데이터의 모양 | 표 (CSV, 데이터베이스) | 글 (규정, 안내문) |
| 찾는 방법 | 키로 조회한다 | 뜻이 가까운 대목을 찾는다 |
| 돌려받는 것 | 값 ("재고 110개") | 근거가 되는 문장 ("제2조에 따르면…") |
| 하루마켓에서는 | 주문, 상품, 재고 | 반품·교환·환불 정책, 멤버십 정책 |
3. 문서를 통째로 넣으면 안 되는가
가장 단순한 방법은 PDF 두 개의 글을 전부 프롬프트에 붙이는 것입니다. 재 보면 두 문서의 전문은 4,412자, 2,889토큰입니다(실습문제 3에서 직접 잽니다). 기술적으로는 가능합니다. 문서가 이만큼 작은 동안은 그것도 방법입니다.
그래도 다른 길을 택하는 이유가 셋입니다.
- 문서는 자랍니다. 지금은 정책이 두 개지만 배송, 개인정보, 이벤트 안내가 더해지면 통째로 넣을 수 없는 날이 옵니다.
- 매 호출의 기본 요금이 됩니다. 고객이 인사만 해도, 주문 조회만 해도 2,889토큰이 함께 갑니다. 10장에서 본 것처럼 루프에서는 스텝마다 다시 보냅니다.
- 필요 없는 조항까지 모델이 읽습니다. 3장의 29,000원이 그런 사례입니다. 관련 없는 규칙이 눈앞에 있으면 모델은 그것을 끌어다 쓸 수 있습니다.
4. RAG란
RAG(Retrieval-Augmented Generation, 검색 증강 생성) 는 이름이 곧 순서입니다.
| 단계 | 뜻 | 하는 일 |
|---|---|---|
| Retrieval (검색) | 찾는다 | 질문과 관련된 문서 조각을 찾는다 |
| Augmented (증강) | 보탠다 | 찾은 조각을 프롬프트에 붙인다 |
| Generation (생성) | 쓴다 | 모델이 그 조각을 근거로 답을 쓴다 |
모델의 기억에 기대지 않고, 질문이 올 때마다 문서를 펼쳐 관련 대목을 옆에 놓아 주는 것입니다. 시험으로 치면 외워서 답하는 것이 아니라 책을 펴 놓고 답하는 방식입니다.
역할 분담은 이렇습니다. 관련 대목을 찾는 것은 우리 코드이고, 그 대목을 읽고 답을 쓰는 것은 모델입니다.
5. 이걸 모르면 무엇을 판단하지 못하는가
- 모델이 규정을 틀리게 안내했을 때 모델의 문제인지, 건넨 자료의 문제인지 가려내지 못합니다.
- 어떤 질문은 도구로, 어떤 질문은 문서 검색으로 풀어야 하는지 나누지 못합니다.
- 답변에 "제2조에 따르면"이라고 근거를 붙이려면 무엇을 미리 준비해야 하는지 모릅니다.
6. 네 장에 걸친 길
| 장 | 하는 일 |
|---|---|
| 12장 (이번 장) | PDF에서 글을 꺼내고 검색할 수 있는 조각으로 자른다 |
| 13장 | 조각을 뜻으로 검색할 수 있게 저장한다 |
| 14장 | 찾은 조각을 근거로, 출처를 밝히며 답하게 한다 |
| 15장 | 검색이 잘되는지 재고 고친다 |
이번 장은 준비 단계입니다. LLM을 호출하지 않으므로 API 키 없이도 동작하고, 누가 실행해도 같은 결과가 나옵니다.
핵심 정리
- 3장에서 환불액이 실행마다 달랐던 것은 모델이 규정을 모르고 짐작했기 때문입니다. 규정은 PDF에 있습니다.
- 규정 질문은 표에서 값을 조회하는 일이 아니라 글에서 대목을 검색하는 일입니다. 도구와는 다른 수단이 필요합니다.
- 문서를 통째로 넣는 방법은 문서가 자라면 무너지고, 매 호출의 비용이 되며, 무관한 조항이 답을 흐립니다.
- RAG는 관련 조각을 찾아서(검색), 프롬프트에 붙이고(증강), 그것을 근거로 답하게(생성) 하는 방법입니다.
- 찾는 것은 우리 코드, 답을 쓰는 것은 모델입니다.