【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_URLELASTICSEARCH_API_KEY (参照连接指南获取),以及 KIBANA_URL(从 Kibana 访问页面获取)。

3. 理解 LLM-as-a-Judge 评估模式

3.1 核心理念

  • 传统方式:人工逐条检查答案 → 费时、费力、标准不一。
  • LLM-as-a-Judge:用强模型当"评委",给弱模型的答案自动打分 → 快速、一致、可重复。

3.2 本文的两阶段流程

#mermaid-svg-RBgf7FjvQSVyfmFy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RBgf7FjvQSVyfmFy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RBgf7FjvQSVyfmFy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RBgf7FjvQSVyfmFy .error-icon{fill:#552222;}#mermaid-svg-RBgf7FjvQSVyfmFy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RBgf7FjvQSVyfmFy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RBgf7FjvQSVyfmFy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RBgf7FjvQSVyfmFy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RBgf7FjvQSVyfmFy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RBgf7FjvQSVyfmFy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RBgf7FjvQSVyfmFy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RBgf7FjvQSVyfmFy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RBgf7FjvQSVyfmFy .marker.cross{stroke:#333333;}#mermaid-svg-RBgf7FjvQSVyfmFy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RBgf7FjvQSVyfmFy p{margin:0;}#mermaid-svg-RBgf7FjvQSVyfmFy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RBgf7FjvQSVyfmFy .cluster-label text{fill:#333;}#mermaid-svg-RBgf7FjvQSVyfmFy .cluster-label span{color:#333;}#mermaid-svg-RBgf7FjvQSVyfmFy .cluster-label span p{background-color:transparent;}#mermaid-svg-RBgf7FjvQSVyfmFy .label text,#mermaid-svg-RBgf7FjvQSVyfmFy span{fill:#333;color:#333;}#mermaid-svg-RBgf7FjvQSVyfmFy .node rect,#mermaid-svg-RBgf7FjvQSVyfmFy .node circle,#mermaid-svg-RBgf7FjvQSVyfmFy .node ellipse,#mermaid-svg-RBgf7FjvQSVyfmFy .node polygon,#mermaid-svg-RBgf7FjvQSVyfmFy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RBgf7FjvQSVyfmFy .rough-node .label text,#mermaid-svg-RBgf7FjvQSVyfmFy .node .label text,#mermaid-svg-RBgf7FjvQSVyfmFy .image-shape .label,#mermaid-svg-RBgf7FjvQSVyfmFy .icon-shape .label{text-anchor:middle;}#mermaid-svg-RBgf7FjvQSVyfmFy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RBgf7FjvQSVyfmFy .rough-node .label,#mermaid-svg-RBgf7FjvQSVyfmFy .node .label,#mermaid-svg-RBgf7FjvQSVyfmFy .image-shape .label,#mermaid-svg-RBgf7FjvQSVyfmFy .icon-shape .label{text-align:center;}#mermaid-svg-RBgf7FjvQSVyfmFy .node.clickable{cursor:pointer;}#mermaid-svg-RBgf7FjvQSVyfmFy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RBgf7FjvQSVyfmFy .arrowheadPath{fill:#333333;}#mermaid-svg-RBgf7FjvQSVyfmFy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RBgf7FjvQSVyfmFy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RBgf7FjvQSVyfmFy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RBgf7FjvQSVyfmFy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RBgf7FjvQSVyfmFy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RBgf7FjvQSVyfmFy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RBgf7FjvQSVyfmFy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RBgf7FjvQSVyfmFy .cluster text{fill:#333;}#mermaid-svg-RBgf7FjvQSVyfmFy .cluster span{color:#333;}#mermaid-svg-RBgf7FjvQSVyfmFy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RBgf7FjvQSVyfmFy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RBgf7FjvQSVyfmFy rect.text{fill:none;stroke-width:0;}#mermaid-svg-RBgf7FjvQSVyfmFy .icon-shape,#mermaid-svg-RBgf7FjvQSVyfmFy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RBgf7FjvQSVyfmFy .icon-shape p,#mermaid-svg-RBgf7FjvQSVyfmFy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RBgf7FjvQSVyfmFy .icon-shape .label rect,#mermaid-svg-RBgf7FjvQSVyfmFy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RBgf7FjvQSVyfmFy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RBgf7FjvQSVyfmFy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RBgf7FjvQSVyfmFy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 知识库

HotpotQA 段落
阶段1:回答模型

Claude Haiku 4.5
评判列表

问题 + 标准答案
候选答案
阶段2:评判模型

Claude Sonnet 4.6
三个评分

正确性 / 忠实度 / 上下文相关性


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),以便用自然语言进行语义检索,无需手动管理嵌入向量。

python 复制代码
INDEX_NAME = "hotpot-knowledge-base"

if es_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)。

json 复制代码
{"question": "Were Scott Derrickson and Ed Wood of the same nationality?", "answer": "yes"}

6. Elasticsearch Workflow 如何运行评估?

6.1 整体流程图

#mermaid-svg-yuSQuA3ehhqhrHQt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yuSQuA3ehhqhrHQt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yuSQuA3ehhqhrHQt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yuSQuA3ehhqhrHQt .error-icon{fill:#552222;}#mermaid-svg-yuSQuA3ehhqhrHQt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yuSQuA3ehhqhrHQt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yuSQuA3ehhqhrHQt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yuSQuA3ehhqhrHQt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yuSQuA3ehhqhrHQt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yuSQuA3ehhqhrHQt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yuSQuA3ehhqhrHQt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yuSQuA3ehhqhrHQt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yuSQuA3ehhqhrHQt .marker.cross{stroke:#333333;}#mermaid-svg-yuSQuA3ehhqhrHQt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yuSQuA3ehhqhrHQt p{margin:0;}#mermaid-svg-yuSQuA3ehhqhrHQt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yuSQuA3ehhqhrHQt .cluster-label text{fill:#333;}#mermaid-svg-yuSQuA3ehhqhrHQt .cluster-label span{color:#333;}#mermaid-svg-yuSQuA3ehhqhrHQt .cluster-label span p{background-color:transparent;}#mermaid-svg-yuSQuA3ehhqhrHQt .label text,#mermaid-svg-yuSQuA3ehhqhrHQt span{fill:#333;color:#333;}#mermaid-svg-yuSQuA3ehhqhrHQt .node rect,#mermaid-svg-yuSQuA3ehhqhrHQt .node circle,#mermaid-svg-yuSQuA3ehhqhrHQt .node ellipse,#mermaid-svg-yuSQuA3ehhqhrHQt .node polygon,#mermaid-svg-yuSQuA3ehhqhrHQt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yuSQuA3ehhqhrHQt .rough-node .label text,#mermaid-svg-yuSQuA3ehhqhrHQt .node .label text,#mermaid-svg-yuSQuA3ehhqhrHQt .image-shape .label,#mermaid-svg-yuSQuA3ehhqhrHQt .icon-shape .label{text-anchor:middle;}#mermaid-svg-yuSQuA3ehhqhrHQt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yuSQuA3ehhqhrHQt .rough-node .label,#mermaid-svg-yuSQuA3ehhqhrHQt .node .label,#mermaid-svg-yuSQuA3ehhqhrHQt .image-shape .label,#mermaid-svg-yuSQuA3ehhqhrHQt .icon-shape .label{text-align:center;}#mermaid-svg-yuSQuA3ehhqhrHQt .node.clickable{cursor:pointer;}#mermaid-svg-yuSQuA3ehhqhrHQt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yuSQuA3ehhqhrHQt .arrowheadPath{fill:#333333;}#mermaid-svg-yuSQuA3ehhqhrHQt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yuSQuA3ehhqhrHQt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yuSQuA3ehhqhrHQt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yuSQuA3ehhqhrHQt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yuSQuA3ehhqhrHQt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yuSQuA3ehhqhrHQt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yuSQuA3ehhqhrHQt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yuSQuA3ehhqhrHQt .cluster text{fill:#333;}#mermaid-svg-yuSQuA3ehhqhrHQt .cluster span{color:#333;}#mermaid-svg-yuSQuA3ehhqhrHQt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yuSQuA3ehhqhrHQt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yuSQuA3ehhqhrHQt rect.text{fill:none;stroke-width:0;}#mermaid-svg-yuSQuA3ehhqhrHQt .icon-shape,#mermaid-svg-yuSQuA3ehhqhrHQt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yuSQuA3ehhqhrHQt .icon-shape p,#mermaid-svg-yuSQuA3ehhqhrHQt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yuSQuA3ehhqhrHQt .icon-shape .label rect,#mermaid-svg-yuSQuA3ehhqhrHQt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yuSQuA3ehhqhrHQt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yuSQuA3ehhqhrHQt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yuSQuA3ehhqhrHQt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 手动触发工作流
步骤1: load_cases

从评判列表加载全部35个问题
步骤2: eval_loop

foreach 遍历每个案例
子步骤: retrieve

对知识库做语义检索,取前4个段落
子步骤: agent_answer

Haiku 根据段落生成答案
子步骤: judge

Sonnet 对答案打分
子步骤: save

将评分结果写入 eval-results 索引
全部完成,结果可查询

6.2 工作流定义(YAML)

工作流采用 YAML 定义,通过 Workflows API(Elastic 9.4+)上传。下面逐段解析关键部分。

常量与触发器
yaml 复制代码
consts:
  kbIndex: hotpot-knowledge-base
  judgeIndex: hotpot-judgement-list
  resultsIndex: eval-results

triggers:
  - type: manual        # 手动触发,便于调试和重放
步骤 1:加载所有评测案例
yaml 复制代码
- name: load_cases
  type: elasticsearch.search
  with:
    index: "{{ consts.judgeIndex }}"
    query:
      match_all: {}
    size: 35
步骤 2:循环处理每个案例(foreach)
yaml 复制代码
- name: eval_loop
  type: foreach
  foreach: "{{ steps.load_cases.output.hits.hits }}"
  steps:
    # 子步骤 2.1:语义检索
    - name: retrieve
      type: elasticsearch.search
      with:
        index: "{{ consts.kbIndex }}"
        query:
          semantic:
            field: semantic_content
            query: "{{ foreach.item._source.question }}"
        size: 4
步骤 3:回答模型(Haiku)

使用 ai.prompt 类型,引用 Kibana 中配置的 AI 连接器 Anthropic-Claude-Haiku-4-5。提示词强制模型仅依据提供的段落作答,若找不到答案则回复"unknown"。

yaml 复制代码
- 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 }}
步骤 4:评判模型(Sonnet)

评判模型接收问题、标准答案、候选答案、检索段落,并输出结构化的 JSON 评分。关键在于 schema------它强制模型返回符合规范的 JSON 对象,无需再解析文本或处理 Markdown 代码块。

yaml 复制代码
- 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
步骤 5:保存结果

将每个案例的评分写入 eval-results 索引。由于 schema 保证了输出是结构化 JSON,我们可以直接用 {``{ steps.judge.output.content.correctness }} 等引用具体字段。

yaml 复制代码
- 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 }}"

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 分数分布图示

#mermaid-svg-T4iBu5VXBirCTekK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-T4iBu5VXBirCTekK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-T4iBu5VXBirCTekK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-T4iBu5VXBirCTekK .error-icon{fill:#552222;}#mermaid-svg-T4iBu5VXBirCTekK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-T4iBu5VXBirCTekK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-T4iBu5VXBirCTekK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-T4iBu5VXBirCTekK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-T4iBu5VXBirCTekK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-T4iBu5VXBirCTekK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-T4iBu5VXBirCTekK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-T4iBu5VXBirCTekK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-T4iBu5VXBirCTekK .marker.cross{stroke:#333333;}#mermaid-svg-T4iBu5VXBirCTekK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-T4iBu5VXBirCTekK p{margin:0;}#mermaid-svg-T4iBu5VXBirCTekK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 各指标平均分(Haiku 4.5 作为回答模型) 正确性忠实度上下文相关性 10.90.80.70.60.50.40.30.20.10 平均分 (0-1)

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 智能体到底表现如何。

相关推荐
tianyuanwo3 小时前
深入掌握 java -jar 命令:从基础到 Jenkins Agent 实战
java·jenkins·jar
小小放舟、3 小时前
Windows 本地安装 Elasticsearch 8.10.0 与 IK 分词器(2026)
java·大数据·windows·spring boot·elasticsearch·搜索引擎·全文检索
腾渊信息科技公司13 小时前
工业数据运维痛点根治方案:基于AI Agent的产线自动化台账系统落地
运维·人工智能·自动化·个人开发·ai编程
csdn_aspnet17 小时前
GitHub Actions自动化运维实战,用CI/CD流水线实现测试、部署、安全扫描一体化
运维·安全·ci/cd·自动化·github
Wzx19801219 小时前
Redis&ES——Retriever的抽象实现
数据库·人工智能·redis·elasticsearch
项目管理与代码20 小时前
基于Webhook+消息队列的自动化项目进度跟踪方案设计
运维·自动化
霸道流氓气质21 小时前
CodeBuddy中配置Playwright MCP 浏览器自动化完全指南
运维·自动化
Elasticsearch1 天前
让向量听懂孤独:我是如何用 Elastic Agent Builder 构建一个情绪疗愈 agent 的
elasticsearch
Elasticsearch1 天前
你的 AI 表现不佳。你的数据基础才是问题
elasticsearch