mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
fix: 统一 input_context_expr 计算口径,移除按 api_format 分支的 CASE 逻辑
input_context_expr() 原先按 OpenAI/Gemini 和 Claude 分支计算输入上下文, 现统一为 input_tokens + cache_read_input_tokens,与 usage 表展示口径一致。 同步更新 admin 和 user_me 路由中的缓存命中率注释,并新增单元测试。
This commit is contained in:
@@ -87,8 +87,8 @@ def _calculate_token_cache_hit_rate(
|
||||
|
||||
Args:
|
||||
total_input_context: 已归一化的总输入上下文 token 数。
|
||||
Claude 格式: input_tokens + cache_read_input_tokens
|
||||
OpenAI/Gemini 格式: input_tokens(已包含 cache_read)
|
||||
由 query.py 的 input_context_expr() 统一计算,固定为
|
||||
input_tokens + cache_read_input_tokens。
|
||||
cache_read_tokens: 缓存读取 token 数
|
||||
"""
|
||||
context = int(total_input_context or 0)
|
||||
@@ -1961,9 +1961,7 @@ def _apply_replay_model_to_body(
|
||||
"""根据目标格式决定是否写入 body.model。"""
|
||||
from src.core.api_format.metadata import resolve_endpoint_definition
|
||||
|
||||
target_meta = (
|
||||
resolve_endpoint_definition(target_api_format) if target_api_format else None
|
||||
)
|
||||
target_meta = resolve_endpoint_definition(target_api_format) if target_api_format else None
|
||||
if target_meta is not None and not target_meta.model_in_body:
|
||||
body.pop("model", None)
|
||||
return
|
||||
@@ -1997,9 +1995,7 @@ class AdminUsageReplayAdapter(AdminApiAdapter):
|
||||
original_api_format.split(":")[0] if ":" in original_api_format else ""
|
||||
)
|
||||
original_request_body = usage_record.get_request_body()
|
||||
body_override_payload = (
|
||||
self.body_override if isinstance(self.body_override, dict) else None
|
||||
)
|
||||
body_override_payload = self.body_override if isinstance(self.body_override, dict) else None
|
||||
override_model: str | None = None
|
||||
if isinstance(body_override_payload, dict):
|
||||
override_val = body_override_payload.get("model")
|
||||
@@ -2262,7 +2258,9 @@ class AdminUsageReplayAdapter(AdminApiAdapter):
|
||||
# envelope 失败仍发送原始体
|
||||
|
||||
# 获取提供商名称
|
||||
provider_name = target_provider_obj.name if target_provider_obj else usage_record.provider_name
|
||||
provider_name = (
|
||||
target_provider_obj.name if target_provider_obj else usage_record.provider_name
|
||||
)
|
||||
|
||||
# 发送请求
|
||||
try:
|
||||
|
||||
@@ -68,7 +68,8 @@ def _calculate_token_cache_hit_rate(total_input_context: int, cache_read_tokens:
|
||||
"""计算缓存命中率。
|
||||
|
||||
Args:
|
||||
total_input_context: 已归一化的总输入上下文 token 数(由 query.py 按 API 格式精确计算)。
|
||||
total_input_context: 已归一化的总输入上下文 token 数
|
||||
(由 query.py 的 input_context_expr() 统一计算,为 input + cache_read)。
|
||||
cache_read_tokens: 缓存读取 token 数。
|
||||
"""
|
||||
context = max(0, int(total_input_context))
|
||||
|
||||
@@ -2,28 +2,25 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from sqlalchemy import Case, case, func
|
||||
from sqlalchemy import case, func
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sqlalchemy.sql.elements import ColumnElement
|
||||
|
||||
from src.core.logger import logger
|
||||
from src.models.database import ApiKey, Usage, User
|
||||
|
||||
|
||||
def input_context_expr() -> Case:
|
||||
"""构造 SQL CASE 表达式,根据 api_format 精确计算每条记录的总输入上下文 token 数。
|
||||
def input_context_expr() -> ColumnElement[int]:
|
||||
"""计算缓存命中率口径下的总输入上下文 token 数。
|
||||
|
||||
- OpenAI/Gemini: input_tokens 已包含 cache_read_input_tokens,直接使用
|
||||
- Claude/未知: input_tokens 不含 cache_read,需要加上
|
||||
为了与 usage 表中“输入 tokens + 缓存读取 tokens”的展示口径保持一致,
|
||||
聚合统计统一使用 `input_tokens + cache_read_input_tokens` 作为分母。
|
||||
"""
|
||||
return case(
|
||||
(
|
||||
Usage.api_format.like("openai:%") | Usage.api_format.like("gemini:%"),
|
||||
Usage.input_tokens,
|
||||
),
|
||||
else_=Usage.input_tokens + Usage.cache_read_input_tokens,
|
||||
)
|
||||
return Usage.input_tokens + Usage.cache_read_input_tokens
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
|
||||
Reference in New Issue
Block a user