This commit is contained in:
Timothy Jaeryang Baek
2026-03-24 17:46:33 -05:00
parent c0fcbc5b4c
commit 631bd20c35
2 changed files with 32 additions and 0 deletions
+5
View File
@@ -92,6 +92,7 @@ from open_webui.utils.misc import (
get_last_user_message_item,
get_last_assistant_message,
get_system_message,
merge_system_messages,
replace_system_message_content,
prepend_to_first_user_message_content,
convert_logit_bias_input_to_json,
@@ -2696,6 +2697,10 @@ async def process_chat_payload(request, form_data, user, metadata, model):
# to prevent errors from providers like Gemini and Claude
form_data['messages'] = strip_empty_content_blocks(form_data.get('messages', []))
# Merge any duplicate system messages into a single message at position 0
# to prevent template parsing errors with strict chat templates (e.g. Qwen)
form_data['messages'] = merge_system_messages(form_data.get('messages', []))
return form_data, metadata, events
+27
View File
@@ -330,6 +330,33 @@ def pop_system_message(messages: list[dict]) -> tuple[Optional[dict], list[dict]
return get_system_message(messages), remove_system_message(messages)
def merge_system_messages(messages: list[dict]) -> list[dict]:
"""
Merge all system messages into one at position 0.
Some chat templates (e.g. Qwen) require exactly one system
message at the start. Multiple pipeline stages may each
insert their own system message; this function consolidates
them.
"""
system_contents: list[str] = []
other_messages: list[dict] = []
for message in messages:
if message.get('role') == 'system':
content = get_content_from_message(message)
if content:
system_contents.append(content)
else:
other_messages.append(message)
if not system_contents:
return other_messages
merged = {'role': 'system', 'content': '\n'.join(system_contents)}
return [merged, *other_messages]
def update_message_content(message: dict, content: str, append: bool = True) -> dict:
if isinstance(message['content'], list):
for item in message['content']: