mirror of
https://github.com/mudler/LocalAI.git
synced 2026-06-27 01:47:18 -04:00
The llama-cpp gRPC backend reconstructs OpenAI messages from proto for the tokenizer-template path and blindly json::parse'd each message's content string. LocalAI's Go layer always flattens content to a plain string, so a user prompt that merely looks like JSON (e.g. mealie's ingredient array ["1/4 cup brown sugar", ...]) was reinterpreted as structured content parts and rejected by oaicompat_chat_params_parse with "unsupported content[].type". Normalize content per role instead: user/system/developer content is opaque text and is never JSON-sniffed; assistant/tool content still collapses a literal JSON null/object (tool-call bookkeeping) to a string, but a plain string is never turned into an array/scalar. The array defense is role-independent, so the role gate only governs the benign null/object case. While here, extract the duplicated per-message reconstruction and the pre-template content sanitization into shared, unit-tested helpers (message_content.h) so the streaming (PredictStream) and non-streaming (Predict) paths cannot drift. This removes ~490 lines of copy-pasted defensive code, the dead tool-role parse branches, and the redundant Predict-only tool_calls branch, while preserving the prior #7324 (null content -> "") and #7528 (tool array content -> string) fixes. Tests: - backend/cpp/llama-cpp/message_content_test.cpp: standalone C++ unit tests for all three helpers (#10524, #7324, #7528, multimodal), discovered and run by `make test-backend-cpp` and a new generic tests-backend-cpp CI job. Also wired as an opt-in CMake/ctest target (-DLLAMA_GRPC_BUILD_TESTS=ON). - core/schema/message_test.go: Go regression pinning that ToProto flattens a JSON-array-looking text part to the verbatim string. - prepare.sh now copies message_content.h into the build tree. 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>
140 lines
5.0 KiB
YAML
140 lines
5.0 KiB
YAML
---
|
|
name: 'tests'
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches:
|
|
- master
|
|
tags:
|
|
- '*'
|
|
|
|
concurrency:
|
|
group: ci-tests-${{ github.event.pull_request.number || github.sha }}-${{ github.repository }}
|
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
|
|
jobs:
|
|
tests-linux:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
go-version: ['1.26.x']
|
|
steps:
|
|
- name: Clone
|
|
uses: actions/checkout@v7
|
|
with:
|
|
submodules: true
|
|
- name: Free disk space
|
|
uses: ./.github/actions/free-disk-space
|
|
- name: Setup Go ${{ matrix.go-version }}
|
|
uses: actions/setup-go@v5
|
|
with:
|
|
go-version: ${{ matrix.go-version }}
|
|
cache: false
|
|
# You can test your matrix by printing the current Go version
|
|
- name: Display Go version
|
|
run: go version
|
|
- name: Proto Dependencies
|
|
run: |
|
|
# Install protoc
|
|
curl -L -s https://github.com/protocolbuffers/protobuf/releases/download/v26.1/protoc-26.1-linux-x86_64.zip -o protoc.zip && \
|
|
unzip -j -d /usr/local/bin protoc.zip bin/protoc && \
|
|
rm protoc.zip
|
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2
|
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@1958fcbe2ca8bd93af633f11e97d44e567e945af
|
|
PATH="$PATH:$HOME/go/bin" make protogen-go
|
|
- name: Dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install curl ffmpeg libopus-dev
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: '22'
|
|
- name: Build React UI
|
|
run: make react-ui
|
|
# Runs the core suite with coverage and fails if total coverage dropped
|
|
# below the committed baseline (coverage-baseline.txt). The gate is
|
|
# strict — any decrease fails. Raise the baseline with
|
|
# `make test-coverage-baseline` and commit it when coverage rises.
|
|
- name: Test (with coverage gate)
|
|
run: |
|
|
PATH="$PATH:/root/go/bin" make --jobs 5 --output-sync=target test-coverage-check
|
|
- name: Upload coverage report
|
|
if: ${{ always() }}
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: coverage-linux
|
|
path: |
|
|
coverage/coverage.out
|
|
coverage/coverage.html
|
|
if-no-files-found: ignore
|
|
- name: Setup tmate session if tests fail
|
|
if: ${{ failure() }}
|
|
uses: mxschmitt/action-tmate@v3.23
|
|
with:
|
|
detached: true
|
|
connect-timeout-seconds: 180
|
|
limit-access-to-actor: true
|
|
|
|
tests-apple:
|
|
runs-on: macos-latest
|
|
strategy:
|
|
matrix:
|
|
go-version: ['1.26.x']
|
|
steps:
|
|
- name: Clone
|
|
uses: actions/checkout@v7
|
|
with:
|
|
submodules: true
|
|
- name: Setup Go ${{ matrix.go-version }}
|
|
uses: actions/setup-go@v5
|
|
with:
|
|
go-version: ${{ matrix.go-version }}
|
|
cache: false
|
|
# You can test your matrix by printing the current Go version
|
|
- name: Display Go version
|
|
run: go version
|
|
- name: Dependencies
|
|
run: |
|
|
brew install protobuf grpc make protoc-gen-go protoc-gen-go-grpc libomp llvm opus ffmpeg
|
|
pip install --user --no-cache-dir grpcio-tools grpcio
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: '22'
|
|
- name: Build React UI
|
|
run: make react-ui
|
|
- name: Test
|
|
run: |
|
|
export C_INCLUDE_PATH=/usr/local/include
|
|
export CPLUS_INCLUDE_PATH=/usr/local/include
|
|
export CC=/opt/homebrew/opt/llvm/bin/clang
|
|
# Used to run the newer GNUMake version from brew that supports --output-sync
|
|
export PATH="/opt/homebrew/opt/make/libexec/gnubin:$PATH"
|
|
PATH="$PATH:$HOME/go/bin" make protogen-go
|
|
PATH="$PATH:$HOME/go/bin" BUILD_TYPE="GITHUB_CI_HAS_BROKEN_METAL" CMAKE_ARGS="-DGGML_F16C=OFF -DGGML_AVX512=OFF -DGGML_AVX2=OFF -DGGML_FMA=OFF" make --jobs 4 --output-sync=target test
|
|
- name: Setup tmate session if tests fail
|
|
if: ${{ failure() }}
|
|
uses: mxschmitt/action-tmate@v3.23
|
|
with:
|
|
detached: true
|
|
connect-timeout-seconds: 180
|
|
limit-access-to-actor: true
|
|
|
|
# Fast standalone unit tests for the backends' pure C++ helpers - currently the
|
|
# llama-cpp message reconstruction (backend/cpp/llama-cpp/message_content.h),
|
|
# which guards the OpenAI chat content normalization (mudler/LocalAI#10524,
|
|
# #7324, #7528). The runner discovers every *_test.cpp under backend/cpp/, so
|
|
# new pure-C++ unit tests are picked up with no CI changes. These need only the
|
|
# C++ stdlib + nlohmann/json, so they run on every PR without the full
|
|
# llama.cpp + gRPC backend build. (The same suite is also wired as an opt-in
|
|
# CMake/ctest target, -DLLAMA_GRPC_BUILD_TESTS=ON, for in-backend-build runs.)
|
|
tests-backend-cpp:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Clone
|
|
uses: actions/checkout@v7
|
|
- name: Run backend C++ unit tests
|
|
run: make test-backend-cpp
|