练习 5:使用向量
练习 5:在 Solr 中使用向量
本练习将使用我们在练习 4 中看到过的电影示例。
准备工作
请确保您已按照 tutorial-films.adoc#restart-solr 中的步骤运行 Solr。然后继续下一节。
准备向量数据
$ bin/solr create -c films
由于我们在创建集合时没有指定 ConfigSet,我们将使用 _default
ConfigSet。
首先,我们需要更新我们的模式,以添加向量字段类型、用于保存向量值的字段以及一些支持字段。
$ curl https://127.0.0.1:8983/solr/films/schema -X POST -H 'Content-type:application/json' --data-binary '{
"add-field-type" : {
"name":"knn_vector_10",
"class":"solr.DenseVectorField",
"vectorDimension":10,
"similarityFunction":"cosine",
"knnAlgorithm":"hnsw"
},
"add-field" : [
{
"name":"film_vector",
"type":"knn_vector_10",
"indexed":true,
"stored":true
},
{
"name":"name",
"type":"text_general",
"multiValued":false,
"stored":true
},
{
"name":"initial_release_date",
"type":"pdate",
"stored":true
}
]
}'
现在使用向量索引电影数据
我们的 films.json
文件中嵌入了向量,因此让我们索引这些数据,利用我们刚刚定义的新模式字段。
$ bin/solr post -c films example/films/films.json
让我们进行一些向量搜索
在进行查询之前,我们定义一个示例目标向量,模拟一个观看过 3 部电影的人:海底总动员、蜜蜂总动员 和 哈利·波特与密室。我们获取每部电影的向量,然后计算出平均向量,该向量将用作以下所有示例查询的输入向量。
[-0.1784, 0.0096, -0.1455, 0.4167, -0.1148, -0.0053, -0.0651, -0.0415, 0.0859, -0.1789]
有兴趣使用 Solr 的 流式功能 计算向量吗?这是一个可以通过 Solr 管理流式界面 运行的流式表达式示例
输出为
|
搜索与我们先前计算的目标向量最相似的前 10 部电影(用于推荐的 KNN 查询)
'https://127.0.0.1:8983/solr/films/query?q={%21knn%20f=film_vector%20topK=10}[-0.1784,0.0096,-0.1455,0.4167,-0.1148,-0.0053,-0.0651,-0.0415,0.0859,-0.1789]'
-
请注意,在结果中,有一些动画家庭电影,如 好奇的乔治 和 小鹿斑比,这是有道理的,因为目标向量是用另外两部动画家庭电影(海底总动员 和 蜜蜂总动员)创建的。
-
我们还注意到,在结果中,有两部电影是这个人已经看过的。在下一个例子中,我们将过滤掉它们。
搜索与结果向量最相似的前 10 部电影,排除已经看过的电影(带有过滤器查询的 KNN 查询)
https://127.0.0.1:8983/solr/films/query?q={!knn%20f=film_vector%20topK=10}[-0.1784,0.0096,-0.1455,0.4167,-0.1148,-0.0053,-0.0651,-0.0415,0.0859,-0.1789]&fq=-id:("%2Fen%2Ffinding_nemo"%20"%2Fen%2Fbee_movie"%20"%2Fen%2Fharry_potter_and_the_chamber_of_secrets_2002")
-
在与目标向量最相似的前 50 部电影中,搜索名称中带有“灰姑娘”(cinderella)的电影(KNN 作为过滤器查询)
https://127.0.0.1:8983/solr/films/query?q=name:cinderella&fq={!knn%20f=film_vector%20topK=50}[-0.1784,0.0096,-0.1455,0.4167,-0.1148,-0.0053,-0.0651,-0.0415,0.0859,-0.1789]
-
索引中有 3 部“灰姑娘”电影,但只有 1 部在与目标向量最相似的前 50 部中(灰姑娘 3:时间扭转)。
-
-
搜索类型为“动画”(animation)的电影,并通过将原始查询分数与目标向量的相似度(乘以 2 倍)相结合(求和)的方式,对前 5 个文档进行重新排序(带有重新排序的 KNN)
https://127.0.0.1:8983/solr/films/query?q=genre:animation&rqq={!knn%20f=film_vector%20topK=10000}[-0.1784,0.0096,-0.1455,0.4167,-0.1148,-0.0053,-0.0651,-0.0415,0.0859,-0.1789]&rq={!rerank%20reRankQuery=$rqq%20reRankDocs=5%20reRankWeight=2}
-
搜索“哈利波特”(harry potter)电影,根据与目标向量的相似度而不是词法查询分数对结果进行排序。除了
q
参数,我们还定义了一个名为q_vector
的“子查询”,它将计算所有电影之间的相似度分数(因为我们设置了topK=10000
)。然后我们使用子查询参数名称作为sort
的输入,指定我们要根据向量相似度分数降序排列(sort=$q_vector desc
)https://127.0.0.1:8983/solr/films/query?q=name:"harry%20potter"&q_vector={!knn%20f=film_vector%20topK=10000}[-0.1784,0.0096,-0.1455,0.4167,-0.1148,-0.0053,-0.0651,-0.0415,0.0859,-0.1789]&sort=$q_vector%20desc
-
搜索名称中带有“the”的电影,保留原始的词法查询排名,但只返回与目标向量的相似度为 0.8 或更高的电影。与之前一样,我们定义子查询
q_vector
,但这次我们将其用作frange
过滤器的输入,指定我们想要向量相似度分数至少为 0.8 的文档https://127.0.0.1:8983/solr/films/query?q=name:the&q_vector={!knn%20f=film_vector%20topK=10000}[-0.1784,0.0096,-0.1455,0.4167,-0.1148,-0.0053,-0.0651,-0.0415,0.0859,-0.1789]&fq={!frange%20l=0.8}$q_vector
-
搜索“蝙蝠侠”(batman)电影,通过结合 70% 的原始词法查询分数和 30% 的与目标向量的相似度来对结果进行排序。除了
q
主查询和q_vector
子查询之外,我们还指定了q_lexical
查询,它将保留主q
查询的词法分数。然后我们指定一个名为score_combined
的参数变量,它会缩放词法分数和相似度分数,应用 0.7 和 0.3 的权重,然后对结果求和。我们设置sort
参数以根据组合分数进行排序,并设置fl
参数,以便我们可以在响应中查看中间值和组合分数https://127.0.0.1:8983/solr/films/query?q=name:batman&q_lexical={!edismax%20v=$q}&q_vector={!knn%20f=film_vector%20topK=10000}[-0.1784,0.0096,-0.1455,0.4167,-0.1148,-0.0053,-0.0651,-0.0415,0.0859,-0.1789]&score_combined=sum(mul(scale($q_lexical,0,1),0.7),mul(scale($q_vector,0,1),0.3))&sort=$score_combined%20desc&fl=name,score,$q_lexical,$q_vector,$score_combined