You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

8.5 KiB

سیستم گاردریل (Guardrails System)

چرا گاردریل؟

ایجنت‌های هوش مصنوعی بدون محدودیت، آسیب‌پذیرند. کاربر می‌تواند:

  • Prompt Injection: با دستورات مخفی، رفتار ایجنت را تغییر دهد (مثلاً «دستورات قبلی‌ات را فراموش کن»)
  • ورودی بسیار طولانی: با ارسال متن‌های عظیم، هزینه توکن را بالا ببرد یا مدل را سردرگم کند
  • محتوای نامناسب: متن‌های توهین‌آمیز یا خارج از چارچوب ادب اسلامی ارسال کند

گاردریل‌ها لایه‌های دفاعی هستند که قبل از رسیدن ورودی به مدل، آن را بررسی می‌کنند و در صورت تخلف، درخواست را رد می‌کنند.


معماری

ورودی کاربر
    │
    ▼
┌──────────────────────────────────┐
│         pre_hooks (به ترتیب)      │
│                                  │
│  1. PromptInjectionGuardrail()   │  ← گاردریل آماده agno (تشخیص prompt injection)
│  2. InputLimitGuardrail()        │  ← گاردریل سفارشی (محدودیت طول ورودی)
│  3. rag_injection_hook           │  ← تزریق RAG context
│                                  │
└──────────────┬───────────────────┘
               │ ✅ ورودی سالم
               ▼
┌──────────────────────────────────┐
│          LLM (مدل زبانی)         │
└──────────────────────────────────┘

گاردریل‌ها در آرایه pre_hooks ایجنت تعریف می‌شوند و به ترتیب اجرا می‌شوند. اگر هر کدام خطا (InputCheckError) بدهند، زنجیره متوقف شده و پیام خطا به کاربر برمی‌گردد — بدون اینکه مدل فراخوانی شود.


ساختار پوشه

src/guardrails/
├── __init__.py          ← ماژول پکیج
└── limit.py             ← InputLimitGuardrail (محدودیت طول ورودی)

گاردریل‌های فعال

۱. PromptInjectionGuardrail (از کتابخانه agno)

آیتم مقدار
منبع agno.guardrails.PromptInjectionGuardrail
هدف تشخیص تلاش‌های Prompt Injection
نحوه کار با استفاده از مدل LLM، ورودی کاربر را تحلیل می‌کند و اگر دستور مخفی تشخیص دهد، درخواست را رد می‌کند
پیکربندی نیازی به تنظیم ندارد — آماده استفاده است
from agno.guardrails import PromptInjectionGuardrail

۲. InputLimitGuardrail (سفارشی)

آیتم مقدار
منبع src/guardrails/limit.py
هدف جلوگیری از ارسال ورودی‌های بسیار طولانی
حد پیش‌فرض ۲۰۰۰ کاراکتر
ویژگی خاص پیام خطا را به زبان کاربر تولید می‌کند

نحوه کار

ورودی کاربر
    │
    ▼
آیا طول ورودی > max_chars؟
    │
    ├─ خیر → ادامه pipeline ✅
    │
    └─ بله → تولید پیام خطا:
              1. ۲۰۰ کاراکتر اول ورودی استخراج می‌شود (نمونه)
              2. با یک prompt به LLM فرستاده می‌شود:
                 «زبان این متن را تشخیص بده و پیام خطای مؤدبانه بنویس»
              3. پیام خطا به زبان کاربر تولید و برگردانده می‌شود
              4. InputCheckError پرتاب می‌شود → pipeline متوقف

پشتیبانی Sync و Async

این گاردریل هر دو حالت را پشتیبانی می‌کند:

متد کاربرد
check() برای فراخوانی‌های sync (مثل agent.run())
async_check() برای فراخوانی‌های async (مثل await agent.arun())

اگر فراخوانی LLM برای تولید پیام خطا شکست بخورد، یک پیام پیش‌فرض انگلیسی برمی‌گردد:

⚠️ Input too long. Max 2000 chars.

نحوه اتصال به ایجنت

گاردریل‌ها در src/agents/base_agent.py درون آرایه pre_hooks تعریف شده‌اند:

self.agent = ContextAwareAgent(
    ...
    pre_hooks=[
        PromptInjectionGuardrail(),   # گاردریل ۱: ضد prompt injection
        InputLimitGuardrail(),         # گاردریل ۲: محدودیت طول ورودی
        rag_injection_hook,            # هوک RAG (گاردریل نیست)
    ],
    ...
)

نکته: ترتیب مهم است. ابتدا prompt injection بررسی می‌شود، سپس طول ورودی، و در نهایت اگر ورودی سالم بود، RAG context تزریق می‌شود.


نحوه اضافه کردن گاردریل جدید

مرحله ۱: ساخت فایل گاردریل

یک فایل جدید در src/guardrails/ بسازید، مثلاً profanity.py:

from agno.guardrails.base import BaseGuardrail
from agno.run.agent import RunInput
from agno.exceptions import CheckTrigger, InputCheckError


class ProfanityGuardrail(BaseGuardrail):
    """گاردریل برای فیلتر محتوای نامناسب"""

    def __init__(self):
        super().__init__()
        self.name = "Profanity Filter Guardrail"

    def check(self, run_input: RunInput) -> None:
        """بررسی sync — اگر مشکلی بود InputCheckError پرتاب کنید"""
        text = run_input.input_content
        if self._contains_profanity(text):
            raise InputCheckError(
                "محتوای نامناسب تشخیص داده شد.",
                check_trigger=CheckTrigger.INPUT_NOT_ALLOWED,
            )

    async def async_check(self, run_input: RunInput) -> None:
        """بررسی async — همان منطق check ولی async"""
        text = run_input.input_content
        if self._contains_profanity(text):
            raise InputCheckError(
                "محتوای نامناسب تشخیص داده شد.",
                check_trigger=CheckTrigger.INPUT_NOT_ALLOWED,
            )

    def _contains_profanity(self, text: str) -> bool:
        # منطق تشخیص محتوای نامناسب
        ...

قوانین کلیدی:

قانون توضیح
از BaseGuardrail ارث‌بری کنید کلاس پایه agno
متد check() را پیاده‌سازی کنید برای فراخوانی‌های sync
متد async_check() را پیاده‌سازی کنید برای فراخوانی‌های async
InputCheckError پرتاب کنید برای رد کردن ورودی
CheckTrigger.INPUT_NOT_ALLOWED استفاده کنید نوع خطا

مرحله ۲: اضافه کردن به ایجنت

در src/agents/base_agent.py:

from src.guardrails.profanity import ProfanityGuardrail

# در تعریف ایجنت:
pre_hooks=[
    PromptInjectionGuardrail(),
    InputLimitGuardrail(),
    ProfanityGuardrail(),          # ← گاردریل جدید
    rag_injection_hook,            # ← همیشه آخر باشد
],

نکته مهم: rag_injection_hook همیشه باید آخرین آیتم در pre_hooks باشد، چون ورودی را تغییر می‌دهد و گاردریل‌ها باید ورودی اصلی کاربر را بررسی کنند.


خلاصه

گاردریل فایل هدف نوع
PromptInjectionGuardrail agno.guardrails ضد prompt injection آماده (built-in)
InputLimitGuardrail src/guardrails/limit.py محدودیت طول ورودی سفارشی
پارامتر ایجنت مقدار نقش
pre_hooks آرایه‌ای از گاردریل‌ها و هوک‌ها اجرای ترتیبی قبل از مدل