Skip to content

Commit 149a35b

Browse files
authored
Merge pull request #9 from audiohacking/copilot/fix-model-path-loading-issue
Fix: backend resolves DiT model names to full paths
2 parents df4268c + 41fa65c commit 149a35b

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

server/src/config/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ function resolveModelsDir(): string {
5656

5757
/** Resolves the DiT model (acestep-v15-turbo-*.gguf). */
5858
function resolveDitModel(modelsDir: string): string {
59-
if (process.env.ACESTEP_MODEL) return resolveFromRoot(process.env.ACESTEP_MODEL);
59+
if (process.env.ACESTEP_MODEL) {
60+
const p = resolveFromRoot(process.env.ACESTEP_MODEL);
61+
if (existsSync(p)) return p;
62+
console.warn(`[config] ACESTEP_MODEL path not found: ${p} — falling back to auto-detection`);
63+
}
6064
if (!existsSync(modelsDir)) return '';
6165

6266
const preference = [

server/src/services/acestep.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,53 @@ export async function checkSpaceHealth(): Promise<boolean> {
169169
}
170170
}
171171

172+
// ---------------------------------------------------------------------------
173+
// Model name → full path resolution
174+
// ---------------------------------------------------------------------------
175+
176+
/**
177+
* Resolves a DiT model name sent by the frontend into an absolute file path.
178+
*
179+
* The UI only knows model names (e.g. "acestep-v15-turbo-Q8_0" or
180+
* "acestep-v15-turbo-shift3"). The backend owns the model directory and is
181+
* solely responsible for turning that name into a real path:
182+
*
183+
* 1. No name supplied → use the default from config (auto-detected or env).
184+
* 2. Already an absolute path → pass through unchanged.
185+
* 3. Exact filename match: look for "<name>.gguf" in the models dir.
186+
* 4. Prefix match: find any gguf whose name starts with "<name>-", preferring
187+
* Q8_0 → Q6_K → Q5_K_M → Q4_K_M → BF16.
188+
* 5. Nothing found → fall back to the configured default.
189+
*/
190+
function resolveParamDitModel(name: string | undefined): string {
191+
if (!name) return config.acestep.ditModel;
192+
if (path.isAbsolute(name)) return name;
193+
194+
const modelsDir = config.models.dir;
195+
if (existsSync(modelsDir)) {
196+
// Exact filename match (e.g. "acestep-v15-turbo-Q8_0" → "…Q8_0.gguf")
197+
const exact = path.join(modelsDir, `${name}.gguf`);
198+
if (existsSync(exact)) return exact;
199+
200+
// Prefix match for variant names without quantization suffix
201+
try {
202+
const files = readdirSync(modelsDir).filter(
203+
f => f.endsWith('.gguf') && !f.endsWith('.part') && f.startsWith(`${name}-`),
204+
);
205+
if (files.length > 0) {
206+
const quants = ['Q8_0', 'Q6_K', 'Q5_K_M', 'Q4_K_M', 'BF16'];
207+
for (const q of quants) {
208+
const match = files.find(f => f === `${name}-${q}.gguf`);
209+
if (match) return path.join(modelsDir, match);
210+
}
211+
return path.join(modelsDir, files[0]);
212+
}
213+
} catch { /* ignore read errors */ }
214+
}
215+
216+
return config.acestep.ditModel;
217+
}
218+
172219
// ---------------------------------------------------------------------------
173220
// Audio path resolution (for reference/source audio inputs)
174221
// ---------------------------------------------------------------------------
@@ -482,7 +529,7 @@ async function runViaSpawn(
482529

483530
const ditVaeBin = config.acestep.ditVaeBin!;
484531
const textEncoderModel = config.acestep.textEncoderModel;
485-
const ditModel = params.ditModel ? params.ditModel : config.acestep.ditModel;
532+
const ditModel = resolveParamDitModel(params.ditModel);
486533
const vaeModel = config.acestep.vaeModel;
487534

488535
if (!textEncoderModel) throw new Error('Text-encoder model not found — run models.sh first');
@@ -622,7 +669,8 @@ function buildHttpRequest(params: GenerationParams): Record<string, unknown> {
622669

623670
if (params.referenceAudioUrl) body.reference_audio = resolveAudioPath(params.referenceAudioUrl);
624671
if (params.sourceAudioUrl) body.src_audio = resolveAudioPath(params.sourceAudioUrl);
625-
if (params.ditModel) body.dit_model = params.ditModel;
672+
const resolvedDitModel = resolveParamDitModel(params.ditModel);
673+
if (resolvedDitModel) body.dit_model = resolvedDitModel;
626674

627675
// Pass LoRA state as request fields
628676
if (loraState.loaded && loraState.active && loraState.path) {

0 commit comments

Comments
 (0)