diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index b85407ebe3..96166e0ac3 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -110,6 +110,7 @@ from open_webui.utils.misc import ( get_last_user_message_item, get_message_list, get_output_text, + get_reasoning_details, get_system_message, is_string_allowed, merge_system_messages, @@ -3916,7 +3917,7 @@ async def non_streaming_chat_response_handler(response, ctx): if not response_output: choice_message = choices[0].get('message', {}) reasoning_content = choice_message.get('reasoning_content') or choice_message.get('reasoning') - reasoning_details = choice_message.get('reasoning_details') + reasoning_details = get_reasoning_details(choice_message) response_output = [] if reasoning_content or reasoning_details: reasoning_item = { @@ -4957,7 +4958,7 @@ async def streaming_chat_response_handler(response, ctx): or delta.get('reasoning') or delta.get('thinking') ) - reasoning_details = delta.get('reasoning_details') + reasoning_details = get_reasoning_details(delta) reasoning_detail_items = ( [item for item in reasoning_details if isinstance(item, dict)] if isinstance(reasoning_details, list) diff --git a/backend/open_webui/utils/misc.py b/backend/open_webui/utils/misc.py index bfb1eff5e9..ac3eec866d 100644 --- a/backend/open_webui/utils/misc.py +++ b/backend/open_webui/utils/misc.py @@ -258,6 +258,17 @@ def reconcile_tool_pairs(messages: list[dict]) -> list[dict]: return reconciled_messages +def get_reasoning_details(payload: dict): + if not isinstance(payload, dict): + return None + + provider_fields = payload.get('provider_specific_fields') or {} + provider_details = ( + provider_fields.get('reasoning_details') if isinstance(provider_fields, dict) else None + ) + return payload.get('reasoning_details') or provider_details + + def convert_output_to_messages( output: list, raw: bool = False, @@ -447,6 +458,14 @@ def convert_output_to_messages( elif item_type == 'reasoning': reasoning_details = item.get('reasoning_details') if raw else None + if reasoning_details: + reasoning_details = reasoning_details if isinstance(reasoning_details, list) else [reasoning_details] + reasoning_details = [ + detail + for detail in reasoning_details + if isinstance(detail, dict) + and (detail.get('format') != 'anthropic-claude-v1' or detail.get('signature')) + ] if not reasoning_format and not reasoning_details: continue @@ -469,9 +488,7 @@ def convert_output_to_messages( pending_reasoning.append(reasoning_text) if reasoning_details: - pending_reasoning_details.extend( - reasoning_details if isinstance(reasoning_details, list) else [reasoning_details] - ) + pending_reasoning_details.extend(reasoning_details) elif item_type == 'open_webui:code_interpreter': # Always include code interpreter content so the LLM knows