From b29544d747cfb0e388249ae47c9ba9afce5a7bd9 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sat, 19 Jul 2025 08:31:33 +0200 Subject: [PATCH] feat: split piper from main binary (#5858) Signed-off-by: Ettore Di Giacinto --- .github/workflows/backend.yml | 13 +++++++ .github/workflows/bump_deps.yaml | 2 +- .github/workflows/release.yaml | 1 - .github/workflows/test.yml | 9 +---- Dockerfile | 10 +---- Makefile | 60 ++++++++---------------------- aio/cpu/embeddings.yaml | 1 + aio/cpu/rerank.yaml | 2 +- aio/cpu/text-to-speech.yaml | 2 +- aio/cpu/text-to-text.yaml | 1 + aio/cpu/vision.yaml | 1 + aio/gpu-8g/embeddings.yaml | 1 + aio/gpu-8g/rerank.yaml | 2 +- aio/gpu-8g/text-to-speech.yaml | 2 +- aio/gpu-8g/text-to-text.yaml | 1 + aio/gpu-8g/vision.yaml | 1 + aio/intel/embeddings.yaml | 1 + aio/intel/rerank.yaml | 2 +- aio/intel/text-to-speech.yaml | 2 +- aio/intel/text-to-text.yaml | 1 + aio/intel/vision.yaml | 1 + backend/Dockerfile.go | 3 +- backend/backend.proto | 1 - backend/cpp/llama-cpp/run.sh | 2 +- backend/go/bark-cpp/Makefile | 5 ++- backend/go/bark-cpp/package.sh | 41 ++++++++++++++++++++ backend/go/bark-cpp/run.sh | 7 ++++ backend/go/piper/Makefile | 37 ++++++++++++++++++ backend/go/{tts => piper}/main.go | 0 backend/go/piper/package.sh | 54 +++++++++++++++++++++++++++ backend/go/{tts => piper}/piper.go | 2 +- backend/go/piper/run.sh | 15 ++++++++ backend/index.yaml | 20 ++++++++++ core/backend/tts.go | 2 +- core/http/app_test.go | 8 +--- core/http/endpoints/localai/tts.go | 8 +--- pkg/model/initializers.go | 13 +------ 37 files changed, 234 insertions(+), 100 deletions(-) create mode 100755 backend/go/bark-cpp/package.sh create mode 100644 backend/go/piper/Makefile rename backend/go/{tts => piper}/main.go (100%) create mode 100755 backend/go/piper/package.sh rename backend/go/{tts => piper}/piper.go (95%) create mode 100755 backend/go/piper/run.sh diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 60643be39..a89b639c7 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -598,6 +598,19 @@ jobs: backend: "bark" dockerfile: "./backend/Dockerfile.python" context: "./backend" + # piper + - build-type: '' + cuda-major-version: "" + cuda-minor-version: "" + platforms: 'linux/amd64,linux/arm64' + tag-latest: 'true' + tag-suffix: '-piper' + runs-on: 'ubuntu-latest' + base-image: "ubuntu:22.04" + skip-drivers: 'false' + backend: "piper" + dockerfile: "./backend/Dockerfile.go" + context: "./" # bark-cpp - build-type: '' cuda-major-version: "" diff --git a/.github/workflows/bump_deps.yaml b/.github/workflows/bump_deps.yaml index 899a974bf..01d60a80d 100644 --- a/.github/workflows/bump_deps.yaml +++ b/.github/workflows/bump_deps.yaml @@ -32,7 +32,7 @@ jobs: - repository: "mudler/go-piper" variable: "PIPER_VERSION" branch: "master" - file: "Makefile" + file: "backend/go/piper/Makefile" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e8e9e2da2..366f330ed 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -296,7 +296,6 @@ jobs: export PATH=/opt/rocm/bin:$PATH source /opt/intel/oneapi/setvars.sh sudo cp /lib64/ld-linux-x86-64.so.2 ld.so - BACKEND_LIBS="./ld.so ./sources/go-piper/piper/build/fi/lib/libfmt.a ./sources/go-piper/piper-phonemize/pi/lib/libonnxruntime.so.1.14.1 ./sources/go-piper/piper-phonemize/pi/src/libespeak-ng/libespeak-ng.so /usr/lib/x86_64-linux-gnu/libdl.so.2 /usr/lib/x86_64-linux-gnu/librt.so.1 /usr/lib/x86_64-linux-gnu/libpthread.so.0 ./sources/go-piper/piper-phonemize/pi/lib/libpiper_phonemize.so.1 ./sources/go-piper/piper/build/si/lib/libspdlog.a ./sources/go-piper/espeak/ei/lib/libucd.so" \ make -j4 dist - uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1f7ca75b1..bdfb3b824 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -103,12 +103,7 @@ jobs: make -C backend/python/transformers - # Pre-build piper before we start tests in order to have shared libraries in place - make sources/go-piper && \ - GO_TAGS="tts" make -C sources/go-piper piper.o && \ - sudo cp -rfv sources/go-piper/piper-phonemize/pi/lib/. /usr/lib/ - - make backends/llama-cpp + make backends/llama-cpp backends/piper env: CUDA_VERSION: 12-4 - name: Test @@ -173,7 +168,7 @@ jobs: PATH="$PATH:$HOME/go/bin" make protogen-go - name: Test run: | - PATH="$PATH:$HOME/go/bin" make backends/llama-cpp docker-build-aio e2e-aio + PATH="$PATH:$HOME/go/bin" make backends/llama-cpp backends/piper docker-build-aio e2e-aio - name: Setup tmate session if tests fail if: ${{ failure() }} uses: mxschmitt/action-tmate@v3.22 diff --git a/Dockerfile b/Dockerfile index 17d92477b..653cf384c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -239,7 +239,7 @@ RUN git clone --recurse-submodules --jobs 4 -b ${GRPC_VERSION} --depth 1 --shall FROM build-requirements AS builder-base -ARG GO_TAGS="tts p2p" +ARG GO_TAGS="p2p" ARG GRPC_BACKENDS ARG MAKEFLAGS ARG LD_FLAGS="-s -w" @@ -315,11 +315,6 @@ COPY . . ## Otherwise just run the normal build RUN make build -RUN if [ ! -d "/build/sources/go-piper/piper-phonemize/pi/lib/" ]; then \ - mkdir -p /build/sources/go-piper/piper-phonemize/pi/lib/ \ - touch /build/sources/go-piper/piper-phonemize/pi/lib/keep \ - ; fi - ################################### ################################### @@ -362,9 +357,6 @@ COPY ./entrypoint.sh . # Copy the binary COPY --from=builder /build/local-ai ./ -# Copy shared libraries for piper -COPY --from=builder /build/sources/go-piper/piper-phonemize/pi/lib/* /usr/lib/ - # Make sure the models directory exists RUN mkdir -p /models /backends diff --git a/Makefile b/Makefile index 81cb6a455..0d1b7ff69 100644 --- a/Makefile +++ b/Makefile @@ -9,10 +9,6 @@ DETECT_LIBS?=true WHISPER_REPO?=https://github.com/ggml-org/whisper.cpp WHISPER_CPP_VERSION?=032697b9a850dc2615555e2a93a683cc3dd58559 -# go-piper version -PIPER_REPO?=https://github.com/mudler/go-piper -PIPER_VERSION?=e10ca041a885d4a8f3871d52924b47792d5e5aa0 - # stablediffusion.cpp (ggml) STABLEDIFFUSION_GGML_REPO?=https://github.com/richiejp/stable-diffusion.cpp STABLEDIFFUSION_GGML_VERSION?=53e3b17eb3d0b5760ced06a1f98320b68b34aaae @@ -209,14 +205,6 @@ ifeq ($(STATIC),true) LD_FLAGS+=-linkmode external -extldflags -static endif -ifeq ($(findstring tts,$(GO_TAGS)),tts) -# OPTIONAL_TARGETS+=go-piper/libpiper_binding.a -# OPTIONAL_TARGETS+=backend-assets/espeak-ng-data - PIPER_CGO_CXXFLAGS+=-I$(CURDIR)/sources/go-piper/piper/src/cpp -I$(CURDIR)/sources/go-piper/piper/build/fi/include -I$(CURDIR)/sources/go-piper/piper/build/pi/include -I$(CURDIR)/sources/go-piper/piper/build/si/include - PIPER_CGO_LDFLAGS+=-L$(CURDIR)/sources/go-piper/piper/build/fi/lib -L$(CURDIR)/sources/go-piper/piper/build/pi/lib -L$(CURDIR)/sources/go-piper/piper/build/si/lib -lfmt -lspdlog -lucd - OPTIONAL_GRPC+=backend-assets/grpc/piper -endif - ALL_GRPC_BACKENDS=backend-assets/grpc/huggingface ALL_GRPC_BACKENDS+=backend-assets/grpc/whisper @@ -248,19 +236,6 @@ endif all: help -## go-piper -sources/go-piper: - mkdir -p sources/go-piper - cd sources/go-piper && \ - git init && \ - git remote add origin $(PIPER_REPO) && \ - git fetch origin && \ - git checkout $(PIPER_VERSION) && \ - git submodule update --init --recursive --depth 1 --single-branch - -sources/go-piper/libpiper_binding.a: sources/go-piper - $(MAKE) -C sources/go-piper libpiper_binding.a example/main piper.o - ## stablediffusion (ggml) sources/stablediffusion-ggml.cpp: git clone --recursive $(STABLEDIFFUSION_GGML_REPO) sources/stablediffusion-ggml.cpp && \ @@ -303,17 +278,15 @@ sources/whisper.cpp/build/src/libwhisper.a: sources/whisper.cpp cd sources/whisper.cpp && cmake $(WHISPER_CMAKE_ARGS) . -B ./build cd sources/whisper.cpp/build && cmake --build . --config Release -get-sources: sources/go-piper sources/stablediffusion-ggml.cpp sources/whisper.cpp +get-sources: sources/stablediffusion-ggml.cpp sources/whisper.cpp replace: $(GOCMD) mod edit -replace github.com/ggerganov/whisper.cpp=$(CURDIR)/sources/whisper.cpp $(GOCMD) mod edit -replace github.com/ggerganov/whisper.cpp/bindings/go=$(CURDIR)/sources/whisper.cpp/bindings/go - $(GOCMD) mod edit -replace github.com/mudler/go-piper=$(CURDIR)/sources/go-piper dropreplace: $(GOCMD) mod edit -dropreplace github.com/ggerganov/whisper.cpp $(GOCMD) mod edit -dropreplace github.com/ggerganov/whisper.cpp/bindings/go - $(GOCMD) mod edit -dropreplace github.com/mudler/go-piper prepare-sources: get-sources replace $(GOCMD) mod download @@ -322,7 +295,6 @@ prepare-sources: get-sources replace rebuild: ## Rebuilds the project $(GOCMD) clean -cache $(MAKE) -C sources/whisper.cpp clean - $(MAKE) -C sources/go-piper clean $(MAKE) build prepare: prepare-sources $(OPTIONAL_TARGETS) @@ -376,11 +348,8 @@ backend-assets/lib: mkdir -p backend-assets/lib dist: - GO_TAGS="tts p2p" $(MAKE) build -ifeq ($(DETECT_LIBS),true) - scripts/prepare-libs.sh backend-assets/grpc/piper -endif - GO_TAGS="tts p2p" STATIC=true $(MAKE) build + GO_TAGS="p2p" $(MAKE) build + GO_TAGS="p2p" STATIC=true $(MAKE) build mkdir -p release # if BUILD_ID is empty, then we don't append it to the binary name ifeq ($(BUILD_ID),) @@ -418,7 +387,7 @@ prepare-test: grpcs ## Test targets test: prepare test-models/testmodel.ggml grpcs @echo 'Running tests' - export GO_TAGS="tts debug" + export GO_TAGS="debug" $(MAKE) prepare-test HUGGINGFACE_GRPC=$(abspath ./)/backend/python/transformers/run.sh TEST_DIR=$(abspath ./)/test-dir/ FIXTURES=$(abspath ./)/tests/fixtures CONFIG_FILE=$(abspath ./)/test-models/config.yaml MODELS_PATH=$(abspath ./)/test-models BACKENDS_PATH=$(abspath ./)/backends \ $(GOCMD) run github.com/onsi/ginkgo/v2/ginkgo --label-filter="!llama-gguf" --flake-attempts $(TEST_FLAKES) --fail-fast -v -r $(TEST_PATHS) @@ -429,6 +398,9 @@ test: prepare test-models/testmodel.ggml grpcs backends/llama-cpp: docker-build-llama-cpp docker-save-llama-cpp build-api ./local-ai backends install "ocifile://$(abspath ./backend-images/llama-cpp.tar)" +backends/piper: docker-build-piper docker-save-piper build-api + ./local-ai backends install "ocifile://$(abspath ./backend-images/piper.tar)" + ######################################################## ## AIO tests ######################################################## @@ -652,9 +624,6 @@ ifeq ($(BUILD_API_ONLY),true) touch backend-assets/keep endif -backend-assets/espeak-ng-data: sources/go-piper sources/go-piper/libpiper_binding.a - mkdir -p backend-assets/espeak-ng-data - @cp -rf sources/go-piper/piper-phonemize/pi/share/espeak-ng-data/. backend-assets/espeak-ng-data backend-assets/grpc: mkdir -p backend-assets/grpc @@ -665,13 +634,6 @@ ifneq ($(UPX),) $(UPX) backend-assets/grpc/huggingface endif -backend-assets/grpc/piper: protogen-go replace sources/go-piper sources/go-piper/libpiper_binding.a backend-assets/grpc backend-assets/espeak-ng-data - CGO_CXXFLAGS="$(PIPER_CGO_CXXFLAGS)" CGO_LDFLAGS="$(PIPER_CGO_LDFLAGS)" LIBRARY_PATH=$(CURDIR)/sources/go-piper \ - $(GOCMD) build -ldflags "$(LD_FLAGS)" -tags "$(GO_TAGS)" -o backend-assets/grpc/piper ./backend/go/tts/ -ifneq ($(UPX),) - $(UPX) backend-assets/grpc/piper -endif - backend-assets/grpc/silero-vad: protogen-go replace backend-assets/grpc backend-assets/lib/libonnxruntime.so.1 CGO_LDFLAGS="$(CGO_LDFLAGS)" CPATH="$(CPATH):$(CURDIR)/sources/onnxruntime/include/" LIBRARY_PATH=$(CURDIR)/backend-assets/lib \ $(GOCMD) build -ldflags "$(LD_FLAGS)" -tags "$(GO_TAGS)" -o backend-assets/grpc/silero-vad ./backend/go/vad/silero @@ -762,9 +724,17 @@ docker-build-llama-cpp: docker-build-bark-cpp: docker build -t local-ai-backend:bark-cpp -f backend/Dockerfile.go --build-arg BACKEND=bark-cpp . +docker-build-piper: + docker build -t local-ai-backend:piper -f backend/Dockerfile.go --build-arg BACKEND=piper . + +docker-save-piper: backend-images + docker save local-ai-backend:piper -o backend-images/piper.tar + docker-save-llama-cpp: backend-images docker save local-ai-backend:llama-cpp -o backend-images/llama-cpp.tar +docker-save-bark-cpp: backend-images + docker save local-ai-backend:bark-cpp -o backend-images/bark-cpp.tar docker-build-rerankers: docker build -t local-ai-backend:rerankers -f backend/Dockerfile.python --build-arg BACKEND=rerankers . diff --git a/aio/cpu/embeddings.yaml b/aio/cpu/embeddings.yaml index f9e0ca5db..0f88f4511 100644 --- a/aio/cpu/embeddings.yaml +++ b/aio/cpu/embeddings.yaml @@ -1,5 +1,6 @@ embeddings: true name: text-embedding-ada-002 +backend: llama-cpp parameters: model: huggingface://bartowski/granite-embedding-107m-multilingual-GGUF/granite-embedding-107m-multilingual-f16.gguf diff --git a/aio/cpu/rerank.yaml b/aio/cpu/rerank.yaml index b52dee773..70d386b2b 100644 --- a/aio/cpu/rerank.yaml +++ b/aio/cpu/rerank.yaml @@ -3,7 +3,7 @@ reranking: true f16: true parameters: model: jina-reranker-v1-tiny-en.f16.gguf - +backend: llama-cpp download_files: - filename: jina-reranker-v1-tiny-en.f16.gguf sha256: 5f696cf0d0f3d347c4a279eee8270e5918554cdac0ed1f632f2619e4e8341407 diff --git a/aio/cpu/text-to-speech.yaml b/aio/cpu/text-to-speech.yaml index 91998e6a7..4009c3f77 100644 --- a/aio/cpu/text-to-speech.yaml +++ b/aio/cpu/text-to-speech.yaml @@ -2,7 +2,7 @@ name: tts-1 download_files: - filename: voice-en-us-amy-low.tar.gz uri: https://github.com/rhasspy/piper/releases/download/v0.0.2/voice-en-us-amy-low.tar.gz - +backend: piper parameters: model: en-us-amy-low.onnx diff --git a/aio/cpu/text-to-text.yaml b/aio/cpu/text-to-text.yaml index c6802137f..19ed1f440 100644 --- a/aio/cpu/text-to-text.yaml +++ b/aio/cpu/text-to-text.yaml @@ -1,5 +1,6 @@ context_size: 8192 f16: true +backend: llama-cpp function: grammar: no_mixed_free_string: true diff --git a/aio/cpu/vision.yaml b/aio/cpu/vision.yaml index 5325f99c7..fa31c2343 100644 --- a/aio/cpu/vision.yaml +++ b/aio/cpu/vision.yaml @@ -1,5 +1,6 @@ context_size: 4096 f16: true +backend: llama-cpp mmap: true mmproj: minicpm-v-2_6-mmproj-f16.gguf name: gpt-4o diff --git a/aio/gpu-8g/embeddings.yaml b/aio/gpu-8g/embeddings.yaml index f9e0ca5db..0f88f4511 100644 --- a/aio/gpu-8g/embeddings.yaml +++ b/aio/gpu-8g/embeddings.yaml @@ -1,5 +1,6 @@ embeddings: true name: text-embedding-ada-002 +backend: llama-cpp parameters: model: huggingface://bartowski/granite-embedding-107m-multilingual-GGUF/granite-embedding-107m-multilingual-f16.gguf diff --git a/aio/gpu-8g/rerank.yaml b/aio/gpu-8g/rerank.yaml index b52dee773..70d386b2b 100644 --- a/aio/gpu-8g/rerank.yaml +++ b/aio/gpu-8g/rerank.yaml @@ -3,7 +3,7 @@ reranking: true f16: true parameters: model: jina-reranker-v1-tiny-en.f16.gguf - +backend: llama-cpp download_files: - filename: jina-reranker-v1-tiny-en.f16.gguf sha256: 5f696cf0d0f3d347c4a279eee8270e5918554cdac0ed1f632f2619e4e8341407 diff --git a/aio/gpu-8g/text-to-speech.yaml b/aio/gpu-8g/text-to-speech.yaml index 8d875a299..782f8624a 100644 --- a/aio/gpu-8g/text-to-speech.yaml +++ b/aio/gpu-8g/text-to-speech.yaml @@ -2,7 +2,7 @@ name: tts-1 download_files: - filename: voice-en-us-amy-low.tar.gz uri: https://github.com/rhasspy/piper/releases/download/v0.0.2/voice-en-us-amy-low.tar.gz - +backend: piper parameters: model: en-us-amy-low.onnx diff --git a/aio/gpu-8g/text-to-text.yaml b/aio/gpu-8g/text-to-text.yaml index 5947f6aa8..7d5c991c9 100644 --- a/aio/gpu-8g/text-to-text.yaml +++ b/aio/gpu-8g/text-to-text.yaml @@ -1,5 +1,6 @@ context_size: 4096 f16: true +backend: llama-cpp function: capture_llm_results: - (?s)(.*?) diff --git a/aio/gpu-8g/vision.yaml b/aio/gpu-8g/vision.yaml index 5325f99c7..d1ef207fc 100644 --- a/aio/gpu-8g/vision.yaml +++ b/aio/gpu-8g/vision.yaml @@ -1,4 +1,5 @@ context_size: 4096 +backend: llama-cpp f16: true mmap: true mmproj: minicpm-v-2_6-mmproj-f16.gguf diff --git a/aio/intel/embeddings.yaml b/aio/intel/embeddings.yaml index f9e0ca5db..0f88f4511 100644 --- a/aio/intel/embeddings.yaml +++ b/aio/intel/embeddings.yaml @@ -1,5 +1,6 @@ embeddings: true name: text-embedding-ada-002 +backend: llama-cpp parameters: model: huggingface://bartowski/granite-embedding-107m-multilingual-GGUF/granite-embedding-107m-multilingual-f16.gguf diff --git a/aio/intel/rerank.yaml b/aio/intel/rerank.yaml index b52dee773..70d386b2b 100644 --- a/aio/intel/rerank.yaml +++ b/aio/intel/rerank.yaml @@ -3,7 +3,7 @@ reranking: true f16: true parameters: model: jina-reranker-v1-tiny-en.f16.gguf - +backend: llama-cpp download_files: - filename: jina-reranker-v1-tiny-en.f16.gguf sha256: 5f696cf0d0f3d347c4a279eee8270e5918554cdac0ed1f632f2619e4e8341407 diff --git a/aio/intel/text-to-speech.yaml b/aio/intel/text-to-speech.yaml index 8d875a299..782f8624a 100644 --- a/aio/intel/text-to-speech.yaml +++ b/aio/intel/text-to-speech.yaml @@ -2,7 +2,7 @@ name: tts-1 download_files: - filename: voice-en-us-amy-low.tar.gz uri: https://github.com/rhasspy/piper/releases/download/v0.0.2/voice-en-us-amy-low.tar.gz - +backend: piper parameters: model: en-us-amy-low.onnx diff --git a/aio/intel/text-to-text.yaml b/aio/intel/text-to-text.yaml index f9c5f17ba..9fe7c1143 100644 --- a/aio/intel/text-to-text.yaml +++ b/aio/intel/text-to-text.yaml @@ -1,5 +1,6 @@ context_size: 4096 f16: true +backend: llama-cpp function: capture_llm_results: - (?s)(.*?) diff --git a/aio/intel/vision.yaml b/aio/intel/vision.yaml index 264d9d0a2..66cbd38dd 100644 --- a/aio/intel/vision.yaml +++ b/aio/intel/vision.yaml @@ -1,4 +1,5 @@ context_size: 4096 +backend: llama-cpp f16: true mmap: true mmproj: minicpm-v-2_6-mmproj-f16.gguf diff --git a/backend/Dockerfile.go b/backend/Dockerfile.go index 933a0cd10..dbfee61e2 100644 --- a/backend/Dockerfile.go +++ b/backend/Dockerfile.go @@ -128,5 +128,4 @@ RUN cd /LocalAI && make protogen-go && make -C /LocalAI/backend/go/${BACKEND} bu FROM scratch ARG BACKEND=rerankers -COPY --from=builder /LocalAI/backend/go/${BACKEND}/${BACKEND} ./ -COPY --from=builder /LocalAI/backend/go/${BACKEND}/run.sh ./ \ No newline at end of file +COPY --from=builder /LocalAI/backend/go/${BACKEND}/package/. ./ diff --git a/backend/backend.proto b/backend/backend.proto index 1cbc0f14c..18ce66155 100644 --- a/backend/backend.proto +++ b/backend/backend.proto @@ -185,7 +185,6 @@ message ModelOptions { string MainGPU = 13; string TensorSplit = 14; int32 Threads = 15; - string LibrarySearchPath = 16; float RopeFreqBase = 17; float RopeFreqScale = 18; float RMSNormEps = 19; diff --git a/backend/cpp/llama-cpp/run.sh b/backend/cpp/llama-cpp/run.sh index e747a2c7a..17a1d0df9 100755 --- a/backend/cpp/llama-cpp/run.sh +++ b/backend/cpp/llama-cpp/run.sh @@ -51,7 +51,7 @@ fi if [ -f $CURDIR/lib/ld.so ]; then echo "Using lib/ld.so" echo "Using binary: $BINARY" - $CURDIR/lib/ld.so $CURDIR/$BINARY "$@" + exec $CURDIR/lib/ld.so $CURDIR/$BINARY "$@" fi echo "Using binary: $BINARY" diff --git a/backend/go/bark-cpp/Makefile b/backend/go/bark-cpp/Makefile index 80fdfb68d..1bff58c4f 100644 --- a/backend/go/bark-cpp/Makefile +++ b/backend/go/bark-cpp/Makefile @@ -42,7 +42,10 @@ bark-cpp: libbark.a CGO_LDFLAGS="$(CGO_LDFLAGS)" C_INCLUDE_PATH="$(CURDIR)" LIBRARY_PATH=$(CURDIR) \ $(GOCMD) build -v -ldflags "$(LD_FLAGS)" -tags "$(GO_TAGS)" -o bark-cpp ./ -build: bark-cpp +package: + bash package.sh + +build: bark-cpp package clean: rm -f gobark.o libbark.a \ No newline at end of file diff --git a/backend/go/bark-cpp/package.sh b/backend/go/bark-cpp/package.sh new file mode 100755 index 000000000..6dce5851f --- /dev/null +++ b/backend/go/bark-cpp/package.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Script to copy the appropriate libraries based on architecture +# This script is used in the final stage of the Dockerfile + +set -e + +CURDIR=$(dirname "$(realpath $0)") + +# Create lib directory +mkdir -p $CURDIR/package/lib +cp -avrf $CURDIR/bark-cpp $CURDIR/package/ +cp -rfv $CURDIR/run.sh $CURDIR/package/ + +# Detect architecture and copy appropriate libraries +if [ -f "/lib64/ld-linux-x86-64.so.2" ]; then + # x86_64 architecture + echo "Detected x86_64 architecture, copying x86_64 libraries..." + cp -arfLv /lib64/ld-linux-x86-64.so.2 $CURDIR/package/lib/ld.so + cp -arfLv /lib/x86_64-linux-gnu/libc.so.6 $CURDIR/package/lib/libc.so.6 + cp -arfLv /lib/x86_64-linux-gnu/libgcc_s.so.1 $CURDIR/package/lib/libgcc_s.so.1 + cp -arfLv /lib/x86_64-linux-gnu/libstdc++.so.6 $CURDIR/package/lib/libstdc++.so.6 + cp -arfLv /lib/x86_64-linux-gnu/libm.so.6 $CURDIR/package/lib/libm.so.6 + cp -arfLv /lib/x86_64-linux-gnu/libgomp.so.1 $CURDIR/package/lib/libgomp.so.1 +elif [ -f "/lib/ld-linux-aarch64.so.1" ]; then + # ARM64 architecture + echo "Detected ARM64 architecture, copying ARM64 libraries..." + cp -arfLv /lib/ld-linux-aarch64.so.1 $CURDIR/package/lib/ld.so + cp -arfLv /lib/aarch64-linux-gnu/libc.so.6 $CURDIR/package/lib/libc.so.6 + cp -arfLv /lib/aarch64-linux-gnu/libgcc_s.so.1 $CURDIR/package/lib/libgcc_s.so.1 + cp -arfLv /lib/aarch64-linux-gnu/libstdc++.so.6 $CURDIR/package/lib/libstdc++.so.6 + cp -arfLv /lib/aarch64-linux-gnu/libm.so.6 $CURDIR/package/lib/libm.so.6 + cp -arfLv /lib/aarch64-linux-gnu/libgomp.so.1 $CURDIR/package/lib/libgomp.so.1 +else + echo "Error: Could not detect architecture" + exit 1 +fi + +echo "Packaging completed successfully" +ls -liah $CURDIR/package/ +ls -liah $CURDIR/package/lib/ \ No newline at end of file diff --git a/backend/go/bark-cpp/run.sh b/backend/go/bark-cpp/run.sh index b66934cd9..567d3b89e 100755 --- a/backend/go/bark-cpp/run.sh +++ b/backend/go/bark-cpp/run.sh @@ -2,5 +2,12 @@ set -ex CURDIR=$(dirname "$(realpath $0)") +export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + +# If there is a lib/ld.so, use it +if [ -f $CURDIR/lib/ld.so ]; then + echo "Using lib/ld.so" + exec $CURDIR/lib/ld.so $CURDIR/bark-cpp "$@" +fi exec $CURDIR/bark-cpp "$@" \ No newline at end of file diff --git a/backend/go/piper/Makefile b/backend/go/piper/Makefile new file mode 100644 index 000000000..020028a5d --- /dev/null +++ b/backend/go/piper/Makefile @@ -0,0 +1,37 @@ + +# go-piper version +PIPER_REPO?=https://github.com/mudler/go-piper +PIPER_VERSION?=e10ca041a885d4a8f3871d52924b47792d5e5aa0 + +CURRENT_DIR=$(abspath ./) +GOCMD=go + +PIPER_CGO_CXXFLAGS+=-I$(CURRENT_DIR)/sources/go-piper/piper/src/cpp -I$(CURRENT_DIR)/sources/go-piper/piper/build/fi/include -I$(CURRENT_DIR)/sources/go-piper/piper/build/pi/include -I$(CURRENT_DIR)/sources/go-piper/piper/build/si/include +PIPER_CGO_LDFLAGS+=-L$(CURRENT_DIR)/sources/go-piper/piper/build/fi/lib -L$(CURRENT_DIR)/sources/go-piper/piper/build/pi/lib -L$(CURRENT_DIR)/sources/go-piper/piper/build/si/lib -lfmt -lspdlog -lucd + +## go-piper +sources/go-piper: + mkdir -p sources/go-piper + cd sources/go-piper && \ + git init && \ + git remote add origin $(PIPER_REPO) && \ + git fetch origin && \ + git checkout $(PIPER_VERSION) && \ + git submodule update --init --recursive --depth 1 --single-branch + +sources/go-piper/libpiper_binding.a: sources/go-piper + $(MAKE) -C sources/go-piper libpiper_binding.a example/main piper.o + +espeak-ng-data: sources/go-piper sources/go-piper/libpiper_binding.a + mkdir -p espeak-ng-data + @cp -rf sources/go-piper/piper-phonemize/pi/share/espeak-ng-data/. espeak-ng-data + +piper: sources/go-piper sources/go-piper/libpiper_binding.a espeak-ng-data + $(GOCMD) mod edit -replace github.com/mudler/go-piper=$(CURRENT_DIR)/sources/go-piper + CGO_CXXFLAGS="$(PIPER_CGO_CXXFLAGS)" CGO_LDFLAGS="$(PIPER_CGO_LDFLAGS)" LIBRARY_PATH=$(CURRENT_DIR)/sources/go-piper \ + $(GOCMD) build -ldflags "$(LD_FLAGS)" -tags "$(GO_TAGS)" -o piper ./ + +package: + bash package.sh + +build: piper package \ No newline at end of file diff --git a/backend/go/tts/main.go b/backend/go/piper/main.go similarity index 100% rename from backend/go/tts/main.go rename to backend/go/piper/main.go diff --git a/backend/go/piper/package.sh b/backend/go/piper/package.sh new file mode 100755 index 000000000..646efc362 --- /dev/null +++ b/backend/go/piper/package.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Script to copy the appropriate libraries based on architecture +# This script is used in the final stage of the Dockerfile + +set -e + +CURDIR=$(dirname "$(realpath $0)") + +# Create lib directory +mkdir -p $CURDIR/package/lib + +cp -avrf $CURDIR/piper $CURDIR/package/ +cp -avrf $CURDIR/espeak-ng-data $CURDIR/package/ +cp -rfv $CURDIR/run.sh $CURDIR/package/ +cp -rfLv $CURDIR/sources/go-piper/piper-phonemize/pi/lib/* $CURDIR/package/lib/ + +# Detect architecture and copy appropriate libraries +if [ -f "/lib64/ld-linux-x86-64.so.2" ]; then + # x86_64 architecture + echo "Detected x86_64 architecture, copying x86_64 libraries..." + cp -arfLv /lib64/ld-linux-x86-64.so.2 $CURDIR/package/lib/ld.so + cp -arfLv /lib/x86_64-linux-gnu/libc.so.6 $CURDIR/package/lib/libc.so.6 + cp -arfLv /lib/x86_64-linux-gnu/libgcc_s.so.1 $CURDIR/package/lib/libgcc_s.so.1 + cp -arfLv /lib/x86_64-linux-gnu/libstdc++.so.6 $CURDIR/package/lib/libstdc++.so.6 + cp -arfLv /lib/x86_64-linux-gnu/libm.so.6 $CURDIR/package/lib/libm.so.6 + cp -arfLv /lib/x86_64-linux-gnu/libgomp.so.1 $CURDIR/package/lib/libgomp.so.1 + cp -arfLv /lib/x86_64-linux-gnu/libgcc_s.so.1 $CURDIR/package/lib/libgcc_s.so.1 + cp -arfLv /lib/x86_64-linux-gnu/libstdc++.so.6 $CURDIR/package/lib/libstdc++.so.6 + cp -arfLv /lib/x86_64-linux-gnu/libdl.so.2 $CURDIR/package/lib/libdl.so.2 + cp -arfLv /lib/x86_64-linux-gnu/librt.so.1 $CURDIR/package/lib/librt.so.1 + cp -arfLv /lib/x86_64-linux-gnu/libpthread.so.0 $CURDIR/package/lib/libpthread.so.0 +elif [ -f "/lib/ld-linux-aarch64.so.1" ]; then + # ARM64 architecture + echo "Detected ARM64 architecture, copying ARM64 libraries..." + cp -arfLv /lib/ld-linux-aarch64.so.1 $CURDIR/package/lib/ld.so + cp -arfLv /lib/aarch64-linux-gnu/libc.so.6 $CURDIR/package/lib/libc.so.6 + cp -arfLv /lib/aarch64-linux-gnu/libgcc_s.so.1 $CURDIR/package/lib/libgcc_s.so.1 + cp -arfLv /lib/aarch64-linux-gnu/libstdc++.so.6 $CURDIR/package/lib/libstdc++.so.6 + cp -arfLv /lib/aarch64-linux-gnu/libm.so.6 $CURDIR/package/lib/libm.so.6 + cp -arfLv /lib/aarch64-linux-gnu/libgomp.so.1 $CURDIR/package/lib/libgomp.so.1 + cp -arfLv /lib/aarch64-linux-gnu/libgcc_s.so.1 $CURDIR/package/lib/libgcc_s.so.1 + cp -arfLv /lib/aarch64-linux-gnu/libstdc++.so.6 $CURDIR/package/lib/libstdc++.so.6 + cp -arfLv /lib/aarch64-linux-gnu/libdl.so.2 $CURDIR/package/lib/libdl.so.2 + cp -arfLv /lib/aarch64-linux-gnu/librt.so.1 $CURDIR/package/lib/librt.so.1 + cp -arfLv /lib/aarch64-linux-gnu/libpthread.so.0 $CURDIR/package/lib/libpthread.so.0 +else + echo "Error: Could not detect architecture" + exit 1 +fi + +echo "Packaging completed successfully" +ls -liah $CURDIR/package/ +ls -liah $CURDIR/package/lib/ \ No newline at end of file diff --git a/backend/go/tts/piper.go b/backend/go/piper/piper.go similarity index 95% rename from backend/go/tts/piper.go rename to backend/go/piper/piper.go index 14c2c0155..2ec985c9f 100644 --- a/backend/go/tts/piper.go +++ b/backend/go/piper/piper.go @@ -23,7 +23,7 @@ func (sd *Piper) Load(opts *pb.ModelOptions) error { } var err error // Note: the Model here is a path to a directory containing the model files - sd.piper, err = New(opts.LibrarySearchPath) + sd.piper, err = New(os.Getenv("ESPEAK_NG_DATA")) return err } diff --git a/backend/go/piper/run.sh b/backend/go/piper/run.sh new file mode 100755 index 000000000..fe120ea88 --- /dev/null +++ b/backend/go/piper/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -ex + +CURDIR=$(dirname "$(realpath $0)") + +export ESPEAK_NG_DATA=$CURDIR/espeak-ng-data +export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH + +# If there is a lib/ld.so, use it +if [ -f $CURDIR/lib/ld.so ]; then + echo "Using lib/ld.so" + exec $CURDIR/lib/ld.so $CURDIR/piper "$@" +fi + +exec $CURDIR/piper "$@" \ No newline at end of file diff --git a/backend/index.yaml b/backend/index.yaml index cfcedd766..82168aefe 100644 --- a/backend/index.yaml +++ b/backend/index.yaml @@ -224,6 +224,26 @@ name: "chatterbox" capabilities: nvidia: "cuda12-chatterbox" +- &piper + name: "piper" + uri: "quay.io/go-skynet/local-ai-backends:latest-piper" + icon: https://github.com/OHF-Voice/piper1-gpl/raw/main/etc/logo.png + urls: + - https://github.com/rhasspy/piper + - https://github.com/mudler/go-piper + license: MIT + description: | + A fast, local neural text to speech system + tags: + - text-to-speech + - TTS + capabilities: + nvidia: "cuda12-piper" + intel: "intel-sycl-f32-piper" + amd: "rocm-piper" +- !!merge <<: *piper + name: "piper-development" + uri: "quay.io/go-skynet/local-ai-backends:master-piper" ## llama-cpp - !!merge <<: *llamacpp name: "darwin-x86-llama-cpp" diff --git a/core/backend/tts.go b/core/backend/tts.go index 81674016f..5793957e3 100644 --- a/core/backend/tts.go +++ b/core/backend/tts.go @@ -21,7 +21,7 @@ func ModelTTS( appConfig *config.ApplicationConfig, backendConfig config.BackendConfig, ) (string, *proto.Result, error) { - opts := ModelOptions(backendConfig, appConfig, model.WithDefaultBackendString(model.PiperBackend)) + opts := ModelOptions(backendConfig, appConfig) ttsModel, err := loader.Load(opts...) if err != nil { return "", nil, err diff --git a/core/http/app_test.go b/core/http/app_test.go index 8d892e287..b4eadbe73 100644 --- a/core/http/app_test.go +++ b/core/http/app_test.go @@ -532,10 +532,6 @@ var _ = Describe("API test", func() { c, cancel = context.WithCancel(context.Background()) galleries := []config.Gallery{ - { - Name: "model-gallery", - URL: "https://raw.githubusercontent.com/go-skynet/model-gallery/main/index.yaml", - }, { Name: "localai", URL: "https://raw.githubusercontent.com/mudler/LocalAI/refs/heads/master/gallery/index.yaml", @@ -665,7 +661,7 @@ var _ = Describe("API test", func() { } response := postModelApplyRequest("http://127.0.0.1:9090/models/apply", modelApplyRequest{ - ID: "model-gallery@voice-en-us-kathleen-low", + ID: "localai@voice-en-us-kathleen-low", }) Expect(response["uuid"]).ToNot(BeEmpty(), fmt.Sprint(response)) @@ -679,7 +675,7 @@ var _ = Describe("API test", func() { }, "360s", "10s").Should(Equal(true)) // An HTTP Post to the /tts endpoint should return a wav audio file - resp, err := http.Post("http://127.0.0.1:9090/tts", "application/json", bytes.NewBuffer([]byte(`{"input": "Hello world", "model": "en-us-kathleen-low.onnx"}`))) + resp, err := http.Post("http://127.0.0.1:9090/tts", "application/json", bytes.NewBuffer([]byte(`{"input": "Hello world", "model": "voice-en-us-kathleen-low"}`))) Expect(err).ToNot(HaveOccurred(), fmt.Sprint(resp)) dat, err := io.ReadAll(resp.Body) Expect(err).ToNot(HaveOccurred(), fmt.Sprint(resp)) diff --git a/core/http/endpoints/localai/tts.go b/core/http/endpoints/localai/tts.go index 90d481bbb..18c692dfb 100644 --- a/core/http/endpoints/localai/tts.go +++ b/core/http/endpoints/localai/tts.go @@ -36,12 +36,8 @@ func TTSEndpoint(cl *config.BackendConfigLoader, ml *model.ModelLoader, appConfi log.Debug().Str("model", input.Model).Msg("LocalAI TTS Request received") - if cfg.Backend == "" { - if input.Backend != "" { - cfg.Backend = input.Backend - } else { - cfg.Backend = model.PiperBackend - } + if cfg.Backend == "" && input.Backend != "" { + cfg.Backend = input.Backend } if input.Language != "" { diff --git a/pkg/model/initializers.go b/pkg/model/initializers.go index 6eca952d7..c54fbdcc3 100644 --- a/pkg/model/initializers.go +++ b/pkg/model/initializers.go @@ -45,7 +45,6 @@ var TypeAlias map[string]string = map[string]string{ const ( WhisperBackend = "whisper" StableDiffusionGGMLBackend = "stablediffusion-ggml" - PiperBackend = "piper" LCHuggingFaceBackend = "huggingface" TransformersBackend = "transformers" @@ -286,17 +285,7 @@ func (ml *ModelLoader) backendLoader(opts ...Option) (client grpc.Backend, err e backend = realBackend } - var backendToConsume string - - switch backend { - case PiperBackend: - o.gRPCOptions.LibrarySearchPath = filepath.Join(o.assetDir, "backend-assets", "espeak-ng-data") - backendToConsume = PiperBackend - default: - backendToConsume = backend - } - - model, err := ml.LoadModel(o.modelID, o.model, ml.grpcModel(backendToConsume, o)) + model, err := ml.LoadModel(o.modelID, o.model, ml.grpcModel(backend, o)) if err != nil { return nil, err }