mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
refactor: 将 global_priority 和 rate_multiplier 改为按 API 格式配置
- 新增 global_priority_by_format 字段,支持按 API 格式设置全局优先级 - 移除已废弃的 rate_multiplier 字段,统一使用 rate_multipliers - 移除已废弃的 timeout 字段(providers 和 provider_endpoints 表) - 更新调度器以支持按格式的优先级排序 - 同步更新前后端类型定义和 API 接口 - 添加数据库迁移脚本,自动迁移现有数据
This commit is contained in:
@@ -50,7 +50,7 @@ async def update_endpoint_key(
|
||||
- `api_key`: 新的 API Key 原文
|
||||
- `name`: Key 名称
|
||||
- `note`: 备注
|
||||
- `rate_multiplier`: 速率倍数
|
||||
- `rate_multipliers`: 按 API 格式的成本倍率
|
||||
- `internal_priority`: 内部优先级
|
||||
- `rpm_limit`: RPM 限制(设置为 null 可切换到自适应模式)
|
||||
- `allowed_models`: 允许的模型列表
|
||||
@@ -82,8 +82,9 @@ async def get_keys_grouped_by_format(
|
||||
- `name`: Key 名称
|
||||
- `api_key_masked`: 脱敏后的 API Key
|
||||
- `internal_priority`: 内部优先级
|
||||
- `global_priority`: 全局优先级
|
||||
- `rate_multiplier`: 速率倍数
|
||||
- `global_priority_by_format`: 按 API 格式的全局优先级
|
||||
- `format_priority`: 当前格式的优先级
|
||||
- `rate_multipliers`: 按 API 格式的成本倍率
|
||||
- `is_active`: 是否活跃
|
||||
- `circuit_breaker_open`: 熔断器状态
|
||||
- `provider_name`: Provider 名称
|
||||
@@ -367,7 +368,6 @@ class AdminGetKeysGroupedByFormatAdapter(AdminApiAdapter):
|
||||
Provider.is_active.is_(True),
|
||||
)
|
||||
.order_by(
|
||||
ProviderAPIKey.global_priority.asc().nullslast(),
|
||||
ProviderAPIKey.internal_priority.asc(),
|
||||
)
|
||||
.all()
|
||||
@@ -427,8 +427,8 @@ class AdminGetKeysGroupedByFormatAdapter(AdminApiAdapter):
|
||||
"name": key.name,
|
||||
"api_key_masked": masked_key,
|
||||
"internal_priority": key.internal_priority,
|
||||
"global_priority": key.global_priority,
|
||||
"rate_multiplier": key.rate_multiplier,
|
||||
"global_priority_by_format": key.global_priority_by_format,
|
||||
"rate_multipliers": key.rate_multipliers,
|
||||
"is_active": key.is_active,
|
||||
"provider_name": provider.name,
|
||||
"api_formats": api_formats,
|
||||
@@ -438,9 +438,10 @@ class AdminGetKeysGroupedByFormatAdapter(AdminApiAdapter):
|
||||
"request_count": key.request_count,
|
||||
}
|
||||
|
||||
# 将 Key 添加到每个支持的格式分组中,并附加格式特定的健康度数据
|
||||
# 将 Key 添加到每个支持的格式分组中,并附加格式特定的数据
|
||||
health_by_format = key.health_by_format or {}
|
||||
circuit_by_format = key.circuit_breaker_by_format or {}
|
||||
priority_by_format = key.global_priority_by_format or {}
|
||||
provider_id = str(provider.id)
|
||||
for api_format in api_formats:
|
||||
if api_format not in grouped:
|
||||
@@ -451,6 +452,8 @@ class AdminGetKeysGroupedByFormatAdapter(AdminApiAdapter):
|
||||
format_key_info["endpoint_base_url"] = endpoint_base_url_map.get(
|
||||
(provider_id, api_format)
|
||||
)
|
||||
# 添加格式特定的优先级
|
||||
format_key_info["format_priority"] = priority_by_format.get(api_format)
|
||||
# 添加格式特定的健康度数据
|
||||
format_health = health_by_format.get(api_format, {})
|
||||
format_circuit = circuit_by_format.get(api_format, {})
|
||||
@@ -597,8 +600,7 @@ class AdminCreateProviderKeyAdapter(AdminApiAdapter):
|
||||
api_key=encrypted_key,
|
||||
name=self.key_data.name,
|
||||
note=self.key_data.note,
|
||||
rate_multiplier=self.key_data.rate_multiplier,
|
||||
rate_multipliers=self.key_data.rate_multipliers, # 按 API 格式的成本倍率
|
||||
rate_multipliers=self.key_data.rate_multipliers,
|
||||
internal_priority=self.key_data.internal_priority,
|
||||
rpm_limit=self.key_data.rpm_limit,
|
||||
allowed_models=self.key_data.allowed_models if self.key_data.allowed_models else None,
|
||||
|
||||
@@ -47,7 +47,7 @@ class RoutingKeyInfo(BaseModel):
|
||||
name: str
|
||||
masked_key: str = Field("", description="脱敏的 API Key")
|
||||
internal_priority: int = Field(..., description="Key 内部优先级")
|
||||
global_priority: Optional[int] = Field(None, description="全局 Key 优先级")
|
||||
global_priority_by_format: Optional[Dict[str, int]] = Field(None, description="按 API 格式的全局优先级")
|
||||
rpm_limit: Optional[int] = Field(None, description="RPM 限制,null 表示自适应")
|
||||
is_adaptive: bool = Field(False, description="是否为自适应 RPM 模式")
|
||||
effective_rpm: Optional[int] = Field(None, description="有效 RPM 限制")
|
||||
@@ -293,8 +293,14 @@ class AdminGetModelRoutingPreviewAdapter(AdminApiAdapter):
|
||||
for ep in provider_endpoints:
|
||||
# 获取该 Endpoint 格式对应的 Keys
|
||||
ep_keys = keys_by_endpoint.get(ep.api_format or "", [])
|
||||
# 按优先级排序
|
||||
ep_keys.sort(key=lambda k: (k.global_priority or 999, k.internal_priority or 0))
|
||||
# 按优先级排序(使用当前格式的全局优先级)
|
||||
api_format = ep.api_format or ""
|
||||
def get_key_priority(k: ProviderAPIKey) -> tuple[int, int]:
|
||||
format_priority = 999
|
||||
if k.global_priority_by_format and api_format in k.global_priority_by_format:
|
||||
format_priority = k.global_priority_by_format[api_format]
|
||||
return (format_priority, k.internal_priority or 0)
|
||||
ep_keys.sort(key=get_key_priority)
|
||||
|
||||
key_infos = []
|
||||
for key in ep_keys:
|
||||
@@ -353,7 +359,7 @@ class AdminGetModelRoutingPreviewAdapter(AdminApiAdapter):
|
||||
name=key.name or "",
|
||||
masked_key=masked_key,
|
||||
internal_priority=key.internal_priority or 0,
|
||||
global_priority=key.global_priority,
|
||||
global_priority_by_format=key.global_priority_by_format,
|
||||
rpm_limit=key.rpm_limit,
|
||||
is_adaptive=is_adaptive,
|
||||
effective_rpm=effective_rpm,
|
||||
|
||||
@@ -213,12 +213,11 @@ async def list_affinities(
|
||||
- `provider_id`: Provider ID
|
||||
- `provider_name`: Provider 显示名称
|
||||
- `endpoint_id`: Endpoint ID
|
||||
- `endpoint_api_format`: Endpoint API 格式
|
||||
- `endpoint_url`: Endpoint 基础 URL
|
||||
- `key_id`: Key ID
|
||||
- `key_name`: Key 名称
|
||||
- `key_prefix`: 脱敏后的 Provider Key
|
||||
- `rate_multiplier`: 速率倍数
|
||||
- `rate_multipliers`: 按 API 格式的成本倍率
|
||||
- `global_model_id`: GlobalModel ID
|
||||
- `model_name`: 模型名称
|
||||
- `model_display_name`: 模型显示名称
|
||||
@@ -821,14 +820,11 @@ class AdminListAffinitiesAdapter(AdminApiAdapter):
|
||||
"provider_id": provider_id,
|
||||
"provider_name": provider.name if provider else None,
|
||||
"endpoint_id": endpoint_id,
|
||||
"endpoint_api_format": (
|
||||
endpoint.api_format if endpoint and endpoint.api_format else None
|
||||
),
|
||||
"endpoint_url": endpoint.base_url if endpoint else None,
|
||||
"key_id": key_id,
|
||||
"key_name": key.name if key else None,
|
||||
"key_prefix": provider_key_masked,
|
||||
"rate_multiplier": key.rate_multiplier if key else 1.0,
|
||||
"rate_multipliers": key.rate_multipliers if key else None,
|
||||
"global_model_id": affinity.get("model_name"), # 原始的 global_model_id
|
||||
"model_name": (
|
||||
global_model_map.get(affinity.get("model_name")).name
|
||||
|
||||
@@ -803,10 +803,9 @@ class AdminExportConfigAdapter(AdminApiAdapter):
|
||||
"name": key.name,
|
||||
"note": key.note,
|
||||
"api_formats": key.api_formats or [],
|
||||
"rate_multiplier": key.rate_multiplier,
|
||||
"rate_multipliers": key.rate_multipliers,
|
||||
"internal_priority": key.internal_priority,
|
||||
"global_priority": key.global_priority,
|
||||
"global_priority_by_format": key.global_priority_by_format,
|
||||
"rpm_limit": key.rpm_limit,
|
||||
"allowed_models": key.allowed_models,
|
||||
"capabilities": key.capabilities,
|
||||
@@ -1159,10 +1158,9 @@ class AdminImportConfigAdapter(AdminApiAdapter):
|
||||
api_key=encrypted_key,
|
||||
name=key_data.get("name") or "Imported Key",
|
||||
note=key_data.get("note"),
|
||||
rate_multiplier=key_data.get("rate_multiplier", 1.0),
|
||||
rate_multipliers=key_data.get("rate_multipliers"),
|
||||
internal_priority=key_data.get("internal_priority", 50),
|
||||
global_priority=key_data.get("global_priority"),
|
||||
global_priority_by_format=key_data.get("global_priority_by_format"),
|
||||
rpm_limit=key_data.get("rpm_limit"),
|
||||
allowed_models=key_data.get("allowed_models"),
|
||||
capabilities=key_data.get("capabilities"),
|
||||
|
||||
Reference in New Issue
Block a user