Repository navigation
Releases
v0.7.0
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-imajevplugin (#4).POST /decidetakes a record (text or JSON), 0-2 photos and 1-8 typed questions:choice,noul(yes/no),scoreandmulti. Each answer carries a probability per option,unknown_probability(the model's trained can't tell) andabstained. 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_filefor 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
xhighreasoning 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.
- It names a Jinja file, resolved like
- 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 inSHA256SUMS.
- Each plugin wheel now carries
Upgrading
- From 0.6.x: check out
v0.7.0and runmake sync, or install the 0.7.0 wheels from this release. Every package moves to 0.7.0 together, andgiq-defaultsnow includesgiq-imajev. - To use decide:
cd envs/imajev && uv sync, then fetchimajev-2bfrom the Add page or withgiq add. Without that interpreter the plugin still loads, theimajevengine shows as missing, and nothing else changes.
Full changelog: v0.6.1...v0.7.0
giq 0.6.1
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/capabilitiescalled 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/statusall 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.pathis one file (a.gguf, a.safetensors…) but whosesourcenames the whole repository (hf:org/repo),giq addand 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.
- For a recipe whose
Upgrading
- From 0.6.0: check out
v0.6.1and runmake 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
sourceand a single file aspath, 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
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 syncor 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 pluginsprints 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-vllmthe vllm engine for LLMs, giq prepare vllmgiq-sdcppimage generation and editing, with their sandbox panels giq-speechspeech to text with diarization, text to speech, voiceprints, /v1/audio/*, their sandbox panelsgiq-ocrdocument OCR, POST /ocrgiq-depthdepth maps, POST /depthgiq-defaultsall 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 pluginsand/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}) andgiq prepare <engine>; - the startup clean-up of leftover servers;
- the modality labels, icons and colours the dashboard shows.
- the routes, smoke tests (
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
multiviewmodality,POST /multiviewand theda3-baserecipe; - the
da3engine andenvs/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
preparehook (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
multiviewmodality, its route and its recipe. The plugin registers all three.
docs/plugins.md walks through each part.
Getting recipes
-
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-runstops 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.
- A source names a whole Hub repository, or one file of it (
-
The vision projector is weights:
weights.parts.mmproj. It is inventoried, fetched and deleted like the rest.params.mmprojin an existing file still loads, with a warning. -
The API follows:
/recipesgives each recipe's availability and the checks behind it;GET /recipes/{name}/planandPOST /recipes/{name}/fetch;GET/DELETE /downloads;DELETE /recipes/{name}/weightsremoves what only that recipe loads;GET /plugins.
Clients see what runs
/capabilitiesadvertises, per modality, only the recipes that run here. They come in preferred order, kept warm first, with adefault. The rest are offered underavailable, with a one-line verdict. Every installed modality is listed, even with nothing ready.GET /capabilities/{modality}returns one entry./v1/modelslists the same LLMs in the same order.- The audio routes run the recipe
modelnames. OpenAI's names (whisper-1,tts-1) get the modality's default. /llm/endpointwithout?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-defaultsholds 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.57loads astransformers, 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 /multiviewand themultiviewmodality 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 syncafter 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/.venvandenvs/da3/.venvare no longer used, andGIQ_UNLIMITED_OCR_PYTHONis ignored. - Behaviour that changed:
/test/{kind}is now/test/{modality};/test/imageis/test/text2image./capabilitiesand/v1/modelsno longer list recipes whose weights are missing./llm/endpointneeds?model=when nothing is kept warm.
- Operator recipe files with
params.mmprojkeep working. Move the line toweights.parts.mmprojto silence the warning. - Re-measure VRAM figures where they matter. The
measured: truefigures date from torch 2.11.
Full changelog: v0.5.3...v0.6.0
giq 0.5.3 — nothing kept warm by default
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 underresidents:, 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-tdnnWhat'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
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
xgrammarbackend 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_whitespacewithbackend: autois 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.
- New default: every vllm recipe uses the
- 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 --helpno longer starts a kernel build. The usage text is an unquoted heredoc, so the backticks aroundgiq prepare vllmwere 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_CONFIGand recipes directory in the environment, twelve policy, runner and registry tests failed against a correctmain. 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
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/completionsrequest without tools, images or streaming kept only the last system and user message, and giq wrote the answer itself withfinish_reason: "stop". So:- an answer cut off by
max_tokenswhile the model was still thinking came back empty and looked finished; - the earlier turns of a conversation never reached the model;
reasoning_contentwas 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 withreasoning_budget_tokens(llama.cpp), or turn it off for extraction withchat_template_kwargs: {"enable_thinking": false}. - an answer cut off by
-
/statusreported 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. -
/statusreported 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 topyproject.toml. Runmake syncafter 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_tokensbought 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
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.
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
modelalone says what to run. flux_kleinis 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 /weightslists 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 /instanceslists what runs on which card: residency, state, port, pid, lanes, VRAM. /recipesreplaces the model control routes.GET /recipes,PUT/DELETE /recipes/{name}/residencyandPUT /recipes/{name}/cardtake 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.
OpenAI Responses API and structured output
Contributed by @pauldkling in #1.
POST /v1/responses, streaming included: tool calls, thedeveloperrole, thinking controls, tool-output parts. Thinking streams asreasoning_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 nativestructured_outputs. Sending both is refused with 400. On/v1/responsesthe same thing istext.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. /statusreports 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):
workerin job bodies →modality. Job and stats JSON now saymodalityandrecipe.GIQ_INSTANCES_DIR→GIQ_RECIPES_DIR.giq initmoves$GIQ_HOME/instances/torecipes/; the systemd unit'sReadWritePathsnamesrecipes.worker: llmin a recipe file →modalities: [llm].llm/gemma-4-12binresidents:andgpu.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

