Files
siemens_ragas/docs/rag-eval-engine-flow.md
2026-06-12 14:02:15 +08:00

417 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# RAG 评测引擎链路说明
## 1. 这份文档解决什么问题
`docs/rag-eval-architecture.md` 主要回答“为什么这样分层、模块边界是什么”。
这份文档回答的是另一件事:**一次评测在代码里到底是怎么跑起来的**。
如果你现在对下面这些问题还有点混淆,这份文档就是给你的:
- `rag_eval/` 到底是评测什么的
- `apps/` 在整个架构里扮演什么角色
- `offline``online` 模式的区别是什么
- dataset、adapter、metrics、reporting 是怎么串起来的
---
## 2. 一句话理解整个引擎
这套系统本质上是一条标准化评测流水线:
```text
scenario -> dataset -> normalize -> app adapter -> metrics -> reporting -> run artifacts
```
也可以拆成更容易理解的话:
1. 先读取一份评测场景配置
2. 再读取待评测数据
3. 把原始数据标准化成统一样本结构
4. 如果需要,调用你的 RAG 应用补齐 `answer``contexts`
5.`ragas` 指标计算分数
6. 把结果写到本地 run 目录
---
## 3. 目录职责
### `rag_eval/`
这是**评测引擎本体**。它负责:
- 加载 scenario
- 加载 dataset
- 调用 app adapter
- 执行指标评分
- 写出结果资产
### `apps/`
这是**被评测应用的接入层**,不是评测框架本身。
这里放的是“你的 RAG 应用如何被框架调用”的示例或适配代码。例如:
```text
apps/
└── sample_python/
├── adapter.py
└── README.md
```
`apps/sample_python/` 的意义不是提供评测逻辑,而是演示:
- 如果你的应用是本地 Python 函数
- 它应该暴露什么接口
- 返回值要长什么样
### `scenarios/`
这是评测配置层,用 YAML 声明:
- 评测模式
- 数据集路径
- judge / embedding 模型
- 要跑哪些 metrics
- 输出目录
- 是否要调用 `http``python` adapter
### `datasets/`
这里存放评测输入数据。通常分为:
- `raw/`:原始输入
- `normalized/`:整理后的标准评测样本
### `outputs/` 或 `runs/`
这里存放每次评测生成的结果资产,比如:
- `scores.csv`
- `invalid.csv`
- `summary.md`
- `metadata.json`
---
## 4. 主入口链路
统一主链路最终都会走到:
- [rag_eval/execution/runner.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/execution/runner.py:1)
核心入口函数是 `run_scenario()`,它负责把所有子模块串起来。
简化后的执行顺序是:
```text
run_scenario()
-> load_scenario()
-> build_adapter()
-> build_metric_pipeline()
-> Evaluator.evaluate()
-> write_run_artifacts()
```
你可以把它理解成整套系统的 orchestration 层。
---
## 5. Scenario 链路
scenario 是一次评测任务的“总配置”。
相关代码:
- [rag_eval/config/loader.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/config/loader.py:1)
- [rag_eval/config/schema.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/config/schema.py:1)
- [rag_eval/config/validators.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/config/validators.py:1)
它定义的内容包括:
- `mode`: `offline``online`
- `dataset`
- `judge_model`
- `embedding_model`
- `metrics`
- `output_dir`
- `runtime`
- `app_adapter`
作用可以概括为一句话:
**scenario 决定“这次评测要怎么跑”。**
---
## 6. Dataset 链路
数据进入评测引擎后,不会直接拿原始 CSV 去打分,而是要先标准化。
相关代码:
- [rag_eval/datasets/loader.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/datasets/loader.py:1)
- [rag_eval/datasets/validators.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/datasets/validators.py:1)
- [rag_eval/datasets/normalizers.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/datasets/normalizers.py:1)
它做三件事:
1. 读取 CSV / Excel / JSONL
2. 校验必要字段
3. 转成统一内部对象 `NormalizedSample`
统一样本结构定义在:
- [rag_eval/shared/models.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/shared/models.py:1)
最关键字段是:
- `question`
- `contexts`
- `answer`
- `ground_truth`
这个统一结构是后续 metrics 和 reporting 能共用一条链路的前提。
---
## 7. Offline 和 Online 的真正区别
这是整个系统最关键的分叉点。
### Offline 模式
离线模式下dataset 里已经有完整评测字段:
- `question`
- `contexts`
- `answer`
- `ground_truth`
所以链路是:
```text
load dataset -> normalize -> score metrics -> write artifacts
```
这个模式不需要调用你的应用。
### Online 模式
在线模式下dataset 往往只有:
- `question`
- 一些 metadata
`answer``contexts` 需要评测时实时调用你的 RAG 应用拿回来。
所以链路会变成:
```text
load dataset -> normalize -> call app adapter -> enrich samples -> score metrics -> write artifacts
```
在线模式比离线模式多出来的核心环节,就是 **adapter 调用**
---
## 8. `apps/sample_python/` 到底是干什么的
这个目录是一个 **Python adapter 示例**
相关文件:
- [apps/sample_python/adapter.py](/C:/Users/A200477427/Learnings/ragas-template/apps/sample_python/adapter.py:1)
- [apps/sample_python/README.md](/C:/Users/A200477427/Learnings/ragas-template/apps/sample_python/README.md:1)
它演示了:如果你的 RAG 应用是本地 Python 代码,那么框架期望你提供一个这样的函数:
```python
def run(question: str, **kwargs) -> dict:
return {
"answer": "...",
"contexts": ["...", "..."],
"raw_response": {...},
}
```
也就是说,`apps/sample_python/` 不是评测引擎的一部分,而是“被评测应用”的一个参考接入模板。
它的作用是:
- 告诉你 Python 类型应用如何接入
-`python` adapter 一个最小可运行示例
- 让你后续把真实 RAG 逻辑替换进去
---
## 9. Adapter 链路
adapter 层的目标是:**把不同类型的目标应用,统一成同一套输入输出协议。**
相关代码:
- [rag_eval/adapters/base.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/adapters/base.py:1)
- [rag_eval/adapters/http.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/adapters/http.py:1)
- [rag_eval/adapters/python.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/adapters/python.py:1)
当前支持两类 adapter
### `python`
适用于本地 Python 应用。
框架会根据 scenario 里的 `module:function` 动态加载函数,然后调用它。
### `http`
适用于独立 HTTP 服务。
框架会构造请求、解析响应,并映射到统一结构。
无论哪种 adapter最后都要返回统一结果
- `answer`
- `contexts`
- `raw_response`(可选)
这一步很关键,因为 metrics 层不应该关心底层到底是 HTTP 服务还是 Python 函数。
---
## 10. Evaluator 链路
评测执行核心在:
- [rag_eval/execution/evaluator.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/execution/evaluator.py:1)
`Evaluator.evaluate()` 大致会做这些事:
1. 记录开始时间
2. 加载 dataset
3. 标准化样本
4. 如果是 `online`,先调用 adapter 补齐样本
5. 调用 metric pipeline 打分
6. 合并样本字段和评分结果
7. 返回 `EvaluationResult`
这里可以把 `Evaluator` 理解成:
**一次评测运行的总执行器**
---
## 11. Metric Pipeline 链路
相关代码:
- [rag_eval/metrics/factory.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/metrics/factory.py:1)
- [rag_eval/metrics/pipeline.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/metrics/pipeline.py:1)
- [rag_eval/metrics/registry.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/metrics/registry.py:1)
这里的职责不是“决定评什么”,而是“把要评的指标真正跑起来”。
具体包括:
- 初始化 OpenAI client
- 创建 judge model / embedding model
- 根据 scenario 装配对应的 ragas metrics
- 并发执行单样本或批量评分
当前支持的指标包括:
- `faithfulness`
- `answer_relevancy`
- `context_recall`
- `context_precision`
所以 metric pipeline 的职责可以总结为:
**把标准样本转换成结构化评分结果。**
---
## 12. Reporting 链路
相关代码:
- [rag_eval/reporting/artifacts.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/reporting/artifacts.py:1)
- [rag_eval/reporting/summary.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/reporting/summary.py:1)
- [rag_eval/reporting/writers.py](/C:/Users/A200477427/Learnings/ragas-template/rag_eval/reporting/writers.py:1)
当评测完成后,结果不会只打印在终端,而是会沉淀成标准资产。
标准输出一般包括:
- `scenario.snapshot.yaml`
- `scores.csv`
- `invalid.csv`
- `summary.md`
- `metadata.json`
这是整套架构很重要的价值点,因为它让每次 run 都具备:
- 可复现性
- 可审计性
- 可对比性
---
## 13. 两条完整链路示意
### Offline 完整链路
```text
main.py
-> run_scenario()
-> load_scenario()
-> load_dataset_records()
-> normalize_records()
-> build_metric_pipeline()
-> score_samples()
-> write_run_artifacts()
```
特点:
- 不调用被评测应用
- 直接对现成样本评分
### Online 完整链路
```text
main.py
-> run_scenario()
-> load_scenario()
-> build_adapter()
-> load_dataset_records()
-> normalize_records()
-> adapter.enrich_sample()
-> build_metric_pipeline()
-> score_samples()
-> write_run_artifacts()
```
特点:
- 会先调用目标应用
- 再对实时生成的 `answer / contexts` 评分
---
## 14. 你应该怎么理解这套架构
如果只记一条心智模型,可以记这个:
- `rag_eval/` 负责“怎么评”
- `apps/` 负责“被评的应用怎么接进来”
- `datasets/` 负责“评测输入是什么”
- `scenarios/` 负责“这次评测要怎么配置”
- `reporting/` 负责“结果怎么沉淀”
从工程拆分上看,这个架构的核心价值不是“能跑一次评测”,而是:
- 可以反复跑
- 可以换应用跑
- 可以换数据跑
- 可以换模型跑
- 可以把每次实验的资产稳定留住
这也是它和一次性离线脚本的根本区别。