This commit is contained in:
Timothy Jaeryang Baek 2026-11-06 11:12:04 +09:00
parent 9598411db2
commit bd6fc15bee
8 changed files with 26 additions and 10 deletions

View file

@ -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'),
}

View file

@ -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:

View file

@ -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')
):

View file

@ -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 @@
>
<Capabilities
bind:capabilities={defaultCapabilities}
functionCalling={defaultParams.function_calling}
bind:defaultFeatureIds
bind:builtinTools
/>

View file

@ -68,6 +68,11 @@
type Capability = keyof typeof capabilityLabels;
export let capabilities: Partial<Record<Capability, boolean>> = {};
export let functionCalling: string | null = null;
$: effectiveCapabilities = {
...capabilities,
file_context: capabilities.file_context ?? functionCalling === 'legacy'
};
export let defaultFeatureIds: string[] = [];
export let builtinTools: Record<string, boolean> = {};
@ -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 @@
<ModelSettingToggle
label={capabilityLabels[key].label}
description={capabilityLabels[key].description}
bind:checked={capabilities[key]}
checked={effectiveCapabilities[key]}
on:change={(e) => (capabilities[key] = e.detail)}
{disabled}
/>
{/each}

View file

@ -94,6 +94,7 @@
let commitMessage = '';
let savedDraft = '';
let defaultMeta: Record<string, any> = {};
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 @@
<div class="space-y-0.5">
<Capabilities
bind:capabilities
functionCalling={params.function_calling ?? defaultFunctionCalling}
bind:defaultFeatureIds
bind:builtinTools
disabled={readOnly}

View file

@ -114,7 +114,7 @@ export const SUPPORTED_FILE_EXTENSIONS = [
];
export const DEFAULT_CAPABILITIES = {
file_context: true,
file_context: undefined as boolean | undefined,
vision: true,
file_upload: true,
web_search: true,

View file

@ -3359,7 +3359,7 @@
"settings.admin.models.capabilities.citations.label": "Citations",
"settings.admin.models.capabilities.codeInterpreter.description": "Model can execute code and perform calculations",
"settings.admin.models.capabilities.codeInterpreter.label": "Code Interpreter",
"settings.admin.models.capabilities.fileContext.description": "Inject file content into conversation context",
"settings.admin.models.capabilities.fileContext.description": "Automatically inject file content into the conversation. Defaults to off in native mode so the model reads files through tools, and on in legacy mode.",
"settings.admin.models.capabilities.fileContext.label": "File Context",
"settings.admin.models.capabilities.fileUpload.description": "Model accepts file inputs",
"settings.admin.models.capabilities.fileUpload.label": "File Upload",