mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-01 01:10:21 +08:00
fix: prevent API 400 errors by ensuring assistant messages with reasoning_content but no content or tool_calls are preserved with a placeholder content value (#8483)
* fix: preserve assistant messages with reasoning_content in sanitize pass When _sanitize_assistant_messages encounters an assistant message with empty content and no tool_calls but with reasoning_content, keep it with content set to empty string instead of dropping it. Reasoning models (DeepSeek V4, MiMo, etc.) require this history for subsequent turn validation. * Update astrbot/core/provider/sources/openai_source.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * fix: default to empty TokenUsage when completion.usage is None When completion.usage is None (e.g. certain proxy/streaming edge cases), llm_response.usage stayed unset (None). Plugins accessing .input_tokens on it would crash with AttributeError. Always assign llm_response.usage — extract from completion.usage if present, otherwise fall back to a zeroed TokenUsage(). Closes #8605 --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: renchonghan <renchonghan@users.noreply.github.com>
This commit is contained in:
@@ -458,12 +458,20 @@ class ProviderOpenAIOfficial(Provider):
|
||||
tool_calls = msg.get("tool_calls")
|
||||
reasoning_content = msg.get("reasoning_content")
|
||||
|
||||
if _is_empty(content) and not tool_calls and not reasoning_content:
|
||||
logger.warning(f"过滤第 {idx} 条空 assistant 消息 (无工具调用)")
|
||||
continue
|
||||
if _is_empty(content) and not tool_calls:
|
||||
if not reasoning_content:
|
||||
# 三者全空,真正的垃圾消息,丢弃
|
||||
logger.debug(f"过滤第 {idx} 条空 assistant 消息 (无 content | tool_calls | reasoning_content)")
|
||||
continue
|
||||
else:
|
||||
# ⭐ 有 reasoning_content 但没有 content 和 tool_calls
|
||||
# 不能丢(推理模型需要 reasoning 历史)
|
||||
# 但 API 要求 content 或 tool_calls 至少有一个
|
||||
# → 设空字符串占位,满足校验
|
||||
msg["content"] = ""
|
||||
|
||||
if _is_empty(content) and tool_calls:
|
||||
msg["content"] = None
|
||||
elif _is_empty(content) and tool_calls:
|
||||
msg["content"] = None # 有 tool_calls,按 OpenAI 规范
|
||||
|
||||
cleaned.append(msg)
|
||||
|
||||
@@ -872,8 +880,11 @@ class ProviderOpenAIOfficial(Provider):
|
||||
llm_response.raw_completion = completion
|
||||
llm_response.id = completion.id
|
||||
|
||||
if completion.usage:
|
||||
llm_response.usage = self._extract_usage(completion.usage)
|
||||
llm_response.usage = (
|
||||
self._extract_usage(completion.usage)
|
||||
if completion.usage
|
||||
else TokenUsage()
|
||||
)
|
||||
|
||||
return llm_response
|
||||
|
||||
|
||||
Reference in New Issue
Block a user