diff --git a/backend/open_webui/routers/configs.py b/backend/open_webui/routers/configs.py
index 1a0608ea51..cf0ebdeb82 100644
--- a/backend/open_webui/routers/configs.py
+++ b/backend/open_webui/routers/configs.py
@@ -769,6 +769,7 @@ class ModelsConfigForm(BaseModel):
async def get_models_defaults(request: Request, user=Depends(get_verified_user)):
return {
'DEFAULT_MODEL_METADATA': await Config.get('models.default_metadata'),
+ 'DEFAULT_FUNCTION_CALLING': (await Config.get('models.default_params') or {}).get('function_calling'),
}
diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index dc771047c4..44a9e676b8 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -172,6 +172,7 @@ from open_webui.utils.tools import (
get_terminal_tools,
get_tools,
get_updated_tool_function,
+ is_file_context_enabled,
)
from starlette.responses import JSONResponse, Response, StreamingResponse
@@ -2889,8 +2890,7 @@ async def process_chat_payload(request, form_data, user, metadata, model):
except Exception as e:
log.exception(e)
- # Check if file context extraction is enabled for this model (default True)
- file_context_enabled = (model.get('info', {}).get('meta', {}).get('capabilities') or {}).get('file_context', True)
+ file_context_enabled = is_file_context_enabled(model, metadata)
if file_context_enabled:
try:
diff --git a/backend/open_webui/utils/tools.py b/backend/open_webui/utils/tools.py
index 09c1a7bbf1..23cbcaea00 100644
--- a/backend/open_webui/utils/tools.py
+++ b/backend/open_webui/utils/tools.py
@@ -585,6 +585,12 @@ async def get_tools(request: Request, tool_ids: list[str], user: UserModel, extr
return tools_dict
+def is_file_context_enabled(model: dict, metadata: dict) -> bool:
+ return (model.get('info', {}).get('meta', {}).get('capabilities') or {}).get(
+ 'file_context', metadata.get('params', {}).get('function_calling') == 'legacy'
+ )
+
+
def get_attached_knowledge(model: dict, metadata: dict) -> list[dict]:
model_meta = model.get('info', {}).get('meta', {})
knowledge = []
@@ -603,8 +609,7 @@ def get_attached_knowledge(model: dict, metadata: dict) -> list[dict]:
knowledge.append({**item, 'source': source})
seen.add(key)
- file_context_enabled = (model_meta.get('capabilities') or {}).get('file_context', True)
- if not file_context_enabled:
+ if not is_file_context_enabled(model, metadata):
for item in metadata.get('files') or []:
if not isinstance(item, dict) or item.get('type') not in ('collection', 'note'):
continue
@@ -736,7 +741,7 @@ async def get_builtin_tools(
if (
is_builtin_tool_enabled('files')
and get_model_capability('file_upload')
- and not get_model_capability('file_context')
+ and not is_file_context_enabled(model, metadata)
and has_chat_files
and await has_user_chat_permission('file_upload')
):
diff --git a/src/lib/components/admin/Settings/Models/ModelDefaultsPanel.svelte b/src/lib/components/admin/Settings/Models/ModelDefaultsPanel.svelte
index 9de03688c3..f02fd30b3f 100644
--- a/src/lib/components/admin/Settings/Models/ModelDefaultsPanel.svelte
+++ b/src/lib/components/admin/Settings/Models/ModelDefaultsPanel.svelte
@@ -83,7 +83,7 @@
const savedMeta = config?.DEFAULT_MODEL_METADATA;
if (savedMeta && Object.keys(savedMeta).length > 0) {
- defaultCapabilities = savedMeta.capabilities ?? { ...DEFAULT_CAPABILITIES };
+ defaultCapabilities = { ...DEFAULT_CAPABILITIES, ...(savedMeta.capabilities ?? {}) };
defaultFeatureIds = savedMeta.defaultFeatureIds ?? [];
builtinTools = savedMeta.builtinTools ?? {};
toolIds = savedMeta.toolIds ?? [];
@@ -215,6 +215,7 @@
>
diff --git a/src/lib/components/workspace/Models/Capabilities.svelte b/src/lib/components/workspace/Models/Capabilities.svelte
index 3b0d07fcc7..7b06624b15 100644
--- a/src/lib/components/workspace/Models/Capabilities.svelte
+++ b/src/lib/components/workspace/Models/Capabilities.svelte
@@ -68,6 +68,11 @@
type Capability = keyof typeof capabilityLabels;
export let capabilities: Partial> = {};
+ export let functionCalling: string | null = null;
+ $: effectiveCapabilities = {
+ ...capabilities,
+ file_context: capabilities.file_context ?? functionCalling === 'legacy'
+ };
export let defaultFeatureIds: string[] = [];
export let builtinTools: Record = {};
@@ -81,7 +86,7 @@
(key !== 'terminal' || hasTerminal) &&
(capabilityLabels[key].enabled ?? true)
);
- $: enabledCapabilityIds = availableCapabilities.filter((key) => capabilities[key]);
+ $: enabledCapabilityIds = availableCapabilities.filter((key) => effectiveCapabilities[key]);
$: availableFeatures = featureKeys.filter((key) => enabledCapabilityIds.includes(key));
$: enabledDefaultIds = availableFeatures.filter((key) => defaultFeatureIds.includes(key));
const setDefault = (key: string, enabled: boolean) => {
@@ -114,7 +119,8 @@
(capabilities[key] = e.detail)}
{disabled}
/>
{/each}
diff --git a/src/lib/components/workspace/Models/ModelEditor.svelte b/src/lib/components/workspace/Models/ModelEditor.svelte
index 1c2bc33b08..75e658b3d3 100644
--- a/src/lib/components/workspace/Models/ModelEditor.svelte
+++ b/src/lib/components/workspace/Models/ModelEditor.svelte
@@ -94,6 +94,7 @@
let commitMessage = '';
let savedDraft = '';
let defaultMeta: Record = {};
+ let defaultFunctionCalling: string | null = null;
let allowNavigation = false;
let showDiscard = false;
let afterDiscard: (() => void) | null = null;
@@ -784,6 +785,7 @@
// reflects the actual defaults rather than hardcoded values
const modelsConfig = await getModelsDefaults(localStorage.token).catch(() => null);
defaultMeta = modelsConfig?.DEFAULT_MODEL_METADATA ?? {};
+ defaultFunctionCalling = modelsConfig?.DEFAULT_FUNCTION_CALLING ?? null;
// Use admin defaults as base, falling back to hardcoded defaults
capabilities = { ...DEFAULT_CAPABILITIES, ...(defaultMeta.capabilities ?? {}) };
@@ -1723,6 +1725,7 @@