إطار عمل Guardrails AI

التحقق من صحة مخططات Pydantic

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

يستفيد Guardrails AI من Pydantic لتعريفات المخططات الآمنة من حيث النوع. يغطي هذا الدرس بناء مخططات معقدة مع كائنات متداخلة ومدققات مخصصة وأنماط الإنتاج.

أنماط المخططات الأساسية

الحقول البسيطة

from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime

class SimpleResponse(BaseModel):
    """مخطط أساسي مع حقول مكتوبة."""

    title: str = Field(
        description="عنوان الاستجابة",
        min_length=1,
        max_length=100
    )

    content: str = Field(
        description="محتوى الاستجابة الرئيسي"
    )

    confidence: float = Field(
        description="درجة الثقة",
        ge=0.0,
        le=1.0
    )

    category: Optional[str] = Field(
        default=None,
        description="فئة اختيارية"
    )

    tags: List[str] = Field(
        default_factory=list,
        description="قائمة العلامات ذات الصلة"
    )

الكائنات المتداخلة

from pydantic import BaseModel, Field
from typing import List, Optional
from enum import Enum

class Priority(str, Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"

class ActionItem(BaseModel):
    """عنصر إجراء متداخل."""
    description: str = Field(description="ما يجب فعله")
    assignee: Optional[str] = Field(default=None)
    due_date: Optional[str] = Field(default=None)
    priority: Priority = Field(default=Priority.MEDIUM)

class MeetingNotes(BaseModel):
    """مخطط معقد مع كائنات متداخلة."""
    title: str = Field(description="عنوان الاجتماع")
    date: str = Field(description="تاريخ الاجتماع (YYYY-MM-DD)")
    attendees: List[str] = Field(description="قائمة أسماء الحضور")
    summary: str = Field(description="ملخص موجز للاجتماع")
    action_items: List[ActionItem] = Field(
        description="عناصر الإجراء من الاجتماع"
    )
    next_meeting: Optional[str] = Field(
        default=None,
        description="تاريخ الاجتماع التالي إذا كان مجدولاً"
    )

مدققات Pydantic المخصصة

from pydantic import BaseModel, Field, field_validator, model_validator
from typing import List
import re

class CustomerTicket(BaseModel):
    ticket_id: str = Field(description="معرف التذكرة بتنسيق TKT-XXXXXX")
    customer_email: str = Field(description="البريد الإلكتروني للعميل")
    issue_type: str = Field(description="نوع المشكلة")
    description: str = Field(description="وصف المشكلة")
    suggested_resolution: str = Field(description="الحل المقترح")

    @field_validator("ticket_id")
    @classmethod
    def validate_ticket_id(cls, v: str) -> str:
        """التأكد من أن معرف التذكرة يطابق التنسيق المتوقع."""
        if not re.match(r"^TKT-\d{6}$", v):
            raise ValueError("معرف التذكرة يجب أن يكون بتنسيق TKT-XXXXXX")
        return v

    @field_validator("customer_email")
    @classmethod
    def validate_email(cls, v: str) -> str:
        """التحقق الأساسي من البريد الإلكتروني."""
        if "@" not in v or "." not in v.split("@")[-1]:
            raise ValueError("تنسيق بريد إلكتروني غير صالح")
        return v.lower()

    @field_validator("issue_type")
    @classmethod
    def validate_issue_type(cls, v: str) -> str:
        """التأكد من أن نوع المشكلة من القائمة المسموح بها."""
        allowed = ["billing", "technical", "account", "general"]
        if v.lower() not in allowed:
            raise ValueError(f"نوع المشكلة يجب أن يكون أحد: {allowed}")
        return v.lower()

    @model_validator(mode="after")
    def validate_resolution_length(self) -> "CustomerTicket":
        """التأكد من أن الحل أطول من الوصف."""
        if len(self.suggested_resolution) < len(self.description) // 2:
            raise ValueError("يجب أن يكون الحل مفصلاً بما يكفي")
        return self

مدققات Guardrails Hub

from guardrails import Guard
from guardrails.hub import (
    ValidLength,
    RegexMatch,
    ValidChoices,
    ToxicLanguage,
    ReadingLevel,
    SimilarToDocument
)
from pydantic import BaseModel, Field

class SupportResponse(BaseModel):
    """مخطط مع مدققات Hub."""

    greeting: str = Field(
        description="تحية مهنية",
        json_schema_extra={
            "validators": [
                ValidLength(min=10, max=50, on_fail="fix"),
                ToxicLanguage(threshold=0.3, on_fail="exception")
            ]
        }
    )

    response: str = Field(
        description="الرد الرئيسي للعميل",
        json_schema_extra={
            "validators": [
                ValidLength(min=50, max=500, on_fail="reask"),
                ReadingLevel(level="8th grade", on_fail="fix"),
                ToxicLanguage(threshold=0.1, on_fail="exception")
            ]
        }
    )

    tone: str = Field(
        description="نبرة الرد",
        json_schema_extra={
            "validators": [
                ValidChoices(
                    choices=["professional", "friendly", "empathetic"],
                    on_fail="fix"
                )
            ]
        }
    )

    reference_number: str = Field(
        description="رقم مرجع الدعم",
        json_schema_extra={
            "validators": [
                RegexMatch(regex=r"^REF-[A-Z]{3}-\d{4}$", on_fail="fix")
            ]
        }
    )

المخططات المتداخلة المعقدة

from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from enum import Enum

class Severity(str, Enum):
    INFO = "info"
    WARNING = "warning"
    ERROR = "error"
    CRITICAL = "critical"

class Finding(BaseModel):
    """نتيجة تحليل فردية."""
    title: str = Field(description="عنوان النتيجة")
    severity: Severity = Field(description="مستوى الخطورة")
    description: str = Field(description="وصف مفصل")
    recommendation: str = Field(description="الإجراء الموصى به")
    affected_areas: List[str] = Field(description="المناطق المتأثرة")

class RiskAssessment(BaseModel):
    """درجة المخاطر والعوامل."""
    overall_score: float = Field(ge=0, le=10, description="درجة المخاطر 0-10")
    factors: Dict[str, float] = Field(description="عوامل المخاطر الفردية")
    mitigation_priority: str = Field(description="مستوى الأولوية")

class AnalysisReport(BaseModel):
    """مخطط تقرير التحليل الكامل."""

    report_id: str = Field(description="معرف التقرير الفريد")
    timestamp: str = Field(description="الطابع الزمني ISO")
    subject: str = Field(description="ما تم تحليله")

    executive_summary: str = Field(
        description="ملخص موجز للمسؤولين التنفيذيين",
        json_schema_extra={
            "validators": [ValidLength(min=100, max=300)]
        }
    )

    findings: List[Finding] = Field(
        description="قائمة النتائج",
        min_length=1
    )

    risk_assessment: RiskAssessment = Field(
        description="تقييم المخاطر العام"
    )

    recommendations: List[str] = Field(
        description="التوصيات ذات الأولوية",
        min_length=1,
        max_length=10
    )

    metadata: Optional[Dict[str, Any]] = Field(
        default=None,
        description="بيانات وصفية إضافية"
    )

توليد المخطط الديناميكي

from pydantic import BaseModel, Field, create_model
from typing import Any, Dict, Type

def create_extraction_schema(
    fields: Dict[str, Dict[str, Any]]
) -> Type[BaseModel]:
    """
    إنشاء مخطط Pydantic ديناميكياً من تعريفات الحقول.

    تنسيق الحقول:
    {
        "field_name": {
            "type": str | int | float | bool,
            "description": "وصف الحقل",
            "required": True | False,
            "validators": [...]  # اختياري
        }
    }
    """
    field_definitions = {}

    for name, config in fields.items():
        field_type = config["type"]
        description = config.get("description", "")
        required = config.get("required", True)
        validators = config.get("validators", [])

        if required:
            field_definitions[name] = (
                field_type,
                Field(
                    description=description,
                    json_schema_extra={"validators": validators} if validators else None
                )
            )
        else:
            field_definitions[name] = (
                field_type | None,
                Field(
                    default=None,
                    description=description,
                    json_schema_extra={"validators": validators} if validators else None
                )
            )

    return create_model("DynamicExtraction", **field_definitions)

# الاستخدام
schema = create_extraction_schema({
    "company_name": {
        "type": str,
        "description": "اسم الشركة",
        "required": True
    },
    "revenue": {
        "type": float,
        "description": "الإيرادات السنوية بالملايين",
        "required": False
    },
    "industry": {
        "type": str,
        "description": "فئة الصناعة",
        "required": True
    }
})

guard = Guard.for_pydantic(schema)

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

from pydantic import BaseModel, Field
from typing import Union

class EmailResponse(BaseModel):
    """استجابة خاصة بالبريد الإلكتروني."""
    subject: str = Field(description="سطر موضوع البريد الإلكتروني")
    body: str = Field(description="نص البريد الإلكتروني")
    sign_off: str = Field(description="توقيع البريد الإلكتروني")

class ChatResponse(BaseModel):
    """استجابة خاصة بالدردشة."""
    message: str = Field(description="رسالة الدردشة")
    suggested_actions: List[str] = Field(description="خيارات الرد السريع")

class TicketResponse(BaseModel):
    """استجابة خاصة بالتذكرة."""
    ticket_update: str = Field(description="تحديث حالة التذكرة")
    internal_notes: str = Field(description="ملاحظات داخلية")
    customer_message: str = Field(description="رسالة للعميل")

class UnifiedResponse(BaseModel):
    """استجابة موحدة تدعم قنوات متعددة."""
    channel: str = Field(description="قناة الاستجابة: email أو chat أو ticket")
    response: Union[EmailResponse, ChatResponse, TicketResponse] = Field(
        description="استجابة خاصة بالقناة"
    )
    confidence: float = Field(ge=0, le=1, description="ثقة الاستجابة")

نصيحة تصميم المخطط: حافظ على المخططات مركزة وقابلة للتركيب. استخدم الوراثة والتركيب لبناء هياكل معقدة من مكونات بسيطة ومختبرة.

التالي: استكشاف مدققات Guardrails Hub لحالات الاستخدام الشائعة. :::

اختبار

الوحدة 5: إطار عمل Guardrails AI

خذ الاختبار
نشرة أسبوعية مجانية

ابقَ على مسار النيرد

بريد واحد أسبوعياً — دورات، مقالات معمّقة، أدوات، وتجارب ذكاء اصطناعي.

بدون إزعاج. إلغاء الاشتراك في أي وقت.