Elasticsearch:Jina Reranker v3

现代搜索pipelines 很少直接从检索中返回最终答案。即使你的 search 系统由高质量的索引或语义检索方法驱动,前几名结果中仍可能包含相关但不一定是最佳答案的候选内容。

这就是 reranking 变得至关重要的原因。

Reranker 会接收一个 query 和一组候选段落,将它们一起阅读,并生成一个新的排序,反映更深层次的语义相关性。它不是孤立地对 documents 打分,而是相互比较,确定哪些段落最直接回答用户的意图。

在本教程中,我们重点介绍如何在 Elasticsearch 内使用 Jina Reranker v3。我们的目标很简单:给定一个 query 和一组 documents,展示 Elasticsearch 如何调用 jina-reranker-v3。

所有操作都在 Dev Tools → Console 中进行,使用 Elasticsearch 的 open Inference API。

步骤 1 --- 在 Elasticsearch 中注册 jina-reranker-v3

Elasticsearch 通过 Inference API 与外部 AI models 集成。要使用 jina-reranker-v3,我们需要定义一个 inference endpoint 并提供 Jina API key。你可以在官网找到你的 API key。

复制代码
PUT _inference/rerank/jina_rerank_v3
{
  "service": "jinaai",
  "service_settings": {
    "api_key": "YOUR_JINA_API_KEY",
    "model_id": "jina-reranker-v3"
  },
  "task_settings": {
    "top_n": 10,
    "return_documents": true
  }
}

当此操作成功完成后,Elasticsearch 就可以将文本和 documents 直接发送到 Jina model,并接收 reranked 结果。

步骤 2 --- 为演示索引一些 documents

(任何文本语料库都可以------我们只需要将 documents 存储在 Elasticsearch 中,以便传递给 reranker。)

这里我们索引了一个小型多语言文学数据集。没有 embedding 逻辑,也没有 vector 字段------我们故意保持索引简单:

复制代码
POST _inference/rerank/jina_rerank_v3
{
  "input": [
    "Pain can lead a person back to truth, for suffering often reveals what comfort hides.",
    "Страдание возвращает человека к истине, ведь в муке открывается то, что скрыто в покое.",
    "La souffrance rapproche de la vérité, car elle met à nu ce que le calme dissimule.",
    "Das Leiden führt den Menschen zur Wahrheit, denn im Schmerz zeigt sich, was die Ruhe verbirgt."
  ],
  "query": "How does suffering reveal hidden truth?",
  "return_documents": true,
  "top_n": 4
}

_inference/rerank API 需要一个 query 字符串和一个候选 documents 的 input 数组。input 中的每个元素都是需要排序的纯文本段落。响应返回一个 rerank 数组,每个条目包含文档的原始索引、语义相关性分数,以及可选的文档文本。

如果一切正常,你应该会看到如下结果:

复制代码
{
  "rerank": [
    {
      "index": 2,
      "relevance_score": 0.31203735,
      "text": "La souffrance rapproche de la vérité, car elle met à nu ce que le calme dissimule."
    },
    {
      "index": 0,
      "relevance_score": 0.2740799,
      "text": "Pain can lead a person back to truth, for suffering often reveals what comfort hides."
    },
    {
      "index": 3,
      "relevance_score": 0.2597439,
      "text": "Das Leiden führt den Menschen zur Wahrheit, denn im Schmerz zeigt sich, was die Ruhe verbirgt."
    },
    {
      "index": 1,
      "relevance_score": 0.24595186,
      "text": "Страдание возвращает человека к истине, ведь в муке открывается то, что скрыто в покое."
    }
  ]
}

从概念上讲,这就是 reranker 的全部功能:给定一个 query 和一小组候选文本,它会决定哪些最相关,并按顺序返回。它不关心这些候选文本是如何获得的------无论是来自 BM25、vector search、filters 还是人工挑选列表------因此你几乎可以将它集成到任何现有的 search 流程中。

2.1 创建 embedding model endpoint

该 endpoint 允许 Elasticsearch 将文本发送到 jina-embeddings-v3,并存储返回的 vectors。

复制代码
PUT _inference/text_embedding/jina_embeddings
{
  "service": "jinaai",
  "service_settings": {
    "api_key": "YOUR_JINA_API_KEY",
    "model_id": "jina-embeddings-v3"
  }
}

如果运行成功,你应该会看到 200 OK 的确认信息。

2.2 创建 reranker model endpoint

接下来,我们注册 jina-reranker-v3 endpoint。

复制代码
PUT _inference/rerank/jina_rerank_v3
{
  "service": "jinaai",
  "service_settings": {
    "api_key": "jina_8dc23ecb303841b6880bebf0b89860ef7OkZrj9jFBpRR13AC1hwZmBKgP6n",
    "model_id": "jina-reranker-v3"
  },
  "task_settings": {
    "top_n": 10,
    "return_documents": true
  }
}

步骤 3 --- 创建包含文本和 vector 字段的索引

现在我们将创建一个包含以下内容的小型索引:

  • metadata(id、lang、title)
  • 文档文本(content)
  • 由 Jina embedding endpoint 生成的 dense vector(embedding)

运行:

复制代码
PUT multilingual-rerank-demo
{
  "mappings": {
    "properties": {
      "id":        { "type": "keyword" },
      "lang":      { "type": "keyword" },
      "title":     { "type": "text"    },
      "content":   { "type": "text"    },
      "embedding": {
        "type": "dense_vector",
        "dims": 1024,
        "index": true,
        "similarity": "cosine"
      }
    }
  }
}

jina-embeddings-v3 可以生成多种尺寸的 vectors,但在本教程中,我们使用 1024 维,因为它提供最强的检索准确性,并且与模型的默认配置一致,让我们可以专注于 search 流程,而不是调整 embedding 参数。在实际部署中,如果需要优化存储或延迟,可以选择较小的维度,例如 256 或 512,但 1024 为演示整个 pipeline 提供了清晰的基线。

步骤 4 --- 添加 ingest pipeline 以自动生成 embeddings

每次索引一个 document 时,Elasticsearch 都可以调用 jina_embeddings endpoint,获取 vector 并直接存储到 embedding 字段中。

创建 pipeline:

复制代码
PUT _ingest/pipeline/jina_embed_pipeline
{
  "description": "Generate embeddings with jina-embeddings-v3",
  "processors": [
    {
      "inference": {
        "model_id": "jina_embeddings",
        "input_output": {
          "input_field": "content",
          "output_field": "embedding"
        }
      }
    }
  ]
}

步骤 5 --- 索引一个小型多语言数据集

我们将索引四段短文本,分别使用四种语言。它们描述的是相同的概念(新兴音乐风格),便于观察 vector search 和 reranking 的表现。

确保在命令中包含 pipeline 参数:

复制代码
POST multilingual-rerank-demo/_doc?pipeline=jina_embed_pipeline
{
  "id": "1",
  "lang": "en",
  "title": "The burden of conscience",
  "content": "Pain can lead a person back to truth, for suffering often reveals what comfort hides."
}

POST multilingual-rerank-demo/_doc?pipeline=jina_embed_pipeline
{
  "id": "2",
  "lang": "ru",
  "title": "Бремя совести",
  "content": "Страдание возвращает человека к истине, ведь в муке открывается то, что скрыто в покое."
}

POST multilingual-rerank-demo/_doc?pipeline=jina_embed_pipeline
{
  "id": "3",
  "lang": "fr",
  "title": "Le poids de la conscience",
  "content": "La souffrance rapproche de la vérité, car elle met à nu ce que le calme dissimule."
}

POST multilingual-rerank-demo/_doc?pipeline=jina_embed_pipeline
{
  "id": "4",
  "lang": "de",
  "title": "Die Last des Gewissens",
  "content": "Das Leiden führt den Menschen zur Wahrheit, denn im Schmerz zeigt sich, was die Ruhe verbirgt."
}

POST multilingual-rerank-demo/_doc?pipeline=jina_embed_pipeline
{
  "id": "5",
  "lang": "en",
  "title": "A quiet confession",
  "content": "A restless heart learns more in a single night of torment than in a year of peaceful silence."
}

POST multilingual-rerank-demo/_doc?pipeline=jina_embed_pipeline
{
  "id": "6",
  "lang": "it",
  "title": "La confessione silenziosa",
  "content": "Un cuore inquieto comprende in una notte di tormento ciò che non scopre in un anno di calma apparente."
}


POST multilingual-rerank-demo/_doc?pipeline=jina_embed_pipeline
{
  "id": "7",
  "lang": "en",
  "title": "The shadow of guilt",
  "content": "When guilt grows heavy, a person searches for truth not out of virtue, but out of necessity."
}


POST multilingual-rerank-demo/_doc?pipeline=jina_embed_pipeline
{
  "id": "8",
  "lang": "ru",
  "title": "Тень вины",
  "content": "Когда вина становится невыносимой, человек ищет правду не из добродетели, а потому что иначе не может жить."
}

这四段文本表达了相同的核心思想,但表述形式完全不同。对于 BM25,它们几乎没有重叠的关键词。对于 dense retrieval 和 reranking,它们形成了一个清晰的语义聚类。这个对比可以让我们清楚地看到每种检索方法的优劣,以及 reranker 如何解决仅靠 keyword search 或 vector search 无法处理的歧义。

现在索引已填充,我们可以观察经典 keyword search 和 dense retrieval 在更抽象问题上的表现。

假设用户提出以下问题:

复制代码
"How does suffering reveal hidden truth?"

我们将首先在 content 字段上运行仅使用 BM25 的查询:

复制代码
POST multilingual-rerank-demo/_search
{
  "query": {
    "match": {
      "content": "How does suffering reveal hidden truth?"
    }
  },
  "_source": ["id", "lang", "title", "content"]
}

BM25 会关注字面重叠:"suffering"、"truth",也可能是"hidden"。根据 Elasticsearch 如何对这些词进行分词和翻译,它可能返回合理的结果,但对精确词语和文档语言非常敏感。Russian 或 Italian 文本可能排名较低,仅仅因为它们与 English 查询没有共享 token,即使它们表达的是相同的想法。

为了对比,我们使用 jina-embeddings-v3 运行 vector search。首先,我们向 embedding endpoint 请求查询的 search embedding:

复制代码
POST _inference/text_embedding/jina_embeddings
{
  "input": ["How does suffering reveal hidden truth?"],
  "input_type": "search"
}

这会返回一个 1024 维的 vector。将响应中的 embedding 数组复制,并将其填入 kNN search:

复制代码
POST multilingual-rerank-demo/_search
{
  "knn": {
    "field": "embedding",
    "query_vector": [YOUR EMBEDDINGS],
    "k": 10,
    "num_candidates": 100
  },
  "_source": ["id", "lang", "title", "content"]
}

现在模型可以忽略字面措辞,专注于语义接近度。任何语言中讨论 suffering、truth、conscience 和 inner struggle 的文档往往会排在前面。这已经比 BM25 显得"更智能",但请注意,排序仍然由每个文档的单一相似度分数驱动:它不会考虑文档之间的关系,也不会判断哪一条是多个合理答案中最好的。

这正是 reranking 要解决的问题。

步骤 7 --- 使用 Reciprocal Rank Fusion (RRF) 构建 hybrid retriever

在实际应用中,我们很少仅在 BM25 和 vector search 之间选择;我们希望两者兼顾。Elasticsearch 提供了一个 RRF retriever,可以将多种检索策略合并成一个单一的 ranked list,使用 reciprocal rank fusion。

无需编写两个独立查询并手动合并结果,我们可以在一次 _search 调用中使用 retriever 语法表达 hybrid search。

首先,再次获取 query embedding(如步骤 6)。然后将 vector 填入以下请求:

复制代码
POST multilingual-rerank-demo/_search
{
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "match": {
                "content": "How does suffering reveal hidden truth?"
              }
            }
          }
        },
        {
          "knn": {
            "field": "embedding",
            "query_vector": [0.0123, -0.0456, ... , 0.0089],
            "k": 20,
            "num_candidates": 100
          }
        }
      ],
      "rank_window_size": 50,
      "rank_constant": 20
    }
  },
  "_source": ["id", "lang", "title", "content"]
}

你通常会看到多语言混合出现在前几名:English、Russian、German、Italian,这取决于 "suffering"、"truth" 和 "conscience" 在 embeddings 和文本中的表示方式。这个 hybrid 列表就是我们将传递给 reranker 的候选集合。

步骤 8 --- 将 Jina Reranker v3 添加为最终排序层

目前,hybrid search 仍然为每个文档生成单一分数,没有 "这段不错,但那段是最优答案" 的概念。Reranker 正是用来做这种判断的。

Elasticsearch 将其暴露为 text_similarity_reranker retriever,它会包装另一个 retriever(这里是我们的 RRF hybrid retriever),并将其 top hits 发送到 rerank inference endpoint。

因为我们已经将 jina_rerank_v3 注册为 rerank endpoint,现在可以写:

复制代码
POST multilingual-rerank-demo/_search
{
  "retriever": {
    "text_similarity_reranker": {
      "retriever": {
        "rrf": {
          "retrievers": [
            {
              "standard": {
                "query": {
                  "match": {
                    "content": "How does suffering reveal hidden truth?"
                  }
                }
              }
            },
            {
              "knn": {
                "field": "embedding",
                "query_vector": [0.0123, -0.0456, ... , 0.0089],
                "k": 20,
                "num_candidates": 100
              }
            }
          ],
          "rank_window_size": 50,
          "rank_constant": 20
        }
      },
      "field": "content",
      "inference_id": "jina_rerank_v3",
      "inference_text": "How does suffering reveal hidden truth?",
      "rank_window_size": 20
    }
  },
  "_source": ["id", "lang", "title", "content"]
}

当我们运行不带 reranking 的 hybrid RRF search 时,English 文本 "Pain can lead a person back to truth, for suffering often reveals what comfort hides" 排在最前面,其次是 English 的 "shadow of guilt" 句子,然后是 Russian 和 French 版本。这很合理:查询是 English,因此 BM25 强烈偏向包含字面词汇(如 "suffering" 和 "truth")的 English 文档,而 vector retriever 会拉入其他语言的文档,但无法完全控制最终排序。

一旦将 jina-reranker-v3 作为第二阶段,排序就会变得更有针对性。Reranker 会将四条 "suffering reveals truth" 的句子 ------ French、German、Russian 和 English ------ 移动到列表顶部,并将更偏题的 "guilt and necessity" 段落排到后面。模型不是简单地融合 lexical 和 vector 分数,而是将 query 和候选段落一起阅读在同一上下文中,然后判断哪些最直接回答问题。最终结果是多语言、语义一致,并且明显优化了用户意图,而不是单纯依赖各自的评分启发式。

原文:https://www.elastic.co/search-labs/tutorials/jina-tutorial/jina-reranker-v3

相关推荐
liu****2 小时前
深度学习简介
人工智能·python·深度学习·python基础
无垠的广袤2 小时前
【工业树莓派 CM0 NANO 单板计算机】基于舵机和人脸识别的智能门禁系统
linux·python·opencv·yolo·ai·树莓派
大学生毕业题目2 小时前
毕业项目推荐:102-基于yolov8/yolov5/yolo11的行人车辆检测识别系统(Python+卷积神经网络)
人工智能·python·yolo·目标检测·cnn·pyqt·行人车辆检测
I_ltt_Itw,2 小时前
深度学习优化器与优化方法
人工智能
Yeats_Liao2 小时前
模型选型指南:7B、67B与MoE架构的业务适用性对比
前端·人工智能·神经网络·机器学习·架构·deep learning
sali-tec2 小时前
C# 基于OpenCv的视觉工作流-章10-中值滤波
图像处理·人工智能·opencv·算法·计算机视觉
百***24372 小时前
GLM-4.7底层技术拆解与落地避坑:开源大模型编码实战指南
人工智能·gpt·开源
予枫的编程笔记2 小时前
【Spring Security】Spring Boot 与 Spring Security 核心版本的对应表
人工智能
星浩AI2 小时前
从0到1:用LlamaIndex工作流构建Text-to-SQL应用完整指南
人工智能·后端·python