diff --git a/pricing/pricing.py b/pricing/pricing.py index dd556cf..fee627b 100644 --- a/pricing/pricing.py +++ b/pricing/pricing.py @@ -537,7 +537,8 @@ order by b.enabled_date desc""" e = Exception(f'config_data is None, {yamlstr=}') exception(f'{e=}') raise e - config_data = config_data.copy() + # 用 DictObject 包装,支持 dot notation 属性访问(derived 表达式依赖此特性) + config_data = DictObject(**config_data) d = None try: d = yaml.safe_load(yamlstr) @@ -553,6 +554,7 @@ order by b.enabled_date desc""" raise Exception(f'定价定义中没有pricing数据') # 处理 derived 字段:从原始 usage 数据计算衍生字段 + # DictObject 支持属性访问嵌套字段,如 prompt_tokens_details.cached_tokens for field_name, field_def in d.fields.items(): if not isinstance(field_def, dict): continue @@ -560,20 +562,14 @@ order by b.enabled_date desc""" if not derived_expr: continue - # 构建 eval 环境:将 config_data 中的所有字段和嵌套字段展平 - # dot notation 转为下划线 key(Python 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('.', '_') + # eval 环境:用 config_data 本身(DictObject 支持 dot notation 属性访问) + eval_env = dict(config_data) + # 将顶层 key 也注入 eval 环境,使 eval 能找到嵌套属性 + for k in list(config_data.keys()): + eval_env[k] = config_data[k] try: - result = eval(processed_expr, {}, eval_env) + result = eval(derived_expr, {}, eval_env) config_data[field_name] = result debug(f'derived field {field_name} = {derived_expr} = {result}') except Exception as e: