File size: 3,605 Bytes
fe71981
9f2b1d2
 
fe71981
 
9f2b1d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fe71981
9f2b1d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fe71981
9f2b1d2
 
 
 
 
 
 
 
fe71981
9f2b1d2
 
 
 
 
 
fe71981
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9f2b1d2
 
 
fe71981
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# main.py (v7.2 终极版 - 包含模型列表接口)

import traceback
import time
from typing import Optional, List, Dict, Any

from fastapi import FastAPI, Request, HTTPException, Depends, Header

from app.core.config import settings
from app.providers.text_provider import TextProvider

app = FastAPI(
    title=settings.APP_NAME,
    version=settings.APP_VERSION,
    description=settings.DESCRIPTION
)

# 只需一个全能的 Provider
text_provider = TextProvider()


# --- 认证依赖项 (保持不变) ---
async def verify_api_key(authorization: Optional[str] = Header(None)):
    """
    检查 API 密钥的依赖项。
    如果设置了 API_MASTER_KEY,则请求头中必须包含正确的密钥。
    """
    # 如果 .env 或 docker-compose.yml 中没有配置 API_MASTER_KEY,则跳过认证
    if not settings.API_MASTER_KEY:
        print("警告:未配置 API_MASTER_KEY,服务将对所有请求开放。")
        return

    # 如果配置了密钥,但请求头中没有 Authorization,则拒绝
    if authorization is None:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized: Missing Authorization header.",
        )
    
    # 检查认证方案和密钥是否正确
    try:
        scheme, token = authorization.split()
        if scheme.lower() != "bearer":
            raise ValueError("Invalid scheme")
    except ValueError:
        raise HTTPException(
            status_code=401,
            detail="Invalid authentication scheme. Use 'Bearer <your_api_key>'.",
        )
    
    # 核心验证:将传入的 token 与我们的主密钥进行安全比较
    if token != settings.API_MASTER_KEY:
        raise HTTPException(
            status_code=403,
            detail="Forbidden: Invalid API Key.",
        )
    # 认证通过,请求将继续被处理


# --- 核心聊天接口 (保持不变) ---
@app.post("/v1/chat/completions", dependencies=[Depends(verify_api_key)])
async def chat_completions(request: Request):
    """
    终极路由:所有请求都交给全能的 TextProvider 处理。
    在处理前会先通过 verify_api_key 进行认证。
    """
    try:
        request_data = await request.json()
        print("接收到聊天请求,认证通过,路由到全能的 TextProvider...")
        return await text_provider.chat_completion(request_data, request)
    except Exception as e:
        traceback.print_exc()
        raise HTTPException(status_code=500, detail=f"主路由发生内部服务器错误: {str(e)}")


# --- 【⭐ 新增功能 ⭐】模型列表接口 ---
@app.get("/v1/models", dependencies=[Depends(verify_api_key)])
async def list_models():
    """
    新增的接口,用于返回兼容OpenAI格式的模型列表。
    它会读取 config.py 中的 SUPPORTED_MODELS 列表。
    """
    print("接收到模型列表请求,认证通过...")
    
    # 从我们的配置文件中获取模型列表
    model_names: List[str] = settings.SUPPORTED_MODELS
    
    # 将模型列表包装成OpenAI API兼容的格式
    model_data: List[Dict[str, Any]] = []
    for name in model_names:
        model_data.append({
            "id": name,
            "object": "model",
            "created": int(time.time()),
            "owned_by": "system"
        })
        
    return {
        "object": "list",
        "data": model_data
    }


# --- 根路由 (保持不变) ---
@app.get("/")
def root():
    """根路由,提供服务基本信息,无需认证。"""
    return {"message": f"Welcome to {settings.APP_NAME}", "version": settings.APP_VERSION}