Treat SAM and Ultralytics models as base-model-independent in search panel

This commit is contained in:
Dariusz L
2026-07-16 09:10:00 +02:00
parent 54dae10be5
commit e4485f3bdf
2 changed files with 90 additions and 3 deletions
@@ -148,6 +148,48 @@ test('base model alias resolves FLUX KREA as Flux.1 Krea', () => {
assert.equal(resolveBaseModelAlias.call(dialog, 'KREA'), 'Krea 2');
});
test('auto base model uses Any model for standalone SAM and Ultralytics models', () => {
const getBaseModelIndependentSearchType = eval(`(${extractMethod(searchPanelMethodsSource, 'getBaseModelIndependentSearchType')})`);
const getMissingAutoBaseModelInfo = eval(`(${extractMethod(searchPanelMethodsSource, 'getMissingAutoBaseModelInfo')})`);
const getMissingAutoBaseModel = eval(`(${extractMethod(searchPanelMethodsSource, 'getMissingAutoBaseModel')})`);
const getSearchBaseModelLabel = eval(`(${extractMethod(searchPanelMethodsSource, 'getSearchBaseModelLabel')})`);
const getSearchBaseModelContext = eval(`(${extractMethod(searchPanelMethodsSource, 'getSearchBaseModelContext')})`);
const state = { selectedBaseModel: 'auto' };
const dialog = {
getBaseModelIndependentSearchType,
getMissingAutoBaseModelInfo,
getMissingAutoBaseModel,
getSearchBaseModelLabel,
getSearchBaseModelContext,
getSearchState() {
return state;
},
getDefaultSearchBaseModel() {
return 'auto';
},
getDominantWorkflowBaseModel() {
return 'SDXL 1.0';
}
};
for (const missing of [
{ category: 'sams', node_type: 'SAMLoader' },
{ category: 'ultralytics', node_type: 'UltralyticsDetectorProvider' }
]) {
assert.equal(getMissingAutoBaseModel.call(dialog, missing), '');
assert.equal(getSearchBaseModelLabel.call(dialog, 'auto', missing), 'Auto (Any model)');
assert.equal(getSearchBaseModelContext.call(dialog, missing), '');
assert.match(getMissingAutoBaseModelInfo.call(dialog, missing).message, /Auto uses Any model/);
}
state.selectedBaseModel = 'SDXL 1.0';
assert.equal(
getSearchBaseModelContext.call(dialog, { category: 'sams' }),
'SDXL 1.0',
'Manual base model selection should remain available'
);
});
test('base model path mapping ignores conflicting full-path base model', () => {
const normalizeBaseModelToken = eval(`(${extractMethod(searchPanelMethodsSource, 'normalizeBaseModelToken')})`);
const getBaseModelTokenVariants = eval(`(${extractMethod(searchPanelMethodsSource, 'getBaseModelTokenVariants')})`);
+48 -3
View File
@@ -188,7 +188,52 @@ export const searchPanelMethods = {
return this.getMissingAutoBaseModelInfo(missing).value;
},
getBaseModelIndependentSearchType(missing = {}) {
const normalizeType = (value) => String(value || '')
.trim()
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
.toLowerCase()
.replace(/[^a-z0-9]+/g, '_')
.replace(/^_+|_+$/g, '');
const typeLabels = {
sam: 'SAM',
sams: 'SAM',
sam_model: 'SAM',
sam_models: 'SAM',
ultralytics: 'Ultralytics',
ultralytics_bbox: 'Ultralytics',
ultralytics_segm: 'Ultralytics',
yolo: 'Ultralytics'
};
const candidates = [
missing?.category,
missing?.model_type,
missing?.urn_type
];
for (const candidate of candidates) {
const label = typeLabels[normalizeType(candidate)];
if (label) return label;
}
const nodeType = normalizeType(missing?.node_type);
if (nodeType === 'samloader' || nodeType === 'sam_loader') return 'SAM';
if (nodeType === 'ultralyticsdetectorprovider' || nodeType === 'ultralytics_detector_provider') {
return 'Ultralytics';
}
return '';
},
getMissingAutoBaseModelInfo(missing = {}) {
const independentType = this.getBaseModelIndependentSearchType(missing);
if (independentType) {
return {
value: '',
source: 'independent model type',
usesAnyModel: true,
message: `${independentType} models are not tied to a base model, so Auto uses Any model.`
};
}
const searchSuggestion = this.getCachedSearchSuggestionData?.(missing) || {};
const directCandidates = [
{ value: missing?.civitai_info?.base_model, source: 'model metadata' },
@@ -408,9 +453,9 @@ export const searchPanelMethods = {
getSearchBaseModelLabel(value = 'auto', missing = {}) {
if (value === 'auto') {
const detected = missing
? this.getMissingAutoBaseModel(missing)
: this.getDominantWorkflowBaseModel();
const autoInfo = missing ? this.getMissingAutoBaseModelInfo(missing) : null;
if (autoInfo?.usesAnyModel) return 'Auto (Any model)';
const detected = autoInfo ? autoInfo.value : this.getDominantWorkflowBaseModel();
return detected ? `Auto (${detected})` : 'Auto';
}
const option = this.getKnownBaseModelOptions().find(item => item.value === value);