Open In Colab GitHub Repository

البحث في النص الكامل مع ميلفوس وهايستاك

البحث في النص الكامل هو طريقة تقليدية لاسترجاع المستندات عن طريق مطابقة كلمات أو عبارات محددة في النص. يقوم بترتيب النتائج بناءً على درجات الملاءمة المحسوبة من عوامل مثل تكرار المصطلح. في حين أن البحث الدلالي أفضل في فهم المعنى والسياق، فإن البحث في النص الكامل يتفوق في مطابقة الكلمات المفتاحية بدقة، مما يجعله مكملاً مفيدًا للبحث الدلالي. تُستخدم خوارزمية BM25 على نطاق واسع للترتيب في البحث في النص الكامل وتلعب دورًا رئيسيًا في التوليد المعزز للاسترجاع (RAG).

يقدمالإصدار Milvus 2.5 إمكانات البحث في النص الكامل الأصلي باستخدام BM25. يقوم هذا النهج بتحويل النص إلى متجهات متفرقة تمثل درجات BM25. يمكنك ببساطة إدخال نص أولي وسيقوم ميلفوس تلقائيًا بتوليد المتجهات المتفرقة وتخزينها، دون الحاجة إلى توليد تضمين يدوي متناثر.

يدعمHaystack الآن ميزة Milvus هذه، مما يجعل من السهل إضافة البحث عن النص الكامل إلى تطبيقات RAG. يمكنك الجمع بين البحث في النص الكامل مع البحث الدلالي في المتجهات الكثيفة للحصول على نهج هجين يستفيد من كل من الفهم الدلالي ودقة مطابقة الكلمات الرئيسية. يعمل هذا الدمج على تحسين دقة البحث وتقديم نتائج أفضل للمستخدمين.

يوضح هذا البرنامج التعليمي كيفية تنفيذ بحث النص الكامل والبحث المختلط في تطبيقك باستخدام Haystack و Milvus.

لاستخدام مخزن Milvus المتجه، حدد خادم Milvus الخاص بك URI (واختيارياً مع TOKEN). لبدء تشغيل خادم Milvus، يمكنك إعداد خادم Milvus باتباع دليل تثبيت Milvus أو ببساطة تجربة Zilliz Cloud(Milvus المدار بالكامل) مجانًا.

  • البحث في النص الكامل متاح حاليًا في Milvus Standalone وMilvus Distributed وZilliz Cloud، على الرغم من عدم دعم هذه الميزة في Milvus Lite (والتي من المقرر أن يتم تطبيق هذه الميزة في المستقبل). تواصل مع support@zilliz.com لمزيد من المعلومات.
  • قبل متابعة هذا البرنامج التعليمي، تأكد من أن لديك فهمًا أساسيًا للبحث في النص الكامل والاستخدام الأساسي لتكامل هايستاك ميلفوس.

المتطلبات الأساسية

قبل تشغيل هذا الدفتر، تأكد من تثبيت التبعيات التالية:

$ pip install --upgrade --quiet pymilvus milvus-haystack

إذا كنت تستخدم Google Colab، لتمكين التبعيات المثبتة للتو، فقد تحتاج إلى إعادة تشغيل وقت التشغيل (انقر على قائمة "وقت التشغيل" في أعلى الشاشة، وحدد "إعادة تشغيل الجلسة" من القائمة المنسدلة).

سنستخدم النماذج من OpenAI. يجب عليك إعداد مفتاح api OPENAI_API_KEY كمتغير بيئة.

import os

os.environ["OPENAI_API_KEY"] = "sk-***********"

قم بإعداد البيانات

قم باستيراد الحزم اللازمة في هذا الدفتر. ثم قم بإعداد بعض نماذج المستندات.

from haystack import Pipeline
from haystack.components.embedders import OpenAIDocumentEmbedder, OpenAITextEmbedder
from haystack.components.writers import DocumentWriter
from haystack.utils import Secret
from milvus_haystack import MilvusDocumentStore, MilvusSparseEmbeddingRetriever
from haystack.document_stores.types import DuplicatePolicy
from milvus_haystack.function import BM25BuiltInFunction
from milvus_haystack import MilvusDocumentStore
from milvus_haystack.milvus_embedding_retriever import MilvusHybridRetriever

from haystack.utils import Secret
from haystack.components.builders import PromptBuilder
from haystack.components.generators import OpenAIGenerator
from haystack import Document

documents = [
    Document(content="Alice likes this apple", meta={"category": "fruit"}),
    Document(content="Bob likes swimming", meta={"category": "sport"}),
    Document(content="Charlie likes white dogs", meta={"category": "pets"}),
]

يعمل دمج البحث في النص الكامل في نظام RAG على تحقيق التوازن بين البحث الدلالي والاسترجاع الدقيق والمتوقع القائم على الكلمات المفتاحية. يمكنك أيضًا اختيار استخدام البحث بالنص الكامل فقط على الرغم من أنه يوصى بدمج البحث بالنص الكامل مع البحث الدلالي للحصول على نتائج بحث أفضل. سنعرض هنا لغرض العرض التوضيحي البحث بالنص الكامل وحده والبحث المختلط.

بحث BM25 بدون تضمين

إنشاء خط أنابيب الفهرسة

للبحث عن النص الكامل يقبل Milvus MilvusDocumentStore معلمة builtin_function. من خلال هذه المعلمة، يمكنك تمرير مثيل BM25BuiltInFunction ، الذي ينفذ خوارزمية BM25 على جانب خادم Milvus. قم بتعيين builtin_function المحدد كمثيل دالة BM25. على سبيل المثال

connection_args = {"uri": "http://localhost:19530"}
# connection_args = {"uri": YOUR_ZILLIZ_CLOUD_URI, "token": Secret.from_env_var("ZILLIZ_CLOUD_API_KEY")}

document_store = MilvusDocumentStore(
    connection_args=connection_args,
    sparse_vector_field="sparse_vector",  # The sparse vector field.
    text_field="text",
    builtin_function=[
        BM25BuiltInFunction(  # The BM25 function converts the text into a sparse vector.
            input_field_names="text",
            output_field_names="sparse_vector",
        )
    ],
    consistency_level="Bounded",  # Supported values are (`"Strong"`, `"Session"`, `"Bounded"`, `"Eventually"`).
    drop_old=True,  # Drop the old collection if it exists and recreate it.
)

بالنسبة لـ connect_args:

  • يمكنك إعداد خادم Milvus أكثر أداءً على docker أو kubernetes. في هذا الإعداد، يرجى استخدام عنوان الخادم، على سبيل المثالhttp://localhost:19530 ، كعنوان uri.
  • إذا كنت ترغب في استخدام Zilliz Cloud، الخدمة السحابية المدارة بالكامل لـ Milvus، اضبط uri و token ، والتي تتوافق مع نقطة النهاية العامة ومفتاح Api في Zilliz Cloud.

قم بإنشاء خط أنابيب فهرسة لكتابة المستندات في مخزن مستندات Milvus.

writer = DocumentWriter(document_store=document_store, policy=DuplicatePolicy.NONE)

indexing_pipeline = Pipeline()
indexing_pipeline.add_component("writer", writer)
indexing_pipeline.run({"writer": {"documents": documents}})
{'writer': {'documents_written': 3}}

إنشاء خط أنابيب الاسترجاع

قم بإنشاء خط أنابيب استرجاع يسترجع المستندات من مخزن مستندات Milvus باستخدام MilvusSparseEmbeddingRetriever ، وهو عبارة عن غلاف حول document_store.

retrieval_pipeline = Pipeline()
retrieval_pipeline.add_component(
    "retriever", MilvusSparseEmbeddingRetriever(document_store=document_store)
)

question = "Who likes swimming?"

retrieval_results = retrieval_pipeline.run({"retriever": {"query_text": question}})

retrieval_results["retriever"]["documents"][0]
Document(id=bd334348dd2087c785e99b5a0009f33d9b8b8198736f6415df5d92602d81fd3e, content: 'Bob likes swimming', meta: {'category': 'sport'}, score: 1.2039074897766113)

إنشاء خط أنابيب الفهرسة

في البحث الهجين، نستخدم الدالة BM25 لإجراء البحث في النص الكامل، ونحدد حقل المتجه الكثيف vector ، لإجراء البحث الدلالي.

document_store = MilvusDocumentStore(
    connection_args=connection_args,
    vector_field="vector",  # The dense vector field.
    sparse_vector_field="sparse_vector",  # The sparse vector field.
    text_field="text",
    builtin_function=[
        BM25BuiltInFunction(  # The BM25 function converts the text into a sparse vector.
            input_field_names="text",
            output_field_names="sparse_vector",
        )
    ],
    consistency_level="Bounded",  # Supported values are (`"Strong"`, `"Session"`, `"Bounded"`, `"Eventually"`).
    drop_old=True,  # Drop the old collection and recreate it.
)

إنشاء خط أنابيب الفهرسة الذي يحول المستندات إلى تضمينات. ثم تتم كتابة المستندات إلى مخزن مستندات Milvus.

writer = DocumentWriter(document_store=document_store, policy=DuplicatePolicy.NONE)

indexing_pipeline = Pipeline()
indexing_pipeline.add_component("dense_doc_embedder", OpenAIDocumentEmbedder())
indexing_pipeline.add_component("writer", writer)
indexing_pipeline.connect("dense_doc_embedder", "writer")
indexing_pipeline.run({"dense_doc_embedder": {"documents": documents}})

print("Number of documents:", document_store.count_documents())
Calculating embeddings: 100%|██████████| 1/1 [00:01<00:00,  1.15s/it]


Number of documents: 3

إنشاء خط أنابيب الاسترجاع

قم بإنشاء خط أنابيب استرجاع يسترجع المستندات من مخزن مستندات Milvus باستخدام MilvusHybridRetriever ، والذي يحتوي على document_store ويستقبل معلمات حول البحث المختلط.

# from pymilvus import WeightedRanker
retrieval_pipeline = Pipeline()
retrieval_pipeline.add_component("dense_text_embedder", OpenAITextEmbedder())
retrieval_pipeline.add_component(
    "retriever",
    MilvusHybridRetriever(
        document_store=document_store,
        # top_k=3,
        # reranker=WeightedRanker(0.5, 0.5),  # Default is RRFRanker()
    ),
)

retrieval_pipeline.connect("dense_text_embedder.embedding", "retriever.query_embedding")
<haystack.core.pipeline.pipeline.Pipeline object at 0x3383ad990>
🚅 Components
  - dense_text_embedder: OpenAITextEmbedder
  - retriever: MilvusHybridRetriever
🛤️ Connections
  - dense_text_embedder.embedding -> retriever.query_embedding (List[float])

عند إجراء البحث الهجين باستخدام MilvusHybridRetriever ، يمكننا اختياريًا تعيين معلمات topK و reranker. سيتعامل تلقائيًا مع التضمينات المتجهة والوظائف المضمنة ويستخدم أخيرًا أداة إعادة الترتيب لتنقيح النتائج. تفاصيل التنفيذ الأساسية لعملية البحث مخفية عن المستخدم.

لمزيد من المعلومات حول البحث الهجين، يمكنك الرجوع إلى مقدمة البحث الهجين.

question = "Who likes swimming?"

retrieval_results = retrieval_pipeline.run(
    {
        "dense_text_embedder": {"text": question},
        "retriever": {"query_text": question},
    }
)

retrieval_results["retriever"]["documents"][0]
Document(id=bd334348dd2087c785e99b5a0009f33d9b8b8198736f6415df5d92602d81fd3e, content: 'Bob likes swimming', meta: {'category': 'sport'}, score: 0.032786883413791656, embedding: vector of size 1536)

تخصيص المحلل

تُعتبر المحللات ضرورية في البحث في النص الكامل من خلال تقسيم الجملة إلى رموز وإجراء تحليل معجمي مثل الجذعية وإزالة كلمات التوقف. عادةً ما تكون المحللات خاصة باللغة. يمكنك الرجوع إلى هذا الدليل لمعرفة المزيد عن المحللات في ميلفوس.

يدعم ميلفوس نوعين من المحللات: المحللات المدمجة والمحللات المخصصة. بشكل افتراضي، سيستخدم BM25BuiltInFunction بشكل افتراضي المحلل المدمج القياسي، وهو المحلل الأساسي الذي يقوم بترميز النص بعلامات الترقيم.

إذا كنت ترغب في استخدام محلل مختلف أو تخصيص المحلل، يمكنك تمرير المعلمة analyzer_params في التهيئة BM25BuiltInFunction.

analyzer_params_custom = {
    "tokenizer": "standard",
    "filter": [
        "lowercase",  # Built-in filter
        {"type": "length", "max": 40},  # Custom filter
        {"type": "stop", "stop_words": ["of", "to"]},  # Custom filter
    ],
}

document_store = MilvusDocumentStore(
    connection_args=connection_args,
    vector_field="vector",
    sparse_vector_field="sparse_vector",
    text_field="text",
    builtin_function=[
        BM25BuiltInFunction(
            input_field_names="text",
            output_field_names="sparse_vector",
            analyzer_params=analyzer_params_custom,  # Custom analyzer parameters.
            enable_match=True,  # Whether to enable match.
        )
    ],
    consistency_level="Bounded",
    drop_old=True,
)

# write documents to the document store
writer = DocumentWriter(document_store=document_store, policy=DuplicatePolicy.NONE)
indexing_pipeline = Pipeline()
indexing_pipeline.add_component("dense_doc_embedder", OpenAIDocumentEmbedder())
indexing_pipeline.add_component("writer", writer)
indexing_pipeline.connect("dense_doc_embedder", "writer")
indexing_pipeline.run({"dense_doc_embedder": {"documents": documents}})
Calculating embeddings: 100%|██████████| 1/1 [00:00<00:00,  1.39it/s]





{'dense_doc_embedder': {'meta': {'model': 'text-embedding-ada-002-v2',
   'usage': {'prompt_tokens': 11, 'total_tokens': 11}}},
 'writer': {'documents_written': 3}}

يمكننا إلقاء نظرة على مخطط مجموعة ميلفوس والتأكد من إعداد المحلل المخصص بشكل صحيح.

document_store.col.schema
{'auto_id': False, 'description': '', 'fields': [{'name': 'text', 'description': '', 'type': <DataType.VARCHAR: 21>, 'params': {'max_length': 65535, 'enable_match': True, 'enable_analyzer': True, 'analyzer_params': {'tokenizer': 'standard', 'filter': ['lowercase', {'type': 'length', 'max': 40}, {'type': 'stop', 'stop_words': ['of', 'to']}]}}}, {'name': 'id', 'description': '', 'type': <DataType.VARCHAR: 21>, 'params': {'max_length': 65535}, 'is_primary': True, 'auto_id': False}, {'name': 'vector', 'description': '', 'type': <DataType.FLOAT_VECTOR: 101>, 'params': {'dim': 1536}}, {'name': 'sparse_vector', 'description': '', 'type': <DataType.SPARSE_FLOAT_VECTOR: 104>, 'is_function_output': True}], 'enable_dynamic_field': True, 'functions': [{'name': 'bm25_function_7b6e15a4', 'description': '', 'type': <FunctionType.BM25: 1>, 'input_field_names': ['text'], 'output_field_names': ['sparse_vector'], 'params': {}}]}

لمزيد من تفاصيل المفهوم، على سبيل المثال، analyzer ، tokenizer ، ، filter ، enable_match ، analyzer_params ، يرجى الرجوع إلى وثائق المحلل.

استخدام البحث الهجين في خط أنابيب RAG

لقد تعلمنا كيفية استخدام الدالة الأساسية BM25 المدمجة في هايستاك وميلفوس وأعددنا تحميل document_store. دعونا نقدم تطبيق RAG الأمثل مع البحث الهجين.

يوضح هذا الرسم البياني عملية الاسترجاع وإعادة الترتيب الهجين، التي تجمع بين BM25 لمطابقة الكلمات الرئيسية والبحث المتجه الكثيف لاسترجاع الدلالات. يتم دمج النتائج من كلتا الطريقتين وإعادة ترتيبها وتمريرها إلى LLM لتوليد الإجابة النهائية.

يوازن البحث الهجين بين الدقة والفهم الدلالي، مما يحسّن الدقة والمتانة للاستعلامات المتنوعة. فهو يسترجع المرشحين باستخدام بحث النص الكامل BM25 والبحث المتجه، مما يضمن استرجاعًا دلاليًا ودقيقًا ومدركًا للسياق.

دعنا نجرب تطبيق RAG الأمثل مع البحث المختلط.

prompt_template = """Answer the following query based on the provided context. If the context does
                     not include an answer, reply with 'I don't know'.\n
                     Query: {{query}}
                     Documents:
                     {% for doc in documents %}
                        {{ doc.content }}
                     {% endfor %}
                     Answer:
                  """

rag_pipeline = Pipeline()
rag_pipeline.add_component("text_embedder", OpenAITextEmbedder())
rag_pipeline.add_component(
    "retriever", MilvusHybridRetriever(document_store=document_store, top_k=1)
)
rag_pipeline.add_component("prompt_builder", PromptBuilder(template=prompt_template))
rag_pipeline.add_component(
    "generator",
    OpenAIGenerator(
        api_key=Secret.from_token(os.getenv("OPENAI_API_KEY")),
        generation_kwargs={"temperature": 0},
    ),
)
rag_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
rag_pipeline.connect("retriever.documents", "prompt_builder.documents")
rag_pipeline.connect("prompt_builder", "generator")

results = rag_pipeline.run(
    {
        "text_embedder": {"text": question},
        "retriever": {"query_text": question},
        "prompt_builder": {"query": question},
    }
)
print("RAG answer:", results["generator"]["replies"][0])
RAG answer: Bob likes swimming.

للمزيد من المعلومات حول كيفية استخدام ميلفوس-هاستاك يُرجى الرجوع إلى المستودع الرسمي لـ ميلفوس-هاستاك.

جرب Managed Milvus مجاناً

Zilliz Cloud خالي من المتاعب، ويعمل بواسطة Milvus ويعمل بسرعة 10 أضعاف.

ابدأ
التعليقات

هل كانت هذه الصفحة مفيدة؟