feat: 使用量轮询接口添加 API 格式转换字段

- 前端:添加 api_format、endpoint_api_format、has_format_conversion 类型定义
- 前端:轮询时同步更新格式转换相关字段
- 后端:查询时返回格式转换字段,包含历史数据兼容逻辑
- 后端:优化 import 位置提升性能
This commit is contained in:
fawney19
2026-01-28 11:24:37 +08:00
parent 5c80be92c9
commit bd843bca61
4 changed files with 33 additions and 0 deletions

View File

@@ -223,6 +223,9 @@ export const meApi = {
rate_multiplier?: number | null rate_multiplier?: number | null
response_time_ms: number | null response_time_ms: number | null
first_byte_time_ms: number | null first_byte_time_ms: number | null
api_format?: string | null
endpoint_api_format?: string | null
has_format_conversion?: boolean | null
}> }>
}> { }> {
const params = ids ? { ids } : {} const params = ids ? { ids } : {}

View File

@@ -201,6 +201,9 @@ export const usageApi = {
first_byte_time_ms: number | null first_byte_time_ms: number | null
provider?: string | null provider?: string | null
api_key_name?: string | null api_key_name?: string | null
api_format?: string | null
endpoint_api_format?: string | null
has_format_conversion?: boolean | null
}> }>
}> { }> {
const params = ids?.length ? { ids: ids.join(',') } : {} const params = ids?.length ? { ids: ids.join(',') } : {}

View File

@@ -290,6 +290,10 @@ async function pollActiveRequests() {
record.rate_multiplier = update.rate_multiplier ?? undefined record.rate_multiplier = update.rate_multiplier ?? undefined
record.response_time_ms = update.response_time_ms ?? undefined record.response_time_ms = update.response_time_ms ?? undefined
record.first_byte_time_ms = update.first_byte_time_ms ?? undefined record.first_byte_time_ms = update.first_byte_time_ms ?? undefined
// API 格式/格式转换streaming 时已可确定,轮询时同步更新
if (update.api_format !== undefined) record.api_format = update.api_format
if (update.endpoint_api_format !== undefined) record.endpoint_api_format = update.endpoint_api_format
if (update.has_format_conversion !== undefined) record.has_format_conversion = update.has_format_conversion
// 管理员接口返回额外字段 // 管理员接口返回额外字段
if ('provider' in update && typeof update.provider === 'string') { if ('provider' in update && typeof update.provider === 'string') {
record.provider = update.provider record.provider = update.provider

View File

@@ -10,6 +10,7 @@ from typing import Any, Dict, List, Optional, Tuple
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from src.core.api_format.metadata import can_passthrough
from src.core.logger import logger from src.core.logger import logger
from src.models.database import ApiKey, Provider, ProviderAPIKey, Usage, User, UserRole from src.models.database import ApiKey, Provider, ProviderAPIKey, Usage, User, UserRole
from src.services.model.cost import ModelCostService from src.services.model.cost import ModelCostService
@@ -1959,6 +1960,10 @@ class UsageService:
Usage.first_byte_time_ms, # 首字时间 (TTFB) Usage.first_byte_time_ms, # 首字时间 (TTFB)
Usage.created_at, Usage.created_at,
Usage.provider_endpoint_id, Usage.provider_endpoint_id,
# API 格式 / 格式转换streaming 状态时已可确定)
Usage.api_format,
Usage.endpoint_api_format,
Usage.has_format_conversion,
) )
# 管理员轮询:可附带 provider 与上游 key 名称(注意:不要在普通用户接口暴露上游 key 信息) # 管理员轮询:可附带 provider 与上游 key 名称(注意:不要在普通用户接口暴露上游 key 信息)
@@ -2008,6 +2013,18 @@ class UsageService:
result: List[Dict[str, Any]] = [] result: List[Dict[str, Any]] = []
for r in records: for r in records:
api_format = getattr(r, "api_format", None)
endpoint_api_format = getattr(r, "endpoint_api_format", None)
has_format_conversion = getattr(r, "has_format_conversion", None)
# 兼容历史数据:当 streaming 状态已拿到两个格式但 has_format_conversion 为空时,回填推断结果
if (
has_format_conversion is None
and api_format
and endpoint_api_format
):
has_format_conversion = not can_passthrough(api_format, endpoint_api_format)
item: Dict[str, Any] = { item: Dict[str, Any] = {
"id": r.id, "id": r.id,
"status": "failed" if r.id in timeout_ids else r.status, "status": "failed" if r.id in timeout_ids else r.status,
@@ -2021,6 +2038,12 @@ class UsageService:
"response_time_ms": r.response_time_ms, "response_time_ms": r.response_time_ms,
"first_byte_time_ms": r.first_byte_time_ms, # 首字时间 (TTFB) "first_byte_time_ms": r.first_byte_time_ms, # 首字时间 (TTFB)
} }
if api_format:
item["api_format"] = api_format
if endpoint_api_format:
item["endpoint_api_format"] = endpoint_api_format
if has_format_conversion is not None:
item["has_format_conversion"] = bool(has_format_conversion)
if include_admin_fields: if include_admin_fields:
item["provider"] = r.provider_name item["provider"] = r.provider_name
item["api_key_name"] = r.api_key_name item["api_key_name"] = r.api_key_name