練習 5:使用向量
練習 5:在 Solr 中使用向量
此練習將使用我們先前在練習 4 中看過的 Films 範例。
準備工作
請確保您已執行 Solr,並依照 tutorial-films.adoc#restart-solr 中的步驟進行。然後繼續到下一節。
準備向量資料
$ bin/solr create -c films
由於我們在建立集合時未指定 ConfigSet,因此我們將使用 _default
ConfigSet。
首先,我們需要更新我們的 schema,以新增向量欄位類型、用於保存向量值的欄位,以及一些支援欄位。
$ 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 資料
我們的向量已嵌入在 films.json
檔案中,因此讓我們索引該資料,並利用我們剛剛定義的新 schema 欄位。
$ 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 管理串流 UI 執行
輸出為
|
搜尋與我們先前計算的目標向量最相似的前 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 部「cinderella」電影,但只有 1 部在前 50 部與目標向量最相似的電影中(仙履奇緣 III:時間的扭曲)。
-
-
搜尋類型為「動畫」的電影,並透過將原始查詢分數與目標向量相似度的兩倍 (2x) 相加,重新排序前 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}
-
搜尋「哈利波特」電影,根據與目標向量的相似度而不是詞彙查詢分數對結果進行排序。除了
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
-
搜尋「蝙蝠俠」電影,透過將原始詞彙查詢分數的 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