<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Sachin Frayne - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Sachin Frayne - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/cn/search-labs/author/sachin-frayne</link>
    </image>
    <link>https://www.elastic.co/cn/search-labs/author/sachin-frayne</link>
    <atom:link href="https://www.elastic.co/cn/search-labs/rss/author/sachin-frayne.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[cn]]></language>
    <lastBuildDate>Mon, 14 Sep 2026 21:48:31 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Elasticsearch 向量搜索速度比 OpenSearch 快 8 倍]]></title>
    <description><![CDATA[探索 OpenSearch 与 Elasticsearch 的过滤向量搜索基准测试，以及为何向量搜索性能对上下文工程系统至关重要。]]></description>
    <content:encoded><![CDATA[<h2>为什么搜索速度对 AI 智能体和上下文工程很重要</h2><p>我们在 2000 万文档语料库上进行的基准测试显示，Elasticsearch 在过滤向量搜索方面的吞吐量比 OpenSearch 高达 8 倍，同时在我们测试的配置中也实现了更高的 Recall@100。上下文工程不仅仅依赖快速的向量检索。随着工作流的迭代，团队还需要强大的相关性控制（如混合搜索和过滤）、操作简便性和可预测的性能。但是，由于智能体通常会在每个请求中多次运行检索、推理、检索循环，因此检索延迟会成倍增加，所以这方面的改进会直接转化为更好的端到端响应能力和更低的成本。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9daec868eed84658/6a170bef6234e0c322db1a19/d5a52a07773f0942c2baa732dacfe782aac0f415-1600x683.png" alt="OpenSearch 对比 Elasticsearch：过滤向量搜索基准测试吞吐量" /><p>对于上下文工程来说，检索不是一次性的步骤。智能体和应用程序会反复运行循环，例如检索→推理→检索，以完善查询、验证事实、组合基础上下文并完成任务。这种模式在智能体工作流和迭代检索增强生成 (RAG) 中很常见。由于每个用户请求可能会多次调用检索，这会增加响应延迟和/或增加基础设施成本。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt718c72fb858e4c98/6a170bf00e2e496e7241a132/54ac476ff20a3cf93484298c9ae47612c12fc110-800x417.png" alt="上下文工程将庞大的上下文池转换为有限的 LLM 上下文窗口。" /><h2>为什么向量搜索性能至关重要？</h2><p></p><p>想象一个购物助手回答以下问题：“我需要一个价格在 60 美元以下的随身背包，它可以容纳一台 15 英寸的笔记本电脑、防水，并且可以在周五之前送达。”</p><p>在生产环境中，助手很少只发出一个向量查询然后停止。它会运行一个检索循环以构建正确的上下文，并且每一步通常会受到过滤条件的限制，如可用性、地区、发货承诺、品牌规则和政策资格。</p><p><strong>第 1 步：解读意图，并转化为约束条件。</strong></p><p>智能体可将请求转化为结构化的过滤条件和语义查询，例如：</p><ul><li><p>过滤条件：有现货，可配送至用户邮编，可在周五前送达，价格低于 60 美元，有效上架</p></li><li><p>向量查询：“随身背包15英寸笔记本电脑防水”</p></li></ul><p><strong>步骤 2：检索候选对象，然后进行细化。</strong></p><p>它通常会重复检索，但会有所变化，以避免遗漏好的匹配结果：</p><ul><li><p>“旅行背包随身便携笔记本电脑保护套”</p></li><li><p>“15 英寸防水通勤背包”</p></li><li><p>“轻型机舱背包”</p></li></ul><p>每个查询都使用相同的资格过滤条件，因为检索无关或不可用的项目会造成上下文的浪费。</p><p><strong>步骤 3：展开以确认详细信息并降低风险。</strong></p><p>代理随后再次检索以验证影响最终答案的关键属性：</p><ul><li><p>材料与防水性表述</p></li><li><p>尺寸和笔记本隔层都适合</p></li><li><p>退货政策或保修限制</p></li><li><p>库存不足时的替代方案</p></li></ul><p>这就是多步上下文工程：检索、推理、检索、组合。</p><h2>延迟与召回为何对上下文工程至关重要</h2><p>这些交互可能涉及每个用户会话中数十次过滤的检索调用。这使得每次调用的延迟成为端到端响应时间的直接倍增因素，而低召回率则迫使进行额外的重试或导致智能体错过符合条件的项目，导致答案质量下降。</p><p>要点：在上下文工程系统中，过滤近似最近邻 (ANN) 并非一次单一查找。由于这是在约束条件下的重复操作，因此即使大型语言模型 (LLM) 是最明显的组件，向量搜索性能也会立即体现在延迟、吞吐量和成本上。</p><h2>基准测试</h2><h3>成果度</h3><p>在图表 2 中，每个点代表一个测试配置。最佳结果出现在左上方，这意味着更高的召回率和更低的延迟。Elasticsearch 的结果始终比 OpenSearch 更接近左上角，表明在相同的工作负载配置下，Elasticsearch 具有更好的速度和准确率。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb562b30a600cc8e1/6a170bf2cf4f253582b2d1b2/c50d1df00968cac18149a2799e6242fbe49b66a0-1600x990.png" alt=" 图表 2：召回率与平均延迟（重评分 1）。" /><h4>一些关键见解</h4><ul><li><p><code>s_n_r_value</code>: <code>size_numCandidates_rescoreOversample</code> 的简写（在这些测试中，k 和 numCandidates 设置为等于 numCandidates），例如，<code>100_500_1</code> 表示 size=100、numCandidates=500 和 k=500，重新评分过采样=1。</p></li><li><p>召回率：该配置的测量召回率@100</p></li><li><p>平均延迟（毫秒）：每次查询的平均端到端延迟</p></li><li><p>吞吐量：每秒查询次数</p></li><li><p>召回率 (%)：Elasticsearch 相较于 OpenSearch 的相对召回率提升 (Elasticsearch - OpenSearch) / OpenSearch</p></li><li><p>延迟 Xs：OpenSearch 平均延迟除以 Elasticsearch 平均延迟</p></li><li><p>吞吐量 Xs：Elasticsearch 吞吐量除以 OpenSearch 吞吐量</p></li></ul><p>引擎</p><p>`s_n_r_value`</p><p>召回</p><p>平均延迟（ms）</p><p>吞吐量</p><p>召回率%</p><p>延迟 Xs</p><p>吞吐量 Xs</p><p>Elasticsearch</p><p>100_250_1</p><p>0.7704</p><p>25</p><p>534.75</p><p>9.70%</p><p>2.28</p><p>1.91</p><p>OpenSearch</p><p>100_250_1</p><p>0.7023</p><p>57.08</p><p>279.58</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_500_1</p><p>0.8577</p><p>25.42</p><p>524.14</p><p>7.20%</p><p>2.4</p><p>2</p><p>OpenSearch</p><p>100_500_1</p><p>0.8001</p><p>60.9</p><p>262.12</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_750_1</p><p>0.8947</p><p>29.67</p><p>528.09</p><p>5.72%</p><p>2.25</p><p>2.21</p><p>OpenSearch</p><p>100_750_1</p><p>0.8463</p><p>66.76</p><p>239.11</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_1000_1</p><p>0.9156</p><p>29.65</p><p>534.5</p><p>4.66%</p><p>2.46</p><p>2.44</p><p>OpenSearch</p><p>100_1000_1</p><p>0.8748</p><p>72.88</p><p>219.01</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_1500_1</p><p>0.9386</p><p>31.84</p><p>497.3</p><p>3.38%</p><p>2.71</p><p>2.68</p><p>OpenSearch</p><p>100_1500_1</p><p>0.9079</p><p>86.16</p><p>185.4</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_2000_1</p><p>0.9507</p><p>34.69</p><p>457.2</p><p>2.57%</p><p>2.98</p><p>2.96</p><p>OpenSearch</p><p>100_2000_1</p><p>0.9269</p><p>103.36</p><p>154.55</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_2500_1</p><p>0.9582</p><p>37.9</p><p>418.43</p><p>1.99%</p><p>3.28</p><p>3.26</p><p>OpenSearch</p><p>100_2500_1</p><p>0.9395</p><p>124.29</p><p>128.53</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_3000_1</p><p>0.9636</p><p>41.86</p><p>379.4</p><p>1.62%</p><p>3.46</p><p>3.44</p><p>OpenSearch</p><p>100_3000_1</p><p>0.9482</p><p>144.67</p><p>110.34</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_4000_1</p><p>0.9705</p><p>50.28</p><p>316.21</p><p>1.06%</p><p>3.87</p><p>3.85</p><p>OpenSearch</p><p>100_4000_1</p><p>0.9603</p><p>194.36</p><p>82.22</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_5000_1</p><p>0.9749</p><p>58.77</p><p>270.91</p><p>0.73%</p><p>4.43</p><p>4.41</p><p>OpenSearch</p><p>100_5000_1</p><p>0.9678</p><p>260.33</p><p>61.38</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_6000_1</p><p>0.9781</p><p>66.75</p><p>238.59</p><p>0.52%</p><p>4.91</p><p>4.89</p><p>OpenSearch</p><p>100_6000_1</p><p>0.973</p><p>327.44</p><p>48.81</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_7000_1</p><p>0.9804</p><p>74.64</p><p>213.49</p><p>0.38%</p><p>5.28</p><p>5.27</p><p>OpenSearch</p><p>100_7000_1</p><p>0.9767</p><p>394.24</p><p>40.53</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_8000_1</p><p>0.9823</p><p>82.28</p><p>193.59</p><p>0.27%</p><p>6.86</p><p>6.83</p><p>OpenSearch</p><p>100_8000_1</p><p>0.9797</p><p>564.14</p><p>28.33</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_9000_1</p><p>0.9837</p><p>90.08</p><p>176.96</p><p>0.16%</p><p>7.63</p><p>7.61</p><p>OpenSearch</p><p>100_9000_1</p><p>0.9821</p><p>687.25</p><p>23.25</p><p></p><p></p><p></p><p>Elasticsearch</p><p>100_10000_1</p><p>0.9848</p><p>97.64</p><p>163.31</p><p>0.08%</p><p>8.38</p><p>8.36</p><p>OpenSearch</p><p>100_10000_1</p><p>0.984</p><p>818.64</p><p>19.53</p><p></p><p></p><p></p><p>例如，在 <code>100_9000_1</code> 处，OpenSearch 每次检索平均为 687 毫秒， Elasticsearch 为 90 毫秒，而在 10 步检索循环中，等待时间约为 10 x (687 - 90) = 6 秒。 </p><p>查看<a href="https://github.com/elastic/competitive-benchmarking-studies/tree/main/es-9.3-vs-os-3.5-vector-search/jingra/results/20260220">完整结果</a>。</p><h3>方法</h3><p>我们使用 Python 发送查询并跟踪响应时间及其他统计数据，向引擎发送了以下查询。请记住，任何向量搜索引擎的性能取决于您如何调整其核心参数：考虑多少个候选项，重新评分的程度，以及返回多少上下文。这些设置直接影响召回率（找到正确答案的可能性）和延迟（获得结果的速度）。</p><p>在我们的基准测试中，我们使用了通常在智能体检索循环中调整的候选对象、重新评分和结果大小设置，并测量了 Elasticsearch 在该工作负载下的表现。然后我们以相同的设置运行了 OpenSearch 作为参考。</p><p>OpenSearch</p>GET &lt;INDEX_NAME&gt;/_search
{
  "query": {
    "knn": {
      "&lt;DENSE_VECTOR_FIELD_NAME&gt;": {
        "vector": [...],
        "k": &lt;NUMBER_OF_CANDIDATES&gt;,
        "method_parameters": {
          "ef_search": &lt;NUMBER_OF_CANDIDATES&gt;
        },
        "rescore": {
          "oversample_factor": &lt;OVERSAMPLE&gt;
        },
        "filter": {
          &lt;SOME_FILTER&gt;
        }
      }
    }
  },
  "size": &lt;RESULT_SIZE&gt;,
  "_source": {
    "excludes": [
      "&lt;DENSE_VECTOR_FIELD_NAME&gt;"
    ]
  }
}<ul><li><p><code>"size": &lt;RESULT_SIZE&gt;</code>：返回给客户端的命中次数。在这个基准测试中，计算 Recall@100 的结果大小为 100。</p></li><li><p><code>"k": &lt;NUMBER_OF_CANDIDATES&gt;</code>：最近邻候选对象的数量。</p></li><li><p><code>"ef_search": &lt;NUMBER_OF_CANDIDATES&gt;</code>：要检查的向量数量。</p></li><li><p><code>"oversample_factor": &lt;OVERSAMPLE&gt;</code>：在重新评分之前检索了多少个候选向量。</p></li></ul><p>Elasticsearch</p>GET &lt;INDEX_NAME&gt;/_search
{
  "query": {
    "knn": {
      "field": "&lt;DENSE_VECTOR_FIELD_NAME&gt;",
      "query_vector": [...],
      "k": &lt;NUMBER_OF_CANDIDATES&gt;,
      "num_candidates": &lt;NUMBER_OF_CANDIDATES&gt;,
      "rescore_vector": {
        "oversample": &lt;OVERSAMPLE&gt;
      },
      "filter": {
        &lt;SOME_FILTER&gt;
      }
    }
  },
  "size": &lt;RESULT_SIZE&gt;,
  "_source": {
    "excludes": [
      "&lt;DENSE_VECTOR_FIELD_NAME&gt;"
    ]
  }
}<ul><li><p><code>"size": &lt;RESULT_SIZE&gt;</code>：返回给客户端的命中次数。在这个基准测试中，计算 Recall@100 的结果大小为 100。</p></li><li><p><code>"k": &lt;NUMBER_OF_CANDIDATES&gt;</code>：从每个分片返回的最近邻数量。</p></li><li><p><code>"num_candidates": &lt;NUMBER_OF_CANDIDATES&gt;</code>：进行 <code>knn</code> 搜索时每个分片要考虑的最近邻候选数目。</p></li><li><p><code>"oversample": &lt;OVERSAMPLE&gt;</code>：在重新评分之前检索了多少个候选向量。</p></li></ul><p>示例</p><p><code>Knn</code> 查询, (<code>100_500_1</code>)，将如下所示：</p><p>OpenSearch</p>GET search_catalog_128/_search
{
  "query": {
    "knn": {
      "search_catalog_embedding": {
        "vector": [...],
        "k": 500,
        "method_parameters": {
          "ef_search": 500
        },
        "rescore": {
          "oversample_factor": 1
        },
        "filter": {
          "term": {
            "valid": true
          }
        }
      }
    }
  },
  "size": 100,
  "_source": {
    "excludes": [
      "search_catalog_embedding"
    ]
  }
}<p>Elasticsearch</p>GET search_catalog_128/_search
{
  "query": {
    "knn": {
      "field": "search_catalog_embedding",
      "query_vector": [...],
      "k": 500,
      "num_candidates": 500,
      "rescore_vector": {
        "oversample": 1
      },
      "filter": {
        "term": {
          "valid": true
        }
      }
    }
  },
  "size": 100,
  "_source": {
    "excludes": [
      "search_catalog_embedding"
    ]
  }
}<p>完整配置、Terraform 脚本、Kubernetes 清单和基准测试代码均可在此<a href="https://github.com/elastic/competitive-benchmarking-studies">存储库</a>的 <a href="https://github.com/elastic/competitive-benchmarking-studies/tree/main/es-9.3-vs-os-3.5-vector-search">es-9.3-vs-os-3.5-vector-search</a> 文件夹中找到。</p><h3>集群设置</h3><p>我们在六台 e2-standard-16 云服务器上运行了测试，每台服务器配备 16 个 vCPU 和 64 GB 内存。在每台服务器上，我们为每个运行搜索引擎节点的 Kubernetes pod 分配了 15 个 vCPU 和 56 GB RAM，其中 28 GB 保留给 JVM 堆。</p><p>这些集群运行 Elasticsearch 9.3.0 和 OpenSearch 3.5.0 (Lucene 10.3.2)。由于在此基准测试中两个系统使用相同的 Lucene 版本，我们观察到的吞吐量和延迟差异不能单独归因于 Lucene，而是反映了每个引擎如何集成和执行过滤后的 k 最近邻 (kNN) 检索和重新评分的差异。我们使用了一个单一索引，包含三个主分片和一个副本（因此总共 6 个分片，每个节点 1 个分片）。</p><p>我们还在同一区域使用了一台独立服务器运行基准客户端，并收集时序统计数据。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7c7bdd567395d5b7/6a170bf3c1e8a56ee2f882f6/f81002c9186e4c2d3e92f49d72418fee9860fc5e-761x401.png" alt="Elasticsearch 和 OpenSearch 基准测试的集群设置" /><h3>该数据集</h3><p></p><p>对于这个基准测试，我们使用了一个大规模电子商务风格的目录嵌入数据集，包含 2000 万份文档，旨在反映实际的大规模筛选后向量检索的扩展能力。</p><p></p><p>每份文件代表一个目录项目，包括：</p><p></p><ul><li><p>一种用于近似 kNN 检索的 128 维稠密向量嵌入。</p></li><li><p>结构化元数据字段用于筛选（例如，项目有效性和可用性，以及其他目录限制条件），从而支持常见的生产环境模式，即仅在符合条件的子集内检索最近邻。</p></li></ul><p></p><p>我们之所以选择这个数据集，是因为它捕捉到了我们在生产中看到的智能体和 RAG 型系统所面临的核心性能挑战：仅有矢量相似性是不够的，检索经常受到筛选条件的限制，系统必须在这些限制条件下保持较高的召回率和较低的延迟。与较小的 QA 风格数据集相比，2000 万文档的语料库更能反映筛选后 ANN 系统在实践中面临的扩展和候选压力。</p><h2>结论</h2><p>在现代 AI 架构中，尤其是在那些围绕上下文工程构建的架构中，向量搜索速度并非一个微不足道的实现细节。它是一个倍增因素。当智能体和工作流迭代检索→推理→检索时，检索性能直接影响端到端延迟、吞吐量以及输入到模型中的上下文质量。</p><p>在我们的基准测试中，与 OpenSearch 相比，当 Elasticsearch 在正确性取决于检索正确文档而不仅仅是相似向量的情况下，始终能以更低的延迟提供更高的召回率。在受控数据集上，差异是显而易见的，而在生产中，这些收益会在大量检索调用中累积，从而提高响应速度、增加容量裕度并降低基础设施成本。</p><h3>延展阅读</h3><ol><li><p><a href="https://www.elastic.co/search-labs/blog/context-engineering-overview">什么是上下文工程？</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/series/context-engineering-hybrid-search-evolution">混合搜索和上下文工程的演进</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/context-engineering-relevance-ai-agents-elasticsearch">相关性在 AI 智能体的上下文工程中的影响</a></p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/opensearch-vs-elasticsearch-filtered-vector-search</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/opensearch-vs-elasticsearch-filtered-vector-search</guid>
    <category><![CDATA[向量数据库]]></category>
    <dc:creator><![CDATA[Sachin Frayne]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4b38e5114bbf098c/6a170bf560084b3a6c3c459d/fb7ee623925ca6696d643e437ce8efe5fe749079-1280x720.png" length="0" type="image/png"/>
    <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[如何在使用案例中实施更好的二进制量化 (BBQ)]]></title>
    <description><![CDATA[探讨为什么要在用例中实施更好的二进制量化 (BBQ) 以及如何实施。]]></description>
    <content:encoded><![CDATA[<p>矢量搜索为实现文本的语义搜索或图像、视频或音频的相似性搜索提供了基础。在矢量搜索中，矢量是数据的数学表示，可能非常庞大，有时也会比较迟钝。更好的二进制量化（以下简称 BBQ）是一种矢量压缩方法。它可以让你找到正确的匹配，同时缩小矢量，使搜索和处理速度更快。本文将介绍 BBQ 和 rescore_vector，这是一个仅适用于量化索引的字段，可自动对向量重新评分。</p><p>本文中提到的所有完整查询和输出都可以在我们的<a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/how-and-why-bbq">Elasticsearch Labs 代码库中</a>找到。</p><h2>为什么要在使用案例中实施更好的二进制量化 (BBQ)？</h2>注：要深入了解 BBQ 背后的数学原理，请查看下面的<a href="https://www.elastic.co/cn/search-labs/blog/bbq-implementation-into-use-case#further-learning">"进一步学习 "部分</a>。就本博客而言，重点是实施。<p>数学知识固然耐人寻味，但要想完全掌握矢量搜索保持精确的原因，这一点至关重要。归根结底，这一切都与压缩有关，因为事实证明，目前的矢量搜索算法受到数据读取速度的限制。因此，如果能将所有数据都存储到内存中，那么与从存储设备中读取数据相比，速度将得到显著提升 （内存的 读取<a href="https://sre.google/static/pdf/rule-of-thumb-latency-numbers-letter.pdf"> 速度约为固态硬盘的 200 倍</a> ）。</p><p>有几点需要注意：</p><ul><li><p>基于图形的索引，如<a href="https://arxiv.org/pdf/1603.09320">HNSW</a>（层次导航小世界），对于向量检索来说是最快的。</p><ul><li><p>HNSW：一种近似近邻搜索算法，可构建多层图结构，从而实现高效的高维相似性搜索。</p></li></ul></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt760bd95c206bfa8f/6a17e2ad505ac393f7ad8a95/590f3b3c72a76023a38a0436cd9ff90a9f80e936-1964x1262.png" alt="HNSW：一种近似近邻搜索算法，可构建多层图结构，从而实现高效的高维相似性搜索。" /><ul><li><p>从根本上说，HNSW 的速度受限于从内存读取数据的速度，或者在最糟糕的情况下，受限于从存储器读取数据的速度。</p><ul><li><p>理想情况下，您希望能够将所有存储的向量加载到内存中。</p></li></ul></li><li><p>嵌入模型通常以 float32 的精度生成向量，每个浮点数 4 个字节。</p></li><li><p>最后，根据向量和/或维数的多少，内存很快就会不够存放所有向量。</p></li></ul><p>如果把这看作是理所当然的，那么一旦你开始摄入数百万甚至数十亿的向量，每个向量都可能有数百甚至数千个维度，你就会发现问题很快就出现了。题为 "<a href="https://www.elastic.co/cn/search-labs/blog/bbq-implementation-into-use-case#approximate-numbers-on-the-compression-ratios">压缩比近似值</a>"的部分提供了一些粗略的数字。</p><h2>开始需要什么？</h2><p>要开始使用，您需要具备以下条件：</p><ul><li><p>如果使用 Elastic Cloud 或内部部署，则需要高于 8.18 的 Elasticsearch 版本。虽然 BBQ 是在 8.16 中引入的，但在本文中，您将使用<code>vector_rescore</code> ，它是在 8.18 中引入的。</p></li><li><p>此外，您还需要确保集群中有一个<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.18/ml-settings.html">机器学习（ML）节点</a>。(注意：加载模型需要至少 4GB 的 ML 节点，但如果要完成生产工作负载，可能需要更大的节点）。</p></li><li><p>如果使用的是无服务器，则需要选择针对向量进行了优化的实例。</p></li><li><p>您还需要具备矢量数据库方面的基础知识。如果您还不熟悉 Elastic 中的矢量搜索概念，可能需要先查看以下资源：</p><ul><li><p><a href="https://www.elastic.co/cn/search-labs/blog/elastic-vector-database-practical-example">导航弹性矢量数据库</a></p></li><li><p><a href="https://www.elastic.co/cn/blog/retrieval-augmented-generation-explained">检索增强生成背后的重大理念</a></p></li></ul></li></ul><h2>更好的二进制量化 (BBQ) 实现</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt18df00df95ff2ca7/6a17e2af414c6411989450df/4d388078495566f0527e931e0c2e38facdce83c6-1503x748.png" alt="Elasticsearch bbq 实现。" /><p>为了使本博客简单明了，您将在可用时使用内置函数。在这种情况下，<a href="https://www.elastic.co/cn/guide/en/machine-learning/8.17/ml-nlp-e5.html"><code>.multilingual-e5-small</code></a> 向量嵌入模型将直接在 Elasticsearch 内部的机器学习节点上运行。请注意，您可以用自己选择的嵌入器<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.18/infer-service-openai.html">（OpenAI</a>、<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.18/infer-service-google-ai-studio.html">Google AI Studio</a>、<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.18/infer-service-cohere.html">Cohere</a>等）替换<code>text_embedding</code> 模型。如果您喜欢的模型尚未集成，您也可以<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.18/bring-your-own-vectors.html">自带密集向量嵌入</a>模型）。</p><p>首先，您需要创建一个推理端点，为给定文本生成向量。您将从 Kibana<a href="https://www.elastic.co/cn/guide/en/kibana/8.18/console-kibana.html">Dev Tools 控制台</a>运行所有这些命令。该命令将下载<code>.multilingual-e5-small</code>.如果端点还不存在，它将为您设置端点；这可能需要一分钟的时间。你可以在 Outputs 文件夹中的<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/how-and-why-bbq/Outputs/01-create-an-inference-endpoint-output.json">01-create-an-inference-endpoint-output.json</a>文件中看到预期输出。 </p>PUT _inference/text_embedding/my_e5_model
{
  "service": "elasticsearch",
  "service_settings": {
    "num_threads": 1,
    "model_id": ".multilingual-e5-small",
    "adaptive_allocations": {
      "enabled": true,
      "min_number_of_allocations": 1
    }
  }
}<p>返回后，模型就设置好了，您可以使用以下命令测试模型是否按预期运行。你可以在 Outputs 文件夹中的<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/how-and-why-bbq/Outputs/02-embed-text-output.json">02-embed-text-output.json</a>文件中看到预期输出。</p>POST _inference/text_embedding/my_e5_model
{
  "input": "my awesome piece of text"
}<p>如果遇到训练好的模型没有分配到任何节点的问题，可能需要手动启动模型。</p>POST _ml/trained_models/.multilingual-e5-small/deployment/_start<p>现在，让我们创建一个带有 2 个属性的新映射，一个标准文本字段 (<code>my_field</code>) 和一个 384 维的密集矢量字段 (<code>my_vector</code>) ，以匹配嵌入模型的输出。您还可以覆盖<code>index_options.type to bbq_hnsw</code> 。你可以在 Outputs 文件夹中的文件<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/how-and-why-bbq/Outputs/03-create-byte-qauntized-index-output.json">03-create-byte-qauntized-index-output.json</a>中看到预期输出。</p>PUT bbq-my-byte-quantized-index
{
  "mappings": {
    "properties": {
      "my_field": {
        "type": "text"
      },
      "my_vector": {
        "type": "dense_vector",
        "dims": 384,
        "index_options": {
          "type": "bbq_hnsw"
        }
      }
    }
  }
}<p>要确保 Elasticsearch 生成向量，可以使用<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.18/ingest.html">Ingest Pipeline</a>。该管道需要三样东西：端点 (<code>model_id</code>)、要为其创建向量的<code>input_field</code> 以及用于存储这些向量的<code>output_field</code> 。下面的第一条命令将创建推理摄取管道，该管道使用<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/current/inference-apis.html">推理服务 </a>，第二条命令将测试管道是否正常工作。你可以在 Outputs 文件夹中的文件<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/how-and-why-bbq/Outputs/04-create-and-simulate-ingest-pipeline-output.json">04-create and-simulate-ingest-pipeline-output.json</a>中看到预期输出。 </p>PUT _ingest/pipeline/my_inference_pipeline
{
  "processors": [
    {
      "inference": {
        "model_id": "my_e5_model",
        "input_output": [
          {
            "input_field": "my_field",
            "output_field": "my_vector"
          }
        ]
      }
    }
  ]
}

POST _ingest/pipeline/my_inference_pipeline/_simulate
{
  "docs": [
    {
      "_source": {
        "my_field": "my awesome text field"
      }
    }
  ]
}<p>现在，您可以使用下面的前 2 个命令添加一些文档，并使用第 3 个命令测试搜索是否有效。你可以在 Outputs 文件夹中的<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/how-and-why-bbq/Outputs/05-bbq-index-output.json">05-bbq-index-output.json</a>文件中查看预期输出。 </p>PUT bbq-my-byte-quantized-index/_doc/1?pipeline=my_inference_pipeline
{
    "my_field": "my awesome text field"
}

PUT bbq-my-byte-quantized-index/_doc/2?pipeline=my_inference_pipeline
{
    "my_field": "some other sentence"
}

GET bbq-my-byte-quantized-index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "knn": {
            "field": "my_vector",
            "query_vector_builder": {
              "text_embedding": {
                "model_id": "my_e5_model",
                "model_text": "my awesome search field"
              }
            },
            "k": 10,
            "num_candidates": 100
          }
        }
      ]
    }
  },
  "_source": [
    "my_field"
  ]
}<p>正如<a href="https://www.elastic.co/cn/search-labs/blog/better-binary-quantization-lucene-elasticsearch#lucene-benchmarking">本文章</a>所建议的，当您扩展到非数量级的数据时，建议使用重采样和超采样，因为它们有助于在受益于压缩优势的同时保持较高的召回准确率。从 Elasticsearch 8.18 版开始，您可以使用<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.18/knn-search.html#dense-vector-knn-search-rescoring">rescore_vector</a> 这样做。预期输出在 Outputs 文件夹中的<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/how-and-why-bbq/Outputs/06-bbq-search-8-18-output.json">06-bbq-search-8-18-output.json</a>文件中。</p>GET bbq-my-byte-quantized-index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "knn": {
            "field": "my_vector",
            "query_vector_builder": {
              "text_embedding": {
                "model_id": "my_e5_model",
                "model_text": "my awesome search field"
              }
            },
            "rescore_vector": {
              "oversample": 3
            },
            "k": 10,
            "num_candidates": 100
          }
        }
      ]
    }
  },
  "_source": [
    "my_field"
  ]
}<p>这些分数与原始数据的分数相比如何？如果您再次进行上述操作，但使用<code>index_options.type: hnsw</code> ，您会发现得分非常接近。你可以在 Outputs 文件夹中的<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/how-and-why-bbq/Outputs/07-raw-vector-output.json">07-raw-vector-output.json</a>文件中看到预期输出。</p>PUT my-raw-vector-index
{
  "mappings": {
    "properties": {
      "my_field": {
        "type": "text"
      },
      "my_vector": {
        "type": "dense_vector",
        "dims": 384,
        "index_options": {
          "type": "hnsw"
        }
      }
    }
  }
}

PUT my-raw-vector-index/_doc/1?pipeline=my_inference_pipeline
{
    "my_field": "my awesome text field"
}

PUT my-raw-vector-index/_doc/2?pipeline=my_inference_pipeline
{
    "my_field": "some other sentence"
}

GET my-raw-vector-index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "knn": {
            "field": "my_vector",
            "query_vector_builder": {
              "text_embedding": {
                "model_id": "my_e5_model",
                "model_text": "my awesome search field"
              }
            },
            "k": 10,
            "num_candidates": 100
          }
        }
      ]
    }
  },
  "_source": [
    "my_field"
  ]
}<h2>压缩比的近似值</h2><p>在使用矢量搜索时，存储和内存需求很快就会成为一项重大挑战。下面的细目说明了不同的量化技术如何显著减少矢量数据的内存占用。</p><p>向量 (V)</p><p>尺寸（D）</p><p>未加工（V x D x 4）</p><p>int8 (V x (D x 1 + 4))</p><p>int4 (V x (D x 0.5 + 4))</p><p>bbq (V x (D x 0.125 + 4))</p><p>10,000,000</p><p>384</p><p>14.31GB</p><p>3.61GB</p><p>1.83GB</p><p>0.58GB</p><p>50,000,000</p><p>384</p><p>71.53GB</p><p>18.07GB</p><p>9.13GB</p><p>2.89GB</p><p>100,000,000</p><p>384</p><p>143.05GB</p><p>36.14GB</p><p>18.25GB</p><p>5.77GB</p><h2>结论</h2><p>BBQ 是一种优化方法，可用于压缩矢量数据而不影响精度。它的工作原理是将向量转换为比特，让您能够有效地搜索数据，并使您能够扩展人工智能工作流程，加快搜索速度并优化数据存储。</p><h2>进一步学习</h2><p>如果您想了解有关烧烤的更多信息，请务必查看以下资源：</p><ul><li><p><a href="https://www.elastic.co/cn/search-labs/blog/better-binary-quantization-lucene-elasticsearch">Lucene 和 Elasticsearch 中的二进制量化 (BBQ)</a></p></li><li><p><a href="https://www.elastic.co/cn/search-labs/blog/bit-vectors-elasticsearch-bbq-vs-pq">更好的二进制量化（BBQ）与乘积量化比较</a></p></li><li><p><a href="https://www.elastic.co/cn/search-labs/blog/optimized-scalar-quantization-elasticsearch">优化的标量量化更好的二进制量化</a></p></li><li><p><a href="https://www.youtube.com/watch?v=04NzMt2Nigc">更好的二进制量化 (BBQ)：从字节到烧烤，更好的矢量搜索的秘密》，本-特伦特著</a></p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/bbq-implementation-into-use-case</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/bbq-implementation-into-use-case</guid>
    <category><![CDATA[向量数据库]]></category>
    <category><![CDATA[基础功能]]></category>
    <dc:creator><![CDATA[Sachin Frayne,Jessica Garson]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3dd0495b536b2615/6a17e2b0414c6488459450e3/66842055367cdd795532b01c167f2a4b03dc65e3-1200x628.png" length="0" type="image/png"/>
    <pubDate>Wed, 23 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>