Skip to content

Releases

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 20 Oct 20:47

giq 0.7.0 adds typed decisions: POST /decide takes a record, up to two photos and typed questions, and returns calibrated probabilities through imajev-2b. LLM recipes can also replace the checkpoint's chat template, and every release now carries its licences, file by file. Thanks to @ewuerger for both features (#3, #4); integration, packaging and licensing by @vik378.

New

  • Decide: a new modality and the curated giq-imajev plugin (#4).
    • POST /decide takes a record (text or JSON), 0-2 photos and 1-8 typed questions: choice, noul (yes/no), score and multi. Each answer carries a probability per option, unknown_probability (the model's trained can't tell) and abstained. Act above a threshold you measured on your own cases; send abstentions to a person.
    • It runs on imajev-2b: Qwen3.5-2B plus a LoRA and a 255-code decision readout, both Apache-2.0. rotations (1-4) averages over option orders.
    • The engine runs on its own interpreter, set up once with cd envs/imajev && uv sync; it installs imajev at a pinned commit.
    • On an RTX 5060 Ti it loads in 4 s and takes 4.5 GiB, answering a text question in about 40 ms and a photo question in about 60 ms once warm. Sleepy: it loads on demand and can be evicted.
    • The sandbox has a Decide tab: a JSON editor for the record and questions, photo upload, and the answers with their probabilities.
  • params.chat_template_file for llama.cpp and vllm recipes (#3).
    • It names a Jinja file, resolved like weights.path, that replaces the checkpoint's own chat template. llama.cpp gets it as --chat-template-file, vllm as --chat-template. Unset, nothing changes.
    • It exists for the fixed Qwen templates: the stock Qwen 3.8 template defaults to xhigh reasoning and breaks on tool-call arguments sent as a JSON string, the OpenAI wire shape. See Chat templates for what was checked, and why it is opt-in per recipe.
  • Licences travel with every copy.
    • Each plugin wheel now carries LICENSES/, as core's already did; CI fails a build where one doesn't.
    • The release has giq-0.7.0.spdx, an SPDX bill of materials of every file's copyright and licence, generated from the REUSE headers and listed in SHA256SUMS.

Upgrading

  • From 0.6.x: check out v0.7.0 and run make sync, or install the 0.7.0 wheels from this release. Every package moves to 0.7.0 together, and giq-defaults now includes giq-imajev.
  • To use decide: cd envs/imajev && uv sync, then fetch imajev-2b from the Add page or with giq add. Without that interpreter the plugin still loads, the imajev engine shows as missing, and nothing else changes.

Full changelog: v0.6.1...v0.7.0

giq 0.6.1

Choose a tag to compare

@github-actions github-actions released this 04 Oct 16:54

giq 0.6.1 fixes two gaps found while installing 0.6.0. A vllm recipe that fills most of a card can now load on demand; before, it only ran when kept warm. And giq add no longer accepts a recipe that would fetch a whole repository into a directory named like a model file.

Fixes

  • vllm recipes load on demand with a margin that fits how vllm uses memory.
    • giq kept up to 2 GB free on top of a recipe's VRAM figure before loading it. That covers engines that grow into compute buffers as they run. vllm reserves its weights, its KV budget and its buffers at start and never grows past them.
    • With the 2 GB margin, qwen3.8-27b-nvfp4-chat (29.7 GB) needed 31.7 GB, more than a 32 GB RTX 5090 has free. It waited three minutes and failed, unless kept warm. Meanwhile the dashboard and /capabilities called it runnable.
    • vllm now declares a 0.5 GB margin, the same one a keep-warm reload gets. On an RTX 5090 with nothing kept warm, a chat request loaded it on demand and answered in 91 s.
    • The load gate, eviction, /recipes, the Add page and /status all use the same margin, so they agree on what fits. A plugin's engine can declare its own (Engine.vram_margin, docs/plugins.md).
  • A source that names a whole repository for a single-file path fails the plan.
    • For a recipe whose weights.path is one file (a .gguf, a .safetensors…) but whose source names the whole repository (hf:org/repo), giq add and the Add page would have downloaded the entire repository into a directory named like the file.
    • The plan now refuses it and says what to write instead: the file in the source, hf:org/repo/<file>. The download process refuses it too.

Upgrading

  • From 0.6.0: check out v0.6.1 and run make sync, or install the 0.6.1 wheels from this release. Every package moves to 0.6.1 together.
  • If one of your recipe files names a repository as source and a single file as path, change the source to name the file. Nothing breaks until you fetch it; the plan says so then.

Full changelog: v0.6.0...v0.6.1

giq 0.6.0

Choose a tag to compare

@github-actions github-actions released this 03 Oct 14:29

giq 0.6.0 splits giq into a small core and plugins.

  • Core: the queue, scheduler, API and dashboard, plus LLMs through llama.cpp. Installed alone it needs no torch and takes about 40 MB.
  • Curated plugins, each its own package, released with core: image generation, speech, OCR, depth and vllm.
  • Installing everything: make sync or the installer, exactly as before.
  • Your own plugins: anything else, including multiview, now comes as a plugin. The contract is documented and versioned.
  • Installing a few: every package is a wheel on this release; giq plugins prints the command for each one not installed.

0.6.0 also changes how models get onto a machine. The Recipes page shows what runs here. A new Add page fetches the rest from the Hugging Face Hub, after showing what that takes. giq add <recipe> does the same from the command line.

Breaking: POST /multiview and five old recipes are gone, and a few defaults moved. Read Upgrading first.

Plugins

A plugin is a Python package that registers engines, modalities, routes, recipes and dashboard panels through the giq.plugins entry point (ADR-004, docs/plugins.md). Installing it is the whole of enabling it.

  • The curated plugins live in this repository as packages of one uv workspace, all version 0.6.0:

    Package Adds
    giq-vllm the vllm engine for LLMs, giq prepare vllm
    giq-sdcpp image generation and editing, with their sandbox panels
    giq-speech speech to text with diarization, text to speech, voiceprints, /v1/audio/*, their sandbox panels
    giq-ocr document OCR, POST /ocr
    giq-depth depth maps, POST /depth
    giq-defaults all of the above

    Each brings its own recipes and dependencies, so torch leaves core's dependency list.

  • Plugins only add. A plugin is refused whole, with the reason in giq plugins and /status, when:

    • it was written for another plugin API version;
    • it does not import;
    • it takes a name or a route that is already registered.

    Core and the other plugins keep serving.

  • Plugins bring dashboard panels. The sandbox draws its tabs from what is installed. The image and speech panels now ship with their plugins, under the same addresses, so links and bookmarks still work. A plugin's module gets React, the API client and the shared components from the dashboard through @giq/plugin-ui, so it never bundles its own copy of React.

  • Child processes speak giq_child, a standard-library-only protocol. A plugin's child can therefore run on an interpreter of its own, without giq, when its dependencies cannot share giq's.

  • Every engine-specific detail is now a registration:

    • the routes, smoke tests (POST /test/{modality}, which replaces /test/{kind}) and giq prepare <engine>;
    • the startup clean-up of leftover servers;
    • the modality labels, icons and colours the dashboard shows.

Multiview leaves giq: the way back is a plugin

Multi-view geometry with Depth Anything 3 served one project. It pinned numpy below 2 and needed its own interpreter, which made it a poor fit for every install. 0.6.0 removes it:

  • the multiview modality, POST /multiview and the da3-base recipe;
  • the da3 engine and envs/da3.

Old multiview jobs in the history still show, in the neutral colour.

If you need multiview, it belongs in an engine plugin, which is the case the contract was designed for:

  • An engine with an interpreter of its own. Its prepare hook (giq prepare da3) builds that interpreter from a lock the plugin ships.
  • A child that speaks giq_child. It runs on that interpreter without giq installed.
  • The multiview modality, its route and its recipe. The plugin registers all three.

docs/plugins.md walks through each part.

Getting recipes

ADR-005.

  • The Recipes page shows what is on this machine. A recipe that cannot run here is marked, with the reason: its engine binary is missing, or no card fits it.

  • The Add page lists everything else by modality, with a search:

    • recipes giq can fetch;
    • recipes whose files you place yourself;
    • curated plugins not installed, with their install command. The dashboard never installs a plugin.
  • giq plans before it fetches. "Check what it takes" shows:

    • whether a card fits it;
    • the download size, from the Hub;
    • free disk where the files go;
    • which parts another recipe already brought;
    • whether a gated repository opens with your token;
    • the licence.

    Then it offers the fetch, with live progress and a stop button. A stopped fetch resumes next time. Files appear in place only when all of them have arrived.

  • giq add <recipe> prints the same plan, asks once, and fetches. --dry-run stops after the plan. Under the hardened systemd unit the service may not write the models directory, so the dashboard hands you this command instead.

  • Every built-in recipe says where its weights come from.

    • A source names a whole Hub repository, or one file of it (hf:org/repo/path/in/repo).
    • Weights under the models directory are pinned to the commit whose files their VRAM figure was measured with. The gemma GGUFs are pinned to the revisions before unsloth's re-uploads.
    • flux_klein now loads z-image's text encoder, which is byte-identical to its own.
  • The vision projector is weights: weights.parts.mmproj. It is inventoried, fetched and deleted like the rest. params.mmproj in an existing file still loads, with a warning.

  • The API follows:

    • /recipes gives each recipe's availability and the checks behind it;
    • GET /recipes/{name}/plan and POST /recipes/{name}/fetch;
    • GET/DELETE /downloads;
    • DELETE /recipes/{name}/weights removes what only that recipe loads;
    • GET /plugins.

Clients see what runs

  • /capabilities advertises, per modality, only the recipes that run here. They come in preferred order, kept warm first, with a default. The rest are offered under available, with a one-line verdict. Every installed modality is listed, even with nothing ready. GET /capabilities/{modality} returns one entry.
  • /v1/models lists the same LLMs in the same order.
  • The audio routes run the recipe model names. OpenAI's names (whisper-1, tts-1) get the modality's default.
  • /llm/endpoint without ?model= points at the first LLM kept warm. It used to point at gemma-4-12b.

Fixes

  • Transcription with diarization and voiceprints no longer fail with a 500 unless kept warm. The on-demand path rejected the plain dicts the audio and voiceprint adapters return. Since 0.5.3 stopped keeping them warm by default, every diarized transcription and every voiceprint failed on a default install.

One torch, and Unlimited-OCR on it

  • giq runs vllm's torch line: torch 2.13, torchvision 0.28, torchaudio 2.11. A card sees one torch, and VRAM figures compare across engines. giq-defaults holds the line for every curated plugin.
  • Unlimited-OCR runs on giq's own transformers 5. Its separate interpreter is gone. giq's OCR child adapts three changes from transformers 4.57: the cache's maximum length, the tokenizer, and the rotary embeddings. Its output is byte-for-byte identical to 4.57's on the pages checked. The OCR child is chosen from the checkpoint's architecture, and engine: transformers-4.57 loads as transformers, with a warning.

Upgrading

  • Multiview users: stay on 0.5.x until a multiview plugin is installed next to giq 0.6.0 (see above). POST /multiview and the multiview modality are gone from giq itself.
  • Five old recipes left the built-in catalog: gemma-3-27b-it-qat, llama-3.2-3b, qwen-coder-30b, qwen3.5-35b-a3b and qwen3.6-27b. If you still run one, copy its file from 0.5.3 into your recipes directory.
  • make sync after checking out 0.6.0. It installs core and every curated plugin, as a single environment did before, and moves it to torch 2.13. That is a large download.
  • Remove the old side environments. envs/unlimited-ocr/.venv and envs/da3/.venv are no longer used, and GIQ_UNLIMITED_OCR_PYTHON is ignored.
  • Behaviour that changed:
    • /test/{kind} is now /test/{modality}; /test/image is /test/text2image.
    • /capabilities and /v1/models no longer list recipes whose weights are missing.
    • /llm/endpoint needs ?model= when nothing is kept warm.
  • Operator recipe files with params.mmproj keep working. Move the line to weights.parts.mmproj to silence the warning.
  • Re-measure VRAM figures where they matter. The measured: true figures date from torch 2.11.

Full changelog: v0.5.3...v0.6.0

giq 0.5.3 — nothing kept warm by default

Choose a tag to compare

@github-actions github-actions released this 02 Oct 20:26

giq 0.5.3 changes one default: nothing is kept warm out of the box.

What changed

Until now three built-in recipes carried a residency priority: gemma-4-12b, whisper-large-v3 and ecapa-tdnn. A new install with their weights on disk kept about 14 GB loaded from its first boot, whether its operator wanted that or not. No built-in recipe pins anything now: a new install loads a model only when a job asks for it.

Keeping models warm is the operator's decision, made in one of three places:

  • config.yaml: list them under residents:, in reload-priority order. The template shows an example.
  • The dashboard: set a recipe to keep warm in the Recipes view. That choice persists in stats.db.
  • A recipe file of your own: set residency.priority.

Upgrading

If you relied on the old default (gemma, whisper and ecapa loaded at boot without residents: in your config), add it explicitly before upgrading:

residents:
  - gemma-4-12b
  - whisper-large-v3
  - ecapa-tdnn

What's unaffected:

  • Installs that already list residents:.
  • Recipes pinned in the dashboard: a keep warm override still applies.

Full changelog: v0.5.2...v0.5.3

giq 0.5.2 — crash fix, large JSON schemas, CI

Choose a tag to compare

@github-actions github-actions released this 02 Oct 16:26

giq 0.5.2 fixes an engine crash in 0.5.1's interactive NVFP4 recipe and makes large JSON schemas converge on vllm. Upgrade in place.

Fixes

  • The interactive NVFP4 recipe could crash under concurrent long requests. qwen3.8-27b-nvfp4-chat (MTP with 3 draft tokens, 5.5 GiB KV, 4 parallel) scheduled 8,192 tokens a step. On a 32 GB card that step's working memory didn't fit beside the weights and the KV pool. Three agents reading their tool results at once ran the engine out of memory (31.2 of 31.8 GiB), and every request failed until giq restarted it.
    • It now schedules 4,096 tokens a step. The same three-agent load ran clean to 40k tokens of history each (peak 30.7 GiB), and a single agent's time to first token and decode rate were unchanged up to 60k.
    • Why nothing caught it at start: with a KV size given in bytes, as giq gives it, vllm skips its memory profiling.
  • Large JSON schemas on vllm no longer run into whitespace. Contributed by @pauldkling in #2. vllm's default grammar allows any whitespace between JSON tokens, and on a large or deeply nested schema the model can wander into newlines and spaces until max_tokens, returning invalid JSON. Reproduced on an RTX PRO 6000 with a 13.5 KB schema: 92% whitespace, finish_reason: length.
    • New default: every vllm recipe uses the xgrammar backend with free whitespace switched off.
    • Opting out: a recipe can ask for vllm's default back with structured_outputs: {backend: auto, disable_any_whitespace: false}.
    • Load-time check: a recipe that pairs disable_any_whitespace with backend: auto is refused when it loads, rather than by vllm minutes into a start.
    • Behaviour change: schema-constrained output from vllm is now compact JSON with no indentation, so fewer tokens and the same content.
  • A restarted engine keeps the previous run's log. giq restarts a crashed resident engine by itself, and the new run used to overwrite the log that held the crash's stack trace. The previous run now moves to <name>.log.1. One run is kept, so a crash loop can't fill the disk.
  • install-debian.sh --help no longer starts a kernel build. The usage text is an unquoted heredoc, so the backticks around giq prepare vllm were command substitution: printing the help ran it wherever giq was installed.
  • CI runs. GitHub Actions now builds and tests every push and pull request, and builds the release files for a tag (this release's were built that way). Its first runs also caught a test that only passed on a machine with a GPU, and the installer bug above. The workflow can be started by hand too (workflow_dispatch).
  • The test suite ignores the shell's giq configuration. With an operator's GIQ_CONFIG and recipes directory in the environment, twelve policy, runner and registry tests failed against a correct main. The suite now drops what configures a giq and keeps what only locates binaries and models.

Agent workload on an RTX 5090

Measured while finding the crash: an agent loop through giq's OpenAI endpoint, streamed with tools, its history growing by a ~5k-token tool result a turn. Recipe settings as qwen3.8-27b-nvfp4-chat in this release, pinned.

History Prefix cache hit Time to first token Decode
6k 0% 0.7 s 167 tok/s
23k 70% 1.1 s 163 tok/s
60k 86% 2.2 s 180 tok/s
102k 92% 2.9 s 170 tok/s
125k 94% 3.5 s 173 tok/s
  • Speed holds at long context. Decoding stays at 153–195 tok/s up to 125k tokens, because the model's linear-attention layers don't slow with context.
  • Prefix caching works. Each turn re-reads about 8k tokens: the new tool result plus a stretch back to the last point where vllm saved the linear-attention state.
  • Tool calls: 63 of 63 parsed correctly across one agent with thinking off, one with thinking on, and three at once.

Full changelog: v0.5.1...v0.5.2

giq 0.5.1 — production fixes and faster NVFP4 recipes

Choose a tag to compare

@vik378 vik378 released this 02 Oct 09:59

giq 0.5.1 fixes three problems found on the first 0.5.0 production deploy, and tunes the NVFP4 Qwen3.8-27B recipes for batch extraction on the strength of a benchmark on an RTX 5090. No breaking changes; upgrade in place.

Fixes

  • Non-streaming chat answers were rebuilt by giq, and lost things. A /v1/chat/completions request without tools, images or streaming kept only the last system and user message, and giq wrote the answer itself with finish_reason: "stop". So:

    • an answer cut off by max_tokens while the model was still thinking came back empty and looked finished;
    • the earlier turns of a conversation never reached the model;
    • reasoning_content was dropped.

    Every non-streaming chat now goes to the engine whole, as streaming and tool calls already did, and the engine's answer comes back as written: "length" when the budget ran out. To keep thinking from eating the answer, cap it with reasoning_budget_tokens (llama.cpp), or turn it off for extraction with chat_template_kwargs: {"enable_thinking": false}.

  • /status reported 0 GB in use by giq on a card running a vllm instance. vllm's API server holds no VRAM; its engine-core child does. Attribution now counts the processes a spawned engine starts.

  • /status reported version 0.4.0 on a 0.5.0 deploy. The package carried its own copy of the version string, which the release bump missed. It now reads the installed version, and a test holds it to pyproject.toml. Run make sync after checking out a new version, as the update steps say.

Faster NVFP4 recipes, measured

Two recipes over the same nvidia/Qwen3.8-27B-NVFP4 checkpoint, each tuned for its job:

  • qwen3.8-27b-nvfp4 (batch): schedules 16 requests at once instead of 32. 16 already saturate the card; more only wait in the queue.
  • qwen3.8-27b-nvfp4-chat (one fast answer): drafts 3 tokens with the model's own multi-token-prediction head instead of 2, with the KV budget raised to the 5.5 GiB that three drafts need for a full 128k request.

Benchmark report

RTX 5090 (32 GB, power limit 500 W), vllm 0.30. Batch extraction: a unique ~3.1k-token document per request (real text from this repository), a shared extraction prompt, ~490 tokens of JSON out under a JSON schema, thinking off, temperature 0. Every one of the ~1,700 outputs was valid JSON with finish_reason: stop.

Batch throughput — the card is compute-bound at about 4,200 tokens/s on this model:

Configuration Documents/min Input tok/s Output tok/s Slowest 5%
16 parallel, no speculation 71 3,640 580 27 s
32 parallel (0.5.0's recipe) 68 3,500 550 139 s
64 parallel 65–71 3,350–3,670 530–580 ~140 s
64 parallel, 16k tokens per step ran out of memory under load
16 parallel, MTP 1 draft token 47 2,400 380 112 s
16 parallel, MTP 2 draft tokens 66 3,400 540 70 s

A single request — speculation is close to free here, and JSON drafts well:

Draft tokens 0 1 2 3
vllm, NVFP4 (tok/s) 69 108 138 162
llama.cpp, Q6_K --spec-type draft-mtp (tok/s) 52 72 82 89
vllm, seconds per document 7.5 4.8 3.7 3.1

The NVFP4 checkpoint and the Q6_K GGUF are the same size (20.4 GiB), so one request reads the same bytes per token on both: the gap is the engine.

Power limit (the 5090 allows 400–575 W):

Limit Batch documents/min Drawn Documents per kWh Single request tok/s
575 W 72 481 W 8,990 162
500 W 71 465 W 9,130 164
450 W 69 442 W 9,460 164
400 W 67 396 W 10,180 163

For batch, 400 W gives 13% more documents per kWh for 7% fewer per minute. A single request never draws more than ~410 W.

What else the benchmark found:

  • Prepare vllm after every upgrade. On an empty cache, vllm 0.30's first start compiled kernels for 14 minutes (819 s), past giq's 600 s start budget. Run giq prepare vllm --recipe <name> after each vllm upgrade.
  • A larger step budget doesn't help. max_num_batched_tokens bought nothing on this workload. With a KV size given in bytes, vllm skips its memory profiling, so a step budget too big for the card fails under load rather than at start.
  • Prefix caching needs long shared prompts. Qwen3.8 is a hybrid model, and vllm caches its prefixes in blocks of 1,568 tokens. A shared prompt shorter than that gets no cache hits; this one was ~400 tokens.
  • The interactive recipe is tight on a 5090. It declares 29.7 GB and passes giq's gate on a 32 GB card with 0.1 GB to spare. On a card that also drives a display it won't load. On larger cards (RTX PRO 6000), replace both files in your recipes directory with a larger kv_cache_memory, and measure there: compute per card is similar, so the 16-parallel saturation point likely holds.

Full changelog: v0.5.0...v0.5.1

giq 0.5.0 — recipes, instances, and the Responses API

Choose a tag to compare

@vik378 vik378 released this 02 Oct 07:05

giq 0.5.0 gives the domain proper names, adds the OpenAI Responses API and structured output, and fixes how giq serves from more than one card. It is a breaking release for the control API: read Upgrading before you deploy.

The control surface

One word per thing

giq now names what it serves in six terms, one meaning each (ADR-003):

  • Weights are the files: a GGUF, a checkpoint directory, an HF repository.
  • An engine runs them: llama.cpp, vllm, sd.cpp, and the Python runtimes.
  • A recipe is weights + engine + parameters, with its VRAM figure. Its name is what a client sends as model, and it serves one or more modalities (llm, text2image, ocr …).
  • An instance is a recipe running on a card. Residency decides whether it stays: keep warm, on demand, or off.

What that changes in practice:

  • Recipes are keyed by name. A name or alias is unique across modalities, so model alone says what to run.
  • flux_klein is one recipe for text-to-image and image edit. Alternating renders and edits no longer reloads it: measured on an RTX 5090, a 12 s render followed by a 2.8 s edit on the same process.
  • The speech-to-text recipes are named after their weights (faster-whisper-tiny … faster-whisper-large-v3). The bare sizes (tiny, large-v3 …) still work as aliases.
  • Weights are an inventory. GET /weights lists every checkpoint once, however many recipes load it, with its format, source, revision, licence and size. DELETE /weights/{id} removes one, and is refused while a recipe using it is loaded. Two recipes that disagree about what one checkpoint is are a load error, not a silent pick.
  • Instances are visible. GET /instances lists what runs on which card: residency, state, port, pid, lanes, VRAM.
  • /recipes replaces the model control routes. GET /recipes, PUT/DELETE /recipes/{name}/residency and PUT /recipes/{name}/card take a recipe by name or alias, and keep the 409 guards: two LLMs pinned to one card, a pinned set that cannot fit its card, a recipe bound to a card it can never fit.

Dashboard

  • Recipes (was Models): one card per recipe with its residency, GPU binding, engine and fit, filterable by modality, engine and residency.
  • Inventory (new): the weights table with delete, the engines and their builds, and the disks.
  • Overview: the GPU cards and the running-instances table are built from /instances.
  • Every string uses the new terms, in English and German.

The recipe catalog in German

OpenAI Responses API and structured output

Contributed by @pauldkling in #1.

  • POST /v1/responses, streaming included: tool calls, the developer role, thinking controls, tool-output parts. Thinking streams as reasoning_text, one output item at a time.
  • Structured output on /v1/chat/completions: response_format (json_object, json_schema; honoured by llama.cpp and vllm) or vllm's native structured_outputs. Sending both is refused with 400. On /v1/responses the same thing is text.format.

Serving fixes

  • Two vllm servers on one card no longer kill each other. A second server of one engine on a card takes a free port from that card's block. Before, two vllm recipes on one GPU restarted each other in a loop and answered with the wrong model.
  • Start budgets per engine and recipe. vllm gets minutes rather than llama.cpp's seconds, a recipe can set its own ready_timeout, and a start that runs out says so instead of reporting a generic timeout.
  • /status reports every card (gpus), and a job waiting for VRAM is judged on the card it is bound to.
  • Storage finds every LLM's weights, NVFP4 and other vllm checkpoints included, not just GGUFs.

Upgrading

Back up stats.db first. On first start, giq renames the job-history columns in place (worker → modality, model → recipe) and moves the residency table to recipe names. History is kept.

Removed (each now returns 404):

Before Now
GET /control/models, GET /stats/models GET /recipes
POST /control/models/{worker}/{model} PUT /recipes/{name}/residency
POST /control/models/{worker}/{model}/device PUT /recipes/{name}/card
DELETE /control/models/{worker}/{model} DELETE /recipes/{name}/residency
DELETE /storage/models/{worker}/{model} DELETE /weights/{id}
the models list in GET /storage GET /weights (/storage keeps the disks, paths and recipe files)

Renamed, with the old form still accepted for one release (a warning names it):

  • worker in job bodies → modality. Job and stats JSON now say modality and recipe.
  • GIQ_INSTANCES_DIR → GIQ_RECIPES_DIR. giq init moves $GIQ_HOME/instances/ to recipes/; the systemd unit's ReadWritePaths names recipes.
  • worker: llm in a recipe file → modalities: [llm].
  • llm/gemma-4-12b in residents: and gpu.bind → gemma-4-12b.

Deploy the dashboard with the backend. The 0.5.0 dashboard needs the 0.5.0 routes: install-debian.sh --ref v0.5.0 --ui-release v0.5.0.

For code that imports giq: giq.workers is now giq.adapters (LlamaCppAdapter, VllmAdapter, SdCppAdapter …), and giq.instances is giq.recipes.

Full changelog: v0.4.0...v0.5.0