تعمق في مصنفات السلامة

نشر ShieldGemma

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

ShieldGemma هي عائلة مصنفات السلامة من Google المبنية على Gemma 2، تقدم أداءً تنافسياً مع LlamaGuard مع توفير مقايضات مختلفة من حيث الحجم والقدرات.

عائلة نماذج ShieldGemma

النموذجالمعاملاتالتأخير (GPU)درجة المعيارالأفضل لـ
ShieldGemma 2B2B30-60 مللي ثانية0.814الحافة/الجوال
ShieldGemma 9B9B80-150 مللي ثانية0.843متوازن
ShieldGemma 27B27B200-400 مللي ثانية0.876أقصى دقة

ملاحظة المعيار: يحقق ShieldGemma 27B تحسناً بنسبة +10.8% على LlamaGuard 2 في معايير تصنيف السلامة (Google، 2024).

فئات السلامة

يصنف ShieldGemma المحتوى إلى أربع فئات ضرر رئيسية:

SHIELDGEMMA_CATEGORIES = {
    "dangerous_content": "محتوى يروج لأنشطة خطيرة",
    "harassment": "التنمر أو التهديدات أو الإساءة المستهدفة",
    "hate_speech": "محتوى يروج للكراهية على أساس الهوية",
    "sexually_explicit": "محتوى جنسي صريح"
}

التنفيذ الأساسي

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
from typing import Dict

class ShieldGemmaClassifier:
    """مصنف سلامة ShieldGemma للاستخدام الإنتاجي."""

    def __init__(self, model_size: str = "2b"):
        # المتاح: 2b، 9b، 27b
        model_id = f"google/shieldgemma-{model_size}"
        self.device = "cuda" if torch.cuda.is_available() else "cpu"

        self.tokenizer = AutoTokenizer.from_pretrained(model_id)
        self.model = AutoModelForCausalLM.from_pretrained(
            model_id,
            torch_dtype=torch.bfloat16,
            device_map="auto"
        )

        # رموز احتمالية ShieldGemma
        self.yes_token = self.tokenizer.encode("Yes", add_special_tokens=False)[0]
        self.no_token = self.tokenizer.encode("No", add_special_tokens=False)[0]

    def classify(
        self,
        user_content: str,
        category: str = "dangerous_content"
    ) -> Dict[str, float]:
        """
        تصنيف المحتوى لفئة ضرر محددة.

        يُرجع:
            Dict مع 'probability' (0-1) و 'is_harmful' (bool)
        """
        prompt = self._build_prompt(user_content, category)

        inputs = self.tokenizer(
            prompt,
            return_tensors="pt"
        ).to(self.device)

        with torch.no_grad():
            outputs = self.model(**inputs)
            logits = outputs.logits[0, -1, :]

            # الحصول على الاحتمالات لرموز Yes/No
            yes_prob = torch.softmax(
                logits[[self.yes_token, self.no_token]], dim=0
            )[0].item()

        return {
            "probability": yes_prob,
            "is_harmful": yes_prob > 0.5,
            "category": category
        }

    def classify_all(self, user_content: str) -> Dict[str, Dict]:
        """فحص جميع فئات الضرر."""
        results = {}
        for category in SHIELDGEMMA_CATEGORIES:
            results[category] = self.classify(user_content, category)
        return results

    def _build_prompt(self, content: str, category: str) -> str:
        """بناء تنسيق موجه ShieldGemma."""
        category_desc = SHIELDGEMMA_CATEGORIES.get(category, category)

        return f"""You are a policy expert determining if the following content
violates the policy on {category_desc}.

User content: {content}

Does this content violate the {category} policy? Answer Yes or No."""

# الاستخدام
classifier = ShieldGemmaClassifier(model_size="2b")
result = classifier.classify(
    user_content="كيف أتعلم البرمجة؟",
    category="dangerous_content"
)
print(f"ضار: {result['is_harmful']}، الاحتمالية: {result['probability']:.2%}")

المعالجة الدفعية للإنتاجية

import asyncio
from concurrent.futures import ThreadPoolExecutor

class ShieldGemmaBatch:
    """معالج دفعي لتصنيف ShieldGemma."""

    def __init__(self, model_size: str = "9b", max_workers: int = 4):
        self.classifier = ShieldGemmaClassifier(model_size=model_size)
        self.executor = ThreadPoolExecutor(max_workers=max_workers)

    async def batch_classify(
        self,
        contents: list[str],
        categories: list[str] = None
    ) -> list[Dict]:
        """تصنيف محتويات متعددة بشكل غير متزامن."""
        categories = categories or ["dangerous_content"]

        loop = asyncio.get_event_loop()
        tasks = []

        for content in contents:
            for category in categories:
                task = loop.run_in_executor(
                    self.executor,
                    self.classifier.classify,
                    content,
                    category
                )
                tasks.append(task)

        results = await asyncio.gather(*tasks)

        # تجميع النتائج حسب المحتوى
        grouped = []
        idx = 0
        for content in contents:
            content_results = {}
            for category in categories:
                content_results[category] = results[idx]
                idx += 1
            grouped.append(content_results)

        return grouped

# الاستخدام
async def main():
    batch = ShieldGemmaBatch(model_size="9b")
    contents = [
        "كيف أطبخ المعكرونة؟",
        "كيف الطقس اليوم؟"
    ]
    results = await batch.batch_classify(
        contents,
        categories=["dangerous_content", "harassment"]
    )
    return results

المقارنة: ShieldGemma مقابل LlamaGuard 3

الجانبShieldGemmaLlamaGuard 3
الفئات4 (مركزة)14 (شاملة)
المخرجدرجة احتماليةثنائي + فئات
الأصغر2B1B
الأكبر27B8B
القوةمعايرة الاحتماليةدقة الفئات

نمط التكامل الإنتاجي

from enum import Enum
from dataclasses import dataclass

class ClassifierChoice(Enum):
    SHIELDGEMMA = "shieldgemma"
    LLAMAGUARD = "llamaguard"

@dataclass
class UnifiedSafetyResult:
    is_safe: bool
    confidence: float
    categories: list[str]
    classifier_used: ClassifierChoice

def unified_safety_check(
    content: str,
    primary: ClassifierChoice = ClassifierChoice.SHIELDGEMMA,
    fallback: ClassifierChoice = ClassifierChoice.LLAMAGUARD,
    confidence_threshold: float = 0.8
) -> UnifiedSafetyResult:
    """
    فحص سلامة موحد مع احتياطي.
    يستخدم المصنف الأساسي، ويتراجع إذا كان غير مؤكد.
    """
    if primary == ClassifierChoice.SHIELDGEMMA:
        classifier = ShieldGemmaClassifier(model_size="9b")
        results = classifier.classify_all(content)

        # التحقق من وجود أي فئة ضارة
        harmful_cats = [
            cat for cat, r in results.items()
            if r["is_harmful"]
        ]
        max_prob = max(r["probability"] for r in results.values())

        # إذا كان غير مؤكد، استخدم الاحتياطي
        if 0.3 < max_prob < 0.7:
            return unified_safety_check(
                content,
                primary=fallback,
                fallback=None,
                confidence_threshold=confidence_threshold
            )

        return UnifiedSafetyResult(
            is_safe=len(harmful_cats) == 0,
            confidence=1 - max_prob if len(harmful_cats) == 0 else max_prob,
            categories=harmful_cats,
            classifier_used=primary
        )

    # احتياطي LlamaGuard
    guard = LlamaGuard3Classifier(model_size="8B")
    decision, categories = guard.classify(content)

    return UnifiedSafetyResult(
        is_safe=decision == "safe",
        confidence=0.9 if decision in ["safe", "unsafe"] else 0.5,
        categories=categories,
        classifier_used=ClassifierChoice.LLAMAGUARD
    )

نصيحة النشر: استخدم ShieldGemma 2B لنشر الحافة أو عندما تحتاج درجات احتمالية. استخدم LlamaGuard 3 عندما تحتاج معلومات فئات دقيقة (14 مقابل 4 فئات).

التالي: مقارنة أداء المصنفات عبر المعايير. :::

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

اختبار

الوحدة 3: تعمق في مصنفات السلامة

خذ الاختبار