Qdrant FastAPI RAG API: ابنِ خدمة تستند إلى الأدلة
ابنِ API لتوليد النصوص المعزَّز بالاسترجاع باستخدام البحث الدلالي في Qdrant، وعمليات التضمين BAAI/bge-m3، وFastAPI، وتنسيق سير العمل عبر LangChain، والتوليد باستخدام GPT-5، والتحقق من استجابات Pydantic.
ما الذي تبنيه Qdrant FastAPI RAG API؟
يربط التوليد المعزَّز بالاسترجاع، أو RAG، نموذجًا لغويًا بمجموعة معرفية خارجية. فبدلًا من مطالبة النموذج بالإجابة اعتمادًا على المعلمات التي تعلّمها فقط، يسترجع التطبيق أولًا المقاطع ذات الصلة، ثم يمررها إلى مرحلة التوليد. وتوفر Qdrant طبقة استرجاع المتجهات في هذه البنية، بينما تتيح FastAPI نقطة وصول التطبيق، ويمكن لـLangChain تنسيق سير عمل الاسترجاع والتوليد.
يتبع هذا الشرح نمط المكونات الموثق في السياق المتحقق منه: Qdrant للبحث الدلالي، وBAAI/bge-m3 لعمليات التضمين متعددة اللغات، وFastAPI لواجهة API الخلفية، وGPT-5 أو GPT-5-mini للتوليد، وPydantic للتحقق المنظم. يسترجع تنفيذ RAGTIME الموثق أفضل ١٥ مقطعًا، ثم يعيد بناء نحو ٥–٧ مستندات قبل التوليد. ونستخدم هذه القيم هنا كخط أساس قابل لإعادة الإنتاج، لا كإعدادات عامة تصلح لكل مجموعة بيانات.
يُعد هذا التصميم مفيدًا للمجموعات المتخصصة، مثل المواد البحثية والوثائق القانونية والمعرفة المؤسسية ومصادر المعلومات متعددة اللغات. ويجمع أحد الأمثلة القانونية البحثية في السياق المتحقق منه بين Qdrant وFastAPI وواجهة أمامية مبنية على React. كما يستخدم نظام موثق آخر Qdrant بوصفها مخزنًا دلاليًا طويل الأمد في مساعد يركز على الخصوصية. وتوضح هذه الأمثلة نمطًا معماريًا، لكنها لا تثبت أن كل عمليات نشر Qdrant توفر المستوى نفسه من الدقة أو زمن الاستجابة أو الخصوصية.
تتكون RAG API من أربع مراحل مفاهيمية. أولًا، تُقسَّم المستندات إلى مقاطع. ثانيًا، يحوّل نموذج التضمين هذه المقاطع إلى متجهات. ثالثًا، تبحث Qdrant عن المقاطع الأقرب إلى متجه السؤال. رابعًا، ينشئ النموذج اللغوي إجابة اعتمادًا على الأدلة المسترجعة. وينبغي التعامل مع الإجابة باعتبارها تركيبًا للسياق المحدد، لا ضمانًا تلقائيًا لصحتها.
البنية والخيارات التصميمية المتحقَّق منها
صُمم مسار الطلب ليكون مباشرًا عمدًا:
- إعداد المستندات: تُنقّى المواد المصدرية وتُقسَّم إلى مقاطع قابلة للاسترجاع.
- التضمين: يحوّل BAAI/bge-m3 المقاطع والأسئلة إلى متجهات مناسبة للبحث الدلالي متعدد اللغات.
- استرجاع المتجهات: تعيد Qdrant المقاطع الأقرب إلى متجه السؤال.
- تجميع السياق: تختار الخدمة أقوى الأدلة وتعيد بناء سياق مستندي يمكن التعامل معه.
- التوليد: يستقبل GPT-5 أو GPT-5-mini السؤال والأدلة المسترجعة.
- التحقق من المخطط: تتحقق Pydantic من استجابة API، ويمكنها فرض عقد يأخذ شكل JSON.
يختلف الاسترجاع الدلالي عن البحث التقليدي بالكلمات المفتاحية. إذ يقارن نظام البحث المتجهي التمثيلات الرقمية للمعنى، لذلك قد يتطابق السؤال مع مقطع حتى عندما لا يشتركان في الصياغة نفسها. ويكتسب ذلك أهمية خاصة في المجموعات متعددة اللغات واللغة المتخصصة. ومع ذلك، لا يثبت التشابه الدلالي أن المقطع يجيب عن السؤال. لذلك يجب تقييم جودة الاسترجاع باستخدام استعلامات ممثلة ومستندات مصدر متوقعة.
يستخدم مثال RAGTIME المتحقق منه بنية مدمجة عمدًا تتكون من Qdrant وBAAI/bge-m3 وFastAPI وGPT-5 أو GPT-5-mini وفرض مخطط JSON عبر Pydantic. ويعرض خط أنابيب ينتج تقارير JSON تستند إلى مصادر موثقة. والدرس الأهم ليس أن هذه الحزمة المحددة هي الأفضل دائمًا، بل إن وجود واجهة صغيرة وواضحة التعريف بين الاسترجاع والتوليد والتحقق قد يجعل فحص النظام أسهل من نظام معقد بلا حاجة.
الخطوة ١: جهّز مشروع Python
أنشئ مشروع Python وثبّت المكتبات المطلوبة للتنفيذ. تُعد نطاقات الإصدارات أدناه أمثلة محافظة عمدًا. اختبر الإصدارات المختارة معًا في بيئتك قبل النشر. يحدد السياق المتحقق منه أدوار FastAPI وQdrant وLangChain وBAAI/bge-m3 والتوليد من عائلة GPT-5 وPydantic، لكنه لا يحدد ملف قفل حزم أو إعداد استضافة عالميًا.
mkdir qdrant-fastapi-rag
cd qdrant-fastapi-rag
python -m venv .venv
# Linux and macOS
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install fastapi uvicorn qdrant-client sentence-transformers openai pydantic
mkdir app
ضع مستنداتك في مجلد باسم documents. استخدم مواد مخولًا بمعالجتها. ولإجراء تقييم متعدد اللغات، أدرج مستندات باللغات التي سيستخدمها جمهورك في الاستعلام. وقع الاختيار على BAAI/bge-m3 هنا لأن السياق المتحقق منه يحدده نموذجًا للتضمين في نظام RAG متعدد اللغات.
عرّف الإعدادات عبر متغيرات البيئة بدلًا من وضع بيانات الاعتماد في الملفات المصدرية:
export QDRANT_URL="http://localhost:6333"
export QDRANT_COLLECTION="multilingual_rag"
export OPENAI_API_KEY="replace-with-an-authorized-key"
export GENERATION_MODEL="gpt-5-mini"
export EMBEDDING_MODEL="BAAI/bge-m3"
لا تحدد المصادر المتحقَّق منها أسلوب استضافة Qdrant أو المنفذ أو آلية المصادقة أو طوبولوجيا النشر. استخدم إعدادات الاتصال التي تتطلبها بيئة Qdrant التي اخترتها. وأبقِ إعدادات مخزن المتجهات ومزود التوليد منفصلة، حتى يمكن تقييم كل مكون بصورة مستقلة.
الخطوة ٢: أنشئ خدمة الإدخال والاسترجاع
أنشئ الملف app/main.py. تحمّل هذه الخدمة المدمجة BAAI/bge-m3، وتنشئ مجموعة Qdrant باستخدام حجم المتجهات الخاص بالنموذج، وتفهرس الملفات النصية العادية، وتسترجع ١٥ مقطعًا لكل سؤال، وتطلب من نموذج من عائلة GPT-5 إنتاج استجابة منظمة. ويستخدم الكود أسلوب إنشاء عميل OpenAI الحديث للتوليد. يجب أن يدعم إعداد مزود التوليد النموذج المختار في بيئتك.
import os
from pathlib import Path
from typing import Anyfrom fastapi import FastAPI, HTTPException
from openai import OpenAI
from pydantic import BaseModel, Field
from qdrant_client import QdrantClient, models
from sentence_transformers import SentenceTransformerQDRANT_URL = os.environ["QDRANT_URL"]
COLLECTION = os.environ.get("QDRANT_COLLECTION", "multilingual_rag")
EMBEDDING_MODEL = os.environ.get("EMBEDDING_MODEL", "BAAI/bge-m3")
GENERATION_MODEL = os.environ.get("GENERATION_MODEL", "gpt-5-mini")qdrant = QdrantClient(url=QDRANT_URL)
embedder = SentenceTransformer(EMBEDDING_MODEL)
generator = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
app = FastAPI(title="Qdrant FastAPI RAG API")class AskRequest(BaseModel):
question: str = Field(min_length=2, max_length=4000)class Source(BaseModel):
source: str
text: str
score: floatclass AskResponse(BaseModel):
answer: str
sources: list[Source]def passages_from_file(path: Path, size: int = 1200) -> list[str]:
text = path.read_text(encoding="utf-8", errors="replace")
text = " ".join(text.split())
return [text[i:i + size] for i in range(0, len(text), size) if text[i:i + size].strip()]def ensure_collection(vector_size: int) -> None:
if qdrant.collection_exists(COLLECTION):
return
qdrant.create_collection(
collection_name=COLLECTION,
vectors_config=models.VectorParams(
size=vector_size,
...تابع القراءة
سجل دخولك مجاناً لقراءة المقال كاملاً والوصول إلى أدوات الذكاء الاصطناعي.
تسجيل الدخول / إنشاء حساب