mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 09:50:21 +08:00
feat: 实现跨 API 格式自动转换功能
- 新增端点级 format_acceptance_config 配置,控制是否接受跨格式请求 - 重构 EndpointFormDialog 为卡片式布局,支持内联编辑和格式转换开关 - StreamProcessor 实现流式响应的跨格式转换,支持 OpenAI/Claude/Gemini 互转 - CacheAwareScheduler 按端点格式筛选候选,同格式优先于跨格式 - 健康度/熔断按 Provider 端点格式分桶,而非客户端请求格式 - 新增 format_conversion_total 和 format_conversion_duration_seconds 指标 - 新增全局配置 format_conversion_enabled 控制总开关 - Input 组件新增 size="sm" 尺寸选项
This commit is contained in:
@@ -12,11 +12,11 @@ from src.core.api_format import APIFormat
|
||||
from src.core.exceptions import ConcurrencyLimitError
|
||||
from src.core.logger import logger
|
||||
from src.services.health.monitor import health_monitor
|
||||
from src.services.provider.format import normalize_api_format
|
||||
from src.services.rate_limit.adaptive_reservation import get_adaptive_reservation_manager
|
||||
from src.services.request.candidate import RequestCandidateService
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class ExecutionContext:
|
||||
candidate_id: str
|
||||
@@ -103,7 +103,9 @@ class RequestExecutor:
|
||||
# 获取有效的 RPM 限制(自适应或固定)
|
||||
if key.rpm_limit is None:
|
||||
# 自适应模式:使用学习值,未学习时为 None(不限制,等待碰壁学习)
|
||||
effective_key_limit = int(key.learned_rpm_limit) if key.learned_rpm_limit is not None else None
|
||||
effective_key_limit = (
|
||||
int(key.learned_rpm_limit) if key.learned_rpm_limit is not None else None
|
||||
)
|
||||
else:
|
||||
effective_key_limit = int(key.rpm_limit)
|
||||
|
||||
@@ -114,9 +116,11 @@ class RequestExecutor:
|
||||
)
|
||||
dynamic_reservation_ratio = reservation_result.ratio
|
||||
|
||||
logger.debug(f"[Executor] 动态预留: key={key.id[:8]}..., "
|
||||
logger.debug(
|
||||
f"[Executor] 动态预留: key={key.id[:8]}..., "
|
||||
f"ratio={dynamic_reservation_ratio:.0%}, phase={reservation_result.phase}, "
|
||||
f"confidence={reservation_result.confidence:.0%}")
|
||||
f"confidence={reservation_result.confidence:.0%}"
|
||||
)
|
||||
|
||||
async with self.concurrency_manager.rpm_guard(
|
||||
key_id=key.id,
|
||||
@@ -140,12 +144,21 @@ class RequestExecutor:
|
||||
|
||||
context.elapsed_ms = int((time.time() - context.start_time) * 1000)
|
||||
|
||||
provider_api_format = getattr(endpoint, "api_format", None)
|
||||
provider_format_str = (
|
||||
provider_api_format.value
|
||||
if isinstance(provider_api_format, APIFormat)
|
||||
else str(provider_api_format or "")
|
||||
)
|
||||
client_format_str = (
|
||||
api_format.value if isinstance(api_format, APIFormat) else str(api_format)
|
||||
)
|
||||
health_format = normalize_api_format(provider_format_str or client_format_str).value
|
||||
|
||||
health_monitor.record_success(
|
||||
db=self.db,
|
||||
key_id=key.id,
|
||||
api_format=(
|
||||
api_format.value if isinstance(api_format, APIFormat) else api_format
|
||||
),
|
||||
api_format=health_format,
|
||||
response_time_ms=context.elapsed_ms,
|
||||
)
|
||||
|
||||
@@ -180,7 +193,9 @@ class RequestExecutor:
|
||||
"is_cached_user": is_cached_user,
|
||||
"model_name": model_name,
|
||||
"api_format": (
|
||||
api_format.value if isinstance(api_format, APIFormat) else api_format
|
||||
api_format.value
|
||||
if isinstance(api_format, APIFormat)
|
||||
else api_format
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user