الدرس 6 من 23
هندسة تطبيقات LLM

إدارة المطالبات

4 دقيقة للقراءة

المطالبات هي "الكود" لأنظمة الذكاء الاصطناعي. إدارتها بشكل صحيح مهم بقدر إدارة الكود المصدري. يغطي هذا الدرس إدارة المطالبات بمستوى الإنتاج.

لماذا إدارة المطالبات مهمة

المشكلةالتأثير
المطالبات مشفرة في الكودصعب التحديث بدون نشر
لا يوجد سجل إصداراتلا يمكن التراجع عن التغييرات السيئة
لا يوجد اختبار A/Bلا يمكن تحسين الأداء
تنسيقات غير متسقةسلوكيات مختلفة عبر الميزات

نظام قوالب المطالبات

from jinja2 import Template

class PromptTemplate:
    def __init__(self, template_str: str, version: str):
        self.template = Template(template_str)
        self.version = version
        self.variables = self._extract_variables()

    def render(self, **kwargs) -> str:
        # التحقق من توفر جميع المتغيرات المطلوبة
        missing = set(self.variables) - set(kwargs.keys())
        if missing:
            raise ValueError(f"متغيرات مفقودة: {missing}")
        return self.template.render(**kwargs)

    def _extract_variables(self) -> set:
        # استخراج أنماط {{ variable }}
        import re
        return set(re.findall(r'\{\{\s*(\w+)\s*\}\}', self.template.source))

# الاستخدام
qa_prompt = PromptTemplate(
    template_str="""
أنت مساعد مفيد. أجب على السؤال بناءً على السياق.

السياق:
{{ context }}

السؤال: {{ question }}

الإجابة:""",
    version="1.2.0"
)

rendered = qa_prompt.render(
    context="بايثون أنشأها جويدو فان روسوم.",
    question="من أنشأ بايثون؟"
)

سجل المطالبات

تخزين مركزي لجميع المطالبات:

class PromptRegistry:
    def __init__(self, storage_backend):
        self.storage = storage_backend
        self.cache = {}

    async def get(self, name: str, version: str = "latest") -> PromptTemplate:
        cache_key = f"{name}:{version}"
        if cache_key in self.cache:
            return self.cache[cache_key]

        prompt_data = await self.storage.fetch(name, version)
        template = PromptTemplate(
            template_str=prompt_data["template"],
            version=prompt_data["version"]
        )
        self.cache[cache_key] = template
        return template

    async def save(self, name: str, template: str, metadata: dict):
        version = self._generate_version()
        await self.storage.save(name, {
            "template": template,
            "version": version,
            "metadata": metadata,
            "created_at": datetime.utcnow()
        })

# التهيئة مع قاعدة البيانات
registry = PromptRegistry(PostgresStorage())

التحكم بالإصدار للمطالبات

# prompts/qa_assistant.yaml
name: qa_assistant
versions:
  - version: "1.0.0"
    date: "2024-01-15"
    template: |
      أجب على السؤال: {{ question }}
    notes: "الإصدار الأولي"

  - version: "1.1.0"
    date: "2024-02-01"
    template: |
      أنت مساعد مفيد.
      أجب على السؤال: {{ question }}
    notes: "إضافة سياق النظام"

  - version: "1.2.0"
    date: "2024-03-10"
    template: |
      أنت مساعد مفيد. أجب بناءً على السياق المقدم.
      السياق: {{ context }}
      السؤال: {{ question }}
    notes: "إضافة دعم سياق RAG"

active_version: "1.2.0"
rollback_version: "1.1.0"

اختبار A/B للمطالبات

import random

class PromptExperiment:
    def __init__(self, name: str, variants: dict):
        self.name = name
        self.variants = variants  # {"control": 50, "variant_a": 50}

    def select_variant(self, user_id: str) -> str:
        # اختيار حتمي بناءً على user_id
        hash_val = hash(f"{self.name}:{user_id}") % 100

        cumulative = 0
        for variant, percentage in self.variants.items():
            cumulative += percentage
            if hash_val < cumulative:
                return variant
        return list(self.variants.keys())[0]

# الاستخدام
experiment = PromptExperiment(
    name="system_prompt_test",
    variants={
        "control": 50,      # المطالبة الحالية
        "concise": 25,      # مطالبة أقصر
        "detailed": 25      # مطالبة أكثر تفصيلاً
    }
)

variant = experiment.select_variant(user_id="user_123")
prompt = registry.get(f"qa_assistant_{variant}")

تركيب المطالبات

بناء مطالبات معقدة من مكونات قابلة لإعادة الاستخدام:

class PromptComposer:
    def __init__(self, registry: PromptRegistry):
        self.registry = registry

    async def compose(self, components: list, variables: dict) -> str:
        """تركيب مطالبة من مكونات متعددة."""
        parts = []
        for component in components:
            template = await self.registry.get(component)
            # تضمين المتغيرات ذات الصلة بهذا المكون فقط
            relevant_vars = {
                k: v for k, v in variables.items()
                if k in template.variables
            }
            parts.append(template.render(**relevant_vars))
        return "\n\n".join(parts)

# الاستخدام
composer = PromptComposer(registry)
full_prompt = await composer.compose(
    components=["system_context", "user_history", "current_query"],
    variables={
        "role": "assistant",
        "history": previous_messages,
        "query": user_input
    }
)

أفضل الممارسات

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

بعد ذلك، سنستكشف استراتيجيات التخزين المؤقت لتقليل التكاليف وزمن الاستجابة. :::

مراجعة سريعة: كيف تجد هذا الدرس؟

اختبار

الوحدة 2: هندسة تطبيقات LLM

خذ الاختبار