Skip to content

Commit de2ec2f

Browse files
localai-botmudler
andauthored
feat(backends): add voice-detect + face-detect ggml backends (replace Python insightface/speaker-recognition) (#10441)
* feat(voice-detect): add Go purego backend for voice-detect.cpp Add backend/go/voice-detect implementing the Backend gRPC voice subset (VoiceEmbed/VoiceVerify/VoiceAnalyze) over libvoicedetect.so via purego, mirroring the parakeet-cpp / omnivoice-cpp backends. The flat voicedetect_capi C ABI is dlopen'd cgo-less; malloc'd string and float-vector returns are owned by Go and released through the matching capi free functions, with the per-ctx last error surfaced into Go errors. Calls are serialized via base.SingleThread since the C context is not reentrant. Proto field mapping: - VoiceEmbed: VoiceEmbedRequest.audio (path) -> embed_path -> Embedding+Model. - VoiceVerify: audio1/audio2 + threshold (<=0 falls back to the verify_threshold option, default 0.25) -> verify_paths -> verified/distance/ threshold/confidence/model/processing_time_ms. - VoiceAnalyze: audio (path) -> analyze_path_json; the JSON age/gender/emotion document maps to a single VoiceAnalysis segment (start/end 0; gender "label" -> dominant_gender with the remaining float scores as the gender map; emotion label/scores -> dominant_emotion/emotion). The Makefile pins voice-detect.cpp to 47546430, clones+builds libvoicedetect.so with ggml static-linked (PIC, GGML_NATIVE off) so dlopen needs no external libggml/libvoicedetect; ldd on the artifact shows only system libs. Ginkgo tests cover option parsing and analyze-JSON mapping; embed/verify smoke specs gate on VOICEDETECT_BACKEND_TEST_MODEL + VOICEDETECT_BACKEND_TEST_WAV. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * feat(voice-detect): wire backend into index, gallery and build Register the voice-detect.cpp speaker-recognition + voice-analysis backend (added in Voice-INT-A) into LocalAI's distribution surfaces, mirroring the ced backend (the closest mudler C++/ggml audio analogue): - backend/index.yaml: add the &voicedetect meta-backend (capabilities platform map, no top-level uri) plus the full set of concrete per-arch image entries (cpu/cuda12/cuda13/metal/rocm/sycl/vulkan/l4t and the -development variants). Referential integrity audited - every alias target resolves. - gallery/index.yaml: add 5 model entries on backend voice-detect - ECAPA-TDNN, WeSpeaker ResNet34, 3D-Speaker ERes2Net, CAM++ and the wav2vec2 age/gender/emotion analyze model. The engine architecture is read from GGUF metadata (voicedetect.arch) at load. GGUF artifacts are not yet published: each files: entry points at the intended mudler/voice-detect-gguf location with a TODO to fill sha256 after upload (no fabricated hashes). - .github/backend-matrix.yml: add the linux build matrix block + the darwin metal entry mirroring ced. - .github/workflows/bump_deps.yaml: track mudler/voice-detect.cpp via VOICEDETECT_VERSION (pin 47546430, = 4754643). - core/config/backend_capabilities.go: register voice-detect in the backend capability map (VoiceVerify/VoiceEmbed/VoiceAnalyze -> speaker_recognition), mirroring speaker-recognition. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * feat(face-detect): add purego Go backend for face-detect.cpp Add the LocalAI Go backend that dlopens libfacedetect.so (the flat facedetect_capi_* C-ABI) via purego, mirroring the sibling voice-detect backend. Implements the Face subset of the Backend gRPC service: - Embeddings(PredictOptions): Images[0] base64 -> temp file -> embed_path -> L2-normalized ArcFace embedding. - Detect(DetectOptions): src -> detect_path_json -> Detection boxes (class_name "face", [x1,y1,x2,y2] -> x/y/w/h). - FaceVerify(FaceVerifyRequest): two images + threshold + anti_spoof -> verify_paths; best-effort img areas via detect. - FaceAnalyze(FaceAnalyzeRequest): img -> analyze_path_json -> per-face age + gender ("M"/"F" normalized to "Man"/"Woman"). The Makefile pins face-detect.cpp to 636a1963 and builds the shared lib with ggml + vendored libjpeg-turbo static (PIC), so the .so is ldd-clean (no libggml) and exports only facedetect_capi_* (no jpeg_ symbols). Gated Ginkgo e2e mirrors voice-detect. Note for the gallery-wiring task: backend registration (index.yaml, gallery, core/config/backend_capabilities.go) is intentionally not touched here. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * fix(voice-detect): replace em dashes in net-new descriptions Project style forbids em/en dashes. Replace the three U+2014 chars introduced by the voice-detect gallery/index wiring with `-`/`:`. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * feat(face-detect): wire backend into index, gallery and build Register the face-detect.cpp face detection / embedding / verification / analysis backend (added in Face-INT-A) into LocalAI's distribution surfaces, mirroring the voice-detect wiring (the closest mudler C++/ggml recognition analogue): - backend/index.yaml: add the &facedetect meta-backend (capabilities platform map, no top-level uri to avoid the meta-backend gotcha) plus the full set of concrete per-arch image entries (cpu/cuda12/cuda13/ metal/rocm/sycl-f16/sycl-f32/vulkan/l4t and the -development variants), 22 entries. Referential integrity audited: every alias target resolves. - gallery/index.yaml: add 4 model entries on backend face-detect - face-detect-buffalo-l/m/s (insightface SCRFD + ArcFace/MBF, NON-COMMERCIAL) and face-detect-yunet-sface (OpenCV-Zoo YuNet + SFace, APACHE-2.0, the commercial-friendly alternative). The detector/embedder architecture is read from GGUF metadata (facedetect.arch) at load; only the real verify_threshold option is set (0.35 buffalo, 0.363 sface). GGUF artifacts are not yet published: each files: entry points at the intended mudler/face-detect-gguf location with a TODO to fill sha256 after upload (no fabricated hashes). - core/config/backend_capabilities.go: register face-detect in the backend capability map (Embedding/Detect/FaceVerify/FaceAnalyze -> face_recognition), mirroring insightface. - .github/backend-matrix.yml: add the linux build matrix block + the darwin metal entry mirroring voice-detect. - .github/workflows/bump_deps.yaml: track mudler/face-detect.cpp via FACEDETECT_VERSION (pin 636a1963). Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * fix(recon): voice-detect metal build branch + face-detect gallery usecases Add the missing metal BUILD_TYPE branch to the voice-detect Makefile forwarding -DVOICEDETECT_GGML_METAL=ON, mirroring face-detect, so the darwin metal CI artifact is built with the Metal backend instead of CPU-only. Expand the 4 face-detect gallery models' known_usecases to [face_recognition, detection, embeddings] to match the backend capabilities map and the mirrored insightface-buffalo entries, so auto-selection for /v1/detect and /embeddings works. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * docs(recon): document voice-detect and face-detect ggml backends Document the new standalone C++/ggml biometric backends as the recommended/default option for face and voice recognition, keeping the existing Python insightface / speaker-recognition backends framed as the legacy path. - features/face-recognition.md: add a face-detect (ggml) backend section with the gallery entries (buffalo-l/m/s non-commercial, yunet-sface Apache-2.0), licensing, and verify/detect/analyze quickstart. - features/voice-recognition.md: add a voice-detect (ggml) backend section with the gallery entries (ecapa-tdnn, wespeaker-resnet34, eres2net, campplus speaker recognizers; emotion-wav2vec2 non-commercial analyze head) and quickstart. - reference/compatibility-table.md: add face-detect.cpp and voice-detect.cpp rows to the Vision, Detection & Recognition table. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(gallery): publish recon backend GGUF uris + sha256 Fill in the published HuggingFace GGUF uris and verified sha256 for the 9 recon gallery entries (voice-detect-* and face-detect-*), and remove the TODO publish markers. Correct the eres2net, campplus, and emotion-wav2vec2 uris to the actual published filenames. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * feat(gallery): re-embed buffalo anti-spoof + add audeering age/gender voice model Update the 3 buffalo face-detect GGUF sha256 (anti-spoof ensemble now embedded and re-uploaded under the same filenames/uris) and note the FaceVerify anti_spoof request flag in each description. Add a new voice-detect-age-gender-wav2vec2 gallery entry mirroring the emotion model. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * feat(gallery): add face-detect-buffalo-sc and antelopev2 packs Add gallery entries for two newly-published insightface face packs on the face-detect backend: buffalo_sc (smallest pack, SCRFD-500M + small ArcFace) and antelopev2 (higher-accuracy, SCRFD-10G + ArcFace glint360k R100, 512-d). Both are non-commercial research-only. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * feat(recon): honor LocalAI per-model threads in voice/face-detect backends LocalAI spawns one backend process per model and serves requests concurrently, so the engines' own min(hardware_concurrency, 8) default can oversubscribe cores. Forward the per-model Threads value from the gRPC LoadModel options into the engine via VOICEDETECT_THREADS / FACEDETECT_THREADS (read at backend construction) before the capi load. A non-positive Threads is treated as unset, leaving the engine default. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump backend pins to CPU-optimized engine commits voice-detect.cpp -> 0d9c1b3 (radix-2 FFT FBank, threads, flash attn + cached pos-conv); face-detect.cpp -> 523aee1 (thread-gated direct conv, threads). Brings the CPU optimizations into the LocalAI backend builds. GGUF format and parity unchanged, so the published HF GGUFs remain valid. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump backend pins to round-2 CPU-optimized engines voice-detect.cpp -> fe7e6a3 (ERes2Net 1x1->mul_mat, CAM++ layout+context, wav2vec2 conv-LN, ECAPA capture-drop, AVX512 dispatch opt-in); face-detect.cpp -> 9c8adb7 (AVX2 Winograd F(2x2,3x3) for SCRFD/ArcFace 3x3 convs, ArcFace BN-fold). Parity unchanged (cosine=1.0); GGUF format unchanged, HF GGUFs valid. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump backend pins to round-3 Winograd engines voice-detect.cpp -> 45122ec (Winograd F(2x2,3x3) for WeSpeaker/ERes2Net 3x3 convs, -22%/-20% @8t); face-detect.cpp -> cd5c962 (Winograd F(4x4,3x3) for SCRFD large maps, -22% @1T on top of F(2x2), more load-stable). Parity held (cosine=1.0); GGUF format unchanged, HF GGUFs valid. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump backend pins to round-4 Winograd engines (CPU opt complete) voice-detect.cpp -> d2839ca (CAM++ FCM 2D convs through Winograd, -15.5%/-10.3%); face-detect.cpp -> c1db23d (AVX2-vectorized Winograd tile transforms, SCRFD detect -14%/-9.6%). Final CPU optimization round; the conv-kernel lever class is now exhausted (parity held cosine=1.0; GGUF/parity unchanged, HF GGUFs valid). Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump face-detect pin to deep-kernel engine (7ae5c4d) face-detect.cpp -> 7ae5c4d: register-blocked winograd-domain GEMM microkernel (2.8x isolated GFLOP/s), AVX-512 zmm evolution behind runtime CPUID dispatch (ship-safe, AVX2 fallback bit-identical), bias/relu fused into the winograd output transform, and SFace Conv+BN fold + bias/PReLU fusion. SCRFD detect ~1.4x faster end-to-end vs the round-4 baseline; parity bit-exact; portable single binary (function-multiversioned, no global -mavx512f). Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump voice-detect pin to ECAPA operand-order win (e9c56ae) voice-detect.cpp -> e9c56ae: weight-as-src0 mul_mat order in ECAPA's F32 conv1d_same (routes through tinyBLAS sgemm); ECAPA embed 1.67x @1T / ~1.3x @8t, parity cosine=1.0. Isolated to encoder.cpp (ECAPA-only); ERes2Net/CAM++/WeSpeaker do not call conv1d_same so are provably unaffected. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump pins to FMA-throughput engines (voice f7b9f89, face 2d2d5f0) face -> 2d2d5f0: route ArcFace 3x3 body convs through the AVX-512 winograd microkernel (kWinoMinSize 80->14); ArcFace 1.62x @1T, SCRFD detect to 0.966 of MLAS @1T, no regression. voice -> f7b9f89: runtime-CPUID-dispatched AVX-512 winograd-GEMM microkernel (ship-safe, AVX2 fallback bit-identical); WeSpeaker 1.90x @1T. Parity cosine=1.0 throughout; portable single binaries. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump pins to MLAS-class direct-conv engines (voice 7ecfd07, face be22d67) Hand-tuned nChw16c AVX-512 register-tiled direct-conv microkernel (~263 GFLOP/s, within 6-7% of MLAS per-op efficiency), runtime-CPUID-dispatched + AVX2 fallback, fused bias/relu. voice 7ecfd07: default 3x3-s1 kernel for WeSpeaker (+37%/+32%) + ERes2Net, CAM++ pinned to Winograd. face be22d67: shape-gated to the ArcFace recognizer body (+25-27% @8t); SCRFD detector stays on Winograd (no regression). Parity cosine=1.0 / detect <=1px on AVX-512 + AVX2 paths. Portable single binaries. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump voice pin to Phase-A blocked backbone (f4e7eef) WeSpeaker ResNet34 runs as one nChw16c blocked island (2 reorders/forward vs ~60) on AVX-512, default; per-conv directconv fallback on AVX2. +2.9% @1T / +17-19% @8t vs per-conv directconv, parity cosine=1.0. The conv microkernel is already FMA-bound near peak (~0.86-0.98x MLAS-implied); residual to MLAS is sub-peak edge + non-conv tail, documented in docs/cpu-optimization.md. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump pins to breadth blocked-backbone (voice 7f66871, face d80092b) voice 7f66871: AVX2-vectorized (ymm) blocked island - AVX2-only hosts now run the blocked backbone for WeSpeaker (2.3x over per-conv-AVX2, cosine=1.0); ERes2Net stays per-conv (blocked regresses, opt-in only); CAM++ Winograd-pinned. face d80092b: ArcFace recognizer blocked island, AVX-512 default (-13% @8t, ~0.90x MLAS, the closest conv result), auto per-conv on AVX2; SCRFD untouched on Winograd (0 island invocations during detect). Parity cosine=1.0 / detect <=1px throughout. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump pins to small-spatial + stem conv kernels (voice 99b1804, face 47fdab6) Measured-gap-driven conv kernels: small-spatial (fill the register tile when output width <= tile width) + small-IC stem + strided-1x1/downsample recovery. ArcFace recognizer 0.57 -> 0.70x MLAS @1T (the closest conv model), WeSpeaker 0.65 -> 0.79x @1T. Parity cosine=1.0 / detect <=1px. The OC-block-sharing lever was a measured dead-end (deep stride-1 is L3-weight-bandwidth bound, not read-port bound) and was NOT shipped. Kernel ceiling reached; further gap needs an algorithm-class change (cache-blocked weight-stationary GEMM, or q8 weights). Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump pins to GPU persistent-graph + multi-model-safe cache (voice 45d2e6b, face 0a4799a) GPU wins (CUDA/ggml backend, no CPU-path change): persistent per-shape graph+context cache in Backend::compute() eliminates the per-call cudaGraph re-instantiation churn -> wav2vec2 emotion+age-gender now AT GPU parity with torch-cuDNN on GB10 (0.97-0.98x), CAM++ -5.7ms; bit-identical parity. Cache hardened multi-model-safe (invalidate-on-free keyed by the ModelLoader weights buffer) so LocalAI multi-model hosting cannot stale-hit. Conv models still trail cuDNN (im2col-materialization-bound) - cuDNN implicit-GEMM lever next. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump pins to cuDNN-conv-capable engines (voice b6e4356, face 6107a24) Adds the opt-in cuDNN implicit-GEMM conv path (VOICEDETECT_GGML_CUDNN / FACEDETECT_GGML_CUDNN, DEFAULT OFF -> zero build/runtime dep until enabled). On GPU it kills the im2col-materialization bottleneck and reaches torch-cuDNN parity on the spill-bound convs: SCRFD detect 14.8->6.4ms (2.3x, ~parity), WeSpeaker ~parity, ERes2Net beats torch (1.10x); ArcFace/CAM++ neutral (no spill). Parity exact (SCRFD <=1px, cosine=1.0). To USE it in LocalAI, the CUDA backend build must enable the flag AND bundle libcudnn - deferred until a cuDNN-bundled GPU image; flag stays OFF here. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * feat(recon): enable cuDNN conv path on arm64+CUDA13 recon backends The voice-detect.cpp / face-detect.cpp engines have an opt-in cuDNN implicit-GEMM conv path behind VOICEDETECT_GGML_CUDNN / FACEDETECT_GGML_CUDNN (default OFF) that kills im2col on the GPU and reaches torch-cuDNN parity (SCRFD 2.3x, WeSpeaker/ERes2Net parity), measured on the GB10 (arm64, CUDA 13, sm_121a). Enable it for the CUDA build, but only where cuDNN actually ships: the arm64 + CUDA 13 image (GB10/Jetson/L4T). x86 CUDA images carry no cuDNN, so flipping it on globally for BUILD_TYPE=cublas would be a link failure. The Makefiles gate on CUDA_MAJOR_VERSION=13 + arch (TARGETARCH from the matrix/Docker build, uname -m fallback for local builds). backend/Dockerfile.golang already installs the runtime libcudnn9-cuda-13 in the arm64+CUDA13 apt block; add the matching libcudnn9-dev-cuda-13 so the build-time link resolves. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): bump voice-detect pin to ERes2Net blocked-default (30beecd) Defaults VD_ERES2NET_BLOCKED ON: routes the ERes2Net Res2Net body through the blocked nChw16c AVX-512 directconv island instead of the 1x1 mul_mat fast path (CONT-transpose + skinny low-K GEMM). On the shipped GGML_NATIVE=OFF build (ggml mul_mat is AVX2-only) this wins ~2x at every thread count (2.07x@1t, 2.2x@4t, 2.05x@8t); pure-AVX2 fallback still 1.3-1.62x. Parity exact (cosine=1.000000 vs golden), so registered voices + verify/identify thresholds are unaffected. The prior default-OFF rested on a stale comment whose 23pct regression only held on the non-shipping GGML_NATIVE=ON build. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * docs(readme): announce native voice-detect + face-detect backends in Latest News Add a Latest News entry for the new from-scratch C++/ggml biometric backends (voice-detect.cpp + face-detect.cpp) that replace the Python insightface and speaker-recognition backends: no Python/onnxruntime at inference, self-contained GGUF, bit-exact parity, GPU cuDNN parity. Mirrors the parakeet.cpp / locate-anything.cpp native-backend news entries. Refs PR #10441. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] * chore(recon): re-pin to the squashed engine release commits The voice-detect.cpp and face-detect.cpp histories were squashed to a single release commit, which orphaned the previous pins (voice 30beecd, face 6107a24). Re-pin to the new single-commit SHAs (voice 3d51077, face 06914b0); the tree is identical, so the backend build is unchanged. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:claude-opus-4-8 [Claude Code] --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
1 parent d3a26f9 commit de2ec2f

28 files changed

Lines changed: 3002 additions & 16 deletions

.github/backend-matrix.yml

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3745,6 +3745,302 @@ include:
37453745
dockerfile: "./backend/Dockerfile.golang"
37463746
context: "./"
37473747
ubuntu-version: '2404'
3748+
# voice-detect
3749+
- build-type: 'cublas'
3750+
cuda-major-version: "12"
3751+
cuda-minor-version: "8"
3752+
platforms: 'linux/amd64'
3753+
tag-latest: 'auto'
3754+
tag-suffix: '-gpu-nvidia-cuda-12-voice-detect'
3755+
runs-on: 'ubuntu-latest'
3756+
base-image: "ubuntu:24.04"
3757+
skip-drivers: 'false'
3758+
backend: "voice-detect"
3759+
dockerfile: "./backend/Dockerfile.golang"
3760+
context: "./"
3761+
ubuntu-version: '2404'
3762+
- build-type: 'cublas'
3763+
cuda-major-version: "13"
3764+
cuda-minor-version: "0"
3765+
platforms: 'linux/amd64'
3766+
tag-latest: 'auto'
3767+
tag-suffix: '-gpu-nvidia-cuda-13-voice-detect'
3768+
runs-on: 'ubuntu-latest'
3769+
base-image: "ubuntu:24.04"
3770+
skip-drivers: 'false'
3771+
backend: "voice-detect"
3772+
dockerfile: "./backend/Dockerfile.golang"
3773+
context: "./"
3774+
ubuntu-version: '2404'
3775+
- build-type: 'cublas'
3776+
cuda-major-version: "13"
3777+
cuda-minor-version: "0"
3778+
platforms: 'linux/arm64'
3779+
skip-drivers: 'false'
3780+
tag-latest: 'auto'
3781+
tag-suffix: '-nvidia-l4t-cuda-13-arm64-voice-detect'
3782+
base-image: "ubuntu:24.04"
3783+
ubuntu-version: '2404'
3784+
runs-on: 'ubuntu-24.04-arm'
3785+
backend: "voice-detect"
3786+
dockerfile: "./backend/Dockerfile.golang"
3787+
context: "./"
3788+
- build-type: ''
3789+
cuda-major-version: ""
3790+
cuda-minor-version: ""
3791+
platforms: 'linux/amd64'
3792+
platform-tag: 'amd64'
3793+
tag-latest: 'auto'
3794+
tag-suffix: '-cpu-voice-detect'
3795+
runs-on: 'ubuntu-latest'
3796+
base-image: "ubuntu:24.04"
3797+
skip-drivers: 'false'
3798+
backend: "voice-detect"
3799+
dockerfile: "./backend/Dockerfile.golang"
3800+
context: "./"
3801+
ubuntu-version: '2404'
3802+
- build-type: ''
3803+
cuda-major-version: ""
3804+
cuda-minor-version: ""
3805+
platforms: 'linux/arm64'
3806+
platform-tag: 'arm64'
3807+
tag-latest: 'auto'
3808+
tag-suffix: '-cpu-voice-detect'
3809+
runs-on: 'ubuntu-24.04-arm'
3810+
base-image: "ubuntu:24.04"
3811+
skip-drivers: 'false'
3812+
backend: "voice-detect"
3813+
dockerfile: "./backend/Dockerfile.golang"
3814+
context: "./"
3815+
ubuntu-version: '2404'
3816+
- build-type: 'sycl_f32'
3817+
cuda-major-version: ""
3818+
cuda-minor-version: ""
3819+
platforms: 'linux/amd64'
3820+
tag-latest: 'auto'
3821+
tag-suffix: '-gpu-intel-sycl-f32-voice-detect'
3822+
runs-on: 'ubuntu-latest'
3823+
base-image: "intel/oneapi-basekit:2025.3.0-0-devel-ubuntu24.04"
3824+
skip-drivers: 'false'
3825+
backend: "voice-detect"
3826+
dockerfile: "./backend/Dockerfile.golang"
3827+
context: "./"
3828+
ubuntu-version: '2404'
3829+
- build-type: 'sycl_f16'
3830+
cuda-major-version: ""
3831+
cuda-minor-version: ""
3832+
platforms: 'linux/amd64'
3833+
tag-latest: 'auto'
3834+
tag-suffix: '-gpu-intel-sycl-f16-voice-detect'
3835+
runs-on: 'ubuntu-latest'
3836+
base-image: "intel/oneapi-basekit:2025.3.0-0-devel-ubuntu24.04"
3837+
skip-drivers: 'false'
3838+
backend: "voice-detect"
3839+
dockerfile: "./backend/Dockerfile.golang"
3840+
context: "./"
3841+
ubuntu-version: '2404'
3842+
- build-type: 'vulkan'
3843+
cuda-major-version: ""
3844+
cuda-minor-version: ""
3845+
platforms: 'linux/amd64'
3846+
platform-tag: 'amd64'
3847+
tag-latest: 'auto'
3848+
tag-suffix: '-gpu-vulkan-voice-detect'
3849+
runs-on: 'ubuntu-latest'
3850+
base-image: "ubuntu:24.04"
3851+
skip-drivers: 'false'
3852+
backend: "voice-detect"
3853+
dockerfile: "./backend/Dockerfile.golang"
3854+
context: "./"
3855+
ubuntu-version: '2404'
3856+
- build-type: 'vulkan'
3857+
cuda-major-version: ""
3858+
cuda-minor-version: ""
3859+
platforms: 'linux/arm64'
3860+
platform-tag: 'arm64'
3861+
tag-latest: 'auto'
3862+
tag-suffix: '-gpu-vulkan-voice-detect'
3863+
runs-on: 'ubuntu-24.04-arm'
3864+
base-image: "ubuntu:24.04"
3865+
skip-drivers: 'false'
3866+
backend: "voice-detect"
3867+
dockerfile: "./backend/Dockerfile.golang"
3868+
context: "./"
3869+
ubuntu-version: '2404'
3870+
- build-type: 'cublas'
3871+
cuda-major-version: "12"
3872+
cuda-minor-version: "0"
3873+
platforms: 'linux/arm64'
3874+
skip-drivers: 'false'
3875+
tag-latest: 'auto'
3876+
tag-suffix: '-nvidia-l4t-arm64-voice-detect'
3877+
base-image: "nvcr.io/nvidia/l4t-jetpack:r36.4.0"
3878+
runs-on: 'ubuntu-24.04-arm'
3879+
backend: "voice-detect"
3880+
dockerfile: "./backend/Dockerfile.golang"
3881+
context: "./"
3882+
ubuntu-version: '2204'
3883+
- build-type: 'hipblas'
3884+
cuda-major-version: ""
3885+
cuda-minor-version: ""
3886+
platforms: 'linux/amd64'
3887+
tag-latest: 'auto'
3888+
tag-suffix: '-gpu-rocm-hipblas-voice-detect'
3889+
base-image: "rocm/dev-ubuntu-24.04:7.2.1"
3890+
runs-on: 'ubuntu-latest'
3891+
skip-drivers: 'false'
3892+
backend: "voice-detect"
3893+
dockerfile: "./backend/Dockerfile.golang"
3894+
context: "./"
3895+
ubuntu-version: '2404'
3896+
# face-detect
3897+
- build-type: 'cublas'
3898+
cuda-major-version: "12"
3899+
cuda-minor-version: "8"
3900+
platforms: 'linux/amd64'
3901+
tag-latest: 'auto'
3902+
tag-suffix: '-gpu-nvidia-cuda-12-face-detect'
3903+
runs-on: 'ubuntu-latest'
3904+
base-image: "ubuntu:24.04"
3905+
skip-drivers: 'false'
3906+
backend: "face-detect"
3907+
dockerfile: "./backend/Dockerfile.golang"
3908+
context: "./"
3909+
ubuntu-version: '2404'
3910+
- build-type: 'cublas'
3911+
cuda-major-version: "13"
3912+
cuda-minor-version: "0"
3913+
platforms: 'linux/amd64'
3914+
tag-latest: 'auto'
3915+
tag-suffix: '-gpu-nvidia-cuda-13-face-detect'
3916+
runs-on: 'ubuntu-latest'
3917+
base-image: "ubuntu:24.04"
3918+
skip-drivers: 'false'
3919+
backend: "face-detect"
3920+
dockerfile: "./backend/Dockerfile.golang"
3921+
context: "./"
3922+
ubuntu-version: '2404'
3923+
- build-type: 'cublas'
3924+
cuda-major-version: "13"
3925+
cuda-minor-version: "0"
3926+
platforms: 'linux/arm64'
3927+
skip-drivers: 'false'
3928+
tag-latest: 'auto'
3929+
tag-suffix: '-nvidia-l4t-cuda-13-arm64-face-detect'
3930+
base-image: "ubuntu:24.04"
3931+
ubuntu-version: '2404'
3932+
runs-on: 'ubuntu-24.04-arm'
3933+
backend: "face-detect"
3934+
dockerfile: "./backend/Dockerfile.golang"
3935+
context: "./"
3936+
- build-type: ''
3937+
cuda-major-version: ""
3938+
cuda-minor-version: ""
3939+
platforms: 'linux/amd64'
3940+
platform-tag: 'amd64'
3941+
tag-latest: 'auto'
3942+
tag-suffix: '-cpu-face-detect'
3943+
runs-on: 'ubuntu-latest'
3944+
base-image: "ubuntu:24.04"
3945+
skip-drivers: 'false'
3946+
backend: "face-detect"
3947+
dockerfile: "./backend/Dockerfile.golang"
3948+
context: "./"
3949+
ubuntu-version: '2404'
3950+
- build-type: ''
3951+
cuda-major-version: ""
3952+
cuda-minor-version: ""
3953+
platforms: 'linux/arm64'
3954+
platform-tag: 'arm64'
3955+
tag-latest: 'auto'
3956+
tag-suffix: '-cpu-face-detect'
3957+
runs-on: 'ubuntu-24.04-arm'
3958+
base-image: "ubuntu:24.04"
3959+
skip-drivers: 'false'
3960+
backend: "face-detect"
3961+
dockerfile: "./backend/Dockerfile.golang"
3962+
context: "./"
3963+
ubuntu-version: '2404'
3964+
- build-type: 'sycl_f32'
3965+
cuda-major-version: ""
3966+
cuda-minor-version: ""
3967+
platforms: 'linux/amd64'
3968+
tag-latest: 'auto'
3969+
tag-suffix: '-gpu-intel-sycl-f32-face-detect'
3970+
runs-on: 'ubuntu-latest'
3971+
base-image: "intel/oneapi-basekit:2025.3.0-0-devel-ubuntu24.04"
3972+
skip-drivers: 'false'
3973+
backend: "face-detect"
3974+
dockerfile: "./backend/Dockerfile.golang"
3975+
context: "./"
3976+
ubuntu-version: '2404'
3977+
- build-type: 'sycl_f16'
3978+
cuda-major-version: ""
3979+
cuda-minor-version: ""
3980+
platforms: 'linux/amd64'
3981+
tag-latest: 'auto'
3982+
tag-suffix: '-gpu-intel-sycl-f16-face-detect'
3983+
runs-on: 'ubuntu-latest'
3984+
base-image: "intel/oneapi-basekit:2025.3.0-0-devel-ubuntu24.04"
3985+
skip-drivers: 'false'
3986+
backend: "face-detect"
3987+
dockerfile: "./backend/Dockerfile.golang"
3988+
context: "./"
3989+
ubuntu-version: '2404'
3990+
- build-type: 'vulkan'
3991+
cuda-major-version: ""
3992+
cuda-minor-version: ""
3993+
platforms: 'linux/amd64'
3994+
platform-tag: 'amd64'
3995+
tag-latest: 'auto'
3996+
tag-suffix: '-gpu-vulkan-face-detect'
3997+
runs-on: 'ubuntu-latest'
3998+
base-image: "ubuntu:24.04"
3999+
skip-drivers: 'false'
4000+
backend: "face-detect"
4001+
dockerfile: "./backend/Dockerfile.golang"
4002+
context: "./"
4003+
ubuntu-version: '2404'
4004+
- build-type: 'vulkan'
4005+
cuda-major-version: ""
4006+
cuda-minor-version: ""
4007+
platforms: 'linux/arm64'
4008+
platform-tag: 'arm64'
4009+
tag-latest: 'auto'
4010+
tag-suffix: '-gpu-vulkan-face-detect'
4011+
runs-on: 'ubuntu-24.04-arm'
4012+
base-image: "ubuntu:24.04"
4013+
skip-drivers: 'false'
4014+
backend: "face-detect"
4015+
dockerfile: "./backend/Dockerfile.golang"
4016+
context: "./"
4017+
ubuntu-version: '2404'
4018+
- build-type: 'cublas'
4019+
cuda-major-version: "12"
4020+
cuda-minor-version: "0"
4021+
platforms: 'linux/arm64'
4022+
skip-drivers: 'false'
4023+
tag-latest: 'auto'
4024+
tag-suffix: '-nvidia-l4t-arm64-face-detect'
4025+
base-image: "nvcr.io/nvidia/l4t-jetpack:r36.4.0"
4026+
runs-on: 'ubuntu-24.04-arm'
4027+
backend: "face-detect"
4028+
dockerfile: "./backend/Dockerfile.golang"
4029+
context: "./"
4030+
ubuntu-version: '2204'
4031+
- build-type: 'hipblas'
4032+
cuda-major-version: ""
4033+
cuda-minor-version: ""
4034+
platforms: 'linux/amd64'
4035+
tag-latest: 'auto'
4036+
tag-suffix: '-gpu-rocm-hipblas-face-detect'
4037+
base-image: "rocm/dev-ubuntu-24.04:7.2.1"
4038+
runs-on: 'ubuntu-latest'
4039+
skip-drivers: 'false'
4040+
backend: "face-detect"
4041+
dockerfile: "./backend/Dockerfile.golang"
4042+
context: "./"
4043+
ubuntu-version: '2404'
37484044
# acestep-cpp
37494045
- build-type: ''
37504046
cuda-major-version: ""
@@ -4928,6 +5224,14 @@ includeDarwin:
49285224
tag-suffix: "-metal-darwin-arm64-ced"
49295225
build-type: "metal"
49305226
lang: "go"
5227+
- backend: "voice-detect"
5228+
tag-suffix: "-metal-darwin-arm64-voice-detect"
5229+
build-type: "metal"
5230+
lang: "go"
5231+
- backend: "face-detect"
5232+
tag-suffix: "-metal-darwin-arm64-face-detect"
5233+
build-type: "metal"
5234+
lang: "go"
49315235
- backend: "acestep-cpp"
49325236
tag-suffix: "-metal-darwin-arm64-acestep-cpp"
49335237
build-type: "metal"

.github/workflows/bump_deps.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ jobs:
4646
variable: "CED_VERSION"
4747
branch: "master"
4848
file: "backend/go/ced/Makefile"
49+
- repository: "mudler/voice-detect.cpp"
50+
variable: "VOICEDETECT_VERSION"
51+
branch: "master"
52+
file: "backend/go/voice-detect/Makefile"
53+
- repository: "mudler/face-detect.cpp"
54+
variable: "FACEDETECT_VERSION"
55+
branch: "master"
56+
file: "backend/go/face-detect/Makefile"
4957
- repository: "mudler/depth-anything.cpp"
5058
variable: "DEPTHANYTHING_VERSION"
5159
branch: "master"

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ For more details, see the [Getting Started guide](https://localai.io/basics/gett
177177

178178
## Latest News
179179

180+
- **June 2026**: New native biometric backends from the LocalAI team: [voice-detect.cpp](https://github.com/mudler/voice-detect.cpp) for speaker recognition and voice analysis (ECAPA-TDNN, WeSpeaker, ERes2Net, CAM++, wav2vec2 age/gender/emotion) and [face-detect.cpp](https://github.com/mudler/face-detect.cpp) for face detection, recognition, demographics and anti-spoofing (SCRFD/ArcFace, YuNet/SFace). Both are from-scratch C++/ggml engines with no Python or onnxruntime at inference, self-contained GGUF weights, bit-exact parity with the reference, and GPU cuDNN parity, replacing the heavier Python `insightface` and `speaker-recognition` backends ([PR #10441](https://github.com/mudler/LocalAI/pull/10441)).
180181
- **June 2026**: New [realtime voice assistant demo](https://github.com/localai-org/localai-realtime-demo) (a tiny Go client for the Realtime API with a full talk-back voice loop and tool calling), plus [streaming of the realtime LLM / TTS / transcription pipeline stages](https://github.com/mudler/LocalAI/pull/10176) and [configurable WebRTC ICE candidates](https://github.com/mudler/LocalAI/pull/10231).
181182
- **June 2026**: Big speech push: the [parakeet.cpp](https://github.com/mudler/parakeet.cpp) ASR engine gains [NeMo-faithful segment timestamps](https://github.com/mudler/LocalAI/pull/10207), a [multilingual streaming Nemotron-3.5 model](https://github.com/mudler/LocalAI/pull/10199), [dynamic batching for concurrent transcription](https://github.com/mudler/LocalAI/pull/10112) and [CUDA graphs](https://github.com/mudler/LocalAI/pull/10273); the new [CrispASR backend](https://github.com/mudler/LocalAI/pull/10099) adds multi-architecture ASR + TTS, and [60 Piper TTS voices across 42 languages](https://github.com/mudler/LocalAI/pull/10296) land in the gallery (plus [per-request TTS instructions and params](https://github.com/mudler/LocalAI/pull/10172)).
182183
- **June 2026**: New backends and models: [locate-anything.cpp](https://github.com/mudler/LocalAI/pull/10264) for open-vocabulary object detection via ggml, [Ideogram4 image generation](https://github.com/mudler/LocalAI/pull/10201) in stablediffusion-ggml, [llama.cpp video input](https://github.com/mudler/LocalAI/pull/10216), and the [Gemma 4 QAT family with MTP speculative-decoding pairs](https://github.com/mudler/LocalAI/pull/10215). Plus an [interactive CLI chat mode](https://github.com/mudler/LocalAI/pull/10226) and [RAG source citations in agent responses](https://github.com/mudler/LocalAI/pull/10228).

backend/Dockerfile.golang

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ RUN <<EOT bash
137137
libcusolver-dev-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION}
138138
if [ "${CUDA_MAJOR_VERSION}" = "13" ] && [ "arm64" = "$TARGETARCH" ]; then
139139
apt-get install -y --no-install-recommends \
140-
libcufile-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} libcudnn9-cuda-${CUDA_MAJOR_VERSION} cuda-cupti-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} libnvjitlink-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION}
140+
libcufile-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} libcudnn9-cuda-${CUDA_MAJOR_VERSION} libcudnn9-dev-cuda-${CUDA_MAJOR_VERSION} cuda-cupti-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION} libnvjitlink-${CUDA_MAJOR_VERSION}-${CUDA_MINOR_VERSION}
141141
fi
142142
apt-get clean && \
143143
rm -rf /var/lib/apt/lists/*

backend/go/face-detect/.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Fetched upstream sources
2+
sources/
3+
4+
# CMake build directories
5+
build*/
6+
7+
# build artifacts staged in-tree by the Makefile (cp from sources/) or
8+
# symlinked for local dev; the real sources live in face-detect.cpp upstream.
9+
*.so
10+
*.so.*
11+
facedetect_capi.h
12+
compile_commands.json
13+
14+
# Compiled backend binary
15+
face-detect-grpc
16+
17+
# Packaging output
18+
package/

0 commit comments

Comments
 (0)