作者来自 Elastic Jeffrey Rengifo了解你的 RAG agent 是否已准备好投入生产。仅使用 Elasticsearch Workflows 和两个 Claude 模型从正确性correctness、忠实性faithfulness和检索质量retrieval quality三个维度对其进行评分。Agent Builder 现已正式发布。立即开始你的 Elastic Cloud Trial并查看 Agent Builder 文档。在Elasticsearch Workflows内部构建完整的 RAG 评测流水线无需外部评测框架也无需额外基础设施。一个小模型基于你的知识库回答问题一个更强的模型则从正确性correctness、忠实性faithfulness和上下文相关性context relevance三个维度对每个回答进行评分。在一个包含 35 个 HotpotQA 测试用例的测试中Claude Haiku 4.5 获得了 0.74 的正确性评分和 0.90 的忠实性评分足以精确定位retrieval或推理过程究竟在哪一步出现问题。知识库、评判标准、workflow 执行过程以及评分结果全部保存在同一个系统中。前提条件一个 Elastic Cloud 集群或自托管的 Elasticsearch / Kibana 9.4。如果还没有可以免费试用。Python 3.13什么是 LLM-as-a-JudgeLLM-as-a-Judge 使用一个更强大的语言模型自动对较弱模型生成的结果进行评分从而替代一致性较差且难以扩展的人工评审。手工评估一个 RAG 系统对于少量问题来说是可行的但无法扩展。如果你修改了检索策略、提示词prompt或模型就需要重新检查所有答案。这不仅耗时而且不同评审人员之间的评分标准也往往不一致。LLM-as-a-Judge 模式通过使用一个更强大的语言模型来评估较弱模型的输出从而解决这一问题。其核心思想非常简单如果一个语言模型能够可靠地判断一个答案是否正确那么你就可以在几分钟内自动完成数百个测试用例的质量评估。在本文中整个流水线包含两个阶段阶段 1回答Claude Haiku 4.5 接收问题以及从知识库中检索出的相关内容passages生成回答。这是需要进行评测的模型。阶段 2评判Claude Sonnet 4.6 接收相同的问题、标准答案ground-truth answer即已知正确答案、候选答案阶段 1 的输出以及检索到的 passages并从三个维度对回答进行评分。RAG 的三个评测指标正确性correctness、忠实性faithfulness和上下文相关性context relevance指标衡量内容低分意味着什么correctness正确性候选答案是否与标准答案一致agent 回答错误。faithfulness忠实性回答是否基于检索到的 passagesagent 产生了幻觉编造了内容。context_relevance上下文相关性检索到的 passages 是否与问题相关retrieval 检索到了错误的文档。这三个指标结合起来能够告诉你问题出在哪里。如果correctness很高而context_relevance很低这就是一个危险信号尽管检索效果不佳模型仍然回答正确很可能是依赖自身训练数据而不是检索结果完成了回答。对于像 Wikipedia 这样的公开知识这种方式通常没有问题但对于模型从未见过的私有数据这种做法就会失效。另一种互补的方法是结合 Elasticsearch 使用 Ragas 指标从基于框架framework-based的角度探索这些评测维度。如何加载并索引 HotpotQA 数据集该流水线使用HotpotQA的distractor配置多跳multi-hop问题每个问题都配有 10 个上下文段落并存储在两个 Elasticsearch 索引中。你可以参考本文配套的完整 notebook其中包含环境配置、连接以及所有辅助代码。完成本教程需要以下信息ELASTICSEARCH_URLELASTICSEARCH_API_KEY可按照连接信息指南获取KIBANA_URL可在Kibana 访问页面找到该流水线使用在 Kibana 中配置好的两个 AI connectorsAnthropic Claude Haiku 4.5作为回答模型体积小、成本低、速度快。Anthropic Claude Sonnet 4.6作为评判模型能力更强。整个流水线要回答的问题是Haiku 在这项任务上的表现是否足够好可以用于生产环境/Is Haiku good enough on this task to be used in production?我们使用HotpotQA的distractor配置。每个问题都包含 10 个上下文段落其中两个支持正确答案另外八个是干扰项distractors。这些段落会被索引到知识库中供第一阶段Stage 1进行 retrieval。这些问题属于多跳multi-hop问题也就是说回答一个问题需要综合来自两个不同段落的信息。我们会抽取部分问题作为样本将其上下文段落展开后索引到知识库索引中并将问题—答案对存储到单独的评判列表judgement list中。最终数据会存储到两个 Elasticsearch 索引中知识库上下文段落hotpot-knowledge-base保存回答模型进行 retrieval 时使用的上下文段落。每个document都包含一个title和一个passage{title: Ed Wood (film), passage: Ed Wood is a 1994 American biographical period comedy-drama film...}passage字段会复制到semantic_content映射为 semantic_text这样第一阶段Stage 1就可以使用自然语言query检索相关段落而无需手动管理 embeddings。Elasticsearch 会自动为已索引的段落生成 embeddings并在执行 语义搜索semantic search 时自动为查询生成 embeddings。INDEX_NAME hotpot-knowledge-base if es_client.indices.exists(indexINDEX_NAME): es_client.indices.delete(indexINDEX_NAME) es_client.indices.create( indexINDEX_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, }, } }, ) print(fCreated index: {INDEX_NAME})评判列表问题与标准答案hotpot-judgement-list保存评测用例。每个 document 都包含一个question和一个answer标准答案ground truth{question: Were Scott Derrickson and Ed Wood of the same nationality?, answer: yes}answer字段包含正确答案。第二阶段Stage 2的 judge 会将回答模型的输出与该答案进行比较。Elasticsearch Workflow 如何运行评测这篇使用 Elastic Workflows 构建自动化的介绍文章详细介绍了 trigger、step 和数据流的核心概念。Workflow 定义该 workflow 使用 YAML 定义并通过 Workflows API 上传Elastic 9.4。以下是完整定义WORKFLOW_YAML name: agent_accuracy_eval description: Batch evaluation. Loads the judgement list, iterates each case with a foreach, runs stage 1 (RAG answer with Haiku) and stage 2 (LLM judge with Sonnet), and indexes every score into the eval results index. enabled: true consts: kbIndex: hotpot-knowledge-base judgeIndex: hotpot-judgement-list resultsIndex: eval-results triggers: - type: manual steps: # Load the judgement list (all cases we want to evaluate). - name: load_cases type: elasticsearch.search with: index: {{ consts.judgeIndex }} query: match_all: {} size: 35 # One iteration one evaluation. - name: eval_loop type: foreach foreach: {{ steps.load_cases.output.hits.hits }} steps: - name: retrieve type: elasticsearch.search with: index: {{ consts.kbIndex }} query: semantic: field: semantic_content query: {{ foreach.item._source.question }} size: 4 - name: agent_answer type: ai.prompt with: connector-id: Anthropic-Claude-Haiku-4-5 prompt: 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 }} - name: judge type: ai.prompt with: connector-id: Anthropic-Claude-Sonnet-4-6 prompt: 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: object properties: correctness: type: number minimum: 0 maximum: 1 faithfulness: type: number minimum: 0 maximum: 1 context_relevance: type: number minimum: 0 maximum: 1 required: - correctness - faithfulness - context_relevance # Persist each scored case so the notebook can query it later. - name: save type: elasticsearch.index with: 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 }} 让我们逐步了解关键部分consts用于定义索引名称的命名常量。这样可以保持 YAML 文件简洁并且方便将同一个 pipeline 指向不同的数据集。load_cases一个elasticsearch.searchstep用于从评判列表中获取所有测试用例。eval_loop一个foreachstep用于遍历搜索结果。每次迭代都会运行以下四个嵌套 stepretrieve使用问题作为 query在知识库上运行语义搜索检索相关内容。agent_answer一个ai.promptstep将问题以及检索到的前四个 passages 发送给 Haiku。connector-id字段引用 Kibana AI Connector。judge另一个ai.promptstep这次调用 Sonnet。schema代码块强制模型返回一个具有固定字段的 JSON 对象。无需 markdown 代码块无需 regex也无需在读取时进行解析。minimum和maximum约束确保评分保持在 0–1 范围内。save一个 elasticsearch.index step用于将每个评分后的测试用例写入结果索引。由于 judge 输出已经通过schema解析为 JSON因此可以直接引用各个字段{{ steps.judge.output.content.correctness }}。上传并运行 workflowElastic 9.4 提供了用于 workflow 的 REST API。我们使用三个端点POST /api/workflows根据 YAML 创建 workflow。POST /api/workflows/{id}/run启动一次执行。GET /api/workflows/executions/{id}轮询查询直到执行完成。对于 35 个测试用例该 workflow 需要几分钟完成。每次迭代都会执行一次语义搜索、一次用于生成答案的大语言模型LLM调用、另一次用于评判的大语言模型调用以及一次索引操作。如何读取和解读 RAG 评测结果每个评分后的测试用例已经作为一个 document 存储在eval-results索引中并包含类型化的评分字段。无需进行解析我们只需要查询该索引并计算每个指标的平均值。35 个测试用例的聚合 RAG 评测分数下面的柱状图展示了 35 个测试用例中每个指标的平均分使用 Haiku 作为回答模型在这次使用 Claude Haiku 4.5 作为回答模型的评测中结果如下correctness0.74大约有 70% 的问题回答正确。对于多跳 Wikipedia 问题来说这是一个合理的表现但仍有提升空间。faithfulness0.90当 Haiku 能够回答时它能够保持基于 passages 生成答案。幻觉并不是这里的主要问题。context_relevance0.86大多数情况下语义检索能够找到相关 passages但一些多跳问题需要的 passages 并没有出现在前四个检索结果中。faithfulness0.90与 correctness0.74之间的差距说明模型并不是在编造内容而是在较难的问题上没有找到正确答案。这是 retrieval 或推理问题而不是幻觉问题。增加检索 passages 的数量或者针对最困难的问题切换到更强的模型都是可行的改进方向。RAG 评测结果对生产环境的意义我们构建了一个完全运行在 Elasticsearch 内部的完整评测流水线。知识库、评判列表、workflow 执行过程以及评分结果全部存储在同一个系统中。workflow YAML 可以进行版本控制可以重复执行并且可以通过 API 触发。如果你更新了知识库或更换了回答模型只需要重新运行相同的 pipeline然后将新的评分结果与旧结果进行比较。对于这个特定数据集结果表明 Haiku 具有较高的忠实性但在多跳问题上并不总能回答正确。是否足够满足你的需求取决于你的具体使用场景以及你自己的数据。评测 pipeline 的价值在于提供数据让你能够基于可靠依据做出决策而不是凭感觉判断。下一步接下来你可以扩展评判列表添加符合实际生产流量的领域专属问题。替换回答模型比较不同模型在同一测试集上的表现。调度 workflow在新文档被索引后自动运行。构建 Kibana 仪表盘基于eval-results索引跟踪质量随时间的变化。相关文章如何使用 Elasticsearch 构建 AI Agentic WorkflowsAgent Builder 与 Workflows创建能够执行操作的 AI agents使用 DeepEva 进行 RAG retrieval 评估与优化这篇内容对你有多大帮助原文LLM-as-a-Judge in Elasticsearch Workflows: RAG evaluation - Elasticsearch Labs