mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-06-02 00:57:41 +08:00
fix(mimo): round-trip reasoning_content for thinking-mode providers
This commit is contained in:
@@ -249,24 +249,49 @@ class OpenAICompatibleBot:
|
||||
def _convert_messages_to_openai_format(self, messages):
|
||||
"""
|
||||
Convert messages from Claude format to OpenAI format
|
||||
|
||||
Claude uses content blocks with types like 'tool_use', 'tool_result'
|
||||
OpenAI uses 'tool_calls' in assistant messages and 'tool' role for results
|
||||
|
||||
Claude content blocks (tool_use / tool_result / thinking) → OpenAI
|
||||
tool_calls / tool role / reasoning_content. Some thinking-mode
|
||||
providers require reasoning_content on assistant messages after a
|
||||
tool_call appears in history; back-fill with empty string when the
|
||||
trace was not captured.
|
||||
"""
|
||||
if not messages:
|
||||
return []
|
||||
|
||||
|
||||
# Detect any prior tool-call turn — gates reasoning_content back-fill below.
|
||||
has_tool_call_history = False
|
||||
for msg in messages:
|
||||
if msg.get("role") != "assistant":
|
||||
continue
|
||||
if msg.get("tool_calls"):
|
||||
has_tool_call_history = True
|
||||
break
|
||||
inner = msg.get("content")
|
||||
if isinstance(inner, list) and any(
|
||||
isinstance(b, dict) and b.get("type") == "tool_use" for b in inner
|
||||
):
|
||||
has_tool_call_history = True
|
||||
break
|
||||
|
||||
openai_messages = []
|
||||
|
||||
|
||||
for msg in messages:
|
||||
role = msg.get("role")
|
||||
content = msg.get("content")
|
||||
|
||||
|
||||
# Handle string content (already in correct format)
|
||||
if isinstance(content, str):
|
||||
openai_messages.append(msg)
|
||||
if (role == "assistant" and has_tool_call_history
|
||||
and isinstance(msg, dict)
|
||||
and "reasoning_content" not in msg):
|
||||
patched = dict(msg)
|
||||
patched["reasoning_content"] = ""
|
||||
openai_messages.append(patched)
|
||||
else:
|
||||
openai_messages.append(msg)
|
||||
continue
|
||||
|
||||
|
||||
# Handle list content (Claude format with content blocks)
|
||||
if isinstance(content, list):
|
||||
# Check if this is a tool result message (user role with tool_result blocks)
|
||||
@@ -305,14 +330,17 @@ class OpenAICompatibleBot:
|
||||
|
||||
# Check if this is an assistant message with tool_use blocks
|
||||
elif role == "assistant":
|
||||
# Separate text content and tool_use blocks
|
||||
text_parts = []
|
||||
tool_calls = []
|
||||
reasoning_parts = []
|
||||
|
||||
for block in content:
|
||||
if block.get("type") == "text":
|
||||
if not isinstance(block, dict):
|
||||
continue
|
||||
btype = block.get("type")
|
||||
if btype == "text":
|
||||
text_parts.append(block.get("text", ""))
|
||||
elif block.get("type") == "tool_use":
|
||||
elif btype == "tool_use":
|
||||
tool_id = block.get("id") or ""
|
||||
if not tool_id:
|
||||
logger.warning(f"[OpenAICompatible] tool_use missing id for '{block.get('name')}'")
|
||||
@@ -324,6 +352,8 @@ class OpenAICompatibleBot:
|
||||
"arguments": json.dumps(block.get("input", {}))
|
||||
}
|
||||
})
|
||||
elif btype == "thinking":
|
||||
reasoning_parts.append(block.get("thinking", ""))
|
||||
|
||||
# Build OpenAI format assistant message
|
||||
openai_msg = {
|
||||
@@ -334,6 +364,13 @@ class OpenAICompatibleBot:
|
||||
if tool_calls:
|
||||
openai_msg["tool_calls"] = tool_calls
|
||||
|
||||
# Round-trip reasoning_content; empty string when missing
|
||||
# after a tool-call turn keeps strict providers happy.
|
||||
if reasoning_parts:
|
||||
openai_msg["reasoning_content"] = "\n".join(reasoning_parts)
|
||||
elif has_tool_call_history:
|
||||
openai_msg["reasoning_content"] = ""
|
||||
|
||||
if msg.get("_gemini_raw_parts"):
|
||||
openai_msg["_gemini_raw_parts"] = msg["_gemini_raw_parts"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user