Saina Helm 3 GGUF
llama.cpp build of run-saina/saina-helm-3-0.8b (model id
saina-helm-3-0.8b). Helm 3, natively multimodal: a decision model that reads text, images and audio together
in one pass and answers typed questions with a probability for every option. No text is generated.
Benchmarks
Saina Helm 3 scores 45.89 on the
Decision Index 0.3 (out of 100, chance-corrected),
measured on run-saina/saina-helm-3-0.8b with the saina runtime.
| Model | Decision Index (text) | Decision Index Vision |
|---|---|---|
| Saina Helm 3 | 45.89 | 47.36 |
| Saina Helm 2 Omni | 37.44 | 46.90 |
Usage
Saina Helm 3 needs the small runner shipped here, omni-hidden-v2, built against llama.cpp and its mtmd library.
score.py builds the prompt with the saina package and applies Helm's answer
head. Stock llama-server and llama-mtmd-cli can load these files but can't produce Helm's answers. For Ollama, use
run-saina/saina-helm-3-0.8b with the Saina Ollama build
(branch).
Build the runner against llama.cpp at the commit it was tested with (its C API changes between versions):
hf download run-saina/saina-helm-3-0.8b-GGUF --local-dir helm3-gguf
git clone https://github.com/ggml-org/llama.cpp && git -C llama.cpp checkout abeada335e2e78bd3fe63febafab7e900ce75810
cmake -S llama.cpp -B llama.cpp/build -DLLAMA_BUILD_TESTS=OFF # add -DGGML_CUDA=ON or -DGGML_METAL=ON for a GPU
cmake --build llama.cpp/build --target llama mtmd -j 8
c++ -std=c++17 -O3 helm3-gguf/omni-hidden-v2.cpp \
-Illama.cpp/include -Illama.cpp/ggml/include -Illama.cpp/tools/mtmd -Lllama.cpp/build/bin \
-Wl,-rpath,"$PWD/llama.cpp/build/bin" -lllama -lmtmd -lggml -lggml-base -o omni-hidden-v2
pip install numpy safetensors "saina[tokenize,media]>=0.9.1"
import sys; sys.path.insert(0, 'helm3-gguf')
from score import Helm
helm = Helm('helm3-gguf', runner='./omni-hidden-v2')
helm.ask('I was charged twice for my subscription this month.',
[{'question': 'Which team should handle this?', 'choices': ['Billing', 'Technical', 'Other']},
{'question': 'Is this urgent?', 'choices': ['No', 'Yes']}])
helm.ask('Inbound call to the bank: a short recording of English speech.',
[{'question': 'Is this speech synthesized or voice-converted by a computer (a spoof)?',
'choices': ['No', 'Yes']}],
audios=['call.wav']) # WAV, FLAC, MP3, Ogg or WebM, up to 10 s each, up to 4 clips
helm.ask('A chess puzzle from an online game.',
[{'question': 'Black to move. Which move is best?', 'choices': ['Rf7', 'h6', 'Rxf1', 'a5']}],
images=['board.png']) # PNG, JPEG or WebP, up to 8 images
# -> one probability list per question, in the order of `choices`
Put the situation in the context and ask about it in the questions. Each question takes choices and an optional
mode: single_label (default; the probabilities sum to 1) or multi_label (one independent probability per
choice). All questions are answered in one pass.
Helm(..., threads=, n_ctx=, gpu_layers=) sets the runner's CPU threads, context size (default 32,768 tokens,
images and spectrograms included) and layers offloaded to a GPU (needs a GPU build of llama.cpp). The prompt is read
in one batch, so n_ctx also sets the batch size and most of the runner's memory: lower it (for example
n_ctx=8192) on small machines if your requests are short.
Don't quantize these files without re-checking against the saina runtime.
Files
| File | Contents |
|---|---|
saina-helm-3-0.8b-f16.gguf |
Language model, F16 |
mmproj-saina-helm-3-0.8b-f16.gguf |
Image encoder, F16 (llama.cpp mtmd projector) |
experts.safetensors, head-config.json |
Helm's answer head, FP32 |
omni-hidden-v2.cpp, score.py |
Runner and scorer |
config.json, tokenizer*.json, chat_template.jinja, preprocessor_config.json |
Read by saina for the prompt, image grid and media token counts |
License
Apache 2.0. Built on Qwen/Qwen3.5-0.8B.