RAG 개선 퀵스타트
RAG 개선 퀵스타트 (Improve RAG Quickstart)
improve_rag 템플릿은 실제 평가 데이터를 사용해서 다양한 RAG 접근 방식을 비교하는 방법을 보여줘요. naive(단일 검색)와 agentic(다단계 검색) RAG 모드를 포함해요. 프로젝트 생성부터 두 모드의 통과율 비교까지 진행할 수 있어요.
출처: 문서
본문
improve_rag 템플릿은 실제 평가 데이터를 사용해서 다양한 RAG 접근 방식을 비교하는 방법을 보여줘요. naive(단일 검색)와 agentic(다단계 검색) RAG 모드를 포함해요.
프로젝트 만들기
# uvx 사용 (설치 불필요)
uvx ragas quickstart improve_rag
cd improve_rag
# 또는 ragas 설치 후
ragas quickstart improve_rag
cd improve_rag
의존성 설치
uv sync
또는 pip으로:
pip install -e .
API 키 설정
export OPENAI_API_KEY="your-openai-key"
평가 실행
Naive RAG 모드 (기본값)
uv run python evals.py
Agentic RAG 모드
uv run python evals.py --agentic
Agentic 모드 요구 사항
Agentic 모드에는 openai-agents 패키지가 필요해요. 다음으로 설치해요.
pip install openai-agents
선택: MLflow 추적
LLM 호출의 상세 추적을 위해 실행 전에 MLflow를 시작해요.
mlflow ui --port 5000
그런 다음 평가를 실행해요. 서버가 실행 중이면 트레이스가 MLflow로 자동 전송돼요.
프로젝트 구조
improve_rag/
├── README.md # Project documentation
├── pyproject.toml # Project configuration
├── rag.py # RAG implementation (naive & agentic)
├── evals.py # Evaluation workflow
├── __init__.py # Python package marker
└── evals/
├── datasets/ # Test datasets (hf_doc_qa_eval.csv)
├── experiments/ # Evaluation results
└── logs/ # Evaluation logs
RAG 모드 이해하기
Naive RAG
naive 접근 방식은 단일 검색 단계를 수행해요.
- Query → BM25가 top-k 문서 검색
- Context → 검색된 문서가 컨텍스트 형성
- Generate → LLM이 컨텍스트에서 응답 생성
rag = RAG(llm_client=client, retriever=retriever, mode="naive")
result = await rag.query("What is the Diffusers library?")
장점:
- 간단하고 빠름
- 예측 가능한 지연 시간
- 더 낮은 비용 (단일 LLM 호출)
단점:
- 다른 용어가 있는 관련 문서를 놓칠 수 있음
- 쿼리 개선 없음
- 단일 검색 전략으로 제한
Agentic RAG
agentic 접근 방식은 에이전트가 검색을 제어하게 해요.
- Query → 에이전트가 질문 분석
- Search → 에이전트가 무엇을 검색할지 결정 (여러 검색 가능)
- Refine → 에이전트가 결과에 따라 검색 개선
- Generate → 에이전트가 최종 답변 합성
rag = RAG(llm_client=client, retriever=retriever, mode="agentic")
result = await rag.query("What command uploads an ESPnet model?")
장점:
- 여러 검색 전략 시도 가능
- 특정 기술 정보를 찾는 데 더 나음
- 초기 결과에 따라 검색 적응
단점:
- 더 높은 지연 시간 (여러 LLM 호출)
- 더 높은 비용
- 덜 예측 가능한 동작
평가 데이터셋
템플릿은 HuggingFace 문서에 대한 질문이 있는 hf_doc_qa_eval.csv를 포함해요.
| Field | Description |
|---|---|
question |
HuggingFace 도구에 대한 기술 질문 |
expected_answer |
ground truth 답변 |
예제 질문:
- "What is the default checkpoint used by the sentiment analysis pipeline?"
- "What command is used to upload an ESPnet model?"
- "What is the purpose of the Diffusers library?"
코드 이해하기
RAG 구현 (rag.py)
BM25Retriever
문서 검색에 BM25(Best Matching 25) 알고리즘을 사용해요.
class BM25Retriever:
def __init__(self, dataset_name="m-ric/huggingface_doc"):
# HuggingFace 문서 로드
# 더 나은 검색을 위해 청크로 분할
# BM25 인덱스 생성
def retrieve(self, query: str, top_k: int = 3):
# top-k 가장 관련성 높은 문서 반환
RAG 클래스
두 모드 모두에 대한 통합 인터페이스:
class RAG:
def __init__(self, llm_client, retriever, mode="naive"):
self.mode = mode
if mode == "agentic":
self._setup_agent()
async def query(self, question: str, top_k: int = 3):
if self.mode == "naive":
return await self._naive_query(question, top_k)
else:
return await self._agentic_query(question, top_k)
평가 스크립트 (evals.py)
correctness 메트릭은 모델 응답을 기대 답변과 비교해요.
correctness_metric = DiscreteMetric(
name="correctness",
prompt="""Compare the model response to the expected answer...
Return 'pass' if correct, 'fail' if incorrect.""",
allowed_values=["pass", "fail"],
)
커스터마이즈
지식 베이스 변경
HuggingFace 문서를 자신의 문서로 교체해요.
class CustomRetriever:
def __init__(self, documents: list[str]):
from langchain_community.retrievers import BM25Retriever
self.retriever = BM25Retriever.from_texts(documents)
def retrieve(self, query: str, top_k: int = 3):
self.retriever.k = top_k
return self.retriever.invoke(query)
다른 모델 사용
evals.py에서 모델을 변경해요.
# 더 나은 정확도를 위해 GPT-4 사용
rag = RAG(llm_client=client, retriever=retriever, model="gpt-4o")
# 또는 다른 프로바이더 사용
from anthropic import Anthropic
client = Anthropic()
# 참고: 비-OpenAI 클라이언트는 rag.py 수정이 필요할 수 있음
커스텀 메트릭 추가
추가 측면을 평가해요.
from ragas.metrics import NumericalMetric
completeness = NumericalMetric(
name="completeness",
prompt="""How complete is the response (1-5)?
Question: {question}
Expected: {expected_answer}
Response: {response}
Score:""",
allowed_values=(1, 5),
)
# 실험에 추가
result = {
**row,
"correctness": correctness_score.value,
"completeness": completeness.score(...).value,
}
에이전트 동작 수정
rag.py에서 agentic 검색 전략을 커스터마이즈해요.
def _setup_agent(self):
@function_tool
def retrieve(query: str) -> str:
"""커스텀 도구 설명..."""
docs = self.retriever.retrieve(query, self.default_k)
return "\n\n".join([doc.page_content for doc in docs])
self._agent = Agent(
name="Custom RAG Assistant",
instructions="Your custom instructions...",
tools=[retrieve]
)
결과 비교
두 모드를 실행하고 비교해요.
# naive 모드 실행
uv run python evals.py
# 결과 saved to experiments/YYYYMMDD-HHMMSS_naiverag.csv
# agentic 모드 실행
uv run python evals.py --agentic
# 결과 saved to experiments/YYYYMMDD-HHMMSS_agenticrag.csv
결과 분석:
import pandas as pd
naive = pd.read_csv("evals/experiments/..._naiverag.csv")
agentic = pd.read_csv("evals/experiments/..._agenticrag.csv")
print(f"Naive pass rate: {(naive['correctness_score'] == 'pass').mean():.1%}")
print(f"Agentic pass rate: {(agentic['correctness_score'] == 'pass').mean():.1%}")
문제 해결
MLflow 경고
MLflow가 트레이스 실패에 대한 경고를 표시하면 다음 중 하나를 해요.
- MLflow 시작:
mlflow ui --port 5000 - 또는 무시해도 됨 - 추적 없이도 평가는 여전히 작동해요
Agentic 모드가 작동하지 않음
agents 패키지가 있는지 확인해요.
pip install openai-agents
첫 실행이 느림
첫 실행은 HuggingFace 문서 데이터셋(약 300MB)을 다운로드해요. 이후 실행은 캐시된 데이터를 사용해요.
더 알아보기 (Learn more)
- RAG Evaluation 가이드 - 더 간단한 평가 설정
- Custom Metrics - 자신만의 메트릭 작성
- Evaluate and Improve RAG - 프로덕션 RAG 평가