From 0ec3ea4a464dd60fc715de20e6f6020a6015360c Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Sat, 14 Mar 2026 01:16:13 +0100 Subject: [PATCH] fix(acestep-cpp): resolve relative model paths in options (#8993) * fix(acestep-cpp): resolve relative model paths in options The acestep-cpp backend was failing to load models because the model paths in options (text_encoder_model, dit_model, vae_model) were being passed to the C++ code without resolving their relative paths. When a user configures acestep-cpp-turbo-4b, the model paths are specified as relative paths like 'acestep-cpp/acestep-v15-turbo-Q8_0.gguf'. The backend was passing these paths directly to the C++ code without joining them with the model directory. This fix: 1. Gets the base directory from the ModelFile path 2. Resolves all relative paths in options to be absolute paths 3. Adds debug logging to show resolved paths for troubleshooting Fixes #8991 Signed-off-by: localai-bot * Apply suggestion from @mudler Signed-off-by: Ettore Di Giacinto * test: fix acestep tests to not join modeldir in options According to code review feedback, the Options array in TestLoadModel and TestSoundGeneration should contain just the model filenames without filepath.Join with modelDir. The model paths are handled internally by the backend. * fix: change bpm parameter type to float32 to match C++ API signature * test: fix TestLoadModel and TestSoundGeneration to use baseDir for model paths - Modified TestLoadModel to compute baseDir from main model path and use it for relative model paths - Modified TestSoundGeneration similarly to use baseDir for model paths - Changed bpm parameter type from int32 to float32 to match C++ API * Apply suggestions from code review Co-authored-by: Ettore Di Giacinto Signed-off-by: Ettore Di Giacinto * Apply suggestions from code review Co-authored-by: Ettore Di Giacinto Signed-off-by: Ettore Di Giacinto --------- Signed-off-by: localai-bot Signed-off-by: Ettore Di Giacinto Co-authored-by: localai-bot Co-authored-by: Ettore Di Giacinto --- backend/go/acestep-cpp/acestepcpp_test.go | 23 ++++++++++++------- backend/go/acestep-cpp/goacestepcpp.go | 27 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/backend/go/acestep-cpp/acestepcpp_test.go b/backend/go/acestep-cpp/acestepcpp_test.go index f9dd86f56..2abe24805 100644 --- a/backend/go/acestep-cpp/acestepcpp_test.go +++ b/backend/go/acestep-cpp/acestepcpp_test.go @@ -106,12 +106,16 @@ func TestLoadModel(t *testing.T) { defer conn.Close() client := pb.NewBackendClient(conn) + + // Get base directory from main model file for relative paths + mainModelPath := filepath.Join(modelDir, "acestep-5Hz-lm-0.6B-Q8_0.gguf") + resp, err := client.LoadModel(context.Background(), &pb.ModelOptions{ - ModelFile: filepath.Join(modelDir, "acestep-5Hz-lm-0.6B-Q8_0.gguf"), + ModelFile: mainModelPath, Options: []string{ - "text_encoder_model:" + filepath.Join(modelDir, "Qwen3-Embedding-0.6B-Q8_0.gguf"), - "dit_model:" + filepath.Join(modelDir, "acestep-v15-turbo-Q8_0.gguf"), - "vae_model:" + filepath.Join(modelDir, "vae-BF16.gguf"), + "text_encoder_model:Qwen3-Embedding-0.6B-Q8_0.gguf", + "dit_model:acestep-v15-turbo-Q8_0.gguf", + "vae_model:vae-BF16.gguf", }, }) if err != nil { @@ -141,13 +145,16 @@ func TestSoundGeneration(t *testing.T) { client := pb.NewBackendClient(conn) + // Get base directory from main model file for relative paths + mainModelPath := filepath.Join(modelDir, "acestep-5Hz-lm-0.6B-Q8_0.gguf") + // Load models loadResp, err := client.LoadModel(context.Background(), &pb.ModelOptions{ - ModelFile: filepath.Join(modelDir, "acestep-5Hz-lm-0.6B-Q8_0.gguf"), + ModelFile: mainModelPath, Options: []string{ - "text_encoder_model:" + filepath.Join(modelDir, "Qwen3-Embedding-0.6B-Q8_0.gguf"), - "dit_model:" + filepath.Join(modelDir, "acestep-v15-turbo-Q8_0.gguf"), - "vae_model:" + filepath.Join(modelDir, "vae-BF16.gguf"), + "text_encoder_model:Qwen3-Embedding-0.6B-Q8_0.gguf", + "dit_model:acestep-v15-turbo-Q8_0.gguf", + "vae_model:vae-BF16.gguf", }, }) if err != nil { diff --git a/backend/go/acestep-cpp/goacestepcpp.go b/backend/go/acestep-cpp/goacestepcpp.go index e1243c3e9..bde8a428c 100644 --- a/backend/go/acestep-cpp/goacestepcpp.go +++ b/backend/go/acestep-cpp/goacestepcpp.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "path/filepath" "strings" "github.com/mudler/LocalAI/pkg/grpc/base" @@ -22,6 +23,9 @@ func (a *AceStepCpp) Load(opts *pb.ModelOptions) error { // ModelFile is the LM model path lmModel := opts.ModelFile + // Get the base directory from ModelFile for resolving relative paths + baseDir := filepath.Dir(lmModel) + var textEncoderModel, ditModel, vaeModel string for _, oo := range opts.Options { @@ -52,6 +56,29 @@ func (a *AceStepCpp) Load(opts *pb.ModelOptions) error { return fmt.Errorf("vae_model option is required") } + // Resolve relative paths to the base directory + // If the path doesn't start with "/" it's relative + if !filepath.IsAbs(textEncoderModel) { + textEncoderModel = filepath.Join(baseDir, textEncoderModel) + } + if !filepath.IsAbs(ditModel) { + ditModel = filepath.Join(baseDir, ditModel) + } + if !filepath.IsAbs(vaeModel) { + vaeModel = filepath.Join(baseDir, vaeModel) + } + + // Also resolve the lmModel if it's relative + if !filepath.IsAbs(lmModel) { + lmModel = filepath.Join(baseDir, lmModel) + } + + fmt.Fprintf(os.Stderr, "[acestep-cpp] Resolved paths:\n") + fmt.Fprintf(os.Stderr, " LM Model: %s\n", lmModel) + fmt.Fprintf(os.Stderr, " Text Encoder: %s\n", textEncoderModel) + fmt.Fprintf(os.Stderr, " DiT Model: %s\n", ditModel) + fmt.Fprintf(os.Stderr, " VAE Model: %s\n", vaeModel) + if ret := CppLoadModel(lmModel, textEncoderModel, ditModel, vaeModel); ret != 0 { return fmt.Errorf("failed to load acestep models (error code: %d)", ret) }