برای آماده سازی کد هوش مصنوعی برای Production به یک خط‌ لوله شفاف نیاز دارید: بازبینی انسانی اجباری، اسکن امنیتی و لایسنس، پوشش تست قابل دفاع، پین‌کردن وابستگی‌ها، اعتبارسنجی ورودی/خروجی، Observability، و استقرار مرحله‌ای با امکان رول‌بک. اگر هر کدام از این حلقه‌ها ضعیف باشد، ریسک باگ‌های پنهان، نشت داده یا ناپایداری در تولید بالا می‌رود.

چه چیزی در کد تولیدشده با هوش مصنوعی متفاوت است؟

خروجی مدل همیشه «ظاهر درست» دارد اما ممکن است ناقص، ناایمن یا ناسازگار با بافت پروژه باشد. رایج‌ترین ریسک‌ها: مدیریت خطای سطحی، کپی الگوهای ناامن، نادیده گرفتن محدودیت‌های عملکردی، وابستگی ناشناس، و ابهام حقوقی در قطعه‌کدهای شبیه کدهای متن‌باز. نتیجه عملی: هیچ قطعه کدی که مستقیما از AI می‌گیرید نباید بدون بازنویسی/بازبینی و عبور از گیت‌های CI/CD وارد Production شود.

چک لیست آماده سازی کد هوش مصنوعی برای Production

  • بازبینی انسانی اجباری: حداقل یک مهندس مستقل تغییرات را با تمرکز بر منطق، امنیت و خوانایی تایید کند.
  • استانداردسازی سبک کدنویسی: اجرای فرمت، Lint و Type Checking برای کاهش ابهام و خطاهای پنهان.
  • تست چندلایه: Unit، Integration، End-to-End، و در اپ‌های AI تست ثبات خروجی (Golden/Contract Test).
  • امنیت و حریم خصوصی: اعتبارسنجی ورودی/خروجی، Rate Limit، Secret Management، و جلوگیری از Prompt Injection.
  • وابستگی‌ها و لایسنس: Lockfile، اسکن CVE، تولید SBOM و تایید مجوزها.
  • پیکربندی و اسرار: جداسازی تنظیمات با متغیر محیطی، عدم هاردکد Secrets، و حداقل سطح دسترسی.
  • کارایی و منابع: بودجه‌گذاری حافظه/CPU/Timeout، Load Test سبک و محافظ‌های Circuit Breaker.
  • Observability: لاگ ساخت‌یافته با حذف داده حساس، متریک‌های کلیدی و Trace برای مسیر خطا.
  • دیپلوی امن: Feature Flag، Canary/Blue-Green، Health Check و مسیر رول‌بک آزموده‌شده.

خط لوله CI/CD پیشنهادی با Gateهای اجباری

یک CI/CD خوب باید قبل از Merge و قبل از Release، گیت‌های سخت‌گیرانه داشته باشد. نمونه زیر برای یک پروژه پایتون، حداقل‌های عملی را نشان می‌دهد.

name: ci

on:
  pull_request:
  push:
    branches: [ main ]

jobs:
  build-test-secure:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install deps
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install pytest coverage ruff mypy bandit pip-audit

      - name: Format & Lint
        run: |
          ruff check .
          mypy --strict src

      - name: Unit tests with coverage
        run: |
          coverage run -m pytest -q
          coverage report --fail-under=85

      - name: Security static analysis
        run: |
          bandit -r src -x tests

      - name: Dependency vulnerability audit
        run: |
          pip-audit

معیارهای عبور

  • Fail Fast: هر خطا در Lint/Type/Test/امنیت، Merge را متوقف کند.
  • Coverage مینیمم: آستانه عملی (مثلا 80-90٪) متناسب با سطح ریسک ماژول.
  • بدون CVE با Severity بالا: تا زمان رفع یا موقتا Pin/Workaround نکنید.
  • دو تایید انسانی روی PRهای حساس (امنیت، زیرساخت، تغییرات دیتابیس).

امنیت و حریم خصوصی ویژه اپ‌های AI

در اپلیکیشن‌هایی که مدل زبانی دخیل است، امنیت صرفا «فایروال و توکن مخفی» نیست؛ باید خروجی مدل را همانند ورودی کاربر غیرقابل اعتماد فرض کنید.

اعتبارسنجی خروجی مدل

  • Schema Validation: خروجی باید با اسکیمای توافقی (JSON/Typed Object) همخوان باشد.
  • قواعد دامنه: طول، فهرست مجاز (Allowlist)، و نرمال‌سازی کاراکترها اعمال شود.
  • اعتماد صفر به Markdown/HTML تولیدی: Sanitize یا رندر امن سمت کلاینت.
from pydantic import BaseModel, Field, ValidationError
from typing import Literal

class Summary(BaseModel):
    topic: str = Field(min_length=3, max_length=100)
    sentiment: Literal["positive", "neutral", "negative"]
    key_points: list[str] = Field(default_factory=list, max_items=5)

def validate_model_output(data: dict) -> Summary:
    try:
        return Summary.model_validate(data)
    except ValidationError as e:
        # لاگ ایمن بدون داده شخصی
        raise ValueError(f"Invalid model output: {e.errors()}")

محافظت در برابر Prompt Injection و داده‌های حساس

  • Context Isolation: داده داخلی/Tokenهای مخفی را هرگز در Prompt قرار ندهید.
  • Content Filtering: ورودی/خروجی را طبق سیاست محتوا و PII Masking فیلتر کنید.
  • Tool Use Guardrails: اگر مدل به ابزار دسترسی دارد، Policy-Check قبل از اجرا.
  • Rate Limit و Abuse Detection: جلوگیری از حملات هزینه‌زا و تکراری.

تست‌هایی که واقعا جلوی خطا را می‌گیرند

تست موثر در اپ‌های AI فقط عدد پوشش نیست؛ باید رگرسیون رفتار مدل و ایمنی داده را هم بسنجد.

  • Unit Test برای منطق قطعی: اعتبارسنجی، نرمال‌سازی، Branchهای خطا.
  • Integration Test با Stub مدل: کل جریان بدون وابستگی به API بیرونی اجرا شود.
  • Golden Test: روی ورودی‌های نماینده، خروجی مورد انتظار یا محدوده قابل قبول را قفل کنید.
  • Seed و Determinism: دانه تصادفی و Temperature را برای تکرارپذیری تست تنظیم کنید.
  • Test Data بی‌خطر: هیچ داده واقعی/حساس در Fixtureها قرار ندهید.
# مثال ساده تزریق وابستگی برای تست‌پذیری
class LLMClient:
    def generate(self, prompt: str, *, temperature: float = 0.0) -> dict:
        raise NotImplementedError

def summarize(llm: LLMClient, text: str) -> dict:
    prompt = f"Summarize briefly:\n{text}"
    raw = llm.generate(prompt, temperature=0.0)
    summary = validate_model_output(raw)
    return summary.model_dump()

# در تست، یک Stub قابل پیش‌بینی تزریق کنید
class StubLLM(LLMClient):
    def generate(self, prompt: str, *, temperature: float = 0.0) -> dict:
        return {"topic": "demo", "sentiment": "neutral", "key_points": ["a","b"]}

def test_summarize_ok():
    out = summarize(StubLLM(), "hello")
    assert out["topic"] == "demo"
    assert len(out["key_points"]) == 2

مدیریت وابستگی، لایسنس و بازتولیدپذیری

وابستگی کنترل‌نشده مساوی با باگ و ریسک امنیتی در تولید است.

  • Pin و Lockfile: نسخه دقیق کتابخانه‌ها را قفل کنید (مانند requirements.txt به همراه hashes).
  • اسکن لایسنس: مطمئن شوید مجوز وابستگی‌ها با سیاست شما سازگار است.
  • SBOM: فهرست اجزای نرم‌افزار را تولید و نگهداری کنید.
  • Buildهای بازتولیدپذیر: نسخه‌گذاری، برچسب Commit و متادیتا در خروجی Build ثبت شود.

Observability در Production

قابل مشاهده بودن یعنی بتوانید بلافاصله بفهمید چه شد، کجا و چرا.

  • لاگ ساخت‌یافته: سطح‌های مناسب، شناسه درخواست، حذف PII، و سقف حجم لاگ.
  • متریک‌ها: تاخیر، نرخ خطا، تعداد درخواست، هزینه تقریبی/استفاده از توکن، نرخ تایم‌اوت.
  • Trace توزیع‌شده: مسیر فراخوانی تا سرویس مدل برای رفع باگ‌های بین‌سرویسی.
  • هشدار عملی: آستانه‌ها و Playbook روشن برای واکنش.

دیپلوی ایمن و قابل برگشت

استقرار خوب یعنی تغییرات کوچک، قابل اندازه‌گیری و برگشت‌پذیر.

  • Feature Flag: فعالسازی تدریجی قابلیت بدون انتشار کد جدید.
  • Canary/Blue-Green: درصد کمی از ترافیک، سپس گسترش مرحله‌ای.
  • Health Check و Smoke Test پس از هر استقرار.
  • Rollback Plan: مسیر بازگشت تست‌شده و مستند.

مثال کوتاه: ارتقای یک تابع AI به استاندارد Production

هدف: یک تابع ساده که به سرویس مدل درخواست می‌فرستد را با Timeout، Retry، اعتبارسنجی، لاگ ایمن و بودجه منابع آماده Production کنیم.

import json
import time
from typing import Any, Dict, Optional
import requests
from pydantic import BaseModel, Field, ValidationError

class Summary(BaseModel):
    topic: str = Field(min_length=3, max_length=100)
    sentiment: str
    key_points: list[str] = Field(default_factory=list, max_items=5)

def redact(text: str) -> str:
    # جایگزینی ساده برای جلوگیری از لاگ PII
    return text.replace("@", "[at]").replace("+98", "[redacted]")

class AIServiceError(Exception):
    pass

def call_model(endpoint: str, api_key: str, payload: Dict[str, Any], *, timeout_s: float = 8.0) -> Dict[str, Any]:
    try:
        res = requests.post(
            endpoint,
            headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
            data=json.dumps(payload),
            timeout=timeout_s,
        )
        if res.status_code != 200:
            raise AIServiceError(f"Bad status: {res.status_code}")
        return res.json()
    except requests.Timeout:
        raise AIServiceError("Model timeout")
    except requests.RequestException as e:
        raise AIServiceError(f"Network error: {e}")

def summarize_production(endpoint: str, api_key: str, text: str, *, max_retries: int = 2) -> Summary:
    prompt = f"Return JSON with fields: topic, sentiment, key_points[]. Text:\\n{text[:2000]}"
    payload = {"prompt": prompt, "temperature": 0.0}

    last_err: Optional[Exception] = None
    for attempt in range(max_retries + 1):
        try:
            raw = call_model(endpoint, api_key, payload, timeout_s=8.0)
            summary = Summary.model_validate(raw)  # اعتبارسنجی سخت‌گیرانه
            return summary
        except (AIServiceError, ValidationError) as e:
            last_err = e
            time.sleep(0.5 * (attempt + 1))  # Backoff ساده
    # لاگ حداقلی و ایمن
    raise AIServiceError(f"Failed summarize after retries: {redact(str(last_err))}")

نحوه بررسی: با Stub سرویس یا محیط Sandbox، مسیرهای موفق و شکست (Timeout، خروجی نامعتبر) را تست کنید و مطمئن شوید استثناها کنترل شده‌اند و لاگ‌ها داده حساس را نشت نمی‌دهند.

سیاست کدنویسی و کپی‌برداری

قبل از ادغام کد، سیاست داخلی را روشن کنید: مالکیت کد تولیدی، ممنوعیت Paste بدون درک منطق، ارجاع به منبع وقتی از قطعه‌کد متن‌باز استفاده می‌شود، و خط‌قرمزهای امنیتی. ابزارهای بررسی شباهت کد می‌توانند از ورود کد مشکوک جلوگیری کنند.

از کجا شروع کنیم؟

یک PR آزمایشی را انتخاب کنید و چک لیست بالا را به CI/CD اضافه کنید: Lint/Type/Test/امنیت/لایسنس به عنوان Gate اجباری، سپس اعتبارسنجی خروجی مدل و Feature Flag برای استقرار مرحله‌ای. اگر تیم شما تازه وارد این حوزه است، گذراندن یک دوره آموزش ابزارهای هوش مصنوعی می‌تواند مبانی Guardrail، Observability و دیپلوی امن را سریع‌تر جا بیندازد.