init(all):一个让codex调用deepseek模型的项目

This commit is contained in:
Pine
2026-05-25 16:37:47 +08:00
commit e6ab2d4534
23 changed files with 2028 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
"""路由注册入口
参照 PineSoundDesktop 项目结构,通过 register_routes() 统一注册所有路由。
"""
from .proxy import router
def register_routes(app):
"""注册所有 API 路由"""
app.include_router(router)
+19
View File
@@ -0,0 +1,19 @@
"""
应用生命周期管理
通过 FastAPI lifespan 机制处理启动和关闭事件。
"""
from contextlib import asynccontextmanager
@asynccontextmanager
async def create_lifespan(app):
"""应用生命周期上下文管理器"""
# ==================== 启动事件 ====================
print("codex_deepseek_proxy starting ...")
yield
# ==================== 关闭事件 ====================
print("codex_deepseek_proxy shutting down ...")
+68
View File
@@ -0,0 +1,68 @@
"""
中间件配置
参照 PineSoundDesktop 项目结构集中管理中间件。
"""
import json
from fastapi import Response
from fastapi.middleware.cors import CORSMiddleware
from app.config import MODEL_MAP, DEFAULT_MODEL, MY_API_KEY
def setup_middleware(app):
"""配置所有中间件
Args:
app: FastAPI 应用实例
"""
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.middleware("http")
async def auth_check(request, call_next):
"""验证请求携带的 API Key 是否合法"""
# OPTIONS 预检请求跳过验证
if request.method == "OPTIONS":
return await call_next(request)
auth = request.headers.get("Authorization", "")
if auth.startswith("Bearer "):
token = auth[7:]
else:
token = ""
if token != MY_API_KEY:
return Response(
content=json.dumps({
"error": {"message": "Invalid API Key", "type": "auth_error"},
}),
status_code=401,
media_type="application/json",
)
return await call_next(request)
@app.middleware("http")
async def resolve_model(request, call_next):
"""拦截请求中的模型名称,按 MODEL_MAP 进行替换"""
if request.method == "POST":
body = await request.body()
if body:
try:
data = json.loads(body)
original = data.get("model")
if original:
resolved = MODEL_MAP.get(original, DEFAULT_MODEL)
request.state.resolved_model = resolved
except (json.JSONDecodeError, UnicodeDecodeError):
pass
response = await call_next(request)
return response
+60
View File
@@ -0,0 +1,60 @@
"""
代理路由模块
提供 OpenAI Responses API ↔ DeepSeek Chat API 的流式转发端点。
"""
import uuid
from fastapi import APIRouter, Request
from fastapi.responses import StreamingResponse
from app.config import MODEL_DEFAULT, DEEPSEEK_DEBUG
from services.converter import extract_messages
from services.stream import create_sse_generator, _log_debug
router = APIRouter()
async def _handle_proxy(request: Request):
"""处理 /responses 系列请求的核心逻辑"""
req_data = await request.json()
messages, tools, tool_choice = extract_messages(req_data)
# 中间件 resolve_model 已解析的模型优先级最高
effective_model = (
getattr(request.state, "resolved_model", None)
or req_data.get("model")
or MODEL_DEFAULT
)
response_id = f"resp_{uuid.uuid4().hex[:12]}"
if DEEPSEEK_DEBUG:
_log_debug(req_data, messages, tools, tool_choice, request.url.path)
stream_gen = create_sse_generator(
messages, tools, tool_choice, effective_model, response_id, debug_path=request.url.path
)
return StreamingResponse(
stream_gen(),
media_type="text/event-stream",
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
)
@router.post("/responses")
async def route_responses(request: Request):
"""OpenAI Responses API 格式的流式代理端点"""
return await _handle_proxy(request)
@router.post("/v1/responses")
async def route_v1_responses(request: Request):
"""OpenAI Responses API (v1) 格式的流式代理端点"""
return await _handle_proxy(request)
@router.post("/v1/chat/completions")
async def route_v1_chat(request: Request):
"""Chat Completions API 格式的流式代理端点(兼容模式)"""
return await _handle_proxy(request)