Ragas Improve RAG 实战:用真实评测数据对比朴素 RAG 与 Agentic RAG
2026/9/21 16:41:36 网站建设 项目流程
  • 人工智能
  • 大模型
  • 模型评测
  • RAG

【免费下载链接】ragas

Supercharge Your LLM Application Evaluations 🚀

项目地址:https://gitcode.com/gh_mirrors/ra/ragas
点击查看免费下载

ragas quickstart improve_rag是 Ragas 提供的一个开箱即用的评测模板,它基于 HuggingFace 官方文档问答数据集(hf_doc_qa_eval.csv),在同一套评测流程中对比两种典型的 RAG 架构——单次检索的朴素 RAG(Naive RAG)与由 Agent 控制检索的 Agentic RAG。读完本文,你将掌握:如何用一条命令搭建可运行的 RAG 评测工程、如何分别运行两种模式的评估并对比通过率、如何通过 MLflow 追踪每次 LLM 调用的轨迹,以及如何把知识库、模型、指标替换成你自己的方案。

模板能解决什么问题

很多团队在优化 RAG 系统时面临一个共同困境:升级到"更智能"的 Agent 架构后,无法量化它到底比朴素方案好在哪里。improve_rag模板的核心价值在于把这个问题变成一个可重复的实验:同一个问题集、同一个 BM25 检索器,只切换 RAG 的驱动方式(一次性检索 vs. Agent 自主多轮检索),然后用统一的correctness离散指标给每个回答打pass/fail,最终输出带时间戳的实验结果 CSV。

从源码看,该模板在 CLI 中的完整描述是"Compare naive vs agentic RAG using BM25 retrieval and HuggingFace docs",位于 cli.py 的 quickstart 模板注册表中;而模板主体存放在仓库的 examples/ragas_examples/improve_rag 目录下,包含rag.py(RAG 双模式实现)、evals.py(评测工作流)、pyproject.toml(依赖声明)以及evals/datasets/hf_doc_qa_eval.csv(真实评测数据集)。

创建项目

ragas quickstart命令支持多种模板(rag_evalagent_evalstext2sqlworkflow_eval等),运行时不带模板名会列出全部可用模板。创建本项目有两种等价方式:

# 方式一:使用 uvx,无需预先安装 ragas uvx ragas quickstart improve_rag cd improve_rag # 方式二:已安装 ragas 时 ragas quickstart improve_rag cd improve_rag

从 cli.py 的实现看,quickstart还支持--output-dir/-o参数指定创建位置,例如ragas quickstart improve_rag -o ./my-project。命令内部会依次尝试:本地安装的ragas_examples包 → 当前开发仓库的examples/ragas_examples→ 从远端归档下载,找到模板后复制到目标目录,并自动创建evals/datasetsevals/experimentsevals/logs三个子目录;如果目录已存在,会交互式询问是否覆盖。

安装依赖

推荐使用uv(项目已声明[tool.uv] managed = true):

uv sync

也可以使用 pip:

pip install -e .

依赖声明见模板的 pyproject.toml,核心依赖包括:

  • ragas[all]>=0.3.0:评测框架本体;
  • openai>=1.0.0:LLM 客户端(AsyncOpenAI);
  • mlflow>=2.0.0:可选的调用追踪;
  • langchainlangchain-communitylangchain-text-splitters:BM25 检索器与文档切分;
  • datasets>=2.0.0:加载 HuggingFace 文档语料;
  • rank-bm25>=0.2.2:BM25 排序算法;
  • python-dotenv>=1.0.0:读取.env配置。

注意:openai-agents被单独声明在[project.optional-dependencies] agentic分组中,也就是说Agentic 模式需要额外安装(详见下文"Agentic 模式")。

设置 API Key

模板默认使用 OpenAI 的gpt-4o-mini

export OPENAI_API_KEY="your-openai-key"

evals.py在启动时会校验该环境变量,缺失则直接抛出ValueError(见 evals.py);同时它也会调用load_dotenv(".env"),因此你也可以把 key 写进项目根目录的.env文件。

运行评估

朴素 RAG 模式(默认)

uv run python evals.py

Agentic RAG 模式

uv run python evals.py --agentic

Agentic 模式前置要求Agentic 模式依赖openai-agents包,需要先安装:

pip install openai-agents

该依赖对应pyproject.toml中的agentic可选组,也可以用uv sync --extra agentic统一安装。若缺失,rag.py_setup_agent()会抛出ImportError("agents package required for agentic mode")(见 rag.py)。

evals.py通过简单的命令行参数解析来决定模式:"--agentic" in sys.argv,其余情况一律走 naive(见 evals.py)。两种模式共用同一套评测流程,结果分别写入evals/experiments/YYYYMMDD-HHMMSS_naiverag.csvevals/experiments/YYYYMMDD-HHMMSS_agenticrag.csv(命名逻辑见run_experiment中的name参数,evals.py)。

可选:开启 MLflow 追踪

想要细粒度观察每次 LLM 调用的输入输出与耗时,可以先启动 MLflow 服务:

mlflow ui --port 5000

再运行评估即可。rag.py中的RAG类会在初始化时探测本地 MLflow 服务是否在线(_check_mlflow_server默认探测http://127.0.0.1:5000,超时 0.5 秒),在线则调用mlflow.openai.autolog()自动追踪所有 OpenAI 调用,并把mlflow_trace_id一并塞进每次查询的返回结果(rag.py)。evals.py还会为每条 trace 构造可直接点击的 MLflow 追踪 URL 写入结果 CSV(construct_mlflow_trace_url,evals.py)。

项目结构

improve_rag/ ├── README.md # 项目文档(由 quickstart 命令自动生成) ├── pyproject.toml # 项目配置与依赖声明 ├── rag.py # RAG 实现(naive 与 agentic 双模式) ├── evals.py # 评测工作流 ├── __init__.py # Python 包标记 └── evals/ ├── datasets/ # 测试数据集(hf_doc_qa_eval.csv) ├── experiments/ # 评测结果 CSV └── logs/ # 评测日志

理解两种 RAG 模式

朴素 RAG

朴素模式执行一次检索、一次生成,流程固定:

  1. 查询→ BM25 检索 top-k 文档
  2. 上下文→ 检索到的文档拼成上下文
  3. 生成→ LLM 基于上下文生成回答

对应RAG._naive_query的实现(rag.py):先用检索器拿到top_k篇文档,用system_prompt(默认模板为"Answer only based on documents. Be concise.\n\nQuestion: {query}\nDocuments:{context}\nAnswer:")格式化后调用chat.completions.create,最终返回{answer, retrieved_documents, num_retrieved, mlflow_trace_id}

rag = RAG(llm_client=client, retriever=retriever, mode="naive") result = await rag.query("What is the Diffusers library?")

优点:

  • 实现简单、速度快
  • 延迟可预期
  • 成本低(单次 LLM 调用)

缺点:

  • 检索词不同(同义表述/术语变体)时可能漏掉相关文档
  • 不做查询改写,问法不佳时直接失败
  • 只有单一检索策略,没有纠错机会

Agentic RAG

Agentic 模式把检索决策权交给 Agent:

  1. 查询→ Agent 分析问题
  2. 搜索→ Agent 自主决定检索什么(可多次搜索)
  3. 修正→ Agent 根据初步结果修正检索词
  4. 生成→ Agent 综合检索结果生成最终回答

rag.py中通过agents包的Agent+function_tool实现(rag.py):Agent 名为RAG Assistant,系统指令明确要求"先用精确术语(命令、API、工具名)搜索,必要时尝试 2-3 次不同检索词,只依据检索到的文档作答并保留准确语法与技术细节";检索工具retrieve的 docstring 同样引导 Agent 采用"具体术语 → 工具名 → 替代词"的搜索策略。执行时由agents.Runner.run驱动(_agentic_query,rag.py),由于检索发生在 Agent 内部,返回结果中retrieved_documents为空、num_retrieved为 0。

rag = RAG(llm_client=client, retriever=retriever, mode="agentic") result = await rag.query("What command uploads an ESPnet model?")

优点:

  • 可尝试多种检索策略
  • 更擅长定位具体的专业技术信息
  • 能根据初步结果自适应调整检索方向

缺点:

  • 延迟更高(多次 LLM 调用)
  • 成本更高
  • 行为不如朴素模式可预期

评测数据集

模板自带evals/datasets/hf_doc_qa_eval.csv,包含关于 HuggingFace 文档的技术问答,共两个字段:

字段说明
question关于 HuggingFace 工具链的技术问题
expected_answer标准答案(ground truth)

数据集中真实存在的问题示例(见 hf_doc_qa_eval.csv):

  • "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?"
  • "What architecture is thetokenizers-linux-x64-muslbinary designed for?"
  • "What method does the EulerAncestralDiscreteScheduler use for sampling?"

这类问题有个共同特点:答案藏在文档的特定位置,且对表述精度敏感(命令名、API 名、默认值),恰好能区分"一次性检索"与"Agent 多轮检索"的能力差异。首次运行时evals.py会尝试从远端拉取该 CSV 到本地(已存在则跳过),随后用Dataset(name="hf_doc_qa_eval", backend="local/csv", root_dir="evals")逐行构建 Ragas 数据集并保存(evals.py)。

理解核心代码

RAG 实现(rag.py

BM25Retriever

基于 BM25(Best Matching 25)算法做词法检索,构建流程(rag.py):

  1. datasets.load_dataset("m-ric/huggingface_doc", split="train")加载 HuggingFace 文档语料;
  2. 逐条转成Document,并把source字段的第二段(如diffusers)写入 metadata;
  3. RecursiveCharacterTextSplitterchunk_size=1000chunk_overlap=100、分隔符依次为段落/换行/句点/空格/空串)切分成块;
  4. page_content去重;
  5. 构建LangchainBM25Retriever索引。
class BM25Retriever: def __init__(self, dataset_name="m-ric/huggingface_doc"): # 加载 HuggingFace 文档 # 切分为 chunk 便于检索 # 构建 BM25 索引 def retrieve(self, query: str, top_k: int = 3): # 返回 top-k 最相关文档

注意retrieve()会动态设置self.retriever.k = top_k,默认top_k取构造时的default_k=3

RAG 类

对外暴露统一接口,内部按模式分发:

class RAG: def __init__(self, llm_client, retriever, mode="naive", system_prompt=None, model="gpt-4o-mini", default_k=3): 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)

从源码可见完整签名还支持system_prompt(自定义提示词模板)、model(默认gpt-4o-mini)与default_k三个可调参数;query()内部对未知模式抛出ValueError,任何异常都会以{"answer": "Error: ..."}的形式兜底返回而不是中断整个评测(rag.py)。

评测脚本(evals.py

评测指标使用 Ragas 的离散指标,将模型回答与标准答案对比:

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"], )

完整提示词(evals.py)明确给出三条判据:是否包含标准答案的关键信息、是否基于给定上下文在事实上准确、是否充分回答了提问。评测循环由@experiment()装饰器包裹的evaluate_rag(row, rag, llm)驱动:对每行数据调用rag.query(question, top_k=4)拿到模型回答,再用correctness_metric.ascore(question=..., expected_answer=..., response=..., llm=llm)异步打分,最后把model_responsecorrectness_scorecorrectness_reasonmlflow_trace_idmlflow_trace_url以及截断到 200 字符的检索文档列表一并写入结果(evals.py)。这里的llmllm_factory("gpt-4o-mini", client=openai_client, temperature=1, top_p=None)构造(evals.py),评测结束时会在日志中打印pass_count/total_count (xx.x%)的汇总通过率。

自定义改造

更换知识库

把 HuggingFace 文档换成你自己的资料,实现一个同签名(retrieve(query, top_k))的检索器即可:

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)

RAG只依赖检索器的retrieve(query, top_k)接口(返回可访问page_content的文档列表),因此任意实现——向量检索、混合检索、外部搜索 API——都能无缝接入。

更换模型

evals.py中改两处即可切换模型:

# 生成端:RAG 构造时指定 rag = RAG(llm_client=client, retriever=retriever, model="gpt-4o") # 评测端:llm_factory 指定 llm = llm_factory("gpt-4o-mini", client=openai_client, temperature=1, top_p=None)

需要注意:rag.py中的RAG类当前面向 OpenAI 兼容的AsyncOpenAI客户端编写(内部直接调用chat.completions.create,Agent 模式使用agents包的Agent(model=...))。如果改用其他提供方(如 Anthropic),需要按对应 SDK 适配rag.py中的调用逻辑;而评测端的llm_factory本身支持多提供方,改动成本更低。

添加自定义指标

correctness之外,可以用 Ragas 的数值指标补充维度,例如完整度评分:

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, }

Ragas 指标体系还提供了更多可选能力:通用离散/数值/字符串指标、基于评价标准(rubrics)的指标等,可参考 available metrics 文档 与 自定义/修改指标提示词指南。

修改 Agent 行为

Agent 的检索策略在rag.py_setup_agent()中定制——改工具描述、系统指令即可控制搜索习惯:

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="你的自定义指令……", tools=[retrieve] )

例如,针对代码库问答可以要求 Agent"优先搜索函数签名与导入路径",针对多语言场景可以要求"同时用中英文术语各搜一次"。

对比结果

依次运行两种模式:

# 朴素模式 uv run python evals.py # 结果保存到 experiments/YYYYMMDD-HHMMSS_naiverag.csv # Agentic 模式 uv run python evals.py --agentic # 结果保存到 experiments/YYYYMMDD-HHMMSS_agenticrag.csv

然后用 pandas 快速汇总通过率:

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%}")

除了通过率,CSV 中的correctness_reason(LLM 给出的判分理由)、mlflow_trace_url(单条 trace 的完整调用链)是定位失败根因的两个关键抓手:先看判分理由缩小问题范围,再顺着 trace 检查 Agent 到底检索了什么、生成了什么。这套流程同样适用于生产环境 RAG 的持续观测,可进一步参考 Evaluate and Improve RAG 与 RAG Evaluation Guide。

故障排查

MLflow 警告

看到 MLflow 报 trace 发送失败的警告时,二选一即可:

  1. 启动 MLflow 服务:mlflow ui --port 5000
  2. 直接忽略——没有追踪时评测照常运行

rag.py在 MLflow 不可用时静默降级:_check_mlflow_server探测失败就把_mlflow_enabled置为False,不再调用mlflow.openai.autolog(),并在日志级别上压制了 mlflow 追踪模块的告警(rag.py)。

Agentic 模式无法运行

确认已安装 agents 包:

pip install openai-agents

若仍报错,检查是否同时存在多个 Python 环境——uv runpip安装进的环境必须一致。

首次运行缓慢

首次运行需要下载 HuggingFace 文档数据集(约 300MB)用于构建 BM25 索引,之后会使用本地缓存(datasets库缓存与evals/datasets下的 CSV 均只下载一次)。评估过程中的 LLM 调用延迟取决于所选模型与网络状况。

总结

improve_rag把"RAG 架构选型"从拍脑袋变成可量化实验:固定知识库、固定问题集、固定评测指标,只改变检索的驱动方式,用correctness通过率说话。朴素模式是低成本基线,Agentic 模式则是能力上限,两者的差距就是你为"更聪明的检索"愿意付出的延迟与成本。以此为骨架,替换检索器、模型与指标,就能把同一套评测方法复用到你自己的知识库与业务场景中。

  • 人工智能
  • 大模型
  • 模型评测
  • RAG

【免费下载链接】ragas

Supercharge Your LLM Application Evaluations 🚀

项目地址:https://gitcode.com/gh_mirrors/ra/ragas
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询