2023年10月23日 星期一

Vespa 的 parent document + weightedSet 撞牆筆記

簡要紀錄,最近遇到在 parent document 裡使用 weightedSet 做資料篩選的時候,本來還沒加 weightedSet 時,latency 是大約 25ms,加了 weightedSet 之後變成大約 730ms。

以下是當時的 schema 設定,簡要來說就是有個讓多個 child document 共用的欄位,叫做 sharedField,它被 child document 繼承時,欄位名字會叫做 fieldInParentDoc

# Schema in parent document.
field sharedField type weightedset<string> {
    indexing: attribute
    attribute: fast-search
}

# Schema in child document
field id type string {
    indexing: attribute
    attribute: fast-search
}

field parentReference type reference<parent_doc> {
    indexing: attribute
}

import field parentReference.sharedField as fieldInParentDoc {}

接著,在查詢時使用的 query 大約是這樣:

SELECT * FROM * sources WHERE (id contains "my_id_1" OR id contains "my_id_2") AND weightedSet(fieldInParentDoc, {"my_key":1});

實際上 ID 欄位是唯一值,並且 query 當中會有 5 個 ID,所以搜尋結果一定只會有 5 筆紀錄。理論上這應該會是很快的 query,但在加上後半段的 parent document 篩選條件後,速度就爆增了 28 倍。

不過如果幫這個 parent document 欄位設定 rank: filter,如下所示,讓它改成 bit vector 的形式,速度會變快不少。具體來說,專案裡測試的結果是會從 730ms 變成約 90ms。雖然還是很慢,但至少勉強還過得去…。

# Schema in parent document.
field sharedField type weightedset<string> {
    indexing: attribute
    attribute: fast-search
    rank: filter
}

2023年10月11日 星期三

在 Vespa 使用語義搜尋(一):簡要的基本知識

在搜尋的世界裡,語義搜尋(semantic search)是近代非常熱門的作法,它可以做到一些傳統的文字搜尋(text matching)做不到的事情。概念上來說,語義搜尋就是把句子的語義萃取出來,轉換成數學裡的向量來表達,然後再利用向量距離來衡量兩個句子的相關程度。這篇文章會簡要紀錄一點語義搜尋時,可能需要知道的基本知識。不過由於這裡面比較多跟資料科學比較有關的知識,在這方面我是個外行,所以這篇基本上都會比較以偏外行的視角在看待這些知識。

Vector Search

技術上來說,語義搜尋也可以稱之為 Vector Search,畢竟語義搜尋是透過向量來做搜尋。而要做語義搜尋,第一要務就是「要如何把一個字串轉換成向量」?這個轉換很大幅度決定了語義搜尋的結果,畢竟轉換成什麼樣的向量,就會決定它跟什麼東西比較近了。其中,把文字轉換成向量的行為,稱為詞嵌入(Embedding)。

Embedding 有很多種技術,近年來比較著名的演算法,就我所知大概是 BERT、FastText 等等的。具體來說,依據我們選擇的 embedding 演算法,會產生出不同維度的向量,這些向量放在向量空間中,就可以接著被用來計算點跟點的距離,並用以決定兩段文字是否相關。

Transformer

Transformer 是 Google 在 2017 年發表的神經網路架構,就我的理解是,這個架構最大的不同是讓神經網路的計算能夠平行化,使得大型模型的訓練變成了可能。目前比較常聽到的像是 GPT(Generative Pre-trained Transformers)、BERT(Bidirectional Encoder Representations from Transformers) 等模型,都是基於 Transformer 架構開發出來的。

Hugging Face

由於市場上現在有很多種模型架構和應用環境,例如有些模型用 TensorFlow、有些用 PyTorch 等等。Hugging Face 是用來提供統一的 API 介面,使得不同架構的模型能夠互通。細節可以參考文章

ONNX

ONNX(Open Neural Network Exchange)是一種神經網路的資料交換格式,用來讓不同架構(例如 Google 的 Tensorflow、Meta 的 PyTorch、微軟的 CNTX 等)訓練出來的模型能夠互通在其他架構。不過據說 Tensorflow 因為發展較早,已經有自己成熟的環境,因此並不支援 ONNX,但有工具能夠將 Tensorflow 模型轉換成 ONNX 格式,如 tf2onnx

Nearest Neighbor Search

NN(Nearest Neighbor)是在向量空間中尋找最近的點的問題。比較著名的解法是 KNN(K-nearest neighbor algorithm)。

Approximate Nearest Neighbor Search

ANN(Approximate Nearest Neighbor Search)是改良版的 NN,目標是用比較粗略的方式,在向量空間中找出距離最近的點。Vespa 在使用 ANN 去計算尋找最近的點時,使用的演算法是 HNSW。