rag1.py
RAG (Retrieval-Augmented Generation) 기본 구현
개요
| 항목 | 내용 |
|---|---|
| RAG | 검색 증강 생성 - LLM + 외부 문서 검색 |
| 목적 | LLM의 지식 한계 극복, 최신 정보 활용 |
| 구성 | 검색(Retrieve) → 증강(Augment) → 생성(Generate) |
RAG 아키텍처
사용자 질문: "RAG가 뭐야?"
↓
┌─────────────────────────────┐
│ 1. 검색 (Retrieve) │
│ → 관련 문서 검색 │
│ → "RAG는 LLM의 한계를..." │
└─────────────┬───────────────┘
↓
┌─────────────────────────────┐
│ 2. 증강 (Augment) │
│ → 검색 결과를 프롬프트에 추가 │
└─────────────┬───────────────┘
↓
┌─────────────────────────────┐
│ 3. 생성 (Generate) │
│ → 컨텍스트 기반 답변 생성 │
│ → 출처 포함 │
└─────────────────────────────┘
전체 소스 코드
import json
from google import genai
from google.genai import types
# ⭐️ 1. 설정 및 클라이언트 초기화
MODEL_NAME = 'gemini-2.5-flash'
MyKey = "YOUR_GEMINI_API_KEY"
# RAG에 최적화된 시스템 지침
SYSTEM_INSTRUCTION = (
"당신은 전문 지식 챗봇입니다. 사용자의 질문에 답변하기 위해 "
"'document_search' 함수를 사용하여 관련 문서를 검색해야 합니다. "
"검색 결과(retrieved_documents)를 바탕으로 사실에 근거한 답변을 생성하고, "
"답변에 출처(Source)를 명시해야 합니다."
)
client = genai.Client(api_key=MyKey)
# 💡 2. 검색(Retrieval) 함수 정의
def document_search(query: str) -> str:
"""
사용자의 질문(query)과 관련된 내부 문서를 검색합니다.
실제로는 Vector DB를 사용하지만, 여기서는 가상 데이터로 시뮬레이션합니다.
"""
print(f"\n **[함수 실행]** 문서 검색 중... 쿼리: '{query}'")
# ⭐️ 가상 검색 결과 (실제로는 Vector DB 조회)
if "인공지능" in query.lower() or "llm" in query.lower():
documents = [
"Source 1: 대규모 언어 모델(LLM)은 방대한 텍스트 데이터를 학습합니다.",
"Source 2: RAG는 LLM의 지식 한계를 극복하기 위한 기술입니다.",
"Source 3: Gemini는 Google에서 개발한 최신 LLM입니다."
]
elif "뉴턴" in query.lower() or "만유인력" in query.lower():
documents = [
"Source 1: 아이작 뉴턴은 17세기 영국의 물리학자입니다.",
"Source 2: 만유인력의 법칙은 두 물체 사이의 인력을 설명합니다."
]
else:
documents = ["Source 1: 관련 문서를 찾을 수 없습니다."]
return json.dumps({"retrieved_documents": documents})
# 💡 3. 함수 매핑
AVAILABLE_FUNCTIONS = {
"document_search": document_search,
}
# 4. 메인 RAG 실행 로직
def run_rag_example(user_query: str):
print("=" * 60)
print(f"사용자 입력: {user_query}")
print("=" * 60)
tools = [document_search]
messages = [{"role": "user", "parts": [types.Part(text=user_query)]}]
# 1차 API 호출: LLM에게 질문과 검색 함수 제공
response = client.models.generate_content(
model=MODEL_NAME,
contents=messages,
config=types.GenerateContentConfig(
tools=tools,
system_instruction=SYSTEM_INSTRUCTION
)
)
# 2단계: LLM이 검색 함수 호출을 요청했는지 확인
if response.function_calls:
function_call = response.function_calls[0]
function_name = function_call.name
function_args = dict(function_call.args)
print(f"🤖 1차 응답: '{function_name}' 호출 요청")
# 3단계: 로컬에서 검색 함수 실행
function_to_call = AVAILABLE_FUNCTIONS.get(function_name)
tool_response_json = function_to_call(**function_args)
print(f" 🐍 함수 실행 완료.")
# 4단계: 검색 결과를 모델에게 다시 전달 (Augmentation)
messages.append(response.candidates[0].content)
messages.append(
types.Content(
role='tool',
parts=[
types.Part.from_function_response(
name=function_name,
response={"result": tool_response_json}
)
]
)
)
# 5단계: 최종 답변 요청 (2차 API 호출)
final_response = client.models.generate_content(
model=MODEL_NAME,
contents=messages,
)
print(f"\n✅ 최종 AI 답변:\n{final_response.text.strip()}")
else:
print(f"\n**AI 응답:** 함수 호출 없이 바로 답변")
print(response.text.strip())
# --- 실행 예제 ---
# 예제 1: RAG 작동 (검색 함수 호출)
query1 = "RAG가 무엇인지 자세히 설명해줘."
run_rag_example(query1)
print("\n" + "=" * 60 + "\n")
# 예제 2: 다른 주제 검색
query2 = "아이작 뉴턴은 어떤 사람이야?"
run_rag_example(query2)
핵심 개념
1. 검색 함수 정의
def document_search(query: str) -> str:
# 실제로는 Vector DB에서 유사 문서 검색
# 여기서는 키워드 기반 시뮬레이션
if "llm" in query.lower():
documents = ["Source 1: LLM은...", "Source 2: RAG는..."]
return json.dumps({"retrieved_documents": documents})
2. 시스템 지침 설정
SYSTEM_INSTRUCTION = (
"검색 결과를 바탕으로 답변하고, 출처를 명시하세요."
)
LLM이 항상 검색 함수를 사용하도록 유도
3. 검색 결과를 LLM에 전달
messages.append(
types.Content(
role='tool',
parts=[
types.Part.from_function_response(
name="document_search",
response={"result": tool_response_json}
)
]
)
)
실행 예시
============================================================
사용자 입력: RAG가 무엇인지 자세히 설명해줘.
============================================================
🤖 1차 응답: 'document_search' 호출 요청
**[함수 실행]** 문서 검색 중... 쿼리: 'RAG'
🐍 함수 실행 완료.
✅ 최종 AI 답변:
RAG(Retrieval-Augmented Generation)는 대규모 언어 모델(LLM)의 한계를
극복하기 위한 기술입니다.
LLM은 학습 데이터에 없는 최신 정보나 특정 도메인 지식에 취약할 수 있는데,
RAG는 외부 문서를 검색하여 이러한 한계를 보완합니다.
**출처:**
- Source 1: LLM은 방대한 텍스트 데이터를 학습합니다.
- Source 2: RAG는 LLM의 지식 한계를 극복하기 위한 기술입니다.
실제 RAG 시스템 구성
| 구성요소 | 설명 | 도구 예시 |
|---|---|---|
| Vector DB | 문서를 벡터로 저장 | Pinecone, ChromaDB, Weaviate |
| Embedding | 텍스트 → 벡터 변환 | text-embedding-004 |
| Chunking | 문서 분할 | LangChain TextSplitter |
| Retriever | 유사 문서 검색 | 코사인 유사도 |