
多租户 LLM 架构设计:SaaS 场景下的隔离与共享
为什么多租户 LLM 架构不同于传统 SaaS 传统 SaaS 多租户解决的是数据隔离问题——数据库加个 tenant_id 列基本就搞定了。LLM SaaS 不一样,它涉及计算资源隔离、模型权重隔离、Prompt 安全、Token 计费四层问题,每一层都有坑。 核心矛盾:LLM 推理极其昂贵,你不可能给每个租户分配独立 GPU,但又不能让大租户的请求挤占小租户的资源。 租户隔离的四个层次 层次一:数据隔离 数据隔离是最基础的要求。用户输入的 Prompt、对话历史、上传的文档,必须严格按租户隔离。 # 租户上下文注入中间件 class TenantContextMiddleware: def __init__(self, db_pool, redis): self.db_pool = db_pool self.redis = redis async def __call__(self, request): tenant_id = request.headers.get("X-Tenant-Id") if not tenant_id: raise HTTPException(401, "Missing tenant context") # 从 Redis 加载租户配置(带缓存) tenant_config = await self.redis.get(f"tenant:{tenant_id}:config") if not tenant_config: tenant_config = await self.load_tenant_config(tenant_id) await self.redis.setex(f"tenant:{tenant_id}:config", 300, tenant_config) request.state.tenant = json.loads(tenant_config) request.state.tenant_id = tenant_id return request async def load_tenant_config(self, tenant_id): async with self.db_pool.acquire() as conn: row = await conn.fetchrow( "SELECT * FROM tenants WHERE id = $1 AND status = 'active'", tenant_id ) if not row: raise HTTPException(403, "Tenant not found or inactive") return json.dumps(dict(row)) 关键原则: 所有数据查询必须强制带 tenant_id 条件,最好在 ORM 层面做硬约束,而不是靠开发者自觉。 ...