إدخال البيانات في ChromaDB والبحث عن الجمل المتشابهة دلالياً (Semantic Search)

دقائق القراءة: 5

ما الذي يعنيه إدخال البيانات في ChromaDB ولماذا نحتاجه؟

عند بناء تطبيق يعتمد على التضمينات (Embeddings)، فإننا لا نخزن النصوص فقط بصيغتها البشرية، بل نحول كل جملة أو فقرة إلى متجه عددي Vector يعبّر عن معناها الدلالي. هنا تظهر أهمية ChromaDB كقاعدة بيانات متجهة مخصصة لتخزين هذه المتجهات وربطها بالنصوص الأصلية والبيانات الوصفية metadata.

الفكرة الهندسية ليست مجرد “حفظ بيانات”، بل إنشاء طبقة استرجاع ذكية تستطيع استقبال استعلام طبيعي مثل: “كيف أُثبت قاعدة بيانات متجهة محلياً؟” ثم تعيد أكثر الجمل أو المقاطع قرباً في المعنى، حتى لو لم تتطابق الكلمات حرفياً. هذا هو قلب قواعد البيانات المتجهة (Vector Databases)، وهو أيضاً الأساس العملي لعدد كبير من تطبيقات RAG المرتبطة بمقال مدخل إلى هندسة الذكاء الاصطناعي التوليدي: كيف تعمل نماذج اللغة الكبيرة (LLMs) برمجياً؟.

المعمارية البرمجية لتدفق البيانات داخل Semantic Search

قبل كتابة الكود، من المهم فهم خط الأنابيب Pipeline هندسياً. عند إدخال البيانات في ChromaDB تمر العملية غالباً بالمراحل التالية:

  • تجهيز الجمل أو الفقرات الخام.
  • إنشاء معرفات فريدة IDs لكل عنصر.
  • توليد Embeddings عبر نموذج مناسب.
  • تخزين النصوص والمتجهات وحقول metadata داخل collection.
  • عند وصول استعلام جديد، يتم تحويله هو أيضاً إلى embedding.
  • تنفيذ مقارنة تشابه مثل cosine similarity أو ما يعادلها داخلياً.
  • إرجاع أقرب النتائج دلالياً مع النص الأصلي ومعلوماته الوصفية.

هذه البنية مهمة جداً لاحقاً عند توصيل قاعدة البيانات مع LangChain أو عند تصميم نظام استرجاع يغذي نموذجاً لغوياً بالإجابات الموثقة.

المتطلبات العملية قبل التنفيذ

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

سنستخدم في هذا الدرس تخزيناً محلياً دائماً Persistent Client حتى تبقى البيانات محفوظة بين تشغيلات السكربت.

تنصيب المكتبات المطلوبة

pip install chromadb sentence-transformers

كتابة سكربت إدخال الجمل داخل ChromaDB

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

import chromadb
from sentence_transformers import SentenceTransformer

client = chromadb.PersistentClient(path="./chroma_storage")
collection = client.get_or_create_collection(name="ai_sentences")

model = SentenceTransformer("all-MiniLM-L6-v2")

documents = [
    "ChromaDB is an open-source vector database for AI applications.",
    "Embeddings convert text into numerical vectors that preserve semantic meaning.",
    "LangChain helps developers connect models, prompts, memory, and retrieval tools.",
    "Semantic search finds related sentences by meaning instead of exact keyword matching.",
    "Fine-tuning changes model behavior by training on specialized domain examples."
]

ids = ["doc1", "doc2", "doc3", "doc4", "doc5"]

metadatas = [
    {"topic": "chromadb", "level": "beginner"},
    {"topic": "embeddings", "level": "beginner"},
    {"topic": "langchain", "level": "intermediate"},
    {"topic": "semantic-search", "level": "intermediate"},
    {"topic": "fine-tuning", "level": "advanced"}
]

embeddings = model.encode(documents).tolist()

collection.add(
    ids=ids,
    documents=documents,
    metadatas=metadatas,
    embeddings=embeddings
)

print("Data inserted successfully.")

هنا قمنا بتوليد embeddings خارجياً باستخدام مكتبة sentence-transformers. هذه طريقة ممتازة عندما تريد التحكم الكامل في نموذج التضمين، أو عندما تبني خط معالجة خاصاً بك كما شرحنا في مقال كتابة سكربت لتحويل مقال كامل إلى Embeddings وحفظه محلياً.

كيف يعمل البحث الدلالي على مستوى التنفيذ؟

عندما يرسل المستخدم استعلاماً، لا يبحث النظام عن نفس الكلمات، بل يبحث عن أقرب تمثيل رياضي في الفضاء المتجهي Vector Space. هذا يعني أن عبارة مثل “قاعدة لتخزين المتجهات” قد تسترجع جملة تحتوي “vector database” حتى بدون تطابق لغوي حرفي.

query = "How can I store vector representations for AI search?"
query_embedding = model.encode([query]).tolist()

results = collection.query(
    query_embeddings=query_embedding,
    n_results=3
)

print(results)

المخرجات تكون عادة بنية تحتوي ids وdocuments وdistances وmetadatas. وكلما كانت المسافة أصغر أو درجة التشابه أعلى، كانت النتيجة أقرب دلالياً.

Expected output conceptually:
The system should return sentences related to ChromaDB, vector database, and semantic meaning even if the user query does not exactly match stored text.

إضافة التصفية باستخدام Metadata Filters

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

results = collection.query(
    query_embeddings=query_embedding,
    n_results=2,
    where={"level": "beginner"}
)

print(results)

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

دمج ChromaDB مع تطبيقات RAG وLangChain

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

مثال على برومبت منظم بعد الاسترجاع:

You are an AI assistant.
Answer the user only using the retrieved context below.
If the answer is not found, say you do not know.

Retrieved context:
{retrieved_chunks}

User question:
{user_question}

هذا النمط يرتبط مباشرة بممارسات هندسة الأوامر (Prompt Engineering) داخل الكود: قوالب النصوص المتغيرة (F-Strings)، ويساعد على تقليل الهلوسة ورفع دقة الإجابات.

أفضل الممارسات الهندسية عند إدخال البيانات

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

أخطاء شائعة يجب الانتباه لها

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

خلاصة هندسية

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

وهذا بالضبط ما يجعل ChromaDB مكوناً محورياً في تطبيقات Semantic Search وRAG، ويمهّد مباشرة للخطوة التالية: ربط الاسترجاع بالنموذج اللغوي لإنتاج إجابات دقيقة مبنية على معرفة مخزنة محلياً.

6 comments

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *