البحث الهجين مع ميلفوس
في هذا البرنامج التعليمي، سنشرح في هذا البرنامج التعليمي كيفية إجراء بحث هجين باستخدام Milvus ونموذج BGE-M3. يمكن لنموذج BGE-M3 تحويل النص إلى متجهات كثيفة ومتناثرة. يدعم Milvus تخزين كلا النوعين من المتجهات في مجموعة واحدة، مما يسمح بالبحث الهجين الذي يعزز أهمية النتائج.
يدعم Milvus طرق الاسترجاع الكثيفة والمتناثرة والهجينة:
- الاسترجاع الكثيف: يستخدم السياق الدلالي لفهم المعنى الكامن وراء الاستعلامات.
- الاسترجاع المتناثر: يركّز على مطابقة النص للعثور على النتائج بناءً على مصطلحات محددة، أي ما يعادل البحث في النص الكامل.
- الاسترجاع الهجين: يجمع بين النهجين الكثيف والمتناثر، حيث يلتقط السياق الكامل والكلمات الرئيسية المحددة للحصول على نتائج بحث شاملة.
من خلال دمج هذه الأساليب، يوازن البحث الهجين في ميلفوس بين أوجه التشابه الدلالي والمعجمي، مما يحسّن من الملاءمة الإجمالية لنتائج البحث. سيتناول هذا الدفتر عملية إعداد واستخدام استراتيجيات الاسترجاع هذه، مع تسليط الضوء على فعاليتها في سيناريوهات البحث المختلفة.
التبعيات والبيئة
$ pip install --upgrade pymilvus "pymilvus[model]"
تحميل مجموعة البيانات
لتوضيح البحث، نحتاج إلى مجموعة من المستندات. لنستخدم مجموعة بيانات Quora Duplicate Questions ونضعها في الدليل المحلي.
مصدر مجموعة البيانات: أول إصدار لمجموعة بيانات Quora: أزواج الأسئلة
# Run this cell to download the dataset
$ wget http://qim.fs.quoracdn.net/quora_duplicate_questions.tsv
تحميل وإعداد البيانات
سنقوم بتحميل مجموعة البيانات وإعداد مجموعة صغيرة للبحث.
import pandas as pd
file_path = "quora_duplicate_questions.tsv"
df = pd.read_csv(file_path, sep="\t")
questions = set()
for _, row in df.iterrows():
obj = row.to_dict()
questions.add(obj["question1"][:512])
questions.add(obj["question2"][:512])
if len(questions) > 500: # Skip this if you want to use the full dataset
break
docs = list(questions)
# example question
print(docs[0])
What is the strongest Kevlar cord?
استخدام نموذج BGE-M3 للتضمين
يمكن لنموذج BGE-M3 تضمين النصوص كمتجهات كثيفة ومتناثرة.
from milvus_model.hybrid import BGEM3EmbeddingFunction
ef = BGEM3EmbeddingFunction(use_fp16=False, device="cpu")
dense_dim = ef.dim["dense"]
# Generate embeddings using BGE-M3 model
docs_embeddings = ef(docs)
Fetching 30 files: 100%|██████████| 30/30 [00:00<00:00, 302473.85it/s]
Inference Embeddings: 100%|██████████| 32/32 [01:59<00:00, 3.74s/it]
إعداد مجموعة ميلفوس والفهرس
سنقوم بإعداد مجموعة Milvus وإنشاء مؤشرات لحقول المتجهات.
- يعد تعيين الفهرس كملف محلي، على سبيل المثال "./milvus.db"، الطريقة الأكثر ملاءمة، حيث يستخدم تلقائيًا Milvus Lite لتخزين جميع البيانات في هذا الملف.
- إذا كان لديك حجم كبير من البيانات، على سبيل المثال أكثر من مليون ناقل، يمكنك إعداد خادم Milvus أكثر أداءً على Docker أو Kubernetes. في هذا الإعداد، يُرجى استخدام uri الخادم، على سبيل المثال http://localhost:19530، كـ uri الخاص بك.
- إذا كنت ترغب في استخدام Zilliz Cloud، الخدمة السحابية المدارة بالكامل لـ Milvus، قم بتعديل uri والرمز المميز، اللذين يتوافقان مع نقطة النهاية العامة ومفتاح واجهة برمجة التطبيقات في Zilliz Cloud.
from pymilvus import (
connections,
utility,
FieldSchema,
CollectionSchema,
DataType,
Collection,
)
# Connect to Milvus given URI
connections.connect(uri="./milvus.db")
# Specify the data schema for the new Collection
fields = [
# Use auto generated id as primary key
FieldSchema(
name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100
),
# Store the original text to retrieve based on semantically distance
FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=512),
# Milvus now supports both sparse and dense vectors,
# we can store each in a separate field to conduct hybrid search on both vectors
FieldSchema(name="sparse_vector", dtype=DataType.SPARSE_FLOAT_VECTOR),
FieldSchema(name="dense_vector", dtype=DataType.FLOAT_VECTOR, dim=dense_dim),
]
schema = CollectionSchema(fields)
# Create collection (drop the old one if exists)
col_name = "hybrid_demo"
if utility.has_collection(col_name):
Collection(col_name).drop()
col = Collection(col_name, schema, consistency_level="Strong")
# To make vector search efficient, we need to create indices for the vector fields
sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"}
col.create_index("sparse_vector", sparse_index)
dense_index = {"index_type": "AUTOINDEX", "metric_type": "IP"}
col.create_index("dense_vector", dense_index)
col.load()
إدراج البيانات في مجموعة ميلفوس
أدرج المستندات وتضميناتها في المجموعة.
# For efficiency, we insert 50 records in each small batch
for i in range(0, len(docs), 50):
batched_entities = [
docs[i : i + 50],
docs_embeddings["sparse"][i : i + 50],
docs_embeddings["dense"][i : i + 50],
]
col.insert(batched_entities)
print("Number of entities inserted:", col.num_entities)
Number of entities inserted: 502
أدخل استعلام البحث
# Enter your search query
query = input("Enter your search query: ")
print(query)
# Generate embeddings for the query
query_embeddings = ef([query])
# print(query_embeddings)
How to start learning programming?
قم بتشغيل البحث
سنقوم أولاً بإعداد بعض الوظائف المفيدة لتشغيل البحث:
dense_search
: البحث فقط عبر حقل متجه كثيفsparse_search
: البحث عبر حقل متجه متناثر فقطhybrid_search
: البحث عبر كلا الحقلين المتجهين الكثيف والمتجه مع إعادة ترتيب مرجحة
from pymilvus import (
AnnSearchRequest,
WeightedRanker,
)
def dense_search(col, query_dense_embedding, limit=10):
search_params = {"metric_type": "IP", "params": {}}
res = col.search(
[query_dense_embedding],
anns_field="dense_vector",
limit=limit,
output_fields=["text"],
param=search_params,
)[0]
return [hit.get("text") for hit in res]
def sparse_search(col, query_sparse_embedding, limit=10):
search_params = {
"metric_type": "IP",
"params": {},
}
res = col.search(
[query_sparse_embedding],
anns_field="sparse_vector",
limit=limit,
output_fields=["text"],
param=search_params,
)[0]
return [hit.get("text") for hit in res]
def hybrid_search(
col,
query_dense_embedding,
query_sparse_embedding,
sparse_weight=1.0,
dense_weight=1.0,
limit=10,
):
dense_search_params = {"metric_type": "IP", "params": {}}
dense_req = AnnSearchRequest(
[query_dense_embedding], "dense_vector", dense_search_params, limit=limit
)
sparse_search_params = {"metric_type": "IP", "params": {}}
sparse_req = AnnSearchRequest(
[query_sparse_embedding], "sparse_vector", sparse_search_params, limit=limit
)
rerank = WeightedRanker(sparse_weight, dense_weight)
res = col.hybrid_search(
[sparse_req, dense_req], rerank=rerank, limit=limit, output_fields=["text"]
)[0]
return [hit.get("text") for hit in res]
دعونا نجري ثلاث عمليات بحث مختلفة بدوال محددة:
dense_results = dense_search(col, query_embeddings["dense"][0])
sparse_results = sparse_search(col, query_embeddings["sparse"]._getrow(0))
hybrid_results = hybrid_search(
col,
query_embeddings["dense"][0],
query_embeddings["sparse"]._getrow(0),
sparse_weight=0.7,
dense_weight=1.0,
)
عرض نتائج البحث
لعرض نتائج عمليات البحث الكثيفة والمتناثرة والهجينة، نحتاج إلى بعض الأدوات المساعدة لتنسيق النتائج.
def doc_text_formatting(ef, query, docs):
tokenizer = ef.model.tokenizer
query_tokens_ids = tokenizer.encode(query, return_offsets_mapping=True)
query_tokens = tokenizer.convert_ids_to_tokens(query_tokens_ids)
formatted_texts = []
for doc in docs:
ldx = 0
landmarks = []
encoding = tokenizer.encode_plus(doc, return_offsets_mapping=True)
tokens = tokenizer.convert_ids_to_tokens(encoding["input_ids"])[1:-1]
offsets = encoding["offset_mapping"][1:-1]
for token, (start, end) in zip(tokens, offsets):
if token in query_tokens:
if len(landmarks) != 0 and start == landmarks[-1]:
landmarks[-1] = end
else:
landmarks.append(start)
landmarks.append(end)
close = False
formatted_text = ""
for i, c in enumerate(doc):
if ldx == len(landmarks):
pass
elif i == landmarks[ldx]:
if close:
formatted_text += "</span>"
else:
formatted_text += "<span style='color:red'>"
close = not close
ldx = ldx + 1
formatted_text += c
if close is True:
formatted_text += "</span>"
formatted_texts.append(formatted_text)
return formatted_texts
ثم يمكننا عرض نتائج البحث في نص مع إبرازات:
from IPython.display import Markdown, display
# Dense search results
display(Markdown("**Dense Search Results:**"))
formatted_results = doc_text_formatting(ef, query, dense_results)
for result in dense_results:
display(Markdown(result))
# Sparse search results
display(Markdown("\n**Sparse Search Results:**"))
formatted_results = doc_text_formatting(ef, query, sparse_results)
for result in formatted_results:
display(Markdown(result))
# Hybrid search results
display(Markdown("\n**Hybrid Search Results:**"))
formatted_results = doc_text_formatting(ef, query, hybrid_results)
for result in formatted_results:
display(Markdown(result))
نتائج البحث الكثيف:
ما هي أفضل طريقة لبدء تعلم الروبوتات؟
كيف يمكنني تعلم لغة كمبيوتر مثل جافا؟
كيف يمكنني البدء في تعلم أمن المعلومات؟
ما هي برمجة جافا؟ كيف أتعلم لغة برمجة جافا؟
كيف يمكنني تعلم أمن المعلومات؟
ما هي أفضل طريقة لبدء برمجة الروبوتات؟ ما هي أفضل لوحة تطوير يمكنني البدء في العمل عليها؟
كيف يمكنني تعلم التحدث باللغة الإنجليزية بطلاقة؟
ما هي أفضل الطرق لتعلم اللغة الفرنسية؟
كيف يمكنني تعلم الفيزياء بسهولة؟
كيف نستعد لامتحان UPSC؟
نتائج بحث متفرقة:
ما هي برمجة ج افا؟ كيف تتعلم لغة برمجة جافا؟
ما هي أفضل طريقة لبدء تعلم الروبوتات؟
ما هو البديل للتعلم الآلي؟
كيف أقوم بإنشاء محطة طرفية جديدة وصدفة جديدة في لينكس باستخدام برمجة C؟
كيف يمكنني إنشاء صدفة جديدة في محطة طرفية جديدة باستخدام البرمجة C (محطة طرفية لينكس)؟
ما هو العمل الأفضل للبدء في حيدر أباد؟
ما هو العمل التجاري الأفضل للبدء في حيدر أباد؟
ما هي أفضل طريقة لبدء الروبوتات؟ ما هي أفضل لوحة تطوير يمكنني البدء في العمل عليها؟
ما هي الرياضيات التي يحتاجها المبتدئ لفهم خوارزميات برمجة الكمبيوتر؟ ما هي الكتب عن الخوارزميات المناسبة للمبتدئ الكامل؟
كيف تجعل الحياة تناسبك وتمنع الحياة من الإساءة إليك عقلياً وعاطفياً؟
نتائج البحث الهجين:
ما هي أفضل طريقة لبدء برمجة الروبوتات؟ ما هي أفضل لوحة تطوير يمكنني البدء في العمل عليها؟
ما هي برمجة ج افا؟ كيف أتعلم لغة برمجة جافا؟
ما هي أفضل طريقة لبدء تعلم الروبوتات؟
كيف نستعد لامتحان UPSC؟
كيف تجعل الفيزياء سهلة التعلم؟
ما هي أفضل الطرق لتعلم اللغة الفرنسية؟
كيف يمكنني تعلم التحدث باللغة الإنجليزية بطلاقة؟
كيف يمكنني تعلم أمن الحاسوب؟
كيف يمكنني البدء في تعلم أمن المعلومات؟
كيف يمكنني تعلم لغة كمبيوتر مثل جافا؟
ما هو البديل للتعلم الآلي؟
كيف يمكنني إنشاء محطة طرفية جديدة وصدفة جديدة في لينكس باستخدام برمجة C؟
كيف يمكنني إنشاء صدفة جديدة في محطة طرفية جديدة باستخدام البرمجة C (محطة طرفية لينكس)؟
ما هو العمل الأفضل للبدء في حيدر أباد؟
ما هو العمل التجاري الأفضل للبدء في حيدر أباد؟
ما هي الرياضيات التي يحتاجها المبتدئ لفهم خوارزميات برمجة الكمبيوتر؟ ما هي الكتب عن الخوارزميات المناسبة للمبتدئ الكامل؟
كيف تجعل الحياة تناسبك وتمنع الحياة من الإساءة إليك عقليًا وعاطفيًا؟
النشر السريع
لمعرفة كيفية بدء عرض توضيحي عبر الإنترنت باستخدام هذا البرنامج التعليمي، يرجى الرجوع إلى مثال التطبيق.