快速结论:当请求经由 OpenRouter 路由模型(如 openrouter/auto)并以 stream=True 调用时,流式分块的 model 字段会被 LiteLLM 覆盖成请求的路由名(如 auto),而非 OpenRouter 实际服务的模型。优先排查 CustomStreamWrapper.chunk_creator 中是否只对 Azure 系 provider 回读 chunk 模型。
适用环境:LiteLLM v1.93.2(issue 报告在 main 分支 932a0d615 上复现);部署方式为 pip / Python SDK,未使用 proxy;OPENROUTER_API_KEY 通过环境变量设置。Issue 未提及操作系统、Python、CUDA、PyTorch 或显卡信息。
最快修复方案:暂无确认的一步修复方案。Issue 讨论中的修复方向是让 stream wrapper 对 OpenRouter 像 Azure 一样从 chunk 回读实际服务的模型,并配合聚合与成本回调的回归测试;对应修复已在 PR #49498 合并,升级到包含该修复的 LiteLLM 版本可优先尝试。
注意事项:该合并修复只出现在 Issue 讨论中,未给出可验证的版本号,因此无法确认从哪个版本起生效;升级前请先核对 release notes。另外,若上游 chunk 缺少模型名,不应凭空构造一个可计价的模型标识,否则可能让计费/日志关联到不存在的价格项。
问题场景
用户在 Python SDK 中直接调用 litellm.completion(),使用 OpenRouter 的路由模型 openrouter/auto 并开启 stream=True,遍历返回的 chunk 读取 chunk.model。OpenRouter 返回的原始 SSE 分块中 "model" 字段是实际服务的模型(例如 deepseek/deepseek-v4.1-flash),但消费端拿到的却始终是路由名 auto。同样请求改用 stream=False 时,response.model 能正确返回服务的模型,说明问题只出现在流式路径。
报错原文
[Bug]: OpenRouter streaming chunks report the requested router name instead of the model OpenRouter served
Output: ['auto']
Raw OpenRouter chunks for the same stream carried "model": "deepseek/deepseek-v4.1-flash"
Expected: ['deepseek/deepseek-v4.1-flash']
原因分析
最可能的原因是 CustomStreamWrapper.chunk_creator(litellm/litellm_core_utils/streaming_handler.py 约 1365 行)在构造每个 chunk 的 ModelResponseStream 时会执行 model_response.model = self.model。代码虽然会为 LlmProviders.AZURE 和 AZURE_AI 重新读取 chunk 自带的模型名(以支持 Azure 模型路由),但 OpenRouter 不在该列表中,因此 OpenRouter 路由流被覆盖回请求的别名。由于 stream_chunk_builder 继承了这个错误名称,最终聚合响应和成本回调也会看到 auto,而该名称没有对应的价格条目,导致路由流无法按实际应答模型计价或记录日志。
环境排查
- 确认 LiteLLM 版本:v1.93.2 可复现;issue 提到 current main 932a0d615 仍可复现。
- 确认调用方式为 pip / Python SDK,且
OPENROUTER_API_KEY已在环境变量中设置。 - 确认请求使用了 OpenRouter 路由模型(如
openrouter/auto)且stream=True。 - 确认
streaming_handler.py中回读 chunk 模型的分支是否包含 OpenRouter,或已升级到包含 PR #49498 的版本。 - Issue 未提供操作系统、Python、CUDA、PyTorch、显卡信息,无需据此排查。
解决步骤
- 先按 issue 的最小复现脚本确认现象:设置
OPENROUTER_API_KEY,用litellm.completion(model="openrouter/auto", messages=[{"role": "user", "content": "Say hi"}], max_tokens=16, stream=True)请求,收集chunk.model并去重输出。 - 若输出仅为
['auto'],同时用stream=False发送同样请求,确认response.model是否为 OpenRouter 实际服务的模型(例如deepseek/deepseek-v4.1-flash)。 - 检查当前 LiteLLM 安装中
litellm/litellm_core_utils/streaming_handler.py的chunk_creator:确认其仅针对LlmProviders.AZURE与AZURE_AI回读 chunk 模型,而 OpenRouter 未覆盖。 - 可优先尝试升级到包含 PR #49498 修复的 LiteLLM 版本(该 PR 在 issue 讨论中标记为已合并,但未给出具体版本号,请先在 release notes 中确认)。
- 升级或修复后,增加回归验证:用同一份合成流分别经过 chunk 聚合与成本/日志回调,确认请求别名作为路由元数据保留,同时实际服务模型在流式 chunk 和聚合响应上都得以保留。
- 补充边界用例:上游 chunk 模型为空或缺失时,不应构造一个可计价的模型标识。
验证方法
重新运行 issue 中的复现脚本,print(sorted(seen)) 输出应为实际服务模型(如 ['deepseek/deepseek-v4.1-flash'])而非 ['auto'],并与同一请求 stream=False 时 response.model 的值一致。进一步用 stream_chunk_builder 聚合该流,检查聚合响应的 model 以及成本回调中记录的模型是否为服务模型,同时确认请求的路由别名仍可在路由元数据中取得。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![[Bug]: aiohttp per-host pool exhaustion is silent, requests just time out with no diagnostic](https://www.chat-gpts.plus/wp-content/uploads/2026/11/46864-00d31e5d-768x403.jpg)
![[Feature]: return a guardrail's structured output from /guardrails/apply_guardrail](https://www.chat-gpts.plus/wp-content/uploads/2026/11/49217-245a9cb9-768x403.jpg)
