التوليد المعزّز للاسترجاع (RAG) باستخدام Milvus و LlamaIndex

Open In Colab GitHub Repository

يوضح هذا الدليل كيفية بناء نظام التوليد المعزز للاسترجاع (RAG) باستخدام LlamaIndex و Milvus.

يجمع نظام RAG بين نظام الاسترجاع والنموذج التوليدي لتوليد نص جديد بناءً على مطالبة معينة. يقوم النظام أولاً باسترجاع المستندات ذات الصلة من مجموعة مستندات باستخدام Milvus، ثم يستخدم نموذجًا توليديًا لتوليد نص جديد بناءً على المستندات المسترجعة.

LlamaIndex هو إطار عمل بسيط ومرن للبيانات لربط مصادر البيانات المخصصة بنماذج لغوية كبيرة (LLMs). Milvus هي قاعدة بيانات المتجهات الأكثر تقدمًا في العالم مفتوحة المصدر، وهي مصممة لتشغيل تطبيقات البحث عن التشابه المضمنة وتطبيقات الذكاء الاصطناعي.

سنعرض في هذا الدفتر عرضًا توضيحيًا سريعًا لاستخدام MilvusVectorStore.

قبل أن تبدأ

تثبيت التبعيات

تتطلب مقتطفات التعليمات البرمجية في هذه الصفحة تبعيات pymilvus و llamaindex. يمكنك تثبيتها باستخدام الأوامر التالية:

$ pip install pymilvus>=2.4.2 milvus-lite
$ pip install llama-index-vector-stores-milvus
$ pip install llama-index

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

إعداد OpenAI

لنبدأ أولاً بإضافة مفتاح Openai api. سيسمح لنا ذلك بالوصول إلى chatgpt.

import openai

openai.api_key = "sk-***********"

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

يمكنك تنزيل عينة من البيانات باستخدام الأوامر التالية:

! mkdir -p 'data/'
! wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham_essay.txt'
! wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/10k/uber_2021.pdf' -O 'data/uber_2021.pdf'

البدء

توليد بياناتنا

كمثال أول، لنقم بإنشاء مستند من الملف paul_graham_essay.txt. إنه مقال واحد من بول غراهام بعنوان What I Worked On. لتوليد المستندات سنستخدم SimpleDirectoryReader.

from llama_index.core import SimpleDirectoryReader

# load documents
documents = SimpleDirectoryReader(
    input_files=["./data/paul_graham_essay.txt"]
).load_data()

print("Document ID:", documents[0].doc_id)
Document ID: 95f25e4d-f270-4650-87ce-006d69d82033

إنشاء فهرس عبر البيانات

الآن بعد أن أصبح لدينا مستند، يمكننا إنشاء فهرس وإدراج المستند. بالنسبة للفهرس سنستخدم MilvusVectorStore. يأخذ MilvusVectorStore بعض الوسيطات:

الوسيطات الأساسية

  • uri (str, optional): URI المطلوب الاتصال به، ويأتي على شكل "https://address:port" لخدمة Milvus أو خدمة Zilliz Cloud، أو "المسار/إلى/إلى/المحلي/ilvus.db" لـ Milvus.db المحلي الخفيف. الافتراضي إلى "./milvus_llamaindex.db".
  • token (str, optional): الرمز المميز لتسجيل الدخول. فارغ في حالة عدم استخدام rbac، وفي حالة استخدام rbac سيكون على الأرجح "اسم المستخدم: كلمة المرور".
  • collection_name (str, optional): اسم المجموعة التي سيتم تخزين البيانات فيها. افتراضي إلى "llamalection".
  • overwrite (bool, optional): ما إذا كان سيتم الكتابة فوق المجموعة الموجودة بنفس الاسم. الإعداد الافتراضي إلى خطأ.

الحقول العددية بما في ذلك معرف المستند والنص

  • doc_id_field (str, optional): اسم حقل doc_id للمجموعة. افتراضي إلى DEFAULT_DOC_ID_KEY.
  • text_key (str, optional): ما نص المفتاح المخزن في المجموعة التي تم تمريرها. يُستخدم عند إحضار المجموعة الخاصة بك. يُستخدم افتراضيًا إلى DEFAULT_TEXT_KEY.
  • scalar_field_names (list, optional): أسماء الحقول العددية الإضافية التي سيتم تضمينها في مخطط المجموعة.
  • scalar_field_types (list, optional): أنواع الحقول العددية الإضافية.

حقل كثيف

  • enable_dense (bool): علامة منطقية لتمكين أو تعطيل التضمين الكثيف. الإعداد الافتراضي إلى صواب.
  • dim (int, optional): بُعد متجهات التضمين للمجموعة. مطلوبة عند إنشاء مجموعة جديدة مع تمكين_التضمين_الكثيف False.
  • embedding_field (str, optional): :: اسم حقل التضمين الكثيف للمجموعة، افتراضيًا إلى DEFAULT_EMBEDDING_KEY.
  • index_config (dict, optional): التكوين المستخدم لبناء فهرس التضمين الكثيف. الافتراضي إلى لا شيء.
  • search_config (dict, optional): التكوين المستخدم للبحث في فهرس ميلفوس الكثيف. لاحظ أن هذا يجب أن يكون متوافقًا مع نوع الفهرس المحدد بواسطة index_config. الإعداد الافتراضي إلى لا شيء.
  • similarity_metric (str, optional): مقياس التشابه المستخدم للتضمين الكثيف، يدعم حاليًا IP وCOSINE و L2.

حقل متناثر

  • enable_sparse (bool): علامة منطقية لتمكين أو تعطيل التضمين المتناثر. الإعداد الافتراضي إلى خطأ.
  • sparse_embedding_field (str): اسم حقل التضمين المتناثر، افتراضيًا إلى DEFAULT_SPARSE_EMBEDDING_KEY.
  • sparse_embedding_function (Union[BaseSparseEmbeddingFunction, BaseMilvusBuiltInFunction], optional): إذا كان enable_sparse صحيحًا، فيجب توفير هذا الكائن لتحويل النص إلى تضمين متناثر. إذا كانت بلا، فسيتم استخدام دالة التضمين المتناثر الافتراضية (BGEM3SparseEmbeddingFunction).
  • sparse_index_config (dict, optional): التكوين المستخدم لبناء فهرس التضمين المتناثر. الإعداد الافتراضي إلى بلا.

مصنف هجين

  • hybrid_ranker (str): يحدد نوع مصنف التصنيف المستخدم في استعلامات البحث المختلط. يدعم حاليًا فقط ["RRFRFRanker"، "RRFRanker"، "WeightedRanker"]. الافتراضي إلى "RRFRFRanker".

  • hybrid_ranker_params (dict, optional): معلمات التكوين لمصنّف البحث الهجين. تعتمد بنية هذا القاموس على مصنف التصنيف المحدد المستخدم:

    • بالنسبة إلى "RRFRFRanker"، يجب أن يتضمن:
      • "k" (int): معلمة تُستخدم في دمج الرتب المتبادل (RRF). تُستخدم هذه القيمة لحساب درجات الترتيب كجزء من خوارزمية RRF، والتي تجمع بين استراتيجيات ترتيب متعددة في درجة واحدة لتحسين ملاءمة البحث.
    • بالنسبة لـ "WeightedRanker"، فإنه يتوقع
      • "الأوزان" (قائمة عائمة): قائمة بأوزان اثنين بالضبط:
        1. الوزن لمكون التضمين الكثيف.
        2. الوزن الخاص بمكون التضمين المتناثر. تُستخدم هذه الأوزان لضبط أهمية المكونات الكثيفة والمتناثرة للتضمينات في عملية الاسترجاع المختلطة. يُفترض أن يكون افتراضيًا لقاموس فارغ، مما يعني أن المصنف سيعمل بإعداداته الافتراضية المحددة مسبقًا.

أخرى

  • collection_properties (dict, optional): خصائص التجميع مثل TTL (الوقت المستغرق) و MMAP (تعيين الذاكرة). الإعدادات الافتراضية إلى لا شيء. يمكن أن تتضمن
    • "collection.ttl.ttl.seconds" (int): بمجرد تعيين هذه الخاصية، تنتهي صلاحية البيانات في المجموعة الحالية في الوقت المحدد. سيتم تنظيف البيانات منتهية الصلاحية في المجموعة ولن يتم تضمينها في عمليات البحث أو الاستعلامات.
    • "mmap.enabled" (صامت): ما إذا كان سيتم تمكين التخزين المعين بالذاكرة على مستوى المجموعة.
  • index_management (IndexManagement): يحدد استراتيجية إدارة الفهرس المراد استخدامها. الإعداد الافتراضي إلى "create_if_not_existing".
  • batch_size (int): تكوين عدد المستندات التي تتم معالجتها في دفعة واحدة عند إدراج البيانات في Milvus. الإعداد الافتراضي إلى DEFAULT_BATCH_SIZE.
  • consistency_level (str, optional): مستوى الاتساق المطلوب استخدامه لمجموعة تم إنشاؤها حديثاً. الإعداد الافتراضي إلى "جلسة عمل".
# Create an index over the documents
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.milvus import MilvusVectorStore


vector_store = MilvusVectorStore(uri="./milvus_demo.db", dim=1536, overwrite=True)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

بالنسبة لمعلمات MilvusVectorStore:

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

الاستعلام عن البيانات

الآن بعد أن أصبح لدينا مستندنا المخزن في الفهرس، يمكننا طرح أسئلة على الفهرس. سيستخدم الفهرس البيانات المخزنة في نفسه كقاعدة معرفية للدردشة.

query_engine = index.as_query_engine()
res = query_engine.query("What did the author learn?")
print(res)
The author learned that philosophy courses in college were boring to him, leading him to switch his focus to studying AI.
res = query_engine.query("What challenges did the disease pose for the author?")
print(res)
The disease posed challenges for the author as it affected his mother's health, leading to a stroke caused by colon cancer. This resulted in her losing her balance and needing to be placed in a nursing home. The author and his sister were determined to help their mother get out of the nursing home and back to her house.

يُظهر الاختبار التالي أن الكتابة فوقها تزيل البيانات السابقة.

from llama_index.core import Document


vector_store = MilvusVectorStore(uri="./milvus_demo.db", dim=1536, overwrite=True)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
    [Document(text="The number that is being searched for is ten.")],
    storage_context,
)
query_engine = index.as_query_engine()
res = query_engine.query("Who is the author?")
print(res)
The author is the individual who created the context information.

يُظهر الاختبار التالي إضافة بيانات إضافية إلى فهرس موجود بالفعل.

del index, vector_store, storage_context, query_engine

vector_store = MilvusVectorStore(uri="./milvus_demo.db", overwrite=False)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
query_engine = index.as_query_engine()
res = query_engine.query("What is the number?")
print(res)
The number is ten.
res = query_engine.query("Who is the author?")
print(res)
Paul Graham

تصفية البيانات الوصفية

يمكننا توليد نتائج عن طريق تصفية مصادر محددة. يوضح المثال التالي تحميل جميع المستندات من الدليل ثم تصفيتها لاحقًا بناءً على البيانات الوصفية.

from llama_index.core.vector_stores import ExactMatchFilter, MetadataFilters

# Load all the two documents loaded before
documents_all = SimpleDirectoryReader("./data/").load_data()

vector_store = MilvusVectorStore(uri="./milvus_demo.db", dim=1536, overwrite=True)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents_all, storage_context)

نريد فقط استرداد المستندات من الملف uber_2021.pdf.

filters = MetadataFilters(
    filters=[ExactMatchFilter(key="file_name", value="uber_2021.pdf")]
)
query_engine = index.as_query_engine(filters=filters)
res = query_engine.query("What challenges did the disease pose for the author?")

print(res)
The disease posed challenges related to the adverse impact on the business and operations, including reduced demand for Mobility offerings globally, affecting travel behavior and demand. Additionally, the pandemic led to driver supply constraints, impacted by concerns regarding COVID-19, with uncertainties about when supply levels would return to normal. The rise of the Omicron variant further affected travel, resulting in advisories and restrictions that could adversely impact both driver supply and consumer demand for Mobility offerings.

نحصل على نتيجة مختلفة هذه المرة عند الاسترداد من الملف paul_graham_essay.txt.

filters = MetadataFilters(
    filters=[ExactMatchFilter(key="file_name", value="paul_graham_essay.txt")]
)
query_engine = index.as_query_engine(filters=filters)
res = query_engine.query("What challenges did the disease pose for the author?")

print(res)
The disease posed challenges for the author as it affected his mother's health, leading to a stroke caused by colon cancer. This resulted in his mother losing her balance and needing to be placed in a nursing home. The author and his sister were determined to help their mother get out of the nursing home and back to her house.

جرب Managed Milvus مجاناً

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

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

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