From 89153fdf80c061f19464ce05ff6fbd8443b84433 Mon Sep 17 00:00:00 2001 From: NayukiChiba Date: Wed, 27 May 2026 21:13:40 +0800 Subject: [PATCH] fix: 8267 mimo reasoning content (#8327) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(openai): 为MiMo推理模型自动补充reasoning_content字段 - 消息过滤时增加reasoning_content判断,保留仅含思考内容的assistant消息 - 自动为MiMo推理模型的assistant历史消息注入空reasoning_content,满足API要求 - 通过模型名称集合和xiaomimimo.com端点双重判断是否为MiMo推理模型 - 添加单元测试覆盖不同模型识别、字段注入、端点检测和已有内容保留等场景 * fix(openai): 移除MiMo推理模型检测中的端点主机名判断 - 回退通过xiaomimimo.com主机名自动识别MiMo推理模型的逻辑 - 仅保留基于模型名称集合的判断方式,避免误判非MiMo模型 - 删除对应主机名检测的单元测试用例 * test(openai): 补充MiMo推理模型仅含reasoning_content消息不过滤的单元测试 - 添加test_mimo_filter_preserves_reasoning_only_assistant_message参数化测试 - 验证仅有reasoning_content的assistant消息不会被_sanitize过滤 - 确保包含reasoning_content的空content消息仍保留在对话历史中 * Update test_openai_source.py --------- Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com> --- .../core/provider/sources/openai_source.py | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/astrbot/core/provider/sources/openai_source.py b/astrbot/core/provider/sources/openai_source.py index 117cfb492..158584698 100644 --- a/astrbot/core/provider/sources/openai_source.py +++ b/astrbot/core/provider/sources/openai_source.py @@ -550,8 +550,9 @@ class ProviderOpenAIOfficial(Provider): content = msg.get("content") tool_calls = msg.get("tool_calls") + reasoning_content = msg.get("reasoning_content") - if _is_empty(content) and not tool_calls: + if _is_empty(content) and not tool_calls and not reasoning_content: logger.warning(f"过滤第 {idx} 条空 assistant 消息 (无工具调用)") continue @@ -1015,6 +1016,16 @@ class ProviderOpenAIOfficial(Provider): model in deepseek_reasoning_models or "api.deepseek.com" in self.client.base_url.host ) + # MiMo 推理模型(MiMo-V2.5-Pro / MiMo-V2.5 / MiMo-V2-Pro / MiMo-V2-Omni / MiMo-V2-Flash) + # 要求 assistant 历史消息必须回传 reasoning_content,否则返回 400 + mimo_reasoning_models = { + "mimo-v2.5-pro", + "mimo-v2.5", + "mimo-v2-pro", + "mimo-v2-omni", + "mimo-v2-flash", + } + is_mimo_reasoning = model in mimo_reasoning_models for message in payloads.get("messages", []): if message.get("role") == "assistant" and isinstance( message.get("content"), list @@ -1043,6 +1054,15 @@ class ProviderOpenAIOfficial(Provider): # history messages, even when the reasoning content is empty. message["reasoning_content"] = "" + if ( + message.get("role") == "assistant" + and is_mimo_reasoning + and "reasoning_content" not in message + ): + # MiMo 推理模型要求 assistant 历史消息回传 reasoning_content, + # 缺失时 API 返回 400。参见 MiMo 官方文档。 + message["reasoning_content"] = "" + # Gemini 的 function_response 要求 google.protobuf.Struct(即 JSON 对象), # 纯文本会触发 400 Invalid argument,需要包一层 JSON。 if is_gemini and message.get("role") == "tool":