From 02e54e298047fe78f1d10462ebf4c0aba2955f54 Mon Sep 17 00:00:00 2001 From: localai-bot Date: Fri, 13 Mar 2026 14:38:33 +0000 Subject: [PATCH 1/7] 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 --- backend/go/acestep-cpp/goacestepcpp.go | 29 +++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/backend/go/acestep-cpp/goacestepcpp.go b/backend/go/acestep-cpp/goacestepcpp.go index e1243c3e9fad..e8b68412ddd2 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" @@ -11,7 +12,7 @@ import ( var ( CppLoadModel func(lmModelPath, textEncoderPath, ditModelPath, vaeModelPath string) int - CppGenerateMusic func(caption, lyrics string, bpm int, keyscale, timesignature string, duration, temperature float32, instrumental bool, seed int, dst string, threads int) int + CppGenerateMusic func(caption, lyrics string, bpm int, keyscale, timesignature string, duration, temperature float32, instrumental bool, seed int, dst string, threads int) ) type AceStepCpp struct { @@ -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) } From 189d3c8fd998c6fe60b0fb102e9d542777562483 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Fri, 13 Mar 2026 17:42:42 +0100 Subject: [PATCH 2/7] Apply suggestion from @mudler Signed-off-by: Ettore Di Giacinto --- backend/go/acestep-cpp/goacestepcpp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/go/acestep-cpp/goacestepcpp.go b/backend/go/acestep-cpp/goacestepcpp.go index e8b68412ddd2..bde8a428c347 100644 --- a/backend/go/acestep-cpp/goacestepcpp.go +++ b/backend/go/acestep-cpp/goacestepcpp.go @@ -12,7 +12,7 @@ import ( var ( CppLoadModel func(lmModelPath, textEncoderPath, ditModelPath, vaeModelPath string) int - CppGenerateMusic func(caption, lyrics string, bpm int, keyscale, timesignature string, duration, temperature float32, instrumental bool, seed int, dst string, threads int) + CppGenerateMusic func(caption, lyrics string, bpm int, keyscale, timesignature string, duration, temperature float32, instrumental bool, seed int, dst string, threads int) int ) type AceStepCpp struct { From 9eb83326783d033e69e1687c94f2fafa93decf1e Mon Sep 17 00:00:00 2001 From: localai-bot Date: Fri, 13 Mar 2026 21:16:10 +0000 Subject: [PATCH 3/7] 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. --- backend/go/acestep-cpp/acestepcpp_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/go/acestep-cpp/acestepcpp_test.go b/backend/go/acestep-cpp/acestepcpp_test.go index f9dd86f563a2..3c126a916ff4 100644 --- a/backend/go/acestep-cpp/acestepcpp_test.go +++ b/backend/go/acestep-cpp/acestepcpp_test.go @@ -109,9 +109,9 @@ func TestLoadModel(t *testing.T) { resp, err := client.LoadModel(context.Background(), &pb.ModelOptions{ ModelFile: filepath.Join(modelDir, "acestep-5Hz-lm-0.6B-Q8_0.gguf"), 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 { @@ -145,9 +145,9 @@ func TestSoundGeneration(t *testing.T) { loadResp, err := client.LoadModel(context.Background(), &pb.ModelOptions{ ModelFile: filepath.Join(modelDir, "acestep-5Hz-lm-0.6B-Q8_0.gguf"), 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 { From c4555c21a11d428f2e7f70a8bd2f5d435b859c1a Mon Sep 17 00:00:00 2001 From: localai-bot Date: Fri, 13 Mar 2026 22:36:38 +0000 Subject: [PATCH 4/7] fix: change bpm parameter type to float32 to match C++ API signature --- backend/go/acestep-cpp/goacestepcpp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/go/acestep-cpp/goacestepcpp.go b/backend/go/acestep-cpp/goacestepcpp.go index bde8a428c347..921231295ce2 100644 --- a/backend/go/acestep-cpp/goacestepcpp.go +++ b/backend/go/acestep-cpp/goacestepcpp.go @@ -12,7 +12,7 @@ import ( var ( CppLoadModel func(lmModelPath, textEncoderPath, ditModelPath, vaeModelPath string) int - CppGenerateMusic func(caption, lyrics string, bpm int, keyscale, timesignature string, duration, temperature float32, instrumental bool, seed int, dst string, threads int) int + CppGenerateMusic func(caption, lyrics string, bpm float32, keyscale, timesignature string, duration, temperature float32, instrumental bool, seed int, dst string, threads int) int ) type AceStepCpp struct { @@ -101,7 +101,7 @@ func (a *AceStepCpp) SoundGeneration(req *pb.SoundGenerationRequest) error { seed := 42 threads := 4 - if ret := CppGenerateMusic(caption, lyrics, bpm, keyscale, timesignature, duration, temperature, instrumental, seed, req.GetDst(), threads); ret != 0 { + if ret := CppGenerateMusic(caption, lyrics, float32(bpm), keyscale, timesignature, duration, temperature, instrumental, seed, req.GetDst(), threads); ret != 0 { return fmt.Errorf("failed to generate music (error code: %d)", ret) } From c3d92a71f1fddf16267ce1386e8003749c3915a7 Mon Sep 17 00:00:00 2001 From: localai-bot Date: Fri, 13 Mar 2026 23:13:55 +0000 Subject: [PATCH 5/7] 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 --- backend/go/acestep-cpp/acestepcpp_test.go | 27 +++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/backend/go/acestep-cpp/acestepcpp_test.go b/backend/go/acestep-cpp/acestepcpp_test.go index 3c126a916ff4..c8064015716b 100644 --- a/backend/go/acestep-cpp/acestepcpp_test.go +++ b/backend/go/acestep-cpp/acestepcpp_test.go @@ -106,12 +106,17 @@ 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") + baseDir := filepath.Dir(mainModelPath) + 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:Qwen3-Embedding-0.6B-Q8_0.gguf", - "dit_model:acestep-v15-turbo-Q8_0.gguf", - "vae_model:vae-BF16.gguf", + baseDir + "/text_encoder_model:Qwen3-Embedding-0.6B-Q8_0.gguf", + baseDir + "/dit_model:acestep-v15-turbo-Q8_0.gguf", + baseDir + "/vae_model:vae-BF16.gguf", }, }) if err != nil { @@ -141,13 +146,17 @@ 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") + baseDir := filepath.Dir(mainModelPath) + // 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:Qwen3-Embedding-0.6B-Q8_0.gguf", - "dit_model:acestep-v15-turbo-Q8_0.gguf", - "vae_model:vae-BF16.gguf", + baseDir + "/text_encoder_model:Qwen3-Embedding-0.6B-Q8_0.gguf", + baseDir + "/dit_model:acestep-v15-turbo-Q8_0.gguf", + baseDir + "/vae_model:vae-BF16.gguf", }, }) if err != nil { @@ -160,7 +169,7 @@ func TestSoundGeneration(t *testing.T) { // Generate music duration := float32(10.0) temperature := float32(0.85) - bpm := int32(120) + bpm := float32(120.0) caption := "A cheerful electronic dance track" timesig := "4/4" From 91606b1becb0a218d4ee4079f318fd35b88b2fa7 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sat, 14 Mar 2026 00:57:03 +0100 Subject: [PATCH 6/7] Apply suggestions from code review Co-authored-by: Ettore Di Giacinto Signed-off-by: Ettore Di Giacinto --- backend/go/acestep-cpp/acestepcpp_test.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/backend/go/acestep-cpp/acestepcpp_test.go b/backend/go/acestep-cpp/acestepcpp_test.go index c8064015716b..2f41c2b9fd59 100644 --- a/backend/go/acestep-cpp/acestepcpp_test.go +++ b/backend/go/acestep-cpp/acestepcpp_test.go @@ -109,14 +109,13 @@ func TestLoadModel(t *testing.T) { // Get base directory from main model file for relative paths mainModelPath := filepath.Join(modelDir, "acestep-5Hz-lm-0.6B-Q8_0.gguf") - baseDir := filepath.Dir(mainModelPath) resp, err := client.LoadModel(context.Background(), &pb.ModelOptions{ ModelFile: mainModelPath, Options: []string{ - baseDir + "/text_encoder_model:Qwen3-Embedding-0.6B-Q8_0.gguf", - baseDir + "/dit_model:acestep-v15-turbo-Q8_0.gguf", - baseDir + "/vae_model: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 { @@ -148,15 +147,14 @@ func TestSoundGeneration(t *testing.T) { // Get base directory from main model file for relative paths mainModelPath := filepath.Join(modelDir, "acestep-5Hz-lm-0.6B-Q8_0.gguf") - baseDir := filepath.Dir(mainModelPath) // Load models loadResp, err := client.LoadModel(context.Background(), &pb.ModelOptions{ ModelFile: mainModelPath, Options: []string{ - baseDir + "/text_encoder_model:Qwen3-Embedding-0.6B-Q8_0.gguf", - baseDir + "/dit_model:acestep-v15-turbo-Q8_0.gguf", - baseDir + "/vae_model: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 { From 85046b5649fec04e5146e5027d292a3a9566c2ff Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sat, 14 Mar 2026 00:59:35 +0100 Subject: [PATCH 7/7] Apply suggestions from code review Co-authored-by: Ettore Di Giacinto Signed-off-by: Ettore Di Giacinto --- backend/go/acestep-cpp/acestepcpp_test.go | 2 +- backend/go/acestep-cpp/goacestepcpp.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/go/acestep-cpp/acestepcpp_test.go b/backend/go/acestep-cpp/acestepcpp_test.go index 2f41c2b9fd59..2abe24805a6e 100644 --- a/backend/go/acestep-cpp/acestepcpp_test.go +++ b/backend/go/acestep-cpp/acestepcpp_test.go @@ -167,7 +167,7 @@ func TestSoundGeneration(t *testing.T) { // Generate music duration := float32(10.0) temperature := float32(0.85) - bpm := float32(120.0) + bpm := int32(120) caption := "A cheerful electronic dance track" timesig := "4/4" diff --git a/backend/go/acestep-cpp/goacestepcpp.go b/backend/go/acestep-cpp/goacestepcpp.go index 921231295ce2..bde8a428c347 100644 --- a/backend/go/acestep-cpp/goacestepcpp.go +++ b/backend/go/acestep-cpp/goacestepcpp.go @@ -12,7 +12,7 @@ import ( var ( CppLoadModel func(lmModelPath, textEncoderPath, ditModelPath, vaeModelPath string) int - CppGenerateMusic func(caption, lyrics string, bpm float32, keyscale, timesignature string, duration, temperature float32, instrumental bool, seed int, dst string, threads int) int + CppGenerateMusic func(caption, lyrics string, bpm int, keyscale, timesignature string, duration, temperature float32, instrumental bool, seed int, dst string, threads int) int ) type AceStepCpp struct { @@ -101,7 +101,7 @@ func (a *AceStepCpp) SoundGeneration(req *pb.SoundGenerationRequest) error { seed := 42 threads := 4 - if ret := CppGenerateMusic(caption, lyrics, float32(bpm), keyscale, timesignature, duration, temperature, instrumental, seed, req.GetDst(), threads); ret != 0 { + if ret := CppGenerateMusic(caption, lyrics, bpm, keyscale, timesignature, duration, temperature, instrumental, seed, req.GetDst(), threads); ret != 0 { return fmt.Errorf("failed to generate music (error code: %d)", ret) }