الشروع في استخدام البحث الدلالي الهجين/البحث عن النص الكامل مع ميلفوس 2.5
في هذه المقالة، سنوضح لك كيفية بدء تشغيل ميزة البحث عن النص الكامل الجديدة بسرعة ودمجها مع البحث الدلالي التقليدي القائم على تضمينات المتجهات.
المتطلبات
أولاً، تأكد من تثبيت ميلفوس 2.5:
pip install -U pymilvus[model]
وأن يكون لديك مثيل قيد التشغيل من Milvus Standalone (على جهازك المحلي على سبيل المثال) باستخدام تعليمات التثبيت في مستندات Milvus.
بناء مخطط البيانات ومؤشرات البحث
نقوم باستيراد الفئات والوظائف المطلوبة:
from pymilvus import MilvusClient, DataType, Function, FunctionType, model
لعلك لاحظت إدخالين جديدين لـ Milvus 2.5، Function
و FunctionType
، والتي سنقوم بشرحها بعد قليل.
بعد ذلك نفتح قاعدة البيانات باستخدام Milvus Standalone، أي محليًا، وننشئ مخطط البيانات. يتألف المخطط من مفتاح أساسي عدد صحيح، وسلسلة نصية، ومتجه كثيف بأبعاد 384، ومتجه متناثر (بأبعاد غير محدودة). لاحظ أن ميلفوس لايت لا يدعم حاليًا البحث في النص الكامل، فقط ميلفوس ستاندالون وميلفوس الموزع.
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}
ربما لاحظت المعلمة enable_analyzer=True
. هذا يخبر ميلفوس 2.5 بتمكين المحلل المعجمي على هذا الحقل وبناء قائمة من الرموز وترددات الرموز الرمزية، وهي مطلوبة للبحث في النص الكامل. سيحتوي الحقل sparse
على تمثيل متجه للوثائق كحقيبة من الكلمات الناتجة عن التحليل text
.
ولكن كيف نربط بين الحقلين text
و sparse
، ونخبر ميلفوس كيف ينبغي حساب sparse
من text
؟ هذا هو المكان الذي نحتاج فيه إلى استدعاء الكائن Function
وإضافته إلى المخطط:
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': {}}]}
إن تجريد كائن Function
أكثر عمومية من تجريد كائن من تطبيق البحث عن النص الكامل. في المستقبل، يمكن استخدامه في حالات أخرى حيث يجب أن يكون أحد الحقول دالة لحقل آخر. في حالتنا، نحدد أن sparse
هو دالة لـ text
عبر الدالة FunctionType.BM25
. BM25
يشير إلى مقياس شائع في استرجاع المعلومات يستخدم لحساب تشابه الاستعلام مع مستند (بالنسبة إلى مجموعة من المستندات).
نحن نستخدم نموذج التضمين الافتراضي في ميلفوس، وهو نموذج إعادة الصياغة-ألبرت-صغير-ف2:
embedding_fn = model.DefaultEmbeddingFunction()
الخطوة التالية هي إضافة مؤشرات البحث الخاصة بنا. لدينا واحد للمتجه الكثيف وآخر منفصل للمتجه المتناثر. نوع الفهرس هو SPARSE_INVERTED_INDEX
مع BM25
نظرًا لأن البحث عن النص الكامل يتطلب طريقة بحث مختلفة عن تلك الخاصة بالمتجهات الكثيفة القياسية.
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"
)
أخيرًا، ننشئ مجموعتنا:
client.drop_collection('demo')
client.list_collections()
[]
client.create_collection(
collection_name='demo',
schema=schema,
index_params=index_params
)
client.list_collections()
['demo']
وبذلك، أصبح لدينا قاعدة بيانات فارغة تم إعدادها لقبول المستندات النصية وإجراء عمليات بحث دلالية وبحث عن النص الكامل!
إدراج البيانات وإجراء بحث بالنص الكامل
لا يختلف إدراج البيانات عن الإصدارات السابقة من ميلفوس:
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}
لنقم أولاً بتوضيح البحث عن النص الكامل قبل أن ننتقل إلى البحث المختلط:
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
)
تشير معلمة البحث drop_ratio_search
إلى نسبة المستندات ذات الدرجات المنخفضة التي سيتم إسقاطها أثناء خوارزمية البحث.
دعونا نعرض النتائج:
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.'}}
إجراء بحث دلالي هجين وبحث بالنص الكامل
دعونا الآن نجمع بين ما تعلمناه لإجراء بحث هجين يجمع بين البحث الدلالي المنفصل والبحث بالنص الكامل مع أداة إعادة البحث:
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.'}}
كما لاحظتم، هذا لا يختلف عن البحث المختلط مع حقلين دلاليين منفصلين (متاح منذ الإصدار 2.4 من ملفوس 2.4). تتطابق النتائج مع البحث بالنص الكامل في هذا المثال البسيط، ولكن بالنسبة لقواعد البيانات الأكبر وعمليات البحث الخاصة بالكلمات المفتاحية عادةً ما يكون البحث الهجين أعلى في الاستدعاء.
الملخص
أنت الآن مجهز بكل المعرفة اللازمة لإجراء بحث النص الكامل والبحث المختلط الدلالي/النص الكامل مع ميلفوس 2.5. راجع المقالات التالية لمزيد من المناقشة حول كيفية عمل البحث بالنص الكامل وسبب تكامله مع البحث الدلالي:
- المتطلبات
- بناء مخطط البيانات ومؤشرات البحث
- إدراج البيانات وإجراء بحث بالنص الكامل
- إجراء بحث دلالي هجين وبحث بالنص الكامل
- الملخص
On This Page
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word