chore: 升级到 Python 3.14 并现代化代码

- 升级 Docker 基础镜像从 Python 3.12 到 3.14
- 更新 pyproject.toml 支持 Python 3.13/3.14
- 移除 Python 3.8/3.9/3.10/3.11 分类器
- 更新 black 和 mypy 配置目标版本
- 将 get_event_loop() 替换为 get_running_loop() 加上 RuntimeError 处理
- 简化 compute_cost_sync 中的 asyncio.run 使用
- Dict/List/Tuple/Set → dict/list/tuple/set (PEP 585)
- Optional[T] → T | None (PEP 604)
- Union[A, B] → A | B (PEP 604)
- 移除废弃的 typing 导入
- 移除不必要的字符串引号注解
This commit is contained in:
AAEE86
2026-01-30 03:10:21 +08:00
parent 3e75bc8964
commit 24d24f6829
255 changed files with 4062 additions and 4173 deletions

View File

@@ -4,7 +4,6 @@
import uuid
from datetime import datetime, timezone
from typing import List, Optional
from sqlalchemy.orm import Session
@@ -22,16 +21,16 @@ class RequestCandidateService:
request_id: str,
candidate_index: int,
retry_index: int = 0, # 新增:重试序号
user_id: Optional[str] = None,
api_key_id: Optional[str] = None,
provider_id: Optional[str] = None,
endpoint_id: Optional[str] = None,
key_id: Optional[str] = None,
user_id: str | None = None,
api_key_id: str | None = None,
provider_id: str | None = None,
endpoint_id: str | None = None,
key_id: str | None = None,
status: str = "available",
skip_reason: Optional[str] = None,
skip_reason: str | None = None,
is_cached: bool = False,
extra_data: Optional[dict] = None,
required_capabilities: Optional[dict] = None,
extra_data: dict | None = None,
required_capabilities: dict | None = None,
) -> RequestCandidate:
"""
创建候选记录
@@ -116,7 +115,7 @@ class RequestCandidateService:
db: Session,
candidate_id: str,
status_code: int = 200,
concurrent_requests: Optional[int] = None,
concurrent_requests: int | None = None,
) -> None:
"""
标记候选为流式传输中
@@ -144,8 +143,8 @@ class RequestCandidateService:
candidate_id: str,
status_code: int,
latency_ms: int,
concurrent_requests: Optional[int] = None,
extra_data: Optional[dict] = None,
concurrent_requests: int | None = None,
extra_data: dict | None = None,
) -> None:
"""
标记候选执行成功
@@ -180,10 +179,10 @@ class RequestCandidateService:
candidate_id: str,
error_type: str,
error_message: str,
status_code: Optional[int] = None,
latency_ms: Optional[int] = None,
concurrent_requests: Optional[int] = None,
extra_data: Optional[dict] = None,
status_code: int | None = None,
latency_ms: int | None = None,
concurrent_requests: int | None = None,
extra_data: dict | None = None,
) -> None:
"""
标记候选执行失败
@@ -218,9 +217,9 @@ class RequestCandidateService:
db: Session,
candidate_id: str,
status_code: int = 499,
latency_ms: Optional[int] = None,
concurrent_requests: Optional[int] = None,
extra_data: Optional[dict] = None,
latency_ms: int | None = None,
concurrent_requests: int | None = None,
extra_data: dict | None = None,
) -> None:
"""
标记候选被客户端取消
@@ -248,7 +247,7 @@ class RequestCandidateService:
@staticmethod
def mark_candidate_skipped(
db: Session, candidate_id: str, skip_reason: Optional[str] = None
db: Session, candidate_id: str, skip_reason: str | None = None
) -> None:
"""
标记候选为已跳过
@@ -267,7 +266,7 @@ class RequestCandidateService:
get_batch_committer().mark_dirty(db)
@staticmethod
def get_candidates_by_request_id(db: Session, request_id: str) -> List[RequestCandidate]:
def get_candidates_by_request_id(db: Session, request_id: str) -> list[RequestCandidate]:
"""
获取请求的所有候选记录

View File

@@ -4,7 +4,9 @@
import time
from dataclasses import dataclass
from typing import Any, Callable, Optional, Union
from typing import Any
from collections.abc import Callable
from sqlalchemy.orm import Session
@@ -24,12 +26,12 @@ class ExecutionContext:
provider_id: str
endpoint_id: str
key_id: str
user_id: Optional[str]
api_key_id: Optional[str]
user_id: str | None
api_key_id: str | None
is_cached_user: bool
start_time: Optional[float] = None
elapsed_ms: Optional[int] = None
concurrent_requests: Optional[int] = None
start_time: float | None = None
elapsed_ms: int | None = None
concurrent_requests: int | None = None
@dataclass
@@ -59,8 +61,8 @@ class RequestExecutor:
candidate_index: int,
user_api_key,
request_func: Callable,
request_id: Optional[str],
api_format: Union[str, APIFormat],
request_id: str | None,
api_format: str | APIFormat,
model_name: str,
is_stream: bool = False,
) -> ExecutionResult:

View File

@@ -13,9 +13,11 @@
- ChatAdapterBase 使用 RequestResult 处理异常响应
"""
from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, AsyncIterator, Dict, Optional
from typing import Any
from collections.abc import AsyncIterator
class RequestStatus(Enum):
@@ -50,20 +52,20 @@ class RequestMetadata:
model: str = "unknown"
# Provider 追踪信息
provider_id: Optional[str] = None
provider_endpoint_id: Optional[str] = None
provider_api_key_id: Optional[str] = None
provider_id: str | None = None
provider_endpoint_id: str | None = None
provider_api_key_id: str | None = None
# 请求/响应头
provider_request_headers: Dict[str, str] = field(default_factory=dict)
provider_response_headers: Dict[str, str] = field(default_factory=dict)
provider_request_headers: dict[str, str] = field(default_factory=dict)
provider_response_headers: dict[str, str] = field(default_factory=dict)
# 其他元数据
attempt_id: Optional[str] = None
original_model: Optional[str] = None # 用户请求的原始模型名(用于价格计算)
attempt_id: str | None = None
original_model: str | None = None # 用户请求的原始模型名(用于价格计算)
# Provider 响应元数据(存储 provider 返回的额外信息,如 Gemini 的 modelVersion
response_metadata: Dict[str, Any] = field(default_factory=dict)
response_metadata: dict[str, Any] = field(default_factory=dict)
def with_provider_info(
self,
@@ -71,7 +73,7 @@ class RequestMetadata:
provider_id: str,
provider_endpoint_id: str,
provider_api_key_id: str,
) -> "RequestMetadata":
) -> RequestMetadata:
"""返回包含 Provider 信息的新 RequestMetadata"""
return RequestMetadata(
api_format=self.api_format,
@@ -87,7 +89,7 @@ class RequestMetadata:
response_metadata=self.response_metadata,
)
def with_response_headers(self, headers: Dict[str, str]) -> "RequestMetadata":
def with_response_headers(self, headers: dict[str, str]) -> RequestMetadata:
"""返回包含响应头的新 RequestMetadata"""
return RequestMetadata(
api_format=self.api_format,
@@ -151,8 +153,8 @@ class RequestResult:
metadata: RequestMetadata
# 响应相关
response_data: Optional[Any] = None # 成功时的响应数据
stream: Optional[AsyncIterator[str]] = None # 流式响应
response_data: Any | None = None # 成功时的响应数据
stream: AsyncIterator[str] | None = None # 流式响应
# 使用量和费用
usage: UsageInfo = field(default_factory=UsageInfo)
@@ -160,16 +162,16 @@ class RequestResult:
# 错误信息
status_code: int = 200
error_message: Optional[str] = None
error_type: Optional[str] = None
error_message: str | None = None
error_type: str | None = None
# 计时
response_time_ms: int = 0
# 请求信息(用于记录)
is_stream: bool = False
request_headers: Dict[str, str] = field(default_factory=dict)
request_body: Dict[str, Any] = field(default_factory=dict)
request_headers: dict[str, str] = field(default_factory=dict)
request_body: dict[str, Any] = field(default_factory=dict)
@property
def is_success(self) -> bool:
@@ -191,7 +193,7 @@ class RequestResult:
usage: UsageInfo,
response_time_ms: int,
is_stream: bool = False,
) -> "RequestResult":
) -> RequestResult:
"""创建成功的请求结果"""
return cls(
status=RequestStatus.SUCCESS,
@@ -212,7 +214,7 @@ class RequestResult:
error_type: str,
response_time_ms: int,
is_stream: bool = False,
) -> "RequestResult":
) -> RequestResult:
"""创建失败的请求结果"""
return cls(
status=RequestStatus.FAILED,
@@ -229,9 +231,9 @@ class RequestResult:
cls,
metadata: RequestMetadata,
response_time_ms: int,
usage: Optional[UsageInfo] = None,
usage: UsageInfo | None = None,
is_stream: bool = False,
) -> "RequestResult":
) -> RequestResult:
"""创建客户端取消的请求结果"""
return cls(
status=RequestStatus.CANCELLED,
@@ -252,7 +254,7 @@ class RequestResult:
model: str,
response_time_ms: int,
is_stream: bool = False,
) -> "RequestResult":
) -> RequestResult:
"""从异常创建失败的请求结果"""
# 尝试从异常中提取 metadata
existing_metadata = getattr(exception, "request_metadata", None)
@@ -338,7 +340,7 @@ class StreamWithMetadata:
self,
stream: AsyncIterator[str],
metadata: RequestMetadata,
response_headers_container: Optional[Dict[str, Any]] = None,
response_headers_container: dict[str, Any] | None = None,
):
self.stream = stream
self.metadata = metadata