【Elasticsearch】工作流自动化评估
想知道你的 RAG 智能体是否准备好上线?只需使用 Elasticsearch Workflows 和两个 Claude 模型,就能在正确性、忠实度和检索质量三个维度上给它打分。
1. 引言:自动化评估
在构建检索增强生成(RAG)系统时,我们总会面临一个核心问题:怎么知道智能体给出的答案到底好不好?
手动抽查几个问题——可行。但如果要调整检索策略、修改提示词、更换模型,每次改动都需要重新验证全部答案,手动评估就变得既不现实又不可靠。人的评分标准也常常摇摆不定,难以复现。
“LLM 即评判者”(LLM-as-a-Judge)应运而生:用一个较强的语言模型来自动评判较弱模型输出的质量,从而取代人工审核。这个思路并不复杂——如果语言模型能够稳定地判断一个答案是否正确,那我们就能在几分钟内自动化完成数百个测试用例的质量检查。
而本文更进一步:将整套评估流程完全内置于 Elasticsearch Workflows 中。无需外部评估框架,无需额外基础设施。一个小模型(Claude Haiku 4.5)负责回答问题,一个大模型(Claude Sonnet 4.6)负责从三个维度打分。知识库、评判列表、工作流执行、评分结果——全部数据都存储在同一个 Elasticsearch 系统中。
在 35 个 HotpotQA 测试案例上,Haiku 4.5 的正确性得分为 0.74,忠实度得分为 0.90。这些数字足以帮我们精准定位:问题出在检索环节,还是推理环节?
2. 前置条件
开始之前,请确保你已具备:
- 一个Elastic Cloud 集群或自管理的Elasticsearch/Kibana 9.4+环境(若没有,可申请免费试用)。
- Python 3.13(用于运行配套的示例 Notebook)。
- 你的
ELASTICSEARCH_URL和ELASTICSEARCH_API_KEY(参照连接指南获取),以及KIBANA_URL(从 Kibana 访问页面获取)。
3. 理解 LLM-as-a-Judge 评估模式
3.1 核心理念
- 传统方式:人工逐条检查答案 → 费时、费力、标准不一。
- LLM-as-a-Judge:用强模型当“评委”,给弱模型的答案自动打分 → 快速、一致、可重复。
3.2 本文的两阶段流程
4. 三大 RAG 评估指标
| 指标 | 衡量什么? | 低分意味着什么? |
|---|---|---|
| 正确性(correctness) | 候选答案是否与标准答案一致? | 智能体答非所问,或给出错误结论。 |
| 忠实度(faithfulness) | 答案是否基于检索到的段落? | 智能体产生了幻觉(编造事实)。 |
| 上下文相关性(context_relevance) | 检索到的段落与问题相关吗? | 检索环节带回了无关文档。 |
三者结合的价值:
假设正确性高但上下文相关性低,那说明模型在检索质量不佳的情况下仍然答对了——很可能依赖了自身训练记忆。这在公开知识(如维基百科)上可能奏效,但在私有数据上就会失效。
5. 加载并索引 HotpotQA 数据集
我们使用HotpotQA 的 distractor 配置:每个问题附带 10 个段落,其中 2 个包含答案(支撑段落),8 个为干扰项。问题多为多跳(multi-hop)类型,需要结合两个段落才能答对。
数据最终存入两个 Elasticsearch 索引:
5.1 知识库索引:hotpot-knowledge-base
存储所有上下文段落,每个文档包含标题和段落内容。段落字段被复制到semantic_content(映射为semantic_text),以便用自然语言进行语义检索,无需手动管理嵌入向量。
INDEX_NAME="hotpot-knowledge-base"ifes_client.indices.exists(index=INDEX_NAME):es_client.indices.delete(index=INDEX_NAME)es_client.indices.create(index=INDEX_NAME,mappings={"properties":{"title":{"type":"keyword"},"passage":{"type":"text","copy_to":"semantic_content",},"semantic_content":{"type":"semantic_text","inference_id":".jina-embeddings-v5-text-small",},}},)5.2 评判列表索引:hotpot-judgement-list
存储评测用例,每个文档包含问题和标准答案(ground truth)。
{"question":"Were Scott Derrickson and Ed Wood of the same nationality?","answer":"yes"}6. Elasticsearch Workflow 如何运行评估?
6.1 整体流程图
6.2 工作流定义(YAML)
工作流采用 YAML 定义,通过 Workflows API(Elastic 9.4+)上传。下面逐段解析关键部分。
常量与触发器
consts:kbIndex:hotpot-knowledge-basejudgeIndex:hotpot-judgement-listresultsIndex:eval-resultstriggers:-type:manual# 手动触发,便于调试和重放步骤 1:加载所有评测案例
-name:load_casestype:elasticsearch.searchwith:index:"{{ consts.judgeIndex }}"query:match_all:{}size:35步骤 2:循环处理每个案例(foreach)
-name:eval_looptype:foreachforeach:"{{ steps.load_cases.output.hits.hits }}"steps:# 子步骤 2.1:语义检索-name:retrievetype:elasticsearch.searchwith:index:"{{ consts.kbIndex }}"query:semantic:field:semantic_contentquery:"{{ foreach.item._source.question }}"size:4步骤 3:回答模型(Haiku)
使用ai.prompt类型,引用 Kibana 中配置的 AI 连接器Anthropic-Claude-Haiku-4-5。提示词强制模型仅依据提供的段落作答,若找不到答案则回复“unknown”。
-name:agent_answertype:ai.promptwith:connector-id:Anthropic-Claude-Haiku-4-5prompt:>You are a Wikipedia QA assistant. Answer the question using ONLY the passages provided. Keep the answer short (one line). If the passages do not contain the answer, reply "unknown".Question:{{foreach.item._source.question}}Passages:1.{{steps.retrieve.output.hits.hits[0]._source.passage}}2.{{steps.retrieve.output.hits.hits[1]._source.passage}}3.{{steps.retrieve.output.hits.hits[2]._source.passage}}4.{{steps.retrieve.output.hits.hits[3]._source.passage}}步骤 4:评判模型(Sonnet)
评判模型接收问题、标准答案、候选答案、检索段落,并输出结构化的 JSON 评分。关键在于schema块——它强制模型返回符合规范的 JSON 对象,无需再解析文本或处理 Markdown 代码块。
-name:judgetype:ai.promptwith:connector-id:Anthropic-Claude-Sonnet-4-6prompt:>You are a STRICT evaluator. Score the candidate answer against the ground truth on three axes. Each score MUST be exactly one of these three values: 0.0, 0.5, or 1.0. Do not return any other number.correctness:1.0 = candidate contains the ground truth answer exactly or an unambiguous synonym,and nothing factually wrong. 0.5 = partially correct (one side of a multi-hop right,or mostly right with minor noise). 0.0 = wrong,missing,or contradicts the ground truth.faithfulness:1.0 = every factual claim is supported by the passages. 0.5 = mostly supported,one minor unsupported claim. 0.0 = contains at least one unsupported claim.context_relevance:1.0 = the passages contain enough to answer the question. 0.5 = partial coverage (one hop covered,the other missing). 0.0 = passages do not cover the answer. Be harsh. If in doubt between two scores,pick the lower one.Question:{{foreach.item._source.question}}Ground truth:{{foreach.item._source.answer}}Candidate:{{steps.agent_answer.output.content}}Passages:1.{{steps.retrieve.output.hits.hits[0]._source.passage}}2.{{steps.retrieve.output.hits.hits[1]._source.passage}}3.{{steps.retrieve.output.hits.hits[2]._source.passage}}4.{{steps.retrieve.output.hits.hits[3]._source.passage}}schema:type:objectproperties:correctness:type:numberminimum:0maximum:1faithfulness:type:numberminimum:0maximum:1context_relevance:type:numberminimum:0maximum:1required:-correctness-faithfulness-context_relevance步骤 5:保存结果
将每个案例的评分写入eval-results索引。由于schema保证了输出是结构化 JSON,我们可以直接用{{ steps.judge.output.content.correctness }}等引用具体字段。
-name:savetype:elasticsearch.indexwith:index:"{{ consts.resultsIndex }}"document:qid:"{{ foreach.item._source.qid }}"question:"{{ foreach.item._source.question }}"ground_truth:"{{ foreach.item._source.answer }}"candidate:"{{ steps.agent_answer.output.content }}"correctness:"{{ steps.judge.output.content.correctness }}"faithfulness:"{{ steps.judge.output.content.faithfulness }}"context_relevance:"{{ steps.judge.output.content.context_relevance }}"6.3 上传并运行工作流
使用 Elastic 9.4 提供的 REST API:
POST /api/workflows— 创建/更新工作流POST /api/workflows/{id}/run— 启动执行GET /api/workflows/executions/{id}— 轮询执行状态
35 个测试案例,整个流程大约几分钟完成(包含 35 次语义检索 + 35 次 Haiku 调用 + 35 次 Sonnet 调用 + 35 次索引写入)。
7. 解读评估结果
7.1 聚合统计
直接从eval-results索引查询并计算各指标均值,无需额外解析。
| 指标 | 平均分 | 解读 |
|---|---|---|
| 正确性 | 0.74 | 约 7/10 的问题答对。对于多跳维基百科问题,算是不错的成绩,但仍有提升空间。 |
| 忠实度 | 0.90 | 当 Haiku 给出答案时,绝大多数内容都基于检索段落。幻觉问题不严重。 |
| 上下文相关性 | 0.86 | 语义检索大多数时候能带回相关段落;但部分多跳问题需要的信息不在前 4 个段落中。 |
7.2 分数分布图示
7.3 洞察:问题出在哪儿?
忠实度(0.90)远高于正确性(0.74)——这说明模型没有编造事实,而是在较难的问题上直接答错了。因此,问题核心在于检索覆盖不足或推理能力不够,而非幻觉。后续优化方向可以是:
- 增加检索段落数量(如从 4 个增至 8 个);
- 对最难的案例切换到更强的模型。
8. 对生产环境的启示
我们构建了一套完全运行在 Elasticsearch 内部的评估流水线。知识库、评判列表、工作流执行、评分结果——所有组件都统一在同一系统内,无需额外基础设施。
- 版本可控:工作流 YAML 可以纳入 Git,方便追踪变更。
- 可重放:当知识库或回答模型更新时,一键重新运行同一管道,对比新旧分数。
- API 可触发:可集成到 CI/CD,实现自动化回归测试。
对于本次测试,Haiku 在忠实度上表现可靠,但在多跳问题上的正确性还有不足。是否满足生产要求,取决于你的具体场景。而评估管道的意义,正是给你数据支撑,让你能自信决策,而非凭感觉猜测。
9. 总结
- LLM-as-a-Judge是一种高效、可扩展的自动化评估方法,用强模型评判弱模型。
- 在 Elasticsearch Workflows 中,我们用Claude Haiku 4.5回答,用Claude Sonnet 4.6从正确性、忠实度、上下文相关性三个维度打分。
- 整个流程通过YAML 工作流定义,所有数据与索引共存于 Elasticsearch。
- 实测结果揭示了 Haiku 的强项(忠实度高)和弱项(多跳正确率一般),为后续优化指明了方向。
立即行动:开始 Elastic Cloud 试用,用你自己的数据和模型跑一遍评估管道,看清你的 RAG 智能体到底表现如何。