[AI-009][중급] 문서를 찾아 근거 있는 답변 만들기
페이지 정보

본문
[이번 수업]
검색 증강 생성(Retrieval-Augmented Generation, RAG)은 질문과 관련된 외부 문서를 먼저 찾고, 그 문서 조각을 근거로 생성 모델이 답하게 하는 방식입니다. 모델이 학습할 때 보지 못한 최신 사내 문서도 재학습 없이 참고할 수 있지만, 검색 결과가 틀리면 답도 틀릴 수 있습니다. 이번 수업에서는 작은 로컬 예제로 검색, 근거 제시, 답변 보류의 흐름을 익힙니다.
[선수지식]
AI-006의 언어 모델 기본 개념, AI-008의 프롬프트 작성법, PY 트랙의 함수와 리스트를 알고 있으면 좋습니다. Python 3만 설치되어 있으면 실습할 수 있습니다.
[학습목표]
1. RAG의 검색 단계와 생성 단계를 구분합니다.
2. 근거가 부족할 때 답을 보류하는 조건을 만듭니다.
3. 출처 표시와 검색 품질을 따로 점검합니다.
[핵심개념]
일반적인 흐름은 문서 수집·정리 → 문서 조각 나누기 → 색인 만들기 → 질문으로 검색하기 → 관련도 재정렬 → 근거와 질문을 모델에 전달하기 → 답과 출처를 기록하기입니다. 색인은 책 뒤의 찾아보기처럼 문서를 빠르게 찾도록 정리한 구조입니다. 임베딩은 문장의 뜻을 숫자 목록으로 바꾸는 표현이며, 벡터 검색은 이 숫자 사이의 가까움을 이용합니다.
문서 조각이 너무 크면 관련 없는 내용이 함께 들어오고, 너무 작으면 앞뒤 맥락이 끊깁니다. 원본 문서 ID, 버전, 작성일, 접근 권한 같은 메타데이터도 조각과 함께 저장해야 합니다. 답변에는 실제 근거가 된 문서 ID를 붙이고, 근거에 없는 주장은 만들지 않도록 지시합니다. RAG는 사실성을 높일 수 있지만 정답을 보장하지는 않습니다.
품질 평가는 두 부분으로 나눕니다. 검색은 필요한 문서가 상위 k개 안에 들어왔는지와 관련도를 보고, 생성은 답의 각 주장이 근거에 의해 뒷받침되는지와 인용이 맞는지 봅니다. 정답 문서가 없는 질문도 넣어 답변 보류가 작동하는지 시험합니다.
[따라하기]
아래 내용을 rag_demo.py로 저장합니다. 표준 라이브러리만 쓰며, 질문과 문서에 함께 나온 단어 수로 가장 가까운 문서를 고릅니다.
```python
import re
documents = [
{"id": "doc-a", "text": "백업은 운영 데이터와 다른 위치에 보관한다."},
{"id": "doc-b", "text": "백업은 정기적으로 복원 시험을 해야 실제로 사용할 수 있는지 확인할 수 있다."},
{"id": "doc-c", "text": "복구 시간 목표는 서비스가 다시 열려야 하는 시간이다."},
]
question = "백업은 왜 복원 시험이 필요한가"
def tokens(text):
return set(re.findall(r"[가-힣A-Za-z0-9]+", text.lower()))
query_tokens = tokens(question)
ranked = sorted(
((len(query_tokens & tokens(doc["text"])), doc) for doc in documents),
key=lambda item: item[0],
reverse=True,
)
score, best = ranked[0]
if score < 2:
print("근거 부족")
else:
print("선택 문서:", best["id"], "점수:", score)
print("답변 근거:", best["text"])
```
macOS와 Linux에서는 `python3 rag_demo.py`, Windows PowerShell에서는 `py rag_demo.py`를 실행합니다. 예상 결과는 다음과 같습니다.
```text
선택 문서: doc-b 점수: 2
답변 근거: 백업은 정기적으로 복원 시험을 해야 실제로 사용할 수 있는지 확인할 수 있다.
```
이 예제는 흐름을 보여 주는 단순 단어 검색입니다. 실제 서비스에서는 형태소, 임베딩, 재정렬 모델 등을 검토하고 평가 데이터로 기준값을 정해야 합니다.
[흔한 실수]
첫 번째 결과를 관련도 기준 없이 항상 믿거나, 문서를 지나치게 크게 잘라 핵심이 묻히게 만들기 쉽습니다. 오래된 문서와 최신 문서를 구분하지 않거나, 출처 링크만 달고 실제 문장이 답을 뒷받침하는지 확인하지 않는 것도 문제입니다. 답변 문장만 평가하지 말고 검색된 조각도 함께 기록해 살펴보세요.
[보안 주의]
검색 단계에서 사용자와 역할별 문서 접근 권한을 먼저 적용해야 합니다. 검색된 문서 안의 명령문은 신뢰할 수 없는 데이터로 취급하고, 시스템 지시를 바꾸거나 링크·도구를 실행하라는 내용은 따르지 않습니다. 원문, 색인, 임베딩, 로그에 개인정보와 비밀값이 남지 않도록 수집 범위, 보관 기간, 삭제 절차를 정합니다. 실습은 본인 소유 또는 사용 허가를 받은 로컬 문서로만 진행합니다.
[직접 해볼 과제]
질문을 `오늘 날씨를 알려줘`로 바꾸어 `근거 부족`이 출력되는지 확인하세요. 그다음 각 문서에 날짜와 원본 경로를 추가하고, 선택 문서 ID와 함께 표시해 간단한 인용 형식을 만드세요.
[확인문제]
1. RAG에서 검색과 생성 단계를 따로 평가해야 하는 이유는 무엇인가요?
2. 관련 문서가 없을 때 답변을 보류해야 하는 이유는 무엇인가요?
3. 사용자별 접근 권한은 검색 전후 중 언제 적용해야 하나요?
[다음 학습]
AI-010에서는 모델이 외부 도구를 안전하게 호출하도록 입력, 권한, 결과를 통제하는 방법을 배웁니다.
[공식 참고 자료]
- RAG 원 논문: https://arxiv.org/abs/2005.11401
- NIST 생성형 AI 프로필: https://nvlpubs.nist.gov/nistpubs/ai/NIST.AI.600-1.pdf
- NIST AI 위험관리 프레임워크: https://www.nist.gov/itl/ai-risk-management-framework
- OWASP 프롬프트 주입 위험: https://genai.owasp.org/llmrisk/llm01-prompt-injection/
- Python 정규표현식 문서: https://docs.python.org/3/library/re.html
검색 증강 생성(Retrieval-Augmented Generation, RAG)은 질문과 관련된 외부 문서를 먼저 찾고, 그 문서 조각을 근거로 생성 모델이 답하게 하는 방식입니다. 모델이 학습할 때 보지 못한 최신 사내 문서도 재학습 없이 참고할 수 있지만, 검색 결과가 틀리면 답도 틀릴 수 있습니다. 이번 수업에서는 작은 로컬 예제로 검색, 근거 제시, 답변 보류의 흐름을 익힙니다.
[선수지식]
AI-006의 언어 모델 기본 개념, AI-008의 프롬프트 작성법, PY 트랙의 함수와 리스트를 알고 있으면 좋습니다. Python 3만 설치되어 있으면 실습할 수 있습니다.
[학습목표]
1. RAG의 검색 단계와 생성 단계를 구분합니다.
2. 근거가 부족할 때 답을 보류하는 조건을 만듭니다.
3. 출처 표시와 검색 품질을 따로 점검합니다.
[핵심개념]
일반적인 흐름은 문서 수집·정리 → 문서 조각 나누기 → 색인 만들기 → 질문으로 검색하기 → 관련도 재정렬 → 근거와 질문을 모델에 전달하기 → 답과 출처를 기록하기입니다. 색인은 책 뒤의 찾아보기처럼 문서를 빠르게 찾도록 정리한 구조입니다. 임베딩은 문장의 뜻을 숫자 목록으로 바꾸는 표현이며, 벡터 검색은 이 숫자 사이의 가까움을 이용합니다.
문서 조각이 너무 크면 관련 없는 내용이 함께 들어오고, 너무 작으면 앞뒤 맥락이 끊깁니다. 원본 문서 ID, 버전, 작성일, 접근 권한 같은 메타데이터도 조각과 함께 저장해야 합니다. 답변에는 실제 근거가 된 문서 ID를 붙이고, 근거에 없는 주장은 만들지 않도록 지시합니다. RAG는 사실성을 높일 수 있지만 정답을 보장하지는 않습니다.
품질 평가는 두 부분으로 나눕니다. 검색은 필요한 문서가 상위 k개 안에 들어왔는지와 관련도를 보고, 생성은 답의 각 주장이 근거에 의해 뒷받침되는지와 인용이 맞는지 봅니다. 정답 문서가 없는 질문도 넣어 답변 보류가 작동하는지 시험합니다.
[따라하기]
아래 내용을 rag_demo.py로 저장합니다. 표준 라이브러리만 쓰며, 질문과 문서에 함께 나온 단어 수로 가장 가까운 문서를 고릅니다.
```python
import re
documents = [
{"id": "doc-a", "text": "백업은 운영 데이터와 다른 위치에 보관한다."},
{"id": "doc-b", "text": "백업은 정기적으로 복원 시험을 해야 실제로 사용할 수 있는지 확인할 수 있다."},
{"id": "doc-c", "text": "복구 시간 목표는 서비스가 다시 열려야 하는 시간이다."},
]
question = "백업은 왜 복원 시험이 필요한가"
def tokens(text):
return set(re.findall(r"[가-힣A-Za-z0-9]+", text.lower()))
query_tokens = tokens(question)
ranked = sorted(
((len(query_tokens & tokens(doc["text"])), doc) for doc in documents),
key=lambda item: item[0],
reverse=True,
)
score, best = ranked[0]
if score < 2:
print("근거 부족")
else:
print("선택 문서:", best["id"], "점수:", score)
print("답변 근거:", best["text"])
```
macOS와 Linux에서는 `python3 rag_demo.py`, Windows PowerShell에서는 `py rag_demo.py`를 실행합니다. 예상 결과는 다음과 같습니다.
```text
선택 문서: doc-b 점수: 2
답변 근거: 백업은 정기적으로 복원 시험을 해야 실제로 사용할 수 있는지 확인할 수 있다.
```
이 예제는 흐름을 보여 주는 단순 단어 검색입니다. 실제 서비스에서는 형태소, 임베딩, 재정렬 모델 등을 검토하고 평가 데이터로 기준값을 정해야 합니다.
[흔한 실수]
첫 번째 결과를 관련도 기준 없이 항상 믿거나, 문서를 지나치게 크게 잘라 핵심이 묻히게 만들기 쉽습니다. 오래된 문서와 최신 문서를 구분하지 않거나, 출처 링크만 달고 실제 문장이 답을 뒷받침하는지 확인하지 않는 것도 문제입니다. 답변 문장만 평가하지 말고 검색된 조각도 함께 기록해 살펴보세요.
[보안 주의]
검색 단계에서 사용자와 역할별 문서 접근 권한을 먼저 적용해야 합니다. 검색된 문서 안의 명령문은 신뢰할 수 없는 데이터로 취급하고, 시스템 지시를 바꾸거나 링크·도구를 실행하라는 내용은 따르지 않습니다. 원문, 색인, 임베딩, 로그에 개인정보와 비밀값이 남지 않도록 수집 범위, 보관 기간, 삭제 절차를 정합니다. 실습은 본인 소유 또는 사용 허가를 받은 로컬 문서로만 진행합니다.
[직접 해볼 과제]
질문을 `오늘 날씨를 알려줘`로 바꾸어 `근거 부족`이 출력되는지 확인하세요. 그다음 각 문서에 날짜와 원본 경로를 추가하고, 선택 문서 ID와 함께 표시해 간단한 인용 형식을 만드세요.
[확인문제]
1. RAG에서 검색과 생성 단계를 따로 평가해야 하는 이유는 무엇인가요?
2. 관련 문서가 없을 때 답변을 보류해야 하는 이유는 무엇인가요?
3. 사용자별 접근 권한은 검색 전후 중 언제 적용해야 하나요?
[다음 학습]
AI-010에서는 모델이 외부 도구를 안전하게 호출하도록 입력, 권한, 결과를 통제하는 방법을 배웁니다.
[공식 참고 자료]
- RAG 원 논문: https://arxiv.org/abs/2005.11401
- NIST 생성형 AI 프로필: https://nvlpubs.nist.gov/nistpubs/ai/NIST.AI.600-1.pdf
- NIST AI 위험관리 프레임워크: https://www.nist.gov/itl/ai-risk-management-framework
- OWASP 프롬프트 주입 위험: https://genai.owasp.org/llmrisk/llm01-prompt-injection/
- Python 정규표현식 문서: https://docs.python.org/3/library/re.html
- 이전글[DATA-009][중급] 데이터 창고·호수·레이크하우스 구분하기 26.09.04
- 다음글[SEC-009][중급] 의존성과 SBOM으로 공급망 위험 줄이기 26.09.04
댓글목록
등록된 댓글이 없습니다.
