PRODمنصة BaaS الأوروبية السياديةافتح لوحة المعلومات →

الذكاء الاصطناعي الأصلي · 10 دقيقة للقراءة

البرنامج التعليمي: خط أنابيب RAG مع Postgres وpgvector

Affane Daylami · Fondateur · 13 أبريل 2026

العودة إلى بلوق

يتطلب إنشاء مسار RAG على Postgres عمومًا تجميع عدة أجزاء بنفسك: أداة تقطيع النص، واستدعاء التضمينات، وجدول pgvector، واستعلام التشابه. هذه هي سلسلة LangChain + PGVectorchain الكلاسيكية. في Aurabase، يوجد خط الأنابيب هذا بالفعل على جانب الخادم: يتم استبداله باستدعاءين، ragIngest() و rag()، مع الاعتماد على PostgreSQL وpgvector القياسيين، بدون قاعدة متجهات خاصة لإضافتها.

تم إنشاء هذا النص الإنجليزي تلقائيًا من النص الأصلي الفرنسي ولم تتم مراجعته بعد.
تمت ترجمة هذه الصفحة تلقائيًا. النسخة الإنجليزية موثوقة.

تعد RAG الأصلية جزءًا من الذكاء الاصطناعي الأصليالمدمج في الواجهة الخلفية Aurabase، إلى جانب NL2SQL: ليست خدمة تابعة لجهة خارجية يتم تجميعها فوق قاعدة عامة. المتطلبات الأساسية لمتابعة هذا البرنامج التعليمي: مشروع Aurabase موجود، وموفر LLM تم تكوينه (OpenAI أو Google Gemini للتضمين، أحد الموفرين الأصليين الثلاثة للإنشاء)، ومفتاح واجهة برمجة تطبيقات المشروع.

الأساسيات
  • يتكون خط أنابيب Aurabase RAG من مكالمتين: ragIngest() لفهرسة مستند، وrag() للاستعلام وإنشاء استجابة. تتم إدارة التقطيع والتضمين والبحث عن المتجهات من جانب الخادم.
  • تحت الغطاء، يوجد PostgreSQL وpgvector القياسيان: جدول embeddings بعمود متجه واحد لكل فئة أبعاد (768، 1536، 3072) وفهرس HNSW جزئي لكل فئة.
  • يستخدم التجميع أداة رمزية حقيقية (tiktoken o200k)، مع تداخل قابل للتكوين وواقي مضاد للانفجار على المستندات الكبيرة.
  • يتم تحييد المحتوى المسترد قبل إدخاله في الموجه: يتم إبطال مفعول المستند الذي يحاول الهروب من علامته لانتحال تعليمات النظام بشكل صريح.
  • يقوم OpenAI وGemini فقط بإنشاء التضمينات على جانب Aurabase. ليس لدى Anthropic/Claude واجهة برمجة تطبيقات عامة للتضمين، فهي تظل مخصصة لإنشاء الاستجابة النهائية.
#
مفهوم

كيف يعمل خط أنابيب RAG هذا

يتم تنفيذ خط الأنابيب على خمس مراحل. عند الاستيعاب، يتم تقطيع النص، ويتم نقل كل جزء دفعة واحدة ثم تخزينه. عند الاستعلام، يتم توجيه السؤال بدوره، مقارنة بالقطع المخزنة بواسطة تشابه جيب التمام، ويتم إدخال المقتطفات الأقرب في الموجه المرسل إلى نموذج التوليد.

التقطيع (tiktoken) ← التضمين (دفعة) ← تخزين pgvector (HNSW) ← بحث التشابه ← الجيل المعزز

تفاصيل معمارية مهمة في الإنتاج: لا يتم تعليق اتصال Postgres أثناء مكالمات الشبكة إلى موفر التضمين أو الإنشاء. يتم إغلاق معاملة قاعدة البيانات قبل المكالمة الخارجية وإعادة فتحها بعد ذلك، لعدم حظر واجهة PgBouncer الخلفية المشتركة مطلقًا لزمن انتقال شبكة الطرف الثالث.

#
الخطوة 1

إنشاء المشروع

على عكس pgvector النموذجي المستضاف ذاتيًا، لا تحتاج إلى تشغيل CREATE EXTENSION vector أو إنشاء جدول بنفسك لخط الأنابيب هذا. يتم توفير مخطط embeddings الخاص بالمشروع، مع أعمدته المتجهة وفهارس HNSW، تلقائيًا عند إنشاء المشروع.

terminalbash
# حساب Aurabase + CLI
npm i -g @aurabase/cli
aura login

# قم بإنشاء المشروع وربطه بهذا المجلد
aura projects create mon-assistant --engine postgres
aura link --project-id <uuid-du-projet>

# استرجع مفاتيح API للمشروع المرتبط
aura projects api-keys

يتم تكوين موفر التضمين مرة واحدة، على جانب المشروع (Studio → IA → الموردون). هذا المزود هو الذي يحدد البعد الفعال للمتجهات الخاصة بك، وبالتالي العمود المستخدم في الجدول embeddings.

#
الخطوة 2

قم بفهرسة مستنداتك باستخدام ragIngest()

استدعاء واحد يكفي لفهرسة مستند: يتم تقسيم النص إلى أجزاء، ويتم توجيه كل قطعة، ثم يتم تخزينها في مساحة الاسم المطلوبة. يستخدم التقسيم أداة رمزية حقيقية (tiktoken، ترميز o200k_base)، وليس تقسيمًا بسيطًا بمسافات، والذي يظل صحيحًا على النص بدون مسافات مثل بعض اللغات الآسيوية.

app/api/ingest/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { content, metadata } = await req.json()

  const { data, error } = await aura.ai.ragIngest({
    namespace: 'docs-produit',
    content,
    metadata,
  })

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data) // {معرف، قطع}
}

في HTTP الخام، المسار المكافئ هو POST /v1/ai/{project_id}/rag/ingest، تمت مصادقته بواسطة مفتاح API الخاص بالمشروع.

terminalbash
curl -X POST https://<votre-gateway>/v1/ai/<project_id>/rag/ingest \
  -H "apikey: <votre-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "namespace": "docs-produit",
    "content": "Le texte complet de votre document ici...",
    "metadata": { "source": "guide-utilisateur.pdf" }
  }'

يكون العرض غير فعال افتراضيًا: يتم اشتقاق معرف المستند تلقائيًا (تجزئة SHA-256 للمحتوى، أو metadata.document_id إذا قدمته). تؤدي إعادة إدخال نفس المحتوى إلى استبدال أجزاءه الموجودة بدلاً من تكرارها، مما يجعل مهمة المزامنة الدورية آمنة لإعادة التشغيل.

#
الخطوة 3

ما يهبط بالفعل في Postgres

لا يوجد سحر خاص هنا: الجدول الذي يستقبل المتجهات الخاصة بك هو جدول Postgres عادي، مع عمود vector واحد لكل فئة البعد وفهرس HNSW جزئي لكل عمود (نشط فقط في الصفوف التي تملأه). وهذا هو تعريفها الحقيقي بشكل مبسط:

مخطط منصة المشروع (مبسط)sql
create table embeddings (
  id               uuid primary key default gen_random_uuid(),
  project_id       text not null,
  namespace        text not null,
  content          text not null,
  embedding_768    vector(768),
  embedding_1536   vector(1536),
  embedding_3072   vector(3072),
  embedding_model  text,
  dims             int,
  metadata         jsonb default '{}'::jsonb,
  created_at       timestamptz not null default now()
);

-- مؤشر HNSW جزئي حسب فئة البعد
create index idx_embeddings_vec_1536 on embeddings
  using hnsw (embedding_1536 vector_cosine_ops)
  where embedding_1536 is not null;

-- بعد أبعاد 2000، لا تدعم HNSW نوع المتجه:
-- يلقي في halfvec للفئة 3072
create index idx_embeddings_vec_3072 on embeddings
  using hnsw ((embedding_3072::halfvec(3072)) halfvec_cosine_ops)
  where embedding_3072 is not null;

يقارن كل بحث المتجهات مع عامل مسافة جيب التمام (<=>)، الذي يستهدفه فئتا عاملي الفهرس vector_cosine_ops و halfvec_cosine_ops. للحصول على تفاصيل حول مقايضات الاستدعاء/زمن الاستجابة لـ HNSW مقابل IVFFlat، راجع المقالة المخصصة لفهرسة HNSW. لاختيار بُعد التضمين نفسه، راجع المقارنة 768 مقابل 1536 مقابل 3072.

#
الخطوة 4

الاستعلام وإنشاء الاستجابة باستخدام rag()

على جانب الاستعلام، يقوم rag() بربط توجيه السؤال، والبحث عن طريق التشابه في مساحة الاسم، وإنشاء الموجه المعزز واستدعاء نموذج الإنشاء، في رحلة ذهابًا وإيابًا على شبكة واحدة من جانب العميل.

app/api/ask/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { question } = await req.json()

  const { data, error } = await aura.ai.rag({
    question,
    namespace: 'docs-produit',
  })

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data)
}

يحمل الرد الرد الناتج ومصادره، مع استخدام الموفر فعليًا:

الرد (مقتطف)json
{
  "data": {
    "answer": "D'après la documentation, ...",
    "sources": [
      { "id": "...", "content": "...", "similarity": 0.87 }
    ],
    "model": "claude-3-5-sonnet",
    "tokens": 412,
    "provider": "anthropic",
    "fallback_used": false
  }
}

لا يتم أبدًا إدخال المحتوى المسترد بشكل خام في موجه النظام. هذه بيانات غير موثوقة (تحميل المستخدم، صفحة مفهرسة): يتم تحييد المستند الذي يحتوي، على سبيل المثال، على علامة قسم إغلاق متبوعة بتعليمات خاطئة قبل التجميع، واستبدال أقواس الزوايا بأقواس، ويتم الحفاظ على النص ولكن يتم إبطال مفعول البنية.

Corpus مفهرسة تحت نموذج آخر

إذا لم يجد rag() شيئًا على الرغم من أن مساحة الاسم الخاصة بك ليست فارغة، فإن الاستجابة تحمل تحذيرًا صريحًا بدلاً من الصمت المضلل: من المحتمل أن تتم فهرسة مجموعتك ضمن نموذج آخر أو بُعد تضمين آخر. أعد فهرسته عبر POST /v1/ai/{project_id}/rag/{namespace}/reindex.

#
مقارنة

من LangChain وpgvector المصنوع يدويًا: ما الذي يتغير؟

إذا كنت قد أنشأت بالفعل روبوت دردشة RAG على PostgreSQL باستخدام LangChain، فإن كل قالب يدوي له مكافئ مُدار من جانب الخادم هنا، دون تغيير قاعدة البيانات الأساسية.

تفكيك النصRecursiveCharacterTextSplitter لتعيين نفسكragIngest (): تقسيم tiktoken المتكامل، 512 رمزًا / 64 رمزًا متداخلًا بشكل افتراضي
التضمينالاتصال اليدوي بـ OpenAIEmbeddings، وإدارة حدود الدفعةإعادة المحاولة المؤقتة المجمعة تلقائيًا
تخزين المتجهاتجدول pgvector + فهرس HNSW لإنشاء وترحيل نفسكالمخطط والفهارس المقدمة لكل مشروع
بحث + موجهPGVector.similarity_search() ثم تجميع الموجه يدويًاrag(): البحث والتوليد المعزز في مكالمة واحدة
المحتوى المستردحقن كما هو الحال في الموجهالتحييد التلقائي لعلامات الهيكل قبل التجميع

هل تقوم بترحيل مشروع موجود مبني على Supabase باستخدام هذا النوع من التجميع اليدوي؟ يتم تغطية منطق الترحيل لبقية الواجهة الخلفية (المخطط، وسياسات RLS، وSDK) في دليل الترحيل Supabase إلى Aurabase.

#
الإنتاج

الإعدادات والحدود التي يجب أن تكون على دراية بها قبل الدخول في الإنتاج

تؤثر ثلاثة إعدادات بشكل مباشر على التكلفة ووقت الاستجابة، ويتم التحقق منها جميعًا في رمز الخدمة aura-ai. عدد المحاولات لاستدعاء التضمين العابر (فشل الشبكة، خطأ الموفر 429) هو 3 بشكل افتراضي، مع تراجع أساسي قدره 100 مللي ثانية. يتم تضمين المستندات الكبيرة في دفعات فرعية تقتصر على 2048 قطعة بشكل افتراضي، وذلك لاحترام الحدود القصوى لواجهة برمجة التطبيقات الخاصة بالموردين دون الفشل في مستند واحد ضخم. يرفض حاجز الحماية (10000 قطعة بشكل افتراضي، قابل للتكوين) بشكل صريح استيعاب مستند من شأنه أن ينتج عددًا شاذًا من القطع.

على جانب البحث، يتم ضبط حجم قائمة مرشحي HNSW تلقائيًا إلى max(64, top_k × 4): كلما زاد عدد النتائج التي تطلبها، زاد عدد المرشحين الذين يستكشفهم الفهرس للحفاظ على الاستدعاء. تظل القيمة الثابتة ممكنة عبر متغير البيئة إذا كان لدى مجموعتك ملف تعريف معين.

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

#
الصدق

الحدود الحالية التي يجب أن تكون على علم بها

يجب أن يقع بُعد التضمين ضمن إحدى الفئات الثلاث المدعومة: 768، أو 1536، أو 3072. يتم رفض الموفر الذي يقوم بإرجاع بُعد آخر بسبب وجود خطأ صريح، ولا يتم اقتطاعه مطلقًا أو إرساله بصمت.

لا يتوفر إنشاء التضمين إلا عبر OpenAI أو Google Gemini من بين الموفرين الأصليين الثلاثة: لا يعرض Anthropic/Claude واجهة برمجة تطبيقات التضمين العامة، لذلك يتم استخدامه فقط لإنشاء الاستجابة النهائية في مسار التدفق هذا، وليس للتوجيه أبدًا.

لم تكشف JavaScript SDK حتى الآن عن تجاوزات top_k وthreshold عند استدعاء rag(): تظل قابلة للوصول في HTTP المباشر، وتقتصر على التوالي على [1، 50] و[0، 1]، ولكن ليس من aura.ai.rag() كما هو الحال اليوم. عتبة التشابه الافتراضية (0.3) مسموح بها بشكل متعمد؛ قم بتضييق نطاقها إلى مجموعة كثيفة لتجنب المصادر غير ذات الصلة في الموجه.

#
اذهب أبعد من ذلك

للذهاب أبعد من ذلك

يغطي RAG الأسئلة المتعلقة بالمحتوى غير المنظم (المستندات والملاحظات والتذاكر). بالنسبة للأسئلة حول بياناتك العلائقية، يقوم NL2SQL الأصلي لـ Aurabase بترجمة السؤال مباشرة إلى SQL تم التحقق من صحته. للحصول على تفاصيل حول معلمات HNSW وفئات الأبعاد المذكورة أعلاه، راجع المقالة حول فهرسة HNSW و مقارنة أبعاد التضمين. يظل مرجع واجهة برمجة التطبيقات (API) الكامل هو وثائق RAG & pgvector ووثائق بوابة AI.

#
الأسئلة المتداولة

الأسئلة الشائعة

هل يتعين عليك إدارة امتداد pgvector وفهرس HNSW بنفسك؟+
لا. يتم توفير مخطط التضمين وامتداد pgvector وفهارس HNSW الجزئية (واحد لكل فئة بُعد: 768، 1536، 3072) تلقائيًا عند إنشاء المشروع. يمكنك الاتصال مباشرة بـ ragIngest() ثم rag(); يظل الضبط الدقيق للفهرس (ef_search، ووضع iterative_scan) متاحًا من جانب الخادم إذا كان مجموعتك تحتوي على ملف تعريف معين.
ما هو بُعد التضمين الذي يجب أن أختاره لحالة الاستخدام الخاصة بي؟+
تتحقق Aurabase من صحة البعد الذي أعاده المورد الخاص بك مقابل ثلاث فئات مدعومة: 768، و1536، و3072. ويعتمد الاختيار على نموذج التضمين الذي تم تكوينه (على سبيل المثال، ينتج تضمين النص -3-small في OpenAI 1536 بُعدًا) وينطوي على حل وسط بين الاستدعاء والتكلفة وحجم التخزين المفصل في مقارنتنا المخصصة لتضمين الأبعاد.

هل أنت جاهز للنشر؟

الواجهة الخلفية الخاصة بك في خمس دقائق.

لا حاجة لبطاقة ائتمان · 500 ميجابايت مجانًا · 50000 MAU