بناء RAG مع Milvus و EmbedAnything
EmbedAnything هو خط أنابيب تضمين فائق السرعة وخفيف الوزن مبني في Rust يدعم النصوص وملفات PDF والصور والصوت وغيرها.
في هذا البرنامج التعليمي، سنشرح في هذا البرنامج التعليمي كيفية إنشاء خط أنابيب توليد معزز للاسترجاع (RAG) باستخدام EmbedAnything مع Milvus. بدلًا من الاقتران بإحكام مع أي قاعدة بيانات محددة، يستخدم EmbedAnything نظام محول قابل للتوصيل - تعمل المحولات كأغلفة تحدد كيفية تنسيق التضمينات وفهرستها وتخزينها في مخزن المتجهات المستهدفة.
من خلال إقران EmbedAnything مع محول Milvus، يمكنك إنشاء تضمينات من أنواع ملفات متنوعة وتخزينها بكفاءة في Milvus في بضعة أسطر من التعليمات البرمجية.
⚠️ ملاحظة: بينما يتعامل المحول في EmbedAnything مع الإدراج في Milvus، إلا أنه لا يدعم البحث خارج الصندوق. لإنشاء خط أنابيب RAG كامل، ستحتاج أيضًا إلى إنشاء MilvusClient بشكل منفصل وتنفيذ منطق الاسترجاع (على سبيل المثال، البحث عن التشابه عبر المتجهات) كجزء من تطبيقك.
التحضير
التبعيات والبيئة
$ pip install -qU pymilvus milvus-lite openai embed_anything
إذا كنت تستخدم Google Colab، لتمكين التبعيات المثبتة للتو، فقد تحتاج إلى إعادة تشغيل وقت التشغيل (انقر على قائمة "وقت التشغيل" في أعلى الشاشة، وحدد "إعادة تشغيل الجلسة" من القائمة المنسدلة).
استنساخ المستودع وتحميل المحول
بعد ذلك، سنقوم باستنساخ مستودع EmbedAnything repo وإضافة الدليل examples/adapters إلى مسار Python. هذا هو المكان الذي نخزن فيه تطبيق محول Milvus المخصص، والذي يسمح ل EmbedAnything بالتواصل مع Milvus لإدخال المتجهات.
import sys
# Clone the EmbedAnything repository if not already cloned
![ -d "EmbedAnything" ] || git clone https://github.com/StarlightSearch/EmbedAnything.git
# Add the `examples/adapters` directory to the Python path
sys.path.append("EmbedAnything/examples/adapters")
print("✅ EmbedAnything cloned and adapter path added.")
✅ EmbedAnything cloned and adapter path added.
سنستخدم OpenAI كمحول LLM في خط أنابيب RAG هذا. يجب إعداد مفتاح api OPENAI_API_KEY كمتغير بيئة.
import os
from openai import OpenAI
os.environ["OPENAI_API_KEY"] = "sk-***********"
openai_client = OpenAI()
بناء RAG
تهيئة ميلفوس
قبل أن نقوم بتضمين أي ملفات، نحتاج إلى إعداد مكونين يتفاعلان مع Milvus:
MilvusVectorAdapter- هذا هو محول Milvus لـ EmbedAnything، ويُستخدم فقط لاستيعاب المتجهات (أي إدراج التضمينات وإنشاء الفهارس). لا يدعم حاليًا عمليات البحث.MilvusClient- هذا هو العميل الرسمي منpymilvus، والذي يتيح الوصول الكامل إلى إمكانيات Milvus بما في ذلك البحث عن المتجهات والتصفية وإدارة المجموعات.
لتجنب الالتباس:
- فكر في
MilvusVectorAdapterكأداة "للكتابة فقط" لتخزين المتجهات. - فكر في
MilvusClientعلى أنه محرك "القراءة والبحث" الخاص بك لإجراء الاستعلامات واسترداد المستندات لـ RAG.
import embed_anything
from embed_anything import (
WhichModel,
EmbeddingModel,
)
from milvus_db import MilvusVectorAdapter
from pymilvus import MilvusClient
# Official Milvus client for full operations
milvus_client = MilvusClient(uri="./milvus.db", token="")
# EmbedAnything adapter for pushing embeddings into Milvus
index_name = "embed_anything_milvus_collection"
milvus_adapter = MilvusVectorAdapter(
uri="./milvus.db", token="", collection_name=index_name
)
# Delete existing collection if it exists
if milvus_client.has_collection(index_name):
milvus_client.drop_collection(index_name)
# Create a new collection with dimension matching the embedding model later used
milvus_adapter.create_index(dimension=384)
Ok - Milvus DB connection established.
Collection 'embed_anything_milvus_collection' created with index.
أما بالنسبة لحجة MilvusVectorAdapter و MilvusClient:
- يعد تعيين
uriكملف محلي، على سبيل المثال./milvus.db، هو الطريقة الأكثر ملاءمة، حيث يستخدم تلقائيًا ميلفوس لايت لتخزين جميع البيانات في هذا الملف. - إذا كان لديك حجم كبير من البيانات، على سبيل المثال أكثر من مليون ناقل، يمكنك إعداد خادم Milvus أكثر أداءً على Docker أو Kubernetes. في هذا الإعداد، يُرجى استخدام عنوان الخادم والمنفذ كـ uri، على سبيل المثال
http://localhost:19530. إذا قمت بتمكين ميزة المصادقة على Milvus، استخدم ": " كرمز مميز، وإلا فلا تقم بتعيين الرمز المميز. - إذا كنت ترغب في استخدام Zilliz Cloud، الخدمة السحابية المدارة بالكامل لـ Milvus، فاضبط
uriوtoken، والتي تتوافق مع نقطة النهاية العامة ومفتاح Api في Zilliz Cloud.
تهيئة نموذج التضمين وتضمين مستند PDF
سنقوم الآن بتهيئة نموذج التضمين. سنستخدم all-MiniLM-L12-v2 model من مكتبة محولات الجملة، وهو نموذج خفيف الوزن لكنه قوي لتوليد تضمينات نصية. إنه ينتج تضمينات ذات 384 بُعدًا، لذا فإن هذا يتماشى مع تعيين بُعد مجموعة ميلفوس إلى 384. هذه المحاذاة أمر بالغ الأهمية ويضمن التوافق بين الأبعاد المتجهة المخزنة في Milvus وتلك التي تم إنشاؤها بواسطة النموذج.
يدعم EmbedAnything الكثير من نماذج التضمين. لمزيد من التفاصيل، يرجى الرجوع إلى الوثائق الرسمية.
# Initialize the embedding model
model = EmbeddingModel.from_pretrained_hf(
WhichModel.Bert, model_id="sentence-transformers/all-MiniLM-L12-v2"
)
والآن، لنقم بتضمين ملف PDF. يجعل EmbedAnything من السهل معالجة مستندات PDF (وغيرها الكثير) وتخزين تضميناتها مباشرةً في Milvus.
# Embed a PDF file
data = embed_anything.embed_file(
"./pdf_files/WhatisMilvus.pdf",
embedder=model,
adapter=milvus_adapter,
)
Converted 12 embeddings for insertion.
Successfully inserted 12 embeddings.
استرجاع وتوليد الاستجابة
مرة أخرى، فإن MilvusVectorAdapter من EmbedAnything حاليًا هو تجريد خفيف الوزن لاستيعاب وفهرسة المتجهات فقط. ولا يدعم استعلامات البحث أو الاسترجاع. لذلك، من أجل البحث عن المستندات ذات الصلة لبناء خط أنابيب RAG الخاص بنا، يجب أن نستخدم مباشرةً مثيل MilvusClient (milvus_client) للاستعلام عن مخزن متجهات Milvus الخاص بنا.
تحديد دالة لاسترداد المستندات ذات الصلة من Milvus.
def retrieve_documents(question, top_k=3):
query_vector = list(
embed_anything.embed_query([question], embedder=model)[0].embedding
)
search_res = milvus_client.search(
collection_name=index_name,
data=[query_vector],
limit=top_k,
output_fields=["text"],
)
docs = [(res["entity"]["text"], res["distance"]) for res in search_res[0]]
return docs
تحديد دالة لإنشاء استجابة باستخدام المستندات المسترجعة في خط أنابيب RAG.
def generate_rag_response(question):
retrieved_docs = retrieve_documents(question)
context = "\n".join([f"Text: {doc[0]}\n" for doc in retrieved_docs])
system_prompt = (
"You are an AI assistant. Provide answers based on the given context."
)
user_prompt = f"""
Use the following pieces of information to answer the question. If the information is not in the context, say you don't know.
Context:
{context}
Question: {question}
"""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
)
return response.choices[0].message.content
دعونا نختبر خط أنابيب RAG باستخدام نموذج سؤال.
question = "How does Milvus search for similar documents?"
answer = generate_rag_response(question)
print(f"Question: {question}")
print(f"Answer: {answer}")
Question: How does Milvus search for similar documents?
Answer: Milvus searches for similar documents primarily through Approximate Nearest Neighbor (ANN) search, which finds the top K vectors closest to a given query vector. It also supports various other types of searches, such as filtering search under specified conditions, range search within a specified radius, hybrid search based on multiple vector fields, and keyword search based on BM25. Additionally, it can perform reranking to adjust the order of search results based on additional criteria, refining the initial ANN search results.