# 中文评判 Prompt 适配设计(judge_language: zh) **日期**: 2026-07-01 **状态**: 已批准,待实现 **范围**: 让 RAGAS 的 LLM 评判 prompt 从默认英文切换为中文,提升对中文语料的判定一致性(架构设计 §10.5)。通过场景 YAML 字段 `judge_language: zh` 和 score API 可选字段 `judge_language` 控制,默认 `en` 保持完全向后兼容。 --- ## 1. 背景与目标 架构设计 §10.5 明确要求: > 语料为中文,评判模型选多语言能力充分者即可。RAGAS 评判 prompt 默认英文,对中文语料应启用其语言适配,将评判 prompt 切换为中文以提升判定一致性。 当前 `rag_eval/metrics/factory.py` 与 `webapp/services/inline_scorer.py` 构建的 RAGAS `ragas.metrics.collections` 指标全部使用默认英文 `instruction` + `examples`。本设计新增中文评判能力: - 场景 YAML 新增 `judge_language: zh`(默认 `en`)。 - score 系列 API(`/api/score`、`/api/score/async`、`/api/score/session_async`)新增可选 `judge_language` 字段。 - 采用 RAGAS 原生 `BasePrompt.adapt()` + 提交到仓库的持久化缓存文件,生产运行完全确定、零额外延迟。 **成功标准**: - `judge_language: zh` 时,6 个 LLM 评判指标使用中文 prompt;`semantic_similarity`(纯 embedding)不受影响。 - 默认 `en` 时,所有既有场景与 API 行为逐字节不变。 - 单变量对比可行:同一数据集分别以 `en` / `zh` 各评一次,比较指标均值与方差。 --- ## 2. 需要本地化的指标与 prompt(已从 RAGAS 0.4.3 源码核实) 每个 LLM 评判指标把 prompt 存为**实例属性**,可在构建后覆盖: | 指标 | prompt 实例属性 | |---|---| | `faithfulness` | `statement_generator_prompt`, `nli_statement_prompt` | | `answer_relevancy` | `prompt` | | `context_recall` | `prompt` | | `context_precision` | `prompt` | | `noise_sensitivity` | 使用函数式 `to_string()`(无 `instruction`/`examples`),无法通过 `adapt()` 本地化,**跳过** | | `factual_correctness` | `prompt`, `nli_prompt` | | `semantic_similarity` | 无(纯 embedding,跳过) | 权威映射(写入 `judge_prompts.py`): ```python METRIC_PROMPT_ATTRS = { "faithfulness": ("statement_generator_prompt", "nli_statement_prompt"), "answer_relevancy": ("prompt",), "context_recall": ("prompt",), "context_precision": ("prompt",), "noise_sensitivity": ("statement_prompt", "faithfulness_prompt"), "factual_correctness": ("prompt", "nli_prompt"), } ``` `ragas.prompt.metrics.base_prompt.BasePrompt` 提供原生 `async adapt(target_language, llm, adapt_instruction=False)`:翻译 `examples`,`adapt_instruction=True` 时同时翻译 `instruction`,返回新 prompt 实例,并设置 `language` 属性。 --- ## 3. 架构与数据流 ``` [一次性] scripts/build_judge_prompt_cache.py --language zh 对每个指标的每个 prompt 调 adapt("chinese", llm, adapt_instruction=True) → 写出 configs/judge_prompts/zh/__.json(提交入库) [运行时·YAML 场景路径] runner → factory.build_metric_pipeline(scenario) 若 scenario.judge_language == "zh": localize_pipeline_prompts(registry, "zh") [运行时·score API 路径] /api/score, /api/score/async, /api/score/session_async → inline_scorer.score(..., judge_language=...) → _build_metric_instances(...) 若 language == "zh": localize_pipeline_prompts(registry, "zh") ``` 两条路径共用同一个本地化器,保持 DRY。 --- ## 4. 组件 ### 4.1 一次性引导脚本 `scripts/build_judge_prompt_cache.py` - 参数:`--language zh`、`--judge-model `(默认取 settings)。 - 对 `METRIC_PROMPT_ATTRS` 每个 (metric, attr):取活体 prompt 实例,`await prompt.adapt("chinese", llm, adapt_instruction=True)`,序列化为 JSON。 - `adapt()` 失败重试若干次;仍失败则整体中止、不写半成品。 - 产物提交入库,评审后即为生产资产。 ### 4.2 缓存文件 `configs/judge_prompts/zh/__.json` 按 `(metric, prompt_attr)` 命名,1:1 对应覆盖目标,零碰撞(多个指标各自独立生成,即使 prompt 类同名也互不影响)。 ```json { "metric": "faithfulness", "prompt_attr": "nli_statement_prompt", "language": "chinese", "ragas_version": "0.4.3", "source_hash": "<英文 instruction + 序列化 examples 的 sha256>", "instruction": "……中文 instruction……", "examples": [ { "input": { }, "output": { } } ] } ``` ### 4.3 运行时本地化器 `rag_eval/metrics/judge_prompts.py` 公开函数:`localize_pipeline_prompts(registry: dict[str, Any], language: str) -> LocalizationReport` - `language == "en"` 或空 → 直接返回,不做任何事。 - 对 registry 中每个已知指标的每个 prompt 属性: 1. 从缓存目录读取对应 JSON(**内存缓存已解析结果**,按 language 键,首次读盘后复用,保证 `/api/score` 高频调用零额外磁盘 IO)。 2. 用**活体 prompt 实例的** `input_model` / `output_model` 从 JSON 重建 `examples`,覆盖 `prompt.instruction`、`prompt.examples`、`prompt.language`。 - 返回 `LocalizationReport`(已应用 / 跳过 / 告警计数),供日志与测试断言。 ### 4.4 配置面 - `rag_eval/settings.py`:新增 `ragas_judge_language`(env `RAGAS_JUDGE_LANGUAGE`,默认 `en`)作为唯一全局默认。 - `rag_eval/shared/models.py`:`Scenario`(`@dataclass`)新增 `judge_language: str = "en"`,存放**已解析**的最终值。 - **YAML 场景路径的解析在配置加载器**(`rag_eval/config`)完成:`judge_language = YAML 显式值 or settings.ragas_judge_language`;同时在此处校验值域 `{en, zh}`(与既有 metrics 校验同层,dataclass 本身不做校验)。因此 `Scenario.judge_language` 对 factory 而言是权威值。 - `webapp/models.py`:`ScoreRequest` 新增 `judge_language: str | None = None`(`SessionScoreRequest` 继承自动获得);score API 路径解析 `request.judge_language or settings.ragas_judge_language`。 - **统一优先级(两条路径一致)**:显式值(YAML 字段 / 请求字段)> `settings.ragas_judge_language`(默认 `en`)。 ### 4.5 集成点改动 - `rag_eval/metrics/factory.py`:`build_metric_pipeline()` 构建 registry 后,若 `scenario.judge_language == "zh"`,调 `localize_pipeline_prompts(registry, "zh")`。 - `webapp/services/inline_scorer.py`:`score()` 与 `_build_metric_instances()` 增加 `judge_language` 参数;构建指标后按需本地化。`(judge_model, embedding_model)` 缓存仅缓存 llm/embeddings,指标每次重建,故每次正确应用本地化,缓存键无需变动。 - `webapp/api/score.py`、`webapp/services/score_job_manager.py`、`webapp/services/session_score_manager.py`:把 `request.judge_language`(回退到 settings 默认)透传给 `inline_scorer.score()`。 --- ## 5. 错误处理与漂移检测 - **运行时缺文件 / JSON 损坏 / examples 按当前 schema 重建失败** → 记 WARNING,保留该 prompt 的英文默认,**绝不中断评分**(优雅降级)。 - **`judge_language: zh` 但缓存整体缺失** → 告警一次,按英文继续。 - **漂移检测**:加载时用当前英文源计算 `source_hash` 与缓存值比对: - 不一致但 schema 仍有效 → 应用中文 + 记 loud WARNING「缓存已过期,请重新运行 build_judge_prompt_cache.py」。 - schema 已失效(重建抛错)→ 自动回退英文。 - **引导脚本** adapt 失败 → 重试后中止,不写半成品。 --- ## 6. 测试(确定性,Mock LLM,遵循 AGENTS.md) 新增 `tests/test_judge_prompt_localizer.py`: - fixture 缓存文件正确覆盖 `metric..instruction` 与 `.examples`(examples 按活体 model 重建成功)。 - 缺文件 → 保留英文默认、不抛异常。 - `source_hash` 不匹配 → 记告警仍应用中文;schema 失效 → 回退英文。 - `language == "en"` → registry 完全不变。 - 内存缓存:同一 language 第二次调用不再读盘(用可计数的假 loader 或 monkeypatch 断言)。 扩展/新增: - `Scenario` schema:`judge_language` 解析、默认 `en`、非法值报错。 - `ScoreRequest`:`judge_language` 可选、默认 `None`。 - 引导脚本:mock LLM(`adapt` 返回预置中文)→ 断言写出预期 JSON 结构与字段。 **可选人工验证(非 CI)**:固定小样本集分别以 `en` / `zh` 各评一次,比较均值/方差,并复核已知正确样本(如 “MAGNETOM Vida 设备总重 7370 kg”)。 --- ## 7. 改动文件清单 **新增**: - `rag_eval/metrics/judge_prompts.py` — 本地化器(加载/覆盖/hash/内存缓存) - `scripts/build_judge_prompt_cache.py` — 一次性引导脚本 - `configs/judge_prompts/zh/*.json` — 提交入库的中文 prompt 缓存 - `tests/test_judge_prompt_localizer.py` — 测试 **修改**: - `rag_eval/shared/models.py` — `Scenario.judge_language` 字段(存已解析值) - `rag_eval/config`(YAML 加载器)— 解析 `judge_language` = 显式值 or settings 默认,并校验值域 - `rag_eval/settings.py` — `ragas_judge_language` 默认 - `rag_eval/metrics/factory.py` — `build_metric_pipeline` 接入本地化 - `webapp/models.py` — `ScoreRequest.judge_language` - `webapp/services/inline_scorer.py` — `score()`/`_build_metric_instances()` +参数+本地化 - `webapp/api/score.py`、`webapp/services/score_job_manager.py`、`webapp/services/session_score_manager.py` — 透传 `judge_language` - 示例场景 YAML(如 `scenarios/siemens_build/*`、一个 offline 示例)— 增加 `judge_language: zh` - `README.md` — 简述机制与「如何重新生成缓存」 --- ## 8. 兼容性与影响 - 三个 score 接口默认(不传 `judge_language`)行为**逐字节不变**,现有 Dify Tool 调用零影响。 - YAML 场景默认 `judge_language: en`,既有 run 结果口径不变。 - 仅当显式 `zh` 时切换中文 prompt;可随时通过重跑脚本刷新缓存。