Skip to content

ignis v0.9.0

Released 2026-10-28. The container image, the archives and the notes as written: the release on GitHub.

[!WARNING] These downloads are not GPU builds: use v0.9.2. This release’s Linux tarball, Windows zip and container images were built without the cuda feature, so the server reports ready and answers with the CPU mock’s placeholder text whatever the model (#408). v0.9.2 is the same code built with CUDA.

ignis now transcribes speech, and tells the speakers apart, on the CPU beside the text or image model, in host memory rather than VRAM. The Playground gains dictation and the Transcribe view (#350-#355, #361, #362).

  • Qwen3-ASR, beside the model on the card (ADR 0067, ADR 0068, guide).
    • An executor of ignis’s own, in Rust, runs it on any CPU with AVX2.
    • It is loaded at first use, unloaded after speech.idle_unload (300 s), and serves through a model switch.
    • Three built-in entries: qwen3-asr-1.7b (the default, 1.5 GiB), qwen3-asr-1.7b-q8 and qwen3-asr-0.6b (1.7B, 0.6B).
    • It is on once its files are on disk, and never downloaded by itself: ignis-server model download qwen3-asr-1.7b.
  • POST /v1/audio/transcriptions, OpenAI’s route.
    • It takes WAV, FLAC, MP3 or AAC, and answers JSON, text or a stream.
    • whisper-1 and OpenAI’s other transcription names reach the speech model.
    • A transcript that only repeats the prompt counts as no speech (speech.context_copy_words).
  • Live transcription, OpenAI’s Realtime transcription session on GET /v1/realtime?intent=transcription (guide). server_vad is the default, on Silero VAD ported to Rust, and deltas carry settled text only. Opt-in ignis events add a provisional tail and each item’s language.
  • Speakers (ADR 0069, #361): Nemotron 3 Diarization, ported to Rust on the CPU, on threads of its own.
    • A server_vad session that sets session.ignis.diarization gets each item’s speaker.
    • An item ends where the speaker changes.
    • Fetch it with ignis-server model download nemotron-3-diarization (gpillon/Nemotron-3-Diarization-GGUF-ignis, F16, about 0.2 GB of RAM).
  • Dictation (#354, guide): a mic in the chat, the image studio and Decide. The text lands at the cursor and is never sent by itself.
  • The Transcribe view (#362, guide) writes down a conversation from the mic, a call or a file, with its speakers. While it listens, you can correct it and tell it the languages and terms. The text model suggests fixes for misheard names, writes notes and answers questions. Exports: .txt, .md, .srt, .vtt or a new chat.

How it was measured. CPU only, on a 10-core desktop CPU and a 4-core Linux container.

  • Speech model (spec speech/01, As built):
    • qwen3-asr-1.7b runs at 4.1-4.7x real time on the desktop and about 3x on 4 cores, at parity with llama.cpp b11840.
    • Its WER is within a point of Transformers FP32: 3.23% against 3.06% on eleven Italian dictations, and 4.05% against 3.63% on 40 FLEURS clips.
  • server_vad (spec speech/05): its utterances score 4.68% WER on those dictations, against 4.03% as one manual commit.
  • Diarizer (spec speech/08, As built):
    • DER is 3.57% live on twenty synthetic Italian conversations, against NeMo-Speech.cpp’s 3.60%.
    • On three real English meetings (AMI) DER is 30.2%, mostly missed speech.
    • On 4 cores the diarizer takes about a quarter of the CPU.
  • Findings:
    • The no-speech guard emptied 15 of 17 copies in a 250-request probe, and nothing else (finding).
    • On clean read speech, naming the language in the prompt fixes mislabelled short clips as forcing does, without translating English clips as forcing did, so the Transcribe view hints by default (finding).
  • The Server view downloads and removes models (ADR 0071, #374-#380, guide).
    • A download runs in the background, and can be cancelled and resumed.
    • A removal refuses the model in use.
    • Every fetch, from the page, the command or the start, needs room for the missing bytes plus download.free_margin (1G).
    • A per-entry lock keeps two fetches of one entry apart.
  • The agent path (#357, guide) is a page for an AI agent working for a user. It covers the checks before installing, the user’s choices, and a 16 GB card test that reports to #360. llms.txt lists every page as Markdown.
  • A docker compose example, docker-compose.yml.example (#385, guide).
  • The presentation video, Ignis in 90 seconds, on the README and the guide’s front page (#384).
  • For contributors (ADR 0070, #363-#372). A spec is a GitHub issue, and its tickets are sub-issues. docs/PENDING.md is gone, and the coding rules are in CODING_STANDARDS.md. make setup turns on a commit-msg hook.
  • Security updates of the web build’s dependencies and the image converter’s Pillow (#314, #344, #382).
  • A 0.8.0 configuration starts as before. speech.model and diarizer.model default to auto, but nothing is downloaded or loaded until the files are on disk and a request comes in.
    • GET /v1/models gains a top-level speech object that says why speech is unavailable, and the Playground’s mics show that reason.
    • In use, the speech model takes 1.4 GB (0.6B) to 3.1 GB (1.7B Q8_0) of RAM, and needs a CPU with AVX2.
  • GET /v1/models lists the speech model right after data[0] once its files are on disk, with kind: "speech" and active: true. A client that reads data[1] as a switch target, or offers every entry for chat, should check kind.
  • The Server view can now download and delete models, with the API key PATCH /v1/config takes, or with no key when none is set. A server reachable beyond localhost should set a key, or pass --download-from-ui false.
  • A start that must fetch its model can now be refused before fetching: when the disk lacks room, or while ignis-server model download is fetching the same entry.
  • ADR 0067: the speech model waits on the host and borrows free KV pages
  • ADR 0068: the speech model’s CPU executor is ours, in Rust
  • ADR 0069: the speakers come from Nemotron 3 Diarization, beside Qwen3-ASR
  • ADR 0070: a spec is a GitHub issue and its tickets are sub-issues
  • ADR 0071: the server downloads and removes models after start, from the Server view
  • Recorded for work still open, not in this release:
    • ADR 0072: the Playground’s system prompt never changes, and what changes rides after the history (#170);
    • ADR 0073: a workspace is kept by the page, and ignis stores no files (#170);
    • ADR 0074: a catalog entry may state its family, and an alias may be another entry’s id (#386).
  • Amended:
    • ADR 0017: the speech metrics;
    • ADR 0046: a family judges only its own slot’s fields;
    • ADR 0049 and ADR 0050: the speech model loads beside the text or image model, and a transcription is no use of the text model.
  • #350: speech recognition. Its open tickets are:
    • #356: the GPU loan of free KV pages, not served yet;
    • #359: deferred measurements, the text decode beside a transcription and a live commit’s latency.
  • #360: 16 GB card reports, from ignis-bench small-card or the agent path’s test.
  • #383: connectors that bring System One, images, transcription and configuration into coding-agent harnesses (finding).
  • #373: two GPU tests that looked slower in a September profile run, never investigated.
  • Carried from 0.8.0:
    • #345: the 16 GB prefill gap;
    • #342: the 27B’s prefill on the 5090;
    • #333: Flash-Next prefix reuse at ~500K and 1M.
podman run --rm --device nvidia.com/gpu=all -p 8000:8000 \
-v /path/to/models:/models:ro \
-e IGNIS_MODEL_ARTIFACT=/models/<name>.ninfer \
ghcr.io/gpillon/ignis:0.9.0

(docker: --gpus all in place of --device.) The image carries the CUDA runtime but no driver — the host’s NVIDIA driver is injected by the container runtime. It is built from the same compile as the Linux tarball below, so the two always carry the same binaries.

The kernel is compiled for SM120a (RTX 5090 / Blackwell consumer) only, and the engine needs a .ninfer artifact, which is not part of this release. The Linux tarball needs the CUDA 13 runtime on the host; the Windows zip carries cudart64_*.dll. Both need an NVIDIA driver new enough for CUDA 13.

Apache-2.0 (LICENSE, NOTICE); the vendored reference ops keep their own terms (NOTICE-kernel).

Full Changelog: https://github.com/gpillon/ignis/compare/v0.8.0...v0.9.0