🚀 Coba Zilliz Cloud, Milvus yang sepenuhnya terkelola, secara gratis—rasakan performa 10x lebih cepat! Coba Sekarang>>

milvus-logo
LFAI
  • Home
  • Blog
  • Memulai Pencarian Semantik / Teks Lengkap Hibrida dengan Milvus 2.5

Memulai Pencarian Semantik / Teks Lengkap Hibrida dengan Milvus 2.5

  • Engineering
December 17, 2024
Stefan Webb

Dalam artikel ini, kami akan menunjukkan kepada Anda cara cepat untuk memulai dan menjalankan fitur pencarian teks lengkap yang baru dan menggabungkannya dengan pencarian semantik konvensional berdasarkan sematan vektor.

Persyaratan

Pertama, pastikan Anda telah menginstal Milvus 2.5:

pip install -U pymilvus[model]

dan memiliki contoh Milvus Standalone yang sedang berjalan (misalnya di mesin lokal Anda) menggunakan petunjuk instalasi di dokumen Milvus.

Membangun Skema Data dan Indeks Pencarian

Kita mengimpor kelas-kelas dan fungsi-fungsi yang dibutuhkan:

from pymilvus import MilvusClient, DataType, Function, FunctionType, model

Anda mungkin telah melihat dua entri baru untuk Milvus 2.5, Function dan FunctionType, yang akan kami jelaskan segera.

Selanjutnya kita membuka database dengan Milvus Standalone, yaitu secara lokal, dan membuat skema data. Skema ini terdiri dari sebuah kunci utama integer, sebuah string teks, sebuah vektor padat berdimensi 384, dan sebuah vektor jarang (dengan dimensi tak terbatas). Perhatikan bahwa Milvus Lite saat ini tidak mendukung pencarian teks lengkap, hanya Milvus Standalone dan Milvus Terdistribusi.

client = MilvusClient(uri="http://localhost:19530")

schema = client.create_schema()

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000, enable_analyzer=True)
schema.add_field(field_name="dense", datatype=DataType.FLOAT_VECTOR, dim=768),
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR)
{'auto_id': False, 'description': '', 'fields': [{'name': 'id', 'description': '', 'type': <DataType.INT64: 5>, 'is_primary': True, 'auto_id': True}, {'name': 'text', 'description': '', 'type': <DataType.VARCHAR: 21>, 'params': {'max_length': 1000, 'enable_analyzer': True}}, {'name': 'dense', 'description': '', 'type': <DataType.FLOAT_VECTOR: 101>, 'params': {'dim': 768}}, {'name': 'sparse', 'description': '', 'type': <DataType.SPARSE_FLOAT_VECTOR: 104>}], 'enable_dynamic_field': False}

Anda mungkin telah memperhatikan parameter enable_analyzer=True. Ini memberitahu Milvus 2.5 untuk mengaktifkan pengurai leksikal pada bidang ini dan membuat daftar token dan frekuensi token, yang diperlukan untuk pencarian teks lengkap. Bidang sparse akan menyimpan representasi vektor dari dokumentasi sebagai kumpulan kata yang dihasilkan dari penguraian text.

Tetapi bagaimana kita menghubungkan bidang text dan sparse, dan memberi tahu Milvus bagaimana sparse harus dihitung dari text? Di sinilah kita perlu memanggil objek Function dan menambahkannya ke dalam skema:

bm25_function = Function(
    name="text_bm25_emb", # Function name
    input_field_names=["text"], # Name of the VARCHAR field containing raw text data
    output_field_names=["sparse"], # Name of the SPARSE_FLOAT_VECTOR field reserved to store generated embeddings
    function_type=FunctionType.BM25,
)

schema.add_function(bm25_function)
{'auto_id': False, 'description': '', 'fields': [{'name': 'id', 'description': '', 'type': <DataType.INT64: 5>, 'is_primary': True, 'auto_id': True}, {'name': 'text', 'description': '', 'type': <DataType.VARCHAR: 21>, 'params': {'max_length': 1000, 'enable_analyzer': True}}, {'name': 'dense', 'description': '', 'type': <DataType.FLOAT_VECTOR: 101>, 'params': {'dim': 768}}, {'name': 'sparse', 'description': '', 'type': <DataType.SPARSE_FLOAT_VECTOR: 104>, 'is_function_output': True}], 'enable_dynamic_field': False, 'functions': [{'name': 'text_bm25_emb', 'description': '', 'type': <FunctionType.BM25: 1>, 'input_field_names': ['text'], 'output_field_names': ['sparse'], 'params': {}}]}

Abstraksi dari objek Function lebih umum daripada menerapkan pencarian teks lengkap. Di masa depan, ini dapat digunakan untuk kasus-kasus lain di mana satu bidang perlu menjadi fungsi dari bidang lain. Dalam kasus kami, kami menetapkan bahwa sparse adalah fungsi dari text melalui fungsi FunctionType.BM25. BM25 mengacu pada metrik umum dalam pencarian informasi yang digunakan untuk menghitung kemiripan kueri dengan sebuah dokumen (relatif terhadap kumpulan dokumen).

Kami menggunakan model penyematan default di Milvus, yaitu paraphrase-albert-small-v2:

embedding_fn = model.DefaultEmbeddingFunction()

Langkah selanjutnya adalah menambahkan indeks pencarian kita. Kita memiliki satu untuk vektor padat dan satu lagi untuk vektor jarang. Jenis indeksnya adalah SPARSE_INVERTED_INDEX dengan BM25 karena pencarian teks lengkap membutuhkan metode pencarian yang berbeda dari yang digunakan untuk vektor padat standar.

index_params = client.prepare_index_params()

index_params.add_index(
    field_name="dense",
    index_type="AUTOINDEX", 
    metric_type="COSINE"
)

index_params.add_index(
    field_name="sparse",
    index_type="SPARSE_INVERTED_INDEX", 
    metric_type="BM25"
)

Akhirnya, kita membuat koleksi kita:

client.drop_collection('demo')
client.list_collections()
[]
client.create_collection(
    collection_name='demo', 
    schema=schema, 
    index_params=index_params
)

client.list_collections()
['demo']

Dan dengan itu, kita memiliki basis data kosong yang disiapkan untuk menerima dokumen teks dan melakukan pencarian semantik dan teks lengkap!

Memasukkan data tidak berbeda dengan versi Milvus sebelumnya:

docs = [
    'information retrieval is a field of study.',
    'information retrieval focuses on finding relevant information in large datasets.',
    'data mining and information retrieval overlap in research.'
]

embeddings = embedding_fn(docs)

client.insert('demo', [
    {'text': doc, 'dense': vec} for doc, vec in zip(docs, embeddings)
])
{'insert_count': 3, 'ids': [454387371651630485, 454387371651630486, 454387371651630487], 'cost': 0}

Pertama-tama, mari kita ilustrasikan pencarian teks lengkap sebelum kita beralih ke pencarian hibrida:

search_params = {
    'params': {'drop_ratio_search': 0.2},
}

results = client.search(
    collection_name='demo', 
    data=['whats the focus of information retrieval?'],
    output_fields=['text'],
    anns_field='sparse',
    limit=3,
    search_params=search_params
)

Parameter pencarian drop_ratio_search mengacu pada proporsi dokumen dengan skor rendah yang akan dibuang selama algoritme pencarian.

Mari kita lihat hasilnya:

for hit in results[0]:
    print(hit)
{'id': 454387371651630485, 'distance': 1.3352930545806885, 'entity': {'text': 'information retrieval is a field of study.'}}
{'id': 454387371651630486, 'distance': 0.29726022481918335, 'entity': {'text': 'information retrieval focuses on finding relevant information in large datasets.'}}
{'id': 454387371651630487, 'distance': 0.2715056240558624, 'entity': {'text': 'data mining and information retrieval overlap in research.'}}

Sekarang mari kita gabungkan apa yang telah kita pelajari untuk melakukan pencarian hibrida yang menggabungkan pencarian semantik dan teks lengkap yang terpisah dengan perangking ulang:

from pymilvus import AnnSearchRequest, RRFRanker
query = 'whats the focus of information retrieval?'
query_dense_vector = embedding_fn([query])

search_param_1 = {
    "data": query_dense_vector,
    "anns_field": "dense",
    "param": {
        "metric_type": "COSINE",
    },
    "limit": 3
}
request_1 = AnnSearchRequest(**search_param_1)

search_param_2 = {
    "data": [query],
    "anns_field": "sparse",
    "param": {
        "metric_type": "BM25",
        "params": {"drop_ratio_build": 0.0}
    },
    "limit": 3
}
request_2 = AnnSearchRequest(**search_param_2)

reqs = [request_1, request_2]
ranker = RRFRanker()

res = client.hybrid_search(
    collection_name="demo",
    output_fields=['text'],
    reqs=reqs,
    ranker=ranker,
    limit=3
)
for hit in res[0]:
    print(hit)
{'id': 454387371651630485, 'distance': 0.032786883413791656, 'entity': {'text': 'information retrieval is a field of study.'}}
{'id': 454387371651630486, 'distance': 0.032258063554763794, 'entity': {'text': 'information retrieval focuses on finding relevant information in large datasets.'}}
{'id': 454387371651630487, 'distance': 0.0317460335791111, 'entity': {'text': 'data mining and information retrieval overlap in research.'}}

Seperti yang mungkin telah Anda ketahui, ini tidak berbeda dengan pencarian hibrida dengan dua bidang semantik yang terpisah (tersedia sejak Milvus 2.4). Hasilnya identik dengan pencarian teks lengkap dalam contoh sederhana ini, tetapi untuk database yang lebih besar dan pencarian spesifik kata kunci, pencarian hibrida biasanya memiliki daya ingat yang lebih tinggi.

Ringkasan

Anda sekarang dilengkapi dengan semua pengetahuan yang dibutuhkan untuk melakukan pencarian teks lengkap dan pencarian semantik/ teks lengkap hibrida dengan Milvus 2.5. Lihat artikel-artikel berikut untuk diskusi lebih lanjut tentang cara kerja pencarian teks lengkap dan mengapa pencarian teks lengkap melengkapi pencarian semantik:

Like the article? Spread the word

Terus Baca