为什么需要AI网关?
当企业使用多个LLM提供商(OpenAI、Anthropic、本地模型等)时,直接对接各家API会面临:密钥管理分散、无法统一限流、缺乏请求日志、故障切换困难。AI网关统一管理所有LLM请求,提供路由、缓存、限流、监控等基础设施。
核心架构
客户端 → AI网关 → LLM提供商A
→ LLM提供商B
→ 本地vLLM
实现方案
统一API接口
from fastapi import FastAPI, Request
from pydantic import BaseModel
app = FastAPI()
class ChatRequest(BaseModel):
model: str
messages: list
temperature: float = 0.7
max_tokens: int = 2048
stream: bool = False
# 提供商配置
PROVIDERS = {
"openai": {"base_url": "https://api.openai.com/v1", "api_key": "..."},
"anthropic": {"base_url": "https://api.anthropic.com", "api_key": "..."},
"local": {"base_url": "http://localhost:8000/v1", "api_key": "..."},
}
# 模型到提供商的路由
MODEL_ROUTING = {
"gpt-4": "openai",
"claude-3": "anthropic",
"qwen3-32b": "local",
}
@app.post("/v1/chat/completions")
async def chat_completions(request: ChatRequest):
provider = MODEL_ROUTING.get(request.model, "local")
config = PROVIDERS[provider]
# 转发请求
async with httpx.AsyncClient() as client:
response = await client.post(
f"{config['base_url']}/chat/completions",
json=request.dict(),
headers={"Authorization": f"Bearer {config['api_key']}"},
timeout=120
)
return response.json()
故障切换
class FailoverRouter:
def __init__(self, routing_config):
self.routing = routing_config # {model: [provider1, provider2, ...]}
self.health = {p: True for providers in routing_config.values() for p in providers}
async def route(self, model, request):
providers = self.routing.get(model, ["local"])
for provider in providers:
if not self.health[provider]:
continue
try:
result = await self.call_provider(provider, request)
return result
except Exception as e:
logger.warning(f"Provider {provider} failed: {e}")
self.health[provider] = False
continue
raise ServiceUnavailableError("All providers failed")
请求缓存
import hashlib
import redis.asyncio as redis
class ResponseCache:
def __init__(self, redis_url="redis://localhost:6379"):
self.redis = redis.from_url(redis_url)
def cache_key(self, model, messages, temperature):
content = json.dumps({"model": model, "messages": messages, "temp": temperature})
return hashlib.sha256(content.encode()).hexdigest()
async def get(self, model, messages, temperature):
key = self.cache_key(model, messages, temperature)
cached = await self.redis.get(key)
return json.loads(cached) if cached else None
async def set(self, model, messages, temperature, response, ttl=3600):
key = self.cache_key(model, messages, temperature)
await self.redis.setex(key, ttl, json.dumps(response))
限流
from datetime import datetime, timedelta
class RateLimiter:
def __init__(self, redis):
self.redis = redis
async def check(self, user_id, limit=60, window=60):
key = f"rate:{user_id}:{datetime.now().strftime('%Y%m%d%H%M')}"
current = await self.redis.incr(key)
if current == 1:
await self.redis.expire(key, window)
if current > limit:
return False
return True
日志与监控
class RequestLogger:
def __init__(self):
self.logger = structlog.get_logger()
async def log(self, request, response, user_id, duration):
self.logger.info("llm_request",
user_id=user_id,
model=request.model,
input_tokens=response.get("usage", {}).get("prompt_tokens", 0),
output_tokens=response.get("usage", {}).get("completion_tokens", 0),
duration_ms=duration * 1000,
provider=response.get("provider", "unknown"),
status="success" if response.get("choices") else "error"
)
部署配置
Docker Compose
version: '3.8'
services:
gateway:
build: .
ports:
- "8080:8080"
environment:
- REDIS_URL=redis://redis:6379
depends_on:
- redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
结语
AI网关是LLM生产基础设施的核心组件。统一API、故障切换、缓存、限流和监控这五大功能,让LLM服务具备企业级的可靠性和可观测性。
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。