前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >向量数据库:使用Elasticsearch实现向量数据存储与搜索

向量数据库:使用Elasticsearch实现向量数据存储与搜索

作者头像
马超的博客
发布2023-09-02 17:48:26
1.6K0
发布2023-09-02 17:48:26
举报
文章被收录于专栏:马超的博客马超的博客

向量数据库:使用Elasticsearch实现向量数据存储与搜索

一、简介

  Elasticsearch在7.x的版本中支持 向量检索[2] 。在向量函数的计算过程中,会对所有匹配的文档进行线性扫描。因此,查询预计时间会随着匹配文档的数量线性增长。出于这个原因,建议使用查询参数来限制匹配文档的数量(类似二次查找的逻辑,先使用match query检索到相关文档,然后使用向量函数计算文档相关度)。

  访问dense_vector的推荐方法是通过cosinessimilarity, dotProduct, 1norm或l2norm函数。但是需要注意,每个DSL脚本只能调用这些函数一次。例如,不要在循环中使用这些函数来计算文档向量和多个其他向量之间的相似性。如果需要该功能,可以通过直接访问向量值来重新实现这些函数。

二、实验前准备

2.1 创建索引设置向量字段

  创建一个支持向量检索的mapping,字段类型为dense_vector

代码语言:javascript
复制
// 7.x 支持的 dims 最大为 1024。
PUT index3
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 3
      },
      "my_text" : {
        "type" : "keyword"
      }
    }
  }
}

2.2 写入数据

代码语言:javascript
复制
PUT index3/_doc/1
{
  "my_text" : "text1",
  "my_vector" : [0.5, 10, 6]
}

PUT index3/_doc/2
{
  "my_text" : "text2",
  "my_vector" : [-0.5, 10, 10]
}

三、向量计算函数

3.1 余弦相似度:cosineSimilarity

  cosinessimilarity函数计算给定查询向量和文档向量之间的余弦相似性度量。

代码语言:javascript
复制
POST index3/_search
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "source": "cosineSimilarity(params.queryVector, doc['my_vector'])+1.0",
        "params": {
          "queryVector": [-0.5, 10, 6]
        }
      }
    }
  }
}
  1. 1. 要限制script_score计算的文档数量,需要提供一个过滤器 (query)。
  2. 2. script脚本在cosineSimilarity上增加了1.0,以防止得分为负。
  3. 3. 为了更好的利用DSL优化器,可以使用参数的方式提供一个查询向量。
  4. 4. 检查缺失值:如果文档中没有用于执行向量函数的向量字段的值,会抛出错误。可以使用doc['my_vector'].size() == 0来检查文档是否有my_vector字段的值。脚本样例:
代码语言:javascript
复制
"source": 
"
doc['my_vector'].size() == 0 ? 0 : 
cosineSimilarity(params.queryVector, 'my_vector')
"

  如果文档的dense_vector字段与查询的向量维度不同,就会抛出异常。

3.2 计算点积:dotProduct

  dotProduct函数计算给定查询向量和文档向量之间的点积度量。

代码语言:javascript
复制
POST index3/_search
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "source": """
        double value = dotProduct(params.queryVector,doc['my_vector']);
        return sigmoid(1, Math.E, -value);
        """,
        "params": {
          "queryVector": [
            -0.5,
            10,
            6
          ]
        }
      }
    }
  }
}
  1. 1. 使用标准的sigmoid函数可以防止分数为负。

3.3 曼哈顿距离:l1norm

l1norm函数计算给定查询向量和文档向量之间的L1距离(曼哈顿距离)。

代码语言:javascript
复制
POST index3/_search
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "source":"1 / (1 + l1norm(params.queryVector, doc['my_vector']))",
        "params": {
          "queryVector": [-0.5, 10, 6]
        }
      }
    }
  }
}
  1. 1. 与表示相似性的余弦相似度不同,1norml2norm表示距离或差异。这意味着,向量越相似,由1norml2norm函数产生的分数就越低。因此,当我们需要相似的向量来获得更高的分数时,我们将1norml2norm的输出反过来。另外,为了避免在文档向量与查询完全匹配时被除0,在分母中加了1。

3.4 欧几里得距离:l2norm

  l2norm函数计算给定查询向量和文档向量之间的L2距离(欧几里德距离)。

代码语言:javascript
复制
POST index3/_search
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "source": "1 / (1 + l2norm(params.queryVector, doc['my_vector']))",
        "params": {
          "queryVector": [
            -0.5,
            10,
            6
          ]
        }
      }
    }
  }
}

3.5 自定义计算函数

  使用函数访问向量的值,自定义实现向量余弦相似度计算。ES 中向量检索 doc[].vectorValue 函数是在 Elasticsearch 7.8.0 版本开始支持的,在ES 7.5.1 或 7.8.0 以下版本会运行失败。

  可以通过以下函数直接访问向量值:

  • doc[<field>].vectorValue – 以浮点数数组的形式返回向量的值。
  • doc[<field>].magnitude – 将向量的大小作为浮点数返回(对于7.5版本之前创建的向量,其向量的大小不会被存储)。所以这个函数每次被调用时都会进行重新计算。
代码语言:javascript
复制
POST index3/_search
{
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "source": """
          float[] v = doc['my_vector'].vectorValue;
          float vm = doc['my_vector'].magnitude;
          float dotProduct = 0;
          for (int i = 0; i < v.length; i++) {
            dotProduct += v[i] * params.queryVector[i];
          }
          return dotProduct / (vm * (float) params.queryVectorMag);
        """,
        "params": {
          "queryVector": [
            -0.5,
            10,
            6
          ],
          "queryVectorMag": 5.25357
        }
      }
    }
  }
}
引用链接

[1] TOC: 向量数据库:使用Elasticsearch实现向量数据存储与搜索 [2] 向量检索: https://github.com/elastic/elasticsearch/blob/e8c382f89553e3a7aaafa88a5934288c1192acdc/docs/reference/vectors/vector-functions.asciidoc

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-06-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 马超的博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 向量数据库:使用Elasticsearch实现向量数据存储与搜索
    • 一、简介
      • 二、实验前准备
        • 2.1 创建索引设置向量字段
        • 2.2 写入数据
      • 三、向量计算函数
        • 3.1 余弦相似度:cosineSimilarity
        • 3.2 计算点积:dotProduct
        • 3.3 曼哈顿距离:l1norm
        • 3.4 欧几里得距离:l2norm
        • 3.5 自定义计算函数
    相关产品与服务
    向量数据库
    腾讯云向量数据库(Tencent Cloud VectorDB)是一款全托管的自研企业级分布式数据库服务,专用于存储、检索、分析多维向量数据。该数据库支持多种索引类型和相似度计算方法,单索引支持千亿级向量规模,可支持百万级 QPS 及毫秒级查询延迟。腾讯云向量数据库不仅能为大模型提供外部知识库,提高大模型回答的准确性,还可广泛应用于推荐系统、自然语言处理等 AI 领域。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档