feat: add derived field support for nested usage data

- Support dot notation in derived expressions (e.g., prompt_tokens_details.cached_tokens)
- Auto-flatten nested dict keys to underscore format for eval
- Calculate uncached_prompt_tokens and cached_tokens from raw usage data
- Test case: qwen3.7-max pricing with derived fields

Test result:
- uncached_prompt_tokens = prompt_tokens - cached_tokens = 1075
- Total cost: 0.007116 元 ✓
This commit is contained in:
yumoqing 2026-06-05 15:04:47 +08:00
parent df1fa2cfe0
commit 022bab8314

View File

@ -529,6 +529,9 @@ order by b.enabled_date desc"""
支持两种格式
1. 旧格式formula 字段eval计算
2. 新格式price_factors + unit_prices + unit自动计算
支持 derived 字段 fields 中定义 derived 表达式从原始 usage 数据计算衍生字段
例如uncached_prompt_tokens.derived = "prompt_tokens - prompt_tokens_details.cached_tokens"
"""
if config_data is None:
e = Exception(f'config_data is None, {yamlstr=}')
@ -549,6 +552,34 @@ order by b.enabled_date desc"""
exception(f'{d} has not "pricings"')
raise Exception(f'定价定义中没有pricing数据')
# 处理 derived 字段:从原始 usage 数据计算衍生字段
for field_name, field_def in d.fields.items():
if not isinstance(field_def, dict):
continue
derived_expr = field_def.get('derived')
if not derived_expr:
continue
# 构建 eval 环境:将 config_data 中的所有字段和嵌套字段展平
# dot notation 转为下划线 keyPython eval 不支持带 dot 的变量名)
eval_env = {}
for k, v in config_data.items():
eval_env[k] = v
if isinstance(v, dict):
for sub_k, sub_v in v.items():
eval_env[f'{k}_{sub_k}'] = sub_v
# 将表达式中的 dot 替换为下划线
processed_expr = derived_expr.replace('.', '_')
try:
result = eval(processed_expr, {}, eval_env)
config_data[field_name] = result
debug(f'derived field {field_name} = {derived_expr} = {result}')
except Exception as e:
debug(f'derived field {field_name} evaluation failed: {derived_expr}, error: {e}')
config_data[field_name] = 0
# 单位映射表
unit_values = d.get('unit_values', {'百万': 1000000, '': 1, '': 1000, '': 1, '': 1, '毫秒': 0.001, '元/百万tokens': 1000000, '元/total_tokens': 1, '元/times': 1})