feat(MM):model settings export import#8872
feat(MM):model settings export import#8872Pfannkuchensack wants to merge 2 commits intoinvoke-ai:mainfrom
Conversation
Add the ability to export model settings (default_settings, trigger_phrases, cpu_only) as JSON and import them back. The model name is used as the filename for exports. https://claude.ai/code/session_01LXKjbRjfzcG3d3vzk3xRCh
…immediately The useForm defaultValues only apply on mount, so importing model settings updated the backend but the forms kept showing stale values. Added useEffect to reset forms when the underlying model config changes. Also fixed lint errors (strict equality, missing React import).
There was a problem hiding this comment.
Pull request overview
This PR adds export/import functionality for model settings in the Model Manager, allowing users to save and restore configurations including default settings, trigger phrases, and CPU-only flags. The changes enable users to backup model configurations and apply them to other models of the same type.
Changes:
- Added ModelSettingsExportButton component to download model settings as JSON
- Added ModelSettingsImportButton component to upload and apply settings from JSON files
- Integrated export/import buttons into ModelView header for models with settings
- Added useEffect hooks to auto-reset forms when model data changes (enabling immediate UI updates after import)
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| ModelView.tsx | Integrated export/import buttons in model header for models with settings |
| ModelSettingsImportButton.tsx | New component handling JSON file upload and settings application via API |
| ModelSettingsExportButton.tsx | New component creating and downloading JSON files with model settings |
| MainModelDefaultSettings.tsx | Added useEffect to reset form when settings change externally |
| LoRAModelDefaultSettings.tsx | Added useEffect to reset form when settings change externally |
| EncoderModelSettings.tsx | Added useEffect to reset form when settings change externally |
| ControlAdapterModelDefaultSettings.tsx | Added useEffect to reset form when settings change externally |
| en.json | Added localization strings for export/import functionality |
Comments suppressed due to low confidence (6)
invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelSettingsExportButton.tsx:66
- Consider disabling the export button when there are no settings to export (i.e., when buildExportData returns an empty object). This would provide better UX by preventing users from exporting empty files. You could check
Object.keys(data).length === 0and setisDisabledon the IconButton accordingly.
return (
<IconButton
size="sm"
icon={<PiDownloadSimpleBold />}
aria-label={t('modelManager.exportSettings')}
tooltip={t('modelManager.exportSettings')}
onClick={handleExport}
/>
invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelSettingsExportButton.tsx:21
- The condition
modelConfig.trigger_phraseswill exclude exporting when trigger_phrases is an empty array, which is a valid state (no trigger phrases). This means if a user clears all trigger phrases, an exported file won't include the trigger_phrases field at all. Consider changing tomodelConfig.trigger_phrases !== null && modelConfig.trigger_phrases !== undefinedto export empty arrays.
if ('trigger_phrases' in modelConfig && modelConfig.trigger_phrases) {
data.trigger_phrases = modelConfig.trigger_phrases;
}
invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelSettingsExportButton.tsx:17
- The condition
modelConfig.default_settingswill exclude exporting when default_settings is an empty object{}, which might be a valid state. Consider changing tomodelConfig.default_settings !== null && modelConfig.default_settings !== undefinedto be more explicit about what should be excluded from export.
if ('default_settings' in modelConfig && modelConfig.default_settings) {
data.default_settings = modelConfig.default_settings;
}
invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelSettingsImportButton.tsx:80
- The error handler catches the error but doesn't add any additional error logging. Consider adding
console.erroror using a logger (similar to how ModelDeleteButton useslogger('models')) to aid in debugging when imports fail. This would help developers and users diagnose issues with malformed JSON files.
} catch {
toast({
id: 'SETTINGS_IMPORT_INVALID',
title: t('modelManager.settingsImportInvalidFile'),
status: 'error',
});
}
invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelSettingsImportButton.tsx:82
- The FileReader lacks error handling. If the file reading fails (e.g., due to permissions issues or corrupted file), no error is reported to the user. Consider adding
reader.onerrorandreader.onaborthandlers similar to the pattern used in other parts of the codebase (see GeneratorTextareaWithFileUpload.tsx or useLoadWorkflowFromFile.tsx).
const reader = new FileReader();
reader.onload = (event) => {
try {
const json = JSON.parse(event.target?.result as string);
applySettings(json);
} catch {
toast({
id: 'SETTINGS_IMPORT_INVALID',
title: t('modelManager.settingsImportInvalidFile'),
status: 'error',
});
}
};
reader.readAsText(file);
invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelSettingsImportButton.tsx:37
- The import function lacks validation of the imported data structure. While the API likely validates the data server-side, there's no client-side validation to check if trigger_phrases contains only strings, or if default_settings has the expected shape. Consider adding basic type validation to provide better error messages to users before attempting the API call.
const applySettings = useCallback(
async (data: Record<string, unknown>) => {
const body: Record<string, unknown> = {};
if ('default_settings' in data && data.default_settings !== null) {
body.default_settings = data.default_settings;
}
if ('trigger_phrases' in data && Array.isArray(data.trigger_phrases)) {
body.trigger_phrases = data.trigger_phrases;
}
if ('cpu_only' in data && data.cpu_only !== null) {
body.cpu_only = data.cpu_only;
}
if (Object.keys(body).length === 0) {
return;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
lstein
left a comment
There was a problem hiding this comment.
I tested with multiple model types and it works well. However, I ran into an edge condition that I think should be addressed. If you save the config from one type of model, such as Main, and then load the .json into another type of model, for example LoRA, you get a big red cryptic error containing the pydantic validation message. It would be better to catch this exception and give the user a shorter and more informative message.
Summary
Add export/import functionality for model settings (default settings, trigger phrases, cpu_only). This allows users to save a model's configuration to a JSON file and re-apply it later or to another model of the same type.
Export saves the current model's
default_settings,trigger_phrases, andcpu_onlyfields to a downloadable.jsonfile.Import reads a
.jsonfile and applies the settings via the existingupdateModelAPI mutation.Related Issues / Discussions
QA Instructions
.jsonfile should download.jsonfileMerge Plan
No special merge considerations. Standard merge to main.
Checklist
What's Newcopy (if doing a release after this PR)