Model Selection UI#
The Set Default Model page in RAGFlow's user settings lets users assign system-wide defaults for six model roles: Chat, Embedding, Image-to-Text, ASR (speech recognition), Rerank, and TTS. The UI is built from two primary components: ModelTreeSelect (a reusable picker) and SystemSetting (the page-level form).
Key Files#
| File | Purpose |
|---|---|
web/src/components/model-tree-select.tsx | Reusable hierarchical model picker and its react-hook-form wrapper |
web/src/pages/user-setting/setting-model/layout/system-setting.tsx | The "Set Default Model" page form that uses ModelTreeSelect |
web/src/components/tree-select.tsx | Base TreeSelect primitive consumed by ModelTreeSelect |
web/src/constants/llm.ts | FieldToModelType mapping field names → model type strings |
web/src/hooks/use-llm-request.tsx | React Query hooks: useFetchAllAddedModels, useFetchDefaultModelDictionary, useSetDefaultModel |
web/src/utils/llm-util.ts | buildModelValue / getRealModelName serialization utilities |
ModelTreeSelect Component#
ModelTreeSelect (model-tree-select.tsx) is the central reusable component. Given a list of modelTypes, it:
- Fetches added models via
useFetchAllAddedModels, optionally scoped toownerTenantId. - Builds a three-level tree via
buildModelTree:Provider → Instance → Model. Leaf nodes carry{ provider_name, instance_name, model_name }in theirdatafield and render aLlmIcon+ display name. - Handles legacy IDs: Legacy string IDs (
modelName@instanceName@providerName) are mapped to currentmodel_id-based IDs at runtime vialegacyIdMap, preserving backward compatibility. - Renders using the base
TreeSelectprimitive withdefaultExpandAlland optional search.
Field-to-Type Mapping#
ModelTypeMap defines which model types each form field accepts:
| Field | Accepted model types |
|---|---|
llm_id | chat, vision |
embd_id | embedding |
img2txt_id | vision |
asr_id | asr |
rerank_id | rerank |
tts_id | tts |
This map is used both in ModelTreeSelect (to filter which models appear) and in FieldToModelType (to resolve the API payload's model_type).
Form Field Wrapper#
ModelTreeSelectFormField wraps ModelTreeSelect in a react-hook-form <FormField>, adding label, tooltip, and validation message support. Use this variant when embedding the picker inside an <Form> context.
SystemSetting Component#
SystemSetting composes ModelFieldItem rows — one per model role — and manages state through three layers:
localStorage(key:ragflow-system-model-settings) — Written on every change viasavePersistedValues, read on mount vialoadPersistedValues. Survives page refreshes and bridges gaps when the backend hasn't returned a value yet.- API response —
useFetchDefaultModelDictionaryfetches current defaults fromGET /api/v1/models/defaultand converts the array to a dictionary keyed by field name. - Empty string fallback — Used when neither localStorage nor the API has a value.
getValue applies this resolution order: localStorage → API → ''.
On change, handleFieldChange immediately updates local state (for instant UI feedback), then calls useSetDefaultModel to persist via the API. llm_id (Chat Model) is the only required field; all others allow clearing .
Data Flow#
useFetchAllAddedModels
│
▼
buildModelTree() ──► Provider → Instance → Model (tree)
│
▼
TreeSelect (base primitive)
│
▼
ModelTreeSelect ◄── ModelTypeMap (filters by role)
│
▼
ModelFieldItem ◄── SystemSetting (getValue / handleFieldChange)
│
▼
useSetDefaultModel → POST /api/v1/models/default
Extension Points#
- Use
ModelTreeSelectstandalone (outside a form) — passvalue+onChangedirectly and setmodelTypesto any subset fromModelTypeMap. - Use
ModelTreeSelectFormFieldinside a<Form>— just passnamematching the react-hook-form field. - Custom leaf rendering —
buildModelTreeaccepts an optionalrenderLeafLabelcallback for custom node display. - Tenant scoping — pass
ownerTenantIdtoModelTreeSelectto fetch models for a specific tenant .