【问题标题】:Elasticsearch script query cosine similarity using dense_vector gives "class_cast_exception" Error使用dense_vector的Elasticsearch脚本查询余弦相似度给出“class_cast_exception”错误
【发布时间】:2020-09-03 19:04:48
【问题描述】:

执行此查询时,我使用的是 Elasticsearch 版本 7.9.0:

curl -XGET 'https:somehost:9200/index_name/_search' -H 'Content-Type: application/json' -d '{
    "size": 10,
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "cosineSimilarity(params.query_vector, \u0027title_embed\u0027) + 1.0",
                "params": {
                    "query_vector": [-0.19277021288871765, 0.10494251549243927,.......]}
            }
        }
    }
}'

注意:query_vector 是 Bert 生成的 768 维向量。 注意:\u0027 是单引号的 Unicode。

我收到此错误作为响应:

    "cosineSimilarity(params.query_vector, 'title_embed') + 1.0","                   
                   ^---- HERE"],"script":"cosineSimilarity(params.query_vector, 'title_embed') + 
1.0","lang":"painless","position":{"offset":38,"start":0,"end":58},"caused_by":
{"type":"class_cast_exception","reason":"class 
org.elasticsearch.index.fielddata.ScriptDocValues$Doubles cannot be cast to class 
org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$DenseVectorScriptDocValues 
(org.elasticsearch.index.fielddata.ScriptDocValues$Doubles is in unnamed module of loader 'app'; 
org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$DenseVectorScriptDocValues is in 
unnamed module of loader java.net.FactoryURLClassLoader @715fb77)"}}}]},"status":400}

虽然索引映射中title_embed的数据类型是Elasticsearch的dense_vector类型,但是报错说是double不知道为什么?

这是映射:

"mappings": {
    "properties": {
        "description": {
            "type": "text",
            "fields": {
                "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                }
            }
        },
        "domain": {
            "type": "text",
            "fields": {
                "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                }
            }
        },
        "link": {
            "type": "text",
            "fields": {
                "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                }
            }
        },
        "pub_date": {
            "type": "date"
        },
        "title": {
            "type": "text",
            "fields": {
                "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                }
            }
        },
        "title_embed": {
            "type": "dense_vector",
            "dims": 768
        },
        "description_embed": {
            "type": "dense_vector",
            "dims": 768
        }
    }
}

当我尝试使用 python 执行此查询时,我收到相同的错误:

status_code, error_message, additional_info
elasticsearch.exceptions.RequestError: RequestError(400, 'search_phase_execution_exception', "class_cast_exception: class org.elasticsearch.index.fielddata.ScriptDocValues$Doubles cannot be cast to class org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$DenseVectorScriptDocValues (org.elasticsearch.index.fielddata.ScriptDocValues$Doubles is in unnamed module of loader 'app'; org.elasticsearch.xpack.vectors.query.VectorScriptDocValues$DenseVectorScriptDocValues is in unnamed module of loader java.net.FactoryURLClassLoader @6d91790b)")

【问题讨论】:

  • 尝试将 cosineSimilarity() 函数的第二个参数设为 doc['title_embed'] 而不仅仅是 'title_embed'

标签: python elasticsearch cosine-similarity


【解决方案1】:

如果可能,检查变量数是否等于映射中的维数,即

dims:768

“query_vector”中的值的个数是否等于768?

我建议通过运行以下命令再次检查映射以查看映射是否良好:

GET index_name/_mapping

此外,您可能在传递“query_vector”时遗漏了一个值。

我在本地做了一个测试,但是向量是 3 维的。

title_embed 的映射为 3,类型为“dense_vector”。

我在我的映射中提取了一些数据,如下所示:

POST /index_name/_doc
{
  "title_embed": [10.01,15,15]
}

如上所述,我尝试用较低的向量维度复制您的查询:

{
"size": 10,
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "cosineSimilarity(params.query_vector,'title_embed') + 1.0",
                "params": {
                    "query_vector": [-0.19277021288871765, 0.10494251549243927,12.202022]
                
                }
            }
        }
    }
}

注意:正如 Tom Elias 所提到的,运行 doc['title_embed'] 会起作用,但在 7.9.0 版本中已弃用。

一个小建议是,在将索引中的数据与映射一起摄取时,是否可以通过减少向量维度来尝试使用较低维度。如果维数为 5,则检查映射中的“dim”值是否为 5,同时将数据摄取到您的索引和“query_vector”中

"query_vector": [12,-1020.02000,10,-5.0000,2]

如果这不起作用,我认为可能对允许的维度数量存在内部限制。

有用的链接: https://www.elastic.co/guide/en/elasticsearch/reference/7.x/query-dsl-script-score-query.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/dense-vector.html

【讨论】:

  • 是否可以迭代地运行这个查询?通过从另一个索引中检索查询向量?
  • 我认为这是不可能的。基于此链接:elastic.co/guide/en/elasticsearch/reference/current/… 我曾想过使用摄取管道从另一个索引中检索数据,但根据我的理解,无法针对查询运行它。对不起,如果我找到任何解决方案,我会更新评论。谢谢。
  • @CharlesVanDamme 您可以在应用程序端对此进行编码,但不能在一个请求本身中进行编码。您永远无法直接在 Elasticsearch 中建立 2 个索引之间的关系。
  • @Jaycreation 如果我在第一个索引中将第二个索引定义为另一种类型的文档会怎样?
  • 如果你这样做,它将是相同的索引。做这种事情的唯一方法是使用嵌套或父子级。嵌套可能是一个很好的答案,但父子很少。但是您仍然无法迭代地做事。大多数时候,当我们尝试在弹性中这样做时,我们误解了一些在设计应用程序时出现的错误
猜你喜欢
  • 2020-08-12
  • 2021-08-04
  • 2011-01-01
  • 2016-08-14
  • 2017-12-12
  • 2019-04-12
  • 2018-02-19
  • 2013-02-27
相关资源
最近更新 更多