稠密向量搜尋
重要概念
稠密向量表示
傳統的符號化 反向索引可以被認為是將文字建模為「稀疏」向量,其中語料庫中的每個詞彙都對應一個向量維度。在這種模型中,維度的數量通常相當高(對應於詞彙表基數),而且任何給定文件的向量都大多包含零(因此它是稀疏的,因為只有少數存在於整體索引中的詞彙會出現在任何給定文件中)。
稠密向量表示與基於詞彙的稀疏向量表示相反,它將近似語義意義提煉成固定(且有限)數量的維度。
這種方法的維度數量通常比稀疏情況少得多,並且任何給定文件的向量都是稠密的,因為它的大部分維度都由非零值填充。
與稀疏方法(使用分詞器直接從文字輸入產生稀疏向量)不同,產生向量的任務必須在 Apache Solr 外部的應用程式邏輯中處理。
在某些情況下,直接搜尋本來就以向量形式存在的資料(例如,科學資料)可能是有意義的;但在文字搜尋上下文中,使用者可能會利用深度學習模型(例如 BERT)將文字資訊編碼為稠密向量,在索引和查詢時明確地將產生的向量提供給 Apache Solr。
如需更多資訊,您可以參考這篇部落格文章。
索引時間
這是 Apache Solr 設計用於支援稠密向量搜尋的欄位類型
DenseVectorField
稠密向量欄位可以索引和搜尋浮點元素的稠密向量。
例如
[1.0, 2.5, 3.7, 4.1]
以下是在架構中應如何設定 DenseVectorField
<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="4" similarityFunction="cosine"/>
<field name="vector" type="knn_vector" indexed="true" stored="true"/>
vectorDimension
-
必要
預設值:無
要傳入的稠密向量的維度。
接受的值:任何整數。
similarityFunction
-
選用
預設值:
euclidean
向量相似度函式;用於搜尋以傳回與目標向量最相似的前 K 個向量。
可接受的值:
euclidean
、dot_product
或cosine
。
此相似度旨在作為執行餘弦相似度的最佳化方法。為了使用它,所有向量必須是單位長度,包括文件和查詢向量。對非單位長度的向量使用點積可能會導致錯誤或不良的搜尋結果。 |
-
cosine
:餘弦相似度
Solr 返回的餘弦相似度分數會像這樣正規化:(1 + cosine_similarity) / 2 。 |
執行餘弦相似度的首選方法是將所有向量正規化為單位長度,然後改用 DOT_PRODUCT。只有在您需要保留原始向量且無法預先正規化它們時,才應使用此函數。 |
若要使用以下自訂編碼格式和 HNSW 演算法超參數的高階參數,請確保正在使用Schema Codec Factory。
以下是如何使用高階超參數設定 DenseVectorField
的方法
<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="4" similarityFunction="cosine" knnAlgorithm="hnsw" hnswMaxConnections="10" hnswBeamWidth="40"/>
<field name="vector" type="knn_vector" indexed="true" stored="true"/>
knnAlgorithm
-
選用
預設值:
hnsw
(高階) 指定要使用的底層 knn 演算法
可接受的值:
hnsw
。
請注意,knnAlgorithm
可接受的值在未來版本中可能會變更。
vectorEncoding
-
選用
預設值:
FLOAT32
(高階) 指定密集向量元素的底層編碼。這會影響索引和儲存欄位(如果已啟用)的記憶體/磁碟影響
可接受的值:
FLOAT32
、BYTE
。 hnswMaxConnections
-
選用
預設值:
16
(高階) 此參數專用於
hnsw
knn 演算法控制有多少個最近鄰居候選連接到新節點。
它的含義與 2018 年論文中的
M
相同。接受的值:任何整數。
hnswBeamWidth
-
選用
預設值:
100
(高階) 此參數專用於
hnsw
knn 演算法它是搜尋圖形以尋找每個新插入節點時要追蹤的最近鄰居候選數量。
它的含義與 2018 年論文中的
efConstruction
相同。接受的值:任何整數。
DenseVectorField
支援以下屬性:indexed
、stored
。
目前不支援多值 |
以下是如何索引 DenseVectorField
的方法
-
JSON
-
XML
-
SolrJ
[{ "id": "1",
"vector": [1.0, 2.5, 3.7, 4.1]
},
{ "id": "2",
"vector": [1.5, 5.5, 6.7, 65.1]
}
]
<add>
<doc>
<field name="id">1</field>
<field name="vector">1.0</field>
<field name="vector">2.5</field>
<field name="vector">3.7</field>
<field name="vector">4.1</field>
</doc>
<doc>
<field name="id">2</field>
<field name="vector">1.5</field>
<field name="vector">5.5</field>
<field name="vector">6.7</field>
<field name="vector">65.1</field>
</doc>
</add>
final SolrClient client = getSolrClient();
final SolrInputDocument d1 = new SolrInputDocument();
d1.setField("id", "1");
d1.setField("vector", Arrays.asList(1.0f, 2.5f, 3.7f, 4.1f));
final SolrInputDocument d2 = new SolrInputDocument();
d2.setField("id", "2");
d2.setField("vector", Arrays.asList(1.5f, 5.5f, 6.7f, 65.1f));
client.add(Arrays.asList(d1, d2));
查詢時間
Apache Solr 提供兩個適用於密集向量欄位的查詢解析器,每個解析器都支援基於向量相似度來比對文件的方式:knn
查詢解析器和 vectorSimilarity
查詢解析器。
兩個解析器都會針對擷取的文件傳回分數,這些分數是與目標向量的近似距離(由索引時設定的 similarityFunction 定義),而且都支援「預先篩選」文件圖形,以減少評估的候選向量數量(無需計算其向量相似度距離)。
兩個查詢解析器的通用參數如下
f
-
必要
預設值:無
要搜尋的
DenseVectorField
。 preFilter
-
選用
預設值:取決於使用情況,請參閱下文。
指定要使用的預先篩選查詢字串的明確清單。
includeTags
-
選用
預設值:無
表示只有具有指定
tag
的fq
篩選器才應被考慮用於隱式預先篩選。不得與preFilter
組合使用。 excludeTags
-
選用
預設值:無
表示應將具有指定
tag
的fq
篩選器排除在隱式預先篩選的考慮之外。不得與preFilter
組合使用。
knn 查詢解析器
knn
k 最近鄰居查詢解析器會將 k 個最近的文件比對到目標向量。
除了上述的通用參數之外,它還接受以下參數
topK
-
選用
預設值:10
要傳回多少個 k 個最近的結果。
以下是簡單 knn
搜尋的範例
?q={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]
擷取的搜尋結果是輸入 [1.0, 2.0, 3.0, 4.0]
中向量的 k=10 個最近的文件,按索引時設定的 similarityFunction
排序。
vectorSimilarity 查詢解析器
vectorSimilarity
向量相似度查詢解析器會比對與目標向量的相似度高於最小閾值的文件。
除了上述的通用參數之外,它還接受以下參數
minReturn
-
必要
預設值:無
圖形中要傳回為符合項的節點的最小相似度閾值
minTraverse
-
選用
預設值:-Infinity
圖形中節點的最小相似度,以繼續追蹤其鄰居
以下是簡單 vectorSimilarity
搜尋的範例
?q={!vectorSimilarity f=vector minReturn=0.7}[1.0, 2.0, 3.0, 4.0]
擷取的搜尋結果是所有與輸入向量 [1.0, 2.0, 3.0, 4.0]
的相似度至少為 0.7
的文件,基於索引時設定的 similarityFunction
。
圖形預先篩選
當走訪圖形時,可以明確或隱式(基於現有的 fq
參數)指定考慮的候選文件集合的預先篩選,具體取決於使用這些密集向量查詢解析器的方式和時間。
明確預先篩選
可以明確指定 preFilter
參數,以減少評估距離計算的候選文件數量
?q={!vectorSimilarity f=vector minReturn=0.7 preFilter=inStock:true}[1.0, 2.0, 3.0, 4.0]
在上面的範例中,只有符合預先篩選 inStock:true
的文件才會在評估針對指定向量的 vectorSimilarity
搜尋時被考慮為候選。
preFilter
參數可以是空白的(例如:preFilter=""
),表示不應執行預先篩選;或可以是多值的,透過重複或透過重複的 參數參考。
這兩個範例是等效的
?q={!knn f=vector topK=10 preFilter=category:AAA preFilter=inStock:true}[1.0, 2.0, 3.0, 4.0]
?q={!knn f=vector topK=10 preFilter=$knnPreFilter}[1.0, 2.0, 3.0, 4.0]
&knnPreFilter=category:AAA
&knnPreFilter=inStock:true
隱式預先篩選
雖然可以在 knn
或 vectorSimilarity
查詢解析器的任何用法上明確指定 preFilter
參數,但預設的預先篩選行為(未指定 preFilter
參數時)會根據查詢解析器的使用方式而有所不同
-
當用作主要的
q
參數時:請求中的fq
篩選器(不是 Solr Post 篩選器)將會組合以形成隱式圖形預先篩選。-
此預設行為會最佳化考慮的向量距離計算數量,消除無論如何都會被
fq
篩選器排除的文件。 -
includeTags
和excludeTags
可用於限制預先篩選中使用的fq
篩選器集合。
-
-
當向量搜尋查詢解析器用作
fq
參數或較大查詢中的子查詢子句時:不會使用隱式預先篩選。-
在這些情況下,不得使用
includeTags
和excludeTags
。
-
下面的範例請求顯示了向量查詢解析器的兩種用法,它們不會從任何 fq
參數取得任何隱式預先篩選,因為這兩種用法都不是主要 q
參數。
?q=(color_str:red OR {!vectorSimilarity f=color_vector minReturn=0.7 v="[1.0, 2.0, 3.0, 4.0]"})
&fq={!knn f=title_vector topK=10}[9.0, 8.0, 7.0, 6.0]
&fq=inStock:true
但是,下一個範例顯示了一個基本請求,其中所有 fq
參數都將用作主要 knn
查詢的隱式預先篩選器
?q={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]
&fq=category:AAA
&fq=inStock:true
如果我們修改上述請求以將標籤新增至 fq
參數,我們可以在 knn
解析器上指定 includeTags
選項,以限制哪些 fq
篩選器用於預先篩選
?q={!knn f=vector topK=10 includeTags=for_knn}[1.0, 2.0, 3.0, 4.0]
&fq=category:AAA
&fq={!tag=for_knn}inStock:true
在本範例中,只會使用 inStock:true
篩選器進行預先篩選,以尋找 topK=10
個文件,並且會獨立套用 category:AAA
篩選器;可能會導致少於 10 個符合項。
某些使用案例中,includeTags
和/或 excludeTags
可能比明確的 preFilter
參數更有用
-
您有一些 在許多請求中重複使用的
fq
參數(即使您不使用搜尋密集向量欄位),您希望在確實搜尋密集向量欄位時將其用作預先篩選器。 -
您通常希望所有
fq
參數都用作knn
查詢中的圖形預先篩選器,但是當使用者「向下鑽取」刻面時,您希望排除新增的fq
參數,以便結果集變小;而不是只計算新的topK
集合。
在重新排序查詢中的用法
兩種密集向量搜尋查詢解析器都可用於重新排序第一遍查詢結果
&q=id:(3 4 9 2)&rq={!rerank reRankQuery=$rqq reRankDocs=4 reRankWeight=1}&rqq={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]
在重新排序中使用 只有當第一遍中的文件 這表示第二遍 最終排序的結果清單會將第一遍分數(主要查詢 有關使用重新排序查詢解析器的詳細資訊,請參閱查詢重新排序章節。 |