改进 RAG Quickstart
improve_rag 模板演示如何用真实评测数据比较不同 RAG 方法。它包含 naive(单次检索)和 agentic(多步检索)两种 RAG 模式。
创建项目
# Using uvx (no installation required)
uvx ragas quickstart improve_rag
cd improve_rag
# Or with ragas installed
ragas quickstart improve_rag
cd improve_rag
安装依赖
uv sync
或使用 pip:
pip install -e .
设置 API Key
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 Tracing
要详细 tracing LLM 调用,运行前先启动 MLflow:
mlflow ui --port 5000
然后运行评测。若服务器正在运行,traces 会自动发送到 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 方法让 agent 控制检索:
- Query → Agent 分析问题
- Search → Agent 决定搜索什么(可多次搜索)
- Refine → Agent 可根据结果精炼搜索
- Generate → Agent 综合最终答案
rag = RAG(llm_client=client, retriever=retriever, mode="agentic")
result = await rag.query("What command uploads an ESPnet model?")
优点:
- 可尝试多种搜索策略
- 更擅长找到特定技术信息
- 根据初始结果调整搜索
缺点:
- 延迟更高(多次 LLM 调用)
- 成本更高
- 行为更不可预测
评测数据集
模板包含 hf_doc_qa_eval.csv,其中是关于 HuggingFace 文档的问题:
| 字段 | 说明 |
|---|---|
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"):
# Loads HuggingFace documentation
# Splits into chunks for better retrieval
# Creates BM25 index
def retrieve(self, query: str, top_k: int = 3):
# Returns top-k most relevant documents
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 中更换模型:
# Use GPT-4 for better accuracy
rag = RAG(llm_client=client, retriever=retriever, model="gpt-4o")
# Or use a different provider
from anthropic import Anthropic
client = Anthropic()
# Note: Would need to modify rag.py for non-OpenAI clients
添加自定义指标
评测额外方面:
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),
)
# Add to experiment
result = {
**row,
"correctness": correctness_score.value,
"completeness": completeness.score(...).value,
}
修改 Agent 行为
在 rag.py 中定制 agentic 搜索策略:
def _setup_agent(self):
@function_tool
def retrieve(query: str) -> str:
"""Custom tool description..."""
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]
)
比较结果
运行两种模式并比较:
# Run naive mode
uv run python evals.py
# Results saved to experiments/YYYYMMDD-HHMMSS_naiverag.csv
# Run agentic mode
uv run python evals.py --agentic
# Results 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 警告
如果看到关于 failed traces 的 MLflow 警告,可以:
- 启动 MLflow:
mlflow ui --port 5000 - 或者忽略它们——没有 tracing 评测仍然可以工作
Agentic 模式无法工作
确保已安装 agents 包:
pip install openai-agents
首次运行较慢
首次运行会下载 HuggingFace 文档数据集(约 300MB)。后续运行使用缓存数据。