الخطوة 5 في RAG: تحسين الدردشة باستخدام RAG

ادمج محرك RAG في نقطة نهاية الدردشة (endpoint) في Flask حتى يجيب الذكاء الاصطناعي على الأسئلة بالاستناد إلى قاعدة معرفتك.

الخطوة 1: إضافة مسار RAG

أضف نقطة نهاية جديدة إلى backend/app/routes.py:

from .rag_engine import search_similar_chunks, build_rag_context, generate_rag_response
from .models import Document


@api.route("/rag-chat", methods=["POST"])
def rag_chat():
    data = request.get_json()
    user_message = data.get("message", "")

    if not user_message:
        return jsonify({"error": "Message is required"}), 400

    user_msg = Message(content=user_message, sender="user")
    db.session.add(user_msg)
    db.session.commit()

    try:
        results = search_similar_chunks(db, user_message, Document, top_k=5)
        context = build_rag_context(results)
        ai_reply = generate_rag_response(user_message, context)

        ai_msg = Message(content=ai_reply, sender="ai")
        db.session.add(ai_msg)
        db.session.commit()

        return jsonify({
            "user_message": user_msg.to_dict(),
            "ai_message": ai_msg.to_dict(),
            "evidence": [
                {"title": r["title"], "similarity": round(r["similarity"], 3)}
                for r in results
            ],
        })

    except Exception as e:
        return jsonify({"error": str(e)}), 500

تتضمن الاستجابة الآن حقل evidence الذي يوضّح المستندات التي استُخدمت.

الخطوة 2: إعادة تشغيل الواجهة الخلفية

أوقفه ثم أعد تشغيله بعد توصيل PostgreSQL:

docker compose -f advanced/docker-compose.rag.yml up --build

الخطوة 3: اختبار دردشة RAG

# اسأل عن الدعم التعليمي
curl -X POST http://localhost:5000/api/rag-chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Where can I get tutoring at Clark?"}'

الاستجابة المتوقعة:

{
  "user_message": {"content": "Where can I get tutoring at Clark?", ...},
  "ai_message": {
    "content": "Clark College offers free tutoring in business, English, math, science, and general education classes. You can also access online eTutoring through e-Chat or e-Questions."
  },
  "evidence": [
    {"title": "Tutoring Services at Clark College", "similarity": 0.843},
    {"title": "Tech Hub at Clark College", "similarity": 0.512},
    {"title": "Libraries at Clark College", "similarity": 0.487}
  ]
}

جرّب مزيدًا من الأسئلة:

# اسأل عن المساعدة المالية
curl -X POST http://localhost:5000/api/rag-chat \
  -H "Content-Type: application/json" \
  -d '{"message": "How can I get help paying for college?"}'

# اسأل عن الأخبار
curl -X POST http://localhost:5000/api/rag-chat \
  -H "Content-Type: application/json" \
  -d '{"message": "What happened at the CTE Showcase?"}'

# اسأل عن الفعاليات
curl -X POST http://localhost:5000/api/rag-chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Tell me about the Sakura Festival"}'

الخطوة 4: المقارنة بين وجود RAG وغيابه

بدون RAG (المسار الأصلي /api/chat):

curl -X POST http://localhost:5000/api/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "What tutoring is available at Clark?"}'
# → إجابة عامة: "Most colleges offer tutoring services..."

مع RAG (/api/rag-chat):

curl -X POST http://localhost:5000/api/rag-chat \
  -H "Content-Type: application/json" \
  -d '{"message": "What tutoring is available at Clark?"}'
# → إجابة محددة: "Clark College offers free tutoring in business, English..."

تقدم نسخة RAG إجابة دقيقة ومحددة لأنها عثرت على مستند الدعم التعليمي.

الخطوة 5: كيف يعمل كل شيء من البداية إلى النهاية

المستخدم: "What tutoring is available at Clark?"

1. تضمين السؤال
   "What tutoring is available at Clark?"
   → [0.04, -0.13, 0.29, ...]                 (متجه بأبعاد 384)

2. البحث في pgvector
   SELECT * FROM document
   ORDER BY embedding <=> :query_vec
   LIMIT 5

3. عُثر على أفضل 3 مقاطع متشابهة:
   [0.84] "Tutoring Services at Clark College"
   [0.51] "Tech Hub at Clark College"
   [0.49] "Libraries at Clark College"

4. حقن النتائج في الموجّه (prompt):
   النظام: "Use this context to answer:\n\n
            [Tutoring Services at Clark College]
            Clark College offers free tutoring..."

5. يولّد النموذج اللغوي الكبير (LLM) إجابة باستخدام السياق
   "Clark College offers free tutoring in business, English..."

6. إعادة الإجابة إلى المستخدم مع تضمين الأدلة (evidence)

اكتب اختبارات لخط أنابيب RAG

اختبر التدفق الكامل — التضمين والبحث وتوليد الاستجابة:

from app import create_app, db
from app.models import Document
from advanced.rag.rag_engine import search_similar_chunks, build_rag_context

app = create_app()
with app.app_context():
    results = search_similar_chunks(db, "free tutoring", Document, top_k=3)
    assert len(results) == 3
    assert results[0]["similarity"] > 0.5
    print(f"Top result: {results[0]['title']} (similarity: {results[0]['similarity']:.3f})")

ما الذي تغطيه هذه الاختبارات

الاختبار ما يتحقق منه
test_embed_text_returns_384_dimensions ينتج نموذج التضمين حجم متجه صحيحًا
test_embed_text_consistent_output المدخل نفسه → المتجه نفسه (حتمي)
test_chunk_text_creates_chunks يُقسَّم النص الطويل بشكل صحيح
test_chunk_text_short_text يبقى النص القصير مقطعًا واحدًا
test_get_all_chunks_returns_list تُحوَّل المستندات إلى مقاطع بشكل صحيح
test_build_rag_context_formats_correctly تُنسَّق سلسلة السياق من أجل النموذج اللغوي

اختبر عملك (يدويًا)

اكتب اختبارًا للتحقق من عمل خط أنابيب RAG:

from app import create_app, db
from app.models import Document
from advanced.rag.rag_engine import search_similar_chunks, build_rag_context

app = create_app()
with app.app_context():
    results = search_similar_chunks(db, "free tutoring", Document, top_k=3)
    assert len(results) == 3
    assert results[0]["similarity"] > 0.5
    print(f"Top result: {results[0]['title']} (similarity: {results[0]['similarity']:.3f})")