Model Registry
The model registry maps a model identifier to its sub-config YAML. You can switch models by editing
llm.model instead of also updating llm.model_config. The registry is an optional convenience layer over
the sub-config merge described in Server Config. The shipped NeMo Labs Voice Agent config
does not use it for any component.
Where It Lives
ConfigManager (nemo_voice_agent/utils/config_manager.py) reads model_registry.yaml from the
server base path — the directory containing the server script. For the example server that is
examples/generic_voice_agent/server/model_registry.yaml. The path is not configurable from YAML.
The file has three top-level sections, one per component:
yaml_id is a bare filename. It is resolved against the sibling directory for that component —
server_configs/llm_configs/, server_configs/tts_configs/, or server_configs/stt_configs/.
Resolution Order
For each large language model (LLM), text-to-speech (TTS), and speech-to-text (STT) component,
ConfigManager selects a sub-config in this order:
server.use_model_registry defaults to true when the key is absent.
Two path-handling details affect resolution:
model_configis reduced to its basename. Only the filename is kept. The directory part of the value is discarded, and the file is looked up in the component’s*_configs/directory. Therefore,model_config: "./server_configs/llm_configs/qwen3-8B.yaml"andmodel_config: "qwen3-8B.yaml"behave identically, and you cannot pointmodel_configat a file outside that directory.- STT keys strip a
.nemopath. Ifstt.modelends in.nemo, the lookup key is the basename without the extension. A local checkpoint path can therefore still match a registry entry.
Whatever sub-config gets loaded, its keys override the top-level block — not the other way round. For that precedence rule, refer to Server Config.
Reasoning Auto-Swap
An LLM registry entry can declare reasoning_supported: true. That is a promise that a sibling file
with the same name plus a _think suffix exists and has been tested — for example qwen3-8B.yaml
and qwen3-8B_think.yaml.
The swap fires only when all three are true:
- The config was resolved through the registry (no explicit
llm.model_config:). - That registry entry sets
reasoning_supported: true. llm.enable_reasoning: truein your server config.
Then ConfigManager rewrites the .yaml suffix to _think.yaml before loading. If the _think
file is missing, startup fails with a FileNotFoundError naming the path it tried.
Today Qwen/Qwen3-8B is the only registry entry with reasoning_supported: true.
The Swap Does Not Fire for the Shipped Default
server_configs/default.yaml sets both llm.model and llm.model_config:
Because model_config is set, the lookup short-circuits at step 1 above. Setting
enable_reasoning: true alone does not load nemotron_nano_v3_think.yaml — that model is not in
the registry at all. Point model_config at the thinking config by hand:
The _think variant raises max_new_tokens to 4096, adds a thinking_budget, and flips the vLLM
enable_thinking chat-template kwarg to True. Both variants keep start_vllm_on_init: false, so
you still start vLLM yourself. For runtime behavior, refer to
Reasoning Mode.
The Registry Does Not Cover Every Shipped Model
The registry is a partial, hand-maintained list. Several configs under server_configs/ have no
entry, and the models named in default.yaml are among them:
All three work because default.yaml sets an explicit model_config for each. Config files with no
registry entry include nemotron_nano_v3.yaml, nemotron_nano_v3_think.yaml,
nemotron_nano_v3_omni.yaml, nemotron_nano_v3_omni_think.yaml, and
tts_configs/magpie_tts_multilingual_357m.yaml — reach them with model_config.
server_configs/default_nvidia.yaml leaves use_model_registry: true but sets no model_config
anywhere. Its hosted model IDs miss the registry, so every component falls to step 4 and uses only the
top-level blocks. Warnings in bot_server.log about a model not being in the registry are expected. Refer to
NVIDIA NIM.
Adding an Entry
Add a registry-backed model by updating both the relevant sub-config and model_registry.yaml.
- Put the sub-config in the right directory, e.g.
server_configs/llm_configs/my-model.yaml. - If you want a tested thinking variant, add
server_configs/llm_configs/my-model_think.yaml. - Register it:
- In your server config, set
llm.model: "my-org/My-Model-8B"and removellm.model_config.
Confirm the resolution in the log — ConfigManager writes a Loading LLM config from: ... line, plus
one line per key it overrode, before the pipeline starts.
Turning the Registry Off
Set server.use_model_registry: false and give every component an explicit model_config (or a
complete top-level block). This is what the evaluation harness does: evaluation/server_configs/*.yaml
all set use_model_registry: false.
Do this whenever your server base path has no model_registry.yaml. With use_model_registry: true and a
missing or unreadable registry file, ConfigManager logs an error and falls back to an empty registry. It
then raises a ConfigAttributeError on the first component that reaches step 2. The first error is
Missing key stt_models because _initialize_config_parameters configures STT before LLM and TTS. The error
is Missing key llm_models if only the STT block has an explicit model_config. A component with an explicit
model_config bypasses the lookup, which can make the failure appear inconsistent. The evaluation/
directory has no registry file, so those configs disable it.
Related Pages
Use these pages to configure the files and runtime behavior that surround registry resolution:
- Server Config — the full merge order and precedence rules.
- Configuration Model — how the config files fit together.
- LLM Backends — what
llm.type(auto,hf,vllm,nvidia) selects. - Reasoning Mode — thinking-mode behavior at runtime.