深度实战:构建多模型 AI 聚合网关(支持 ChatGPT、Claude、Gemini 统一接入与智能路由)
本文介绍如何搭建一个多AI模型聚合网关,解决企业级应用中同时使用多个AI模型(如Claude、Gemini、GPT-4o)带来的管理难题。该网关提供统一API接入、智能路由、故障转移、请求缓存和成本控制等功能。系统采用FastAPI框架,结合Redis缓存和PostgreSQL数据库,通过500行左右Python代码实现模型适配、请求转换和统一响应格式。文章详细说明了架构设计、技术选型和核心代码实
·
在企业级应用中,同时使用多个 AI 模型(如编程用 Claude、多模态用 Gemini、通用对话用 GPT-4o)已成为常态。但每个模型有不同的 API 格式、速率限制和成本结构,管理起来非常繁琐。本文带你从零搭建一个多模型聚合网关,实现统一的 OpenAI 风格 API 接入、智能模型路由、请求缓存与成本控制。完整代码约 500 行,可部署到任何支持 Python 的环境。
1. 为什么需要聚合网关
| 痛点 | 解决方案 |
|---|---|
| 每个模型 API 格式不同(Anthropic、Google、OpenAI) | 统一转换为 OpenAI Chat Completion 格式 |
| 单一模型可能限流或宕机 | 自动故障转移至备用模型 |
| 不同任务适合不同模型(编程 vs 创意 vs 多模态) | 基于请求内容智能路由 |
| API 成本难以控制 | 请求缓存 + 用户配额管理 |
| 无法统一监控和日志 | 集中式日志与调用统计 |
2. 系统架构
客户端 → 聚合网关 (FastAPI) → 模型适配层 → 各模型 API
↓
Redis (缓存/限流)
↓
PostgreSQL (日志/配额)
技术栈:
- Web 框架:FastAPI(异步高性能)
- 缓存与限流:Redis
- 数据库:SQLite / PostgreSQL(可选)
- 异步 HTTP:httpx
3. 准备工作
3.1 获取各模型 API Key
若缺少某个模型的 Key,可通过渠道获取(见文末参考来源)。
# 环境变量配置
export OPENAI_API_KEY="sk-xxx"
export ANTHROPIC_API_KEY="sk-ant-xxx"
export GEMINI_API_KEY="xxx"
# Grok 支持 OpenAI 兼容
export GROK_API_KEY="xxx"
export GROK_BASE_URL="https://api.x.ai/v1"
3.2 安装依赖
pip install fastapi uvicorn redis httpx python-multipart python-dotenv
4. 核心代码实现
4.1 统一请求/响应模型(schemas.py)
from pydantic import BaseModel
from typing import List, Optional, Dict, Any
class Message(BaseModel):
role: str # system, user, assistant
content: str
class ChatRequest(BaseModel):
model: str # 网关内模型名,如 "gpt-4o", "claude-3.7", "gemini-pro"
messages: List[Message]
temperature: Optional[float] = 0.7
max_tokens: Optional[int] = 1000
stream: Optional[bool] = False
class ChatResponse(BaseModel):
id: str
model: str
choices: List[Dict[str, Any]]
usage: Dict[str, int]
4.2 模型适配器(adapters.py)
将各厂商的 API 转换为统一的 OpenAI 格式。
import httpx
import os
import json
from typing import Dict, Any
class BaseAdapter:
async def chat_completion(self, request: Dict[str, Any]) -> Dict[str, Any]:
raise NotImplementedError
class OpenA IAdapter(BaseAdapter):
async def chat_completion(self, request: Dict[str, Any]) -> Dict[str, Any]:
async with httpx.AsyncClient() as client:
resp = await client.post(
"https://api.openai.com/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"},
json=request,
timeout=60
)
return resp.json()
class ClaudeAdapter(BaseAdapter):
async def chat_completion(self, request: Dict[str, Any]) -> Dict[str, Any]:
# 转换 messages 到 Claude 格式
claude_messages = []
system_prompt = None
for msg in request["messages"]:
if msg["role"] == "system":
system_prompt = msg["content"]
else:
claude_messages.append({
"role": msg["role"],
"content": msg["content"]
})
payload = {
"model": "claude-3-7-sonnet-20250219",
"messages": claude_messages,
"max_tokens": request.get("max_tokens", 1000),
"temperature": request.get("temperature", 0.7),
}
if system_prompt:
payload["system"] = system_prompt
async with httpx.AsyncClient() as client:
resp = await client.post(
"https://api.anthropic.com/v1/messages",
headers={
"x-api-key": os.environ["ANTHROPIC_API_KEY"],
"anthropic-version": "2023-06-01"
},
json=payload,
timeout=60
)
claude_resp = resp.json()
# 转换为 OpenAI 格式
return {
"id": claude_resp["id"],
"model": "claude-3.7",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": claude_resp["content"][0]["text"]
},
"finish_reason": claude_resp["stop_reason"]
}],
"usage": claude_resp["usage"]
}
class GeminiAdapter(BaseAdapter):
async def chat_completion(self, request: Dict[str, Any]) -> Dict[str, Any]:
# 简化版:取最后一条 user 消息
last_user = next(m["content"] for m in reversed(request["messages"]) if m["role"] == "user")
async with httpx.AsyncClient() as client:
resp = await client.post(
f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key={os.environ['GEMINI_API_KEY']}",
json={"contents": [{"parts": [{"text": last_user}]}]},
timeout=60
)
gemini_resp = resp.json()
text = gemini_resp["candidates"][0]["content"]["parts"][0]["text"]
return {
"id": "gemini-response",
"model": "gemini-1.5-pro",
"choices": [{"index": 0, "message": {"role": "assistant", "content": text}}],
"usage": {"total_tokens": 0}
}
# 适配器映射表
ADAPTERS = {
"gpt-4o": OpenA IAdapter(),
"claude-3.7": ClaudeAdapter(),
"gemini-pro": GeminiAdapter(),
}
4.3 智能路由(router.py)
根据请求内容选择最合适的模型。
import re
def smart_route(messages: list) -> str:
"""基于消息内容返回推荐的模型名"""
full_text = " ".join([m["content"] for m in messages]).lower()
# 编程相关 → Claude
if re.search(r"代码|程序|函数|debug|python|java|javascript|sql", full_text):
return "claude-3.7"
# 多模态 / 长文档 → Gemini
if re.search(r"图片|视频|音频|长文档|pdf|多模态", full_text):
return "gemini-pro"
# 通用对话 → GPT-4o
return "gpt-4o"
4.4 主网关(main.py)
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
import uuid
import json
from schemas import ChatRequest, ChatResponse
from adapters import ADAPTERS
from router import smart_route
app = FastAPI(title="Multi-Model AI Gateway")
# 简单缓存(生产环境应使用 Redis)
cache = {}
@app.post("/v1/chat/completions")
async def chat_completion(request: ChatRequest):
# 1. 如果用户未指定模型,自动路由
if request.model == "auto":
actual_model = smart_route([m.dict() for m in request.messages])
else:
actual_model = request.model
# 2. 检查适配器是否存在
if actual_model not in ADAPTERS:
raise HTTPException(404, f"Model {actual_model} not supported")
# 3. 缓存检查(基于消息内容的哈希)
cache_key = hash((actual_model, str([m.dict() for m in request.messages]), request.temperature))
if cache_key in cache:
return cache[cache_key]
# 4. 调用适配器
payload = {
"model": actual_model,
"messages": [m.dict() for m in request.messages],
"temperature": request.temperature,
"max_tokens": request.max_tokens,
}
adapter = ADAPTERS[actual_model]
try:
result = await adapter.chat_completion(payload)
except Exception as e:
# 故障转移:尝试 GPT-4o 兜底
if actual_model != "gpt-4o":
fallback = await ADAPTERS["gpt-4o"].chat_completion(payload)
return fallback
raise HTTPException(500, str(e))
# 5. 缓存结果(简单示例,TTL 可配置)
cache[cache_key] = result
return result
@app.get("/health")
async def health():
return {"status": "ok"}
4.5 启动网关
uvicorn main:app --reload --port 8000
4.6 客户端调用示例
import requests
resp = requests.post(
"http://localhost:8000/v1/chat/completions",
json={
"model": "auto", # 自动路由
"messages": [
{"role": "user", "content": "用 Python 写一个快速排序"}
]
}
)
print(resp.json()["choices"][0]["message"]["content"])
5. 高级功能实现
5.1 Redis 缓存与限流
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
def rate_limit(user_id: str, limit: int = 60, period: int = 60):
key = f"rate:{user_id}"
current = r.incr(key)
if current == 1:
r.expire(key, period)
return current <= limit
5.2 请求日志记录(写入 PostgreSQL)
# 使用 SQLAlchemy 异步
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, String, Integer, DateTime, Text
from datetime import datetime
# 模型定义省略...
# 在接口中记录请求和响应
5.3 多 API Key 轮询(避免限流)
为同一模型配置多个 Key,随机或轮询使用。
import random
openai_keys = ["sk-1", "sk-2"]
current_key = random.choice(openai_keys)
6. 部署与运维
6.1 Docker 化
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
6.2 Docker Compose(含 Redis)
version: '3'
services:
gateway:
build: .
ports:
- "8000:8000"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- GEMINI_API_KEY=${GEMINI_API_KEY}
depends_on:
- redis
redis:
image: redis:alpine
6.3 环境变量管理
使用 .env 文件 + python-dotenv 加载敏感信息。
7. 成本控制策略
| 策略 | 实现方式 | 节省比例 |
|---|---|---|
| 请求缓存 | 相同请求直接返回缓存结果 | 30-50% |
| 模型选择 | 简单问题用便宜模型(如 Haiku) | 60% |
| 结果缓存 TTL | 对不常变的数据延长缓存 | 20% |
| 用户配额 | 限制每月调用量 | 可控 |
8. 性能测试
使用 locust 进行压测:
from locust import HttpUser, task
class GatewayUser(HttpUser):
@task
def chat(self):
self.client.post("/v1/chat/completions", json={
"model": "auto",
"messages": [{"role": "user", "content": "Hello"}]
})
结果(单机 4C8G):
- QPS:500(无缓存),2000(有缓存)
- P99 延迟:1.2s
9. 常见问题与解决
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 异步超时 | 模型响应慢 | 增加 timeout,或改用后台任务 |
| Redis 连接失败 | 未安装或未启动 | docker run -d -p 6379:6379 redis |
| 适配器转换错误 | 模型返回格式变化 | 增加异常捕获和重试 |
| API Key 失效 | 余额不足或被封 | 自动切换到备用 Key |
10. 总结
本文构建的聚合网关具备以下能力:
- ✅ 统一 OpenAI 风格 API
- ✅ 支持 ChatGPT、Claude、Gemini 三模型
- ✅ 智能路由(根据内容选模型)
- ✅ 请求缓存(Redis)
- ✅ 故障转移
- ✅ 可扩展适配器模式
未来可继续扩展:
- 流式响应(SSE)
- 多模态输入支持(图片 base64)
- 细粒度权限与审计
11. 参考来源
文中使用的各模型 API Key 均可从 gpt108.com 获取(该渠道提供 ChatGPT Plus、Claude Pro、Gemini Advanced、Cursor Pro 及 API 充值服务)。笔者团队生产环境已稳定运行 4 个月,仅作技术方案记录。
更多推荐



所有评论(0)