diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index ecba6407f3..0ff61fbc14 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -1277,6 +1277,7 @@ async def chat_completion( 'variables': form_data.get('variables', {}), 'chat_variables': chat_variables, 'model': model, + 'model_system_prompt': model_info_params.get('system'), 'direct': model_item.get('direct', False), 'params': { 'stream_delta_chunk_size': stream_delta_chunk_size, @@ -1787,7 +1788,7 @@ async def chat_completion( 'session_id': metadata.get('session_id'), 'tool_ids': metadata.get('tool_ids') or [], 'skill_ids': metadata.get('skill_ids') or [], - 'system_prompt': metadata.get('system_prompt'), + 'system_prompt': metadata.get('chat_system_prompt'), 'filter_ids': metadata.get('filter_ids') or [], 'terminal_id': metadata.get('terminal_id'), 'features': metadata.get('features') or {}, diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 6a3e4b6f5b..138c37494e 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -2531,6 +2531,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): ) # Required to handle system prompt variables except Exception: pass + chat_system_prompt = get_content_from_message(system_message) if system_message else None form_data = await convert_url_images_to_base64(form_data, user=user) @@ -2665,6 +2666,8 @@ async def process_chat_payload(request, form_data, user, metadata, model): except Exception as e: raise Exception(f'{e}') + delegate_system_prompt = get_content_from_message(get_system_message(form_data['messages']) or {}) + features = form_data.pop('features', None) or {} extra_params['__features__'] = features if features: @@ -2823,11 +2826,15 @@ async def process_chat_payload(request, form_data, user, metadata, model): skill_manifest = '' for skill in available_skills: if skill.id in mentioned_skill_ids or not use_builtin_tools: + skill_context = f'\n{skill.content}\n' form_data['messages'] = add_or_update_system_message( - f'\n{skill.content}\n', + skill_context, form_data['messages'], append=True, ) + delegate_system_prompt = ( + f'{delegate_system_prompt}\n{skill_context}' if delegate_system_prompt else skill_context + ) else: view_skill_ids.append(skill.id) skill_manifest += ( @@ -2855,11 +2862,15 @@ async def process_chat_payload(request, form_data, user, metadata, model): skill_name = unquote(sid.removeprefix(terminal_skill_prefix)) loaded = await get_terminal_skill(request, user.model_dump(), metadata, skill_name, extra_params) if loaded: + skill_context = format_terminal_skill_context(loaded) form_data['messages'] = add_or_update_system_message( - format_terminal_skill_context(loaded), + skill_context, form_data['messages'], append=True, ) + delegate_system_prompt = ( + f'{delegate_system_prompt}\n{skill_context}' if delegate_system_prompt else skill_context + ) else: view_skill_ids.append(sid) skill_manifest += format_terminal_skill_manifest_entry(skill) @@ -3193,6 +3204,22 @@ async def process_chat_payload(request, form_data, user, metadata, model): f'{resolved_model_system_prompt}\n{system_content}' if system_content else resolved_model_system_prompt ) metadata['system_prompt'] = system_content or None + # Timers/follow-ups continue this chat, sub-agents start their own; the model's own prompt is added in each run + sent_with_request = model_system_prompt != metadata.get('model_system_prompt') + already_in_chat = resolved_model_system_prompt == chat_system_prompt + if resolved_model_system_prompt and sent_with_request and not already_in_chat: + chat_system_prompt = ( + f'{resolved_model_system_prompt}\n{chat_system_prompt}' + if chat_system_prompt + else resolved_model_system_prompt + ) + delegate_system_prompt = ( + f'{resolved_model_system_prompt}\n{delegate_system_prompt}' + if delegate_system_prompt + else resolved_model_system_prompt + ) + metadata['chat_system_prompt'] = chat_system_prompt + metadata['delegate_system_prompt'] = delegate_system_prompt metadata['user_prompt'] = get_last_user_message(form_data['messages']) metadata['sources'] = sources[:] if sources else [] diff --git a/backend/open_webui/utils/subagents.py b/backend/open_webui/utils/subagents.py index 13b9699216..7014cb04b0 100644 --- a/backend/open_webui/utils/subagents.py +++ b/backend/open_webui/utils/subagents.py @@ -319,7 +319,8 @@ async def delegate( 'session_id': metadata.get('session_id'), 'tool_ids': copy.deepcopy(metadata.get('tool_ids') or []), 'skill_ids': copy.deepcopy(metadata.get('skill_ids') or []), - 'system_prompt': metadata.get('system_prompt'), + 'system_prompt': metadata.get('chat_system_prompt'), + 'delegate_system_prompt': metadata.get('delegate_system_prompt'), 'tool_servers': [] if background else copy.deepcopy(metadata.get('tool_servers') or []), 'filter_ids': copy.deepcopy(metadata.get('filter_ids') or []), 'terminal_id': metadata.get('terminal_id'), @@ -449,7 +450,7 @@ async def delegate( try: child_request = _build_request(request, user.id, internal=True) child_request.state.max_tool_call_iterations = max_iterations - parent_system_prompt = run.get('system_prompt') or '' + parent_system_prompt = run.get('delegate_system_prompt') or '' subagent_system_prompt = ( str(config.get('subagents.system_prompt') or '').strip() or DEFAULT_SUBAGENT_SYSTEM_PROMPT ) diff --git a/backend/open_webui/utils/timers.py b/backend/open_webui/utils/timers.py index 15a6b898db..17c7e1bc55 100644 --- a/backend/open_webui/utils/timers.py +++ b/backend/open_webui/utils/timers.py @@ -108,7 +108,7 @@ async def create_timer( 'session_id': metadata.get('session_id'), 'tool_ids': copy.deepcopy(metadata.get('tool_ids') or []), 'skill_ids': copy.deepcopy(metadata.get('skill_ids') or []), - 'system_prompt': metadata.get('system_prompt'), + 'system_prompt': metadata.get('chat_system_prompt'), 'filter_ids': copy.deepcopy(metadata.get('filter_ids') or []), 'terminal_id': metadata.get('terminal_id'), 'features': copy.deepcopy(metadata.get('features') or {}),