[Bug]: Databricks service_tier is dropped in request translation, streaming, and pricing

在 LiteLLM 1.100.0 中调用 Databricks 模型并传入 service_tier="priority" 时,该字段会在请求翻译、参数过滤、流式聚合和计费环节被丢弃,导致 priority 费率未生效或返回层级丢失。优先排查 Databricks 的 supported para

快速结论:在 LiteLLM 1.100.0 中调用 Databricks 模型并传入 service_tier="priority" 时,该字段会在请求翻译、参数过滤、流式聚合和计费环节被丢弃,导致 priority 费率未生效或返回层级丢失。优先排查 Databricks 的 supported params 白名单、Responses→Chat 请求桥接、cost_calculator 是否透传 service_tier,以及流式 chunk 聚合是否保留终结 chunk 上的层级。

适用环境:LiteLLM litellm[proxy]==1.100.0;Python 3.11 独立虚拟环境;使用 Databricks 提供方(provider)的 Chat/Responses 调用路径。复现测试不需要 API 凭证、真实 provider 调用、代理或下游仓库文件。

最快修复方案:暂无确认的一步修复方案。Issue 中给出的是需要同时处理请求翻译、参数过滤、流式聚合和计费的多处源码修改,并附有可在干净 1.100.0 上运行的 pytest 复现文件(干净环境下 6 失败、7 通过,应用本地修复后 13 项全部通过)。

注意事项:不能只修 pricing。Issue 明确指出:若只修计费,当 Databricks 在回退后实际返回 service_tier="default" 时,仍可能按请求的 priority 费率计费(过度计费)。另外,返回的具体 default 层级应覆盖请求的 priority;该行为在修复后仍需保持,否则会破坏现有的 fallback 对照用例。

问题场景

用户在 LiteLLM 1.100.0 中通过 Databricks provider 调用模型,并设置 service_tier="priority"(通过显式参数、请求参数或响应返回)。触发问题的具体环节包括:

  • 计算 completion 成本时,priority 的输入/输出/cache-read 费率未被使用;
  • 将 Responses API 请求转换为 Chat Completion 请求时,service_tier 字段丢失(测试断言出现 KeyError);
  • Databricks 参数映射在 drop_params=True 时丢弃 service_tier;
  • 流式响应中层级只出现在最终的 usage-only chunk 时,聚合后的响应层级为 None,而不是预期的 "default"。

复现使用合成模型价格与响应对象,注册一个 databricks/offline-tier-test 模型(标准费率 $1/$4 每百万输入/输出 token、$0.20 每百万 cached 输入 token,priority 为其两倍),100 输入 token(其中 20 cached)、50 输出 token。标准价 $0.000284,priority 应为 $0.000568。

报错原文

[Bug]: Databricks service_tier is dropped in request translation, streaming, and pricing

Observed results: 6 failed, 7 passed.

Priority pricing from explicit argument, request params, or response
Expected: $0.000568
Actual: $0.000284 in all three cases

Responses-to-Chat request translation
Expected: service_tier="priority" preserved
Actual: Field absent (KeyError)

Databricks parameter mapping with drop_params=True
Expected: service_tier="priority" preserved
Actual: Field absent (KeyError)

Stream with tier on terminal usage-only chunk
Expected: Aggregated response has service_tier="default"
Actual: None

原因分析

Issue 给出的根因定位(均以 LiteLLM 1.100.0 源码为准):

  • litellm/llms/databricks/chat/transformation.py 中 DatabricksConfig.get_supported_openai_params(约第 259 行)未把 service_tier 列入支持的参数列表。
  • litellm/responses/litellm_completion_transformation/transformation.py 中 transform_responses_api_request_to_chat_completion_request(约第 340 行)读取的是 kwargs.get("service_tier"),而层级实际位于 responses_api_request 中;仅补上 Databricks 白名单并不能修复这个更早发生的丢失。
  • litellm/cost_calculator.py(约第 623 行)与 litellm/llms/databricks/cost_calculator.py(约第 34 行)中的 Databricks 分发/辅助逻辑没有把 service_tier 传给 generic_cost_per_token。
  • litellm/litellm_core_utils/streaming_chunk_builder_utils.py 的流聚合未携带返回的层级,包括层级只在最终 usage chunk 上出现的情况;Databricks 响应解析、stream-wrapper 重建以及 Chat/Responses/Messages 转换同样需要保留该字段才能端到端记账。
  • completion_cost 当前让请求层级优先于返回层级;对 Databricks 而言,具体返回的 default 应覆盖请求的 priority。

这些缺陷需要一起处理。Issue 明确警告:单独修复定价会在 Databricks 回退后返回 service_tier="default" 时错误应用 priority 费率。

环境排查

  • 确认 LiteLLM 版本为 1.100.0(Issue 复现版本)。
  • 确认 Python 版本为 3.11,且使用独立虚拟环境(避免与下游仓库依赖互相干扰)。
  • 确认安装包含 proxy extra:litellm[proxy]==1.100.0,并安装 pytest。
  • 确认运行时设置 LITELLM_LOCAL_MODEL_COST_MAP=True,以使用内置 cost map。
  • 确认调用路径覆盖到了 Databricks provider 的 Chat/Responses 转换、参数映射、流聚合与 cost 计算。
  • 无需 API 凭证或真实 provider 调用;如出现失败,优先区分是请求翻译、参数过滤、流聚合还是计费环节。

解决步骤

  1. 保存 Issue 评论中提供的测试文件为 test_databricks_service_tier_upstream.py,放在任何已有 checkout 之外。
  2. 创建隔离环境并安装依赖:
    python3 -m venv /tmp/databricks-tier-repro
    /tmp/databricks-tier-repro/bin/pip install 'litellm[proxy]==1.100.0' pytest
  3. 运行复现测试,确认基线为 6 failed、7 passed:
    LITELLM_LOCAL_MODEL_COST_MAP=True /tmp/databricks-tier-repro/bin/python -m pytest -q test_databricks_service_tier_upstream.py
  4. 对照失败用例定位需要修改的环节:三个 priority 定价用例(explicit/request/response 三种来源)、两个请求映射用例(Responses→Chat 桥接与 drop_params=True 下的参数映射)、一个流聚合用例(终结 usage chunk 上的层级)。
  5. 在本地修复中同时处理以下位置:把 service_tier 加入 Databricks supported params 白名单;修正 Responses→Chat 转换读取 responses_api_request 中的层级;让 Databricks cost 分发/辅助逻辑把 service_tier 传给 generic_cost_per_token;让流聚合(含仅出现在最终 usage chunk 的情况)与响应解析、stream-wrapper 重建、Chat/Responses/Messages 转换保留层级。
  6. 调整 completion_cost 的层级优先级:对 Databricks,让具体返回的 default 覆盖请求的 priority。
  7. 重新运行同一测试文件,确认 13 项全部通过,尤其是原本通过的 7 个对照用例(默认定价、旧版 Databricks 模型解析、返回 default 的 fallback 对照)仍然通过。

如果只是想临时验证优先级费率是否被读取,可优先尝试在本地注册模型时显式提供 input_cost_per_token_priority/output_cost_per_token_priority/cache_read_input_token_cost_priority,并分别从显式参数、optional_params 和响应对象三个来源传入层级,观察 litellm.completion_cost 结果是否符合预期;但这只是验证手段,不构成已验证的修复方案。

验证方法

使用同一 test_databricks_service_tier_upstream.py 在干净环境与修复后环境分别运行 pytest -q:干净 1.100.0 应为 6 failed、7 passed;应用修复后应为 13 passed。重点确认:

  • priority 定价在 explicit、request、response 三种来源下均返回约 $0.000568,而非 $0.000284;
  • Responses→Chat 请求翻译结果中 result["service_tier"] == "priority";
  • drop_params=True 时 Databricks 参数映射仍保留 service_tier;
  • 层级只出现在终结 usage chunk 时,stream_chunk_builder 聚合结果保留 "default";
  • 返回 default 的 fallback 对照用例仍按标准费率 $0.0003 计费,不因 priority 请求而超额计费。

参考来源

BerriAI/litellm #41834

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 29003

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注