diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index ebb51cb559..06b420f6c7 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -303,6 +303,15 @@ def tool_result_content(tool_result: Any) -> str: return str(tool_result) +def append_text(container: dict, key: str, value: str) -> None: + text = container.get(key, '') + container[key] = '' # dropping the dict's reference lets CPython extend the str in place + try: + text += value + finally: # a non-str value raises above and would leave the slot cleared + container[key] = text + + def merge_streamed_reasoning_details(target: list, details) -> None: items = details if isinstance(details, list) else [details] for item in items: @@ -321,7 +330,7 @@ def merge_streamed_reasoning_details(target: list, details) -> None: for key, value in item.items(): if key in ('text', 'summary') and isinstance(value, str) and isinstance(existing.get(key), str): - existing[key] += value + append_text(existing, key, value) else: existing[key] = value @@ -5136,7 +5145,7 @@ async def streaming_chat_response_handler(response, ctx): # Append to reasoning content parts = reasoning_item.get('content', []) if parts and parts[-1].get('type') == 'output_text': - parts[-1]['text'] += reasoning_content + append_text(parts[-1], 'text', reasoning_content) else: reasoning_item['content'] = [ { @@ -5234,11 +5243,11 @@ async def streaming_chat_response_handler(response, ctx): if inside_tag_block: # Append to the existing tag-based item if last_item_type == 'open_webui:code_interpreter': - last_item['code'] = last_item.get('code', '') + value + append_text(last_item, 'code', value) elif last_item_type == 'reasoning': parts = last_item.get('content', []) if parts and parts[-1].get('type') == 'output_text': - parts[-1]['text'] += value + append_text(parts[-1], 'text', value) else: last_item['content'] = [ { @@ -5250,7 +5259,7 @@ async def streaming_chat_response_handler(response, ctx): # solution or other _tag_type message msg_parts = last_item.get('content', []) if msg_parts and msg_parts[-1].get('type') == 'output_text': - msg_parts[-1]['text'] += value + append_text(msg_parts[-1], 'text', value) else: last_item['content'] = [ { @@ -5278,7 +5287,7 @@ async def streaming_chat_response_handler(response, ctx): # Append value to last message item's text msg_parts = output[-1].get('content', []) if msg_parts and msg_parts[-1].get('type') == 'output_text': - msg_parts[-1]['text'] += value + append_text(msg_parts[-1], 'text', value) else: output[-1]['content'] = [ {