在今天的數位時代,搜尋資訊的能力非常重要,幾乎每個應用程式和網站都需要搜尋功能。為了提高搜尋結果的準確性和相關性,架構師和開發人員必須不斷探索新的方法和架構。其中一種方法是利用由深度學習模型生成的向量嵌入,可以提高搜尋結果的準確性和相關性。
同時隨著大型語言模型(LLM)的興起,索引增強生成(RAG)為了實現更好的效果,RAG也需要結合向量搜尋服務。為什麼呢?
- 擴展範圍:LLM可能無法涵蓋所有相關信息,尤其在大型文本庫中。向量搜尋服務能夠擴展搜索範圍,提供更全面的信息支持。
- 提高效率:即使LLM具有強大的生成能力,但檢索過程仍然需要高效率。向量搜尋服務通過優化搜索算法,提高檢索效率,使得RAG服務更加實用。
- 增強質量:結合向量搜尋服務可以幫助RAG模型更好地理解上下文,生成更具內容和一致性的文本,提高了生成質量。
因此許多組織正在利用索引技術將其數據轉換為向量空間,以便於客製化的知識資料庫。通過將數據表示為向量,可以進行相似性搜尋,返回最相關的結果。
這邊將探討如何使用深度學習模型創建向量嵌入,然後利用Redis進行高效且準確的索引搜尋。透過深入了解這種方法,架構師和開發人員可以更好地了解AI驅動的搜尋功能的潛力,並找到改善用戶搜尋體驗的最佳方法。
介紹將有以下流程:
- 透過 HggingFace模型 產生向量嵌入(embedding)
- 利用 Redis進行向量索引以實現高效和準確的搜尋
因此,對於希望提高應用程式或網站搜尋功能效能的架構師和開發人員非常有用,尤其是對於需要處理大量數據並提供高精度搜尋結果的企業和組織。
透過 HggingFace模型 產生向量嵌入(embedding)
from sentence_transformers import SentenceTransformer
import re
def embedding(text):
model = SentenceTransformer('sentence-transformers/all-distilroberta-v1')
return model.encode(text)
使用Redis進行索引
- 通過docker-compose建置Redis
version: "3.8"
services:
redis:
restart: unless-stopped
image: redis/redis-stack
# ports:
# - '6379:6379'
command: redis-server --save 20 1 --loglevel warning --protected-mode no --loadmodule /opt/redis-stack/lib/redisearch.so --loadmodule /opt/redis-stack/lib/rejson.so
volumes:
- ./redis-data:/data
healthcheck:
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
interval: 30s
timeout: 10s
retries: 5
2. 新建表格
samples: https://github.com/Chunshan-Theta/VectorSearch/blob/main/api/initRedis.py
# Create Redis Table
VECTOR_DIM = len(data['vec'][0]) # length of the vectors
VECTOR_NUMBER = len(data) # initial number of vectors
INDEX_NAME = "embeddings-index" # name of the search index
PREFIX = "doc" # prefix for the document keys
DISTANCE_METRIC = "COSINE" # distance metric for the vectors (ex. COSINE, IP, L2)
VECTOR_COLUME_NAME = "vec"
CONTENT_COLUME_NAME = "title"
# Define RediSearch fields for each of the columns in the dataset
text = TextField(name=CONTENT_COLUME_NAME)
text_embedding = VectorField(VECTOR_COLUME_NAME,
"FLAT", {
"TYPE": "FLOAT32",
"DIM": VECTOR_DIM,
"DISTANCE_METRIC": DISTANCE_METRIC,
"INITIAL_CAP": VECTOR_NUMBER,
}
)
fields = [text, text_embedding]
# Check if index exists
try:
redis_client.ft(INDEX_NAME).info()
except:
# Create RediSearch Index
redis_client.ft(INDEX_NAME).create_index(
fields = fields,
definition = IndexDefinition(prefix=[PREFIX], index_type=IndexType.HASH)
)
3. 新增資料
sample: https://github.com/Chunshan-Theta/VectorSearch/blob/main/api/main.py#L71
key = f"{prefix}:{str(doc['id'])}"
client.hset(key, mapping = doc)
4. 搜尋資料
sample: https://github.com/Chunshan-Theta/VectorSearch/blob/main/api/main.py#L39
from redis.commands.search.query import Query
sql = f'(@tableName:{tableName})=>[KNN {k} @{vector_field} $vec_param AS vector_score]'
q = Query(sql).sort_by('vector_score').paging(0,k).dialect(2)
params_dict = {"vec_param": embedding(text)}
results = redis_client.ft(INDEX_NAME).search(q, query_params = params_dict)