AI Infrastructure

هم‌راستایی کش در محیط‌های LLM چند مستأجری: جلوگیری از نشت داده و پاسخ‌های منقضی‌شده

مدل‌های زبانی بزرگ (LLM) منابع زیادی مصرف می‌کنند، بنابراین کش کردن پاسخ‌ها استراتژی ضروری برای کاهش تأخیر و هزینه‌های محاسباتی است. با این حال، استقرار LLM در محیط چند مستأجری پیچیدگی قابل‌توجهی ایجاد می‌کند. یک استراتژی کش ساده می‌تواند منجر به دو شکست بحرانی شود: نشت داده، جایی که مستأجر A پاسخ‌های کش‌شده‌ای را دریافت می‌کند که برای مستأجر B تولید شده‌اند، و پاسخ‌های منقضی‌شده، جایی که مدل اطلاعاتی قدیمی را ارائه می‌دهد که با زمینه‌های جدیدتر و خاص مستأجر در تضاد است. این پست بررسی می‌کند که چگونه پروتکل هم‌راستایی کش را طراحی کنیم تا هم امنیت و هم تازگی در زیرساخت مشترک LLM تضمین شود.

مشکل کش ساده

در یک API استاندارد REST، کش معمولاً با امضای درخواست‌ها مدیریت می‌شود. اما برای LLM، «ورودی» به ندرت یک رشته ساده است. شامل پرامپت‌های سیستمی، تاریخچه کاربر، زمینه تولید تقویت‌شده با بازیابی (RAG) و به احتمال زیاد پارامترهای خاص مستأجر مانند دما یا مقادیر top-k است. اگر کلید کش شما صرفاً بر اساس پرامپت نهایی کاربر باشد، با برخورد (collision) روبرو می‌شوید. دو مستأجر مختلف ممکن است بپرسند «سیاست بازپرداخت شما چیست؟» سیاست مستأجر A سختگیرانه است، در حالی که سیاست مستأجر B انعطاف‌پذیر است. اگر سیستم اولین پاسخ را کش کند، مستأجر B سیاست نادرست مستأجر A را دریافت می‌کند، که منجر به نشت داده و شکست در منطق کسب‌وکار می‌شود.

طراحی کلید کش چندبُعدی

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

  1. شناسه مستأجر: مهم‌ترین مرز امنیتی.
  2. نسخه مدل: وزن‌های مدل یا پرامپت‌های سیستمی مختلف نیاز به کش‌های جداگانه دارند.
  3. هش پنجره زمینه: هش از تکه‌های خاص RAG یا جستجوهای پایگاه داده استفاده‌شده برای آن درخواست.

import hashlib
import json

def generate_coherent_cache_key(tenant_id: str, model_version: str, prompt: str, context_chunks: list[str], params: dict) -> str:
    """
    Generates a unique cache key that ensures tenant isolation and context freshness.
    """
    # 1. Combine all immutable state
    state = {
        "tenant": tenant_id,
        "model": model_version,
        "prompt": prompt,
        "context": sorted(context_chunks), # Sort to ensure consistency regardless of order
        "params": {
            "temperature": params.get("temperature"),
            "top_k": params.get("top_k")
        }
    }
    
    # 2. Create a stable JSON representation
    stable_json = json.dumps(state, sort_keys=True)
    
    # 3. Hash for storage
    return hashlib.sha256(stable_json.encode('utf-8')).hexdigest()

مدیریت زمینه منقضی‌شده و استراتژی‌های TTL

حتی با یک کلید کامل، داده‌ها منقضی می‌شوند. اگر خط لوله RAG شما پایگاه دانش را به‌روزرسانی کند، کش‌های قبلی نامعتبر می‌شوند. زمان ماندگاری (TTL) ضروری است، اما اتکا صرف به آن خطرناک است. به جای آن، یک توکن زمینه نسخه‌دار پیاده‌سازی کنید. هنگام به‌روزرسانی پایگاه دانش، یک شماره نسخه را افزایش دهید. این نسخه را در کلید کش گنجانده کنید.

برای مکالمات پویا، یک TTL پنجره‌ای لغزنده را در نظر بگیرید. اگر کاربر در میانه یک مکالمه چندگانه باشد، کش باید به سرعت منقضی شود (مثلاً 30 ثانیه) تا اطمینان حاصل شود که پرامپت بعدی دور قبل را در نظر می‌گیرد، که ممکن است نیت معنایی کوئری بعدی را تغییر دهد.

پیاده‌سازی عملی: Redis با نام‌گذاری (Namespacing)

با استفاده از Redis، می‌توانید جداسازی را از طریق نام‌گذاری (Namespacing) اجبار کنید. در حالی که هش ترکیبی از برخورد محافظت می‌کند، استفاده از یک پیشوند Redis جداگانه برای هر مستأجر لایه اضافی دفاع در برابر خطاهای منطقی در تولید کلید اضافه می‌کند.


class LLMCacheService:
    def __init__(self, redis_client):
        self.redis = redis_client

    def get_or_generate(self, tenant_id: str, key_hash: str, generate_fn):
        # Namespaced key for defense in depth
        namespaced_key = f"llm:cache:{tenant_id}:{key_hash}"
        
        cached_response = self.redis.get(namespaced_key)
        if cached_response:
            return json.loads(cached_response)

        # Cache miss: Generate new response
        response = generate_fn()
        
        # Set with TTL (e.g., 3600 seconds = 1 hour)
        self.redis.setex(namespaced_key, 3600, json.dumps(response))
        
        return response

پایش برای تشخیص ناهنجاری‌ها

لاگ‌نویسی را برای شناسایی مشکلات احتمالی هم‌راستایی پیاده‌سازی کنید. نرخ برخورد کش را برای هر مستأجر ردیابی کنید. افت ناگهانی نرخ برخورد برای یک مستأجر خاص ممکن است نشان‌دهنده باگ در منطق تولید زمینه آن‌ها باشد، که باعث می‌شود کلیدهای منحصربه‌فرد برای هر درخواست ایجاد شود (که پرهزینه است). برعکس، نرخ برخورد بالا برای کوئری‌های «حساس» در بین مستأجران مختلف باید هشدار برای بررسی دستی ایجاد کند، زیرا ممکن است نشان‌دهنده آسیب‌پذیری برخورد کلید باشد.

نتیجه‌گیری

هم‌راستایی کش در محیط‌های LLM چند مستأجری فقط یک نگرانی عملکردی نیست؛ بلکه یک الزام امنیتی است. با طراحی کلیدهای کش ترکیبی که شامل شناسه‌های مستأجر، نسخه‌های مدل و هش‌های زمینه هستند، می‌توانید به‌طور ایمن از کش برای کاهش هزینه‌ها استفاده کنید. همیشه این کار را با مدیریت قوی TTL و پایش همراه کنید تا اطمینان حاصل شود که در حالی که زیرساخت هوش مصنوعی شما مقیاس‌پذیر می‌شود، مرزهای داده شما نفوذناپذیر باقی می‌مانند و پاسخ‌های شما دقیق هستند.

Share: