Files
command-center/agent/models.yml
T

257 lines
14 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OMP agent model registry — single source of truth (OMP is the primary
# harness; there is no second copy to keep in sync).
# Conversion notes from the pi-era import:
# - apiKey "EMPTY" -> auth: none (keyless local endpoint)
# - thinkingLevelMap {max: xhigh} -> compat.reasoningEffortMap
providers:
# Provider NAMES are labels, and every reference to them lives in config.yml
# (modelRoles, agentModelOverrides) or in another model's compactionModel —
# rename one and a missed reference fails at call time. So each label is
# migrated with its model in the same edit. One provider per HOST:PORT, so
# Dankclaw's second endpoint (:7771) is a separate block rather than a second
# model inside the :7770 one.
"llamacpp (dankserver)":
baseUrl: http://192.168.0.235:7770/v1
api: openai-completions
auth: none
models:
- id: frank-archon
# Model id renamed from frank-archon on 2026-10-08 (official
# unit-name scheme; the systemd service, scripts and runbooks keep
# the frank-archon name — service names are unchanged).
# Server-side compaction routes to compaction.remoteEndpoint in
# config.yml (192.168.0.143:7771 — frank-zealot's 3090); the
# compactionModel candidate keeps the wire model id valid there.
compactionModel: llamacpp (dankclaw-3090)/frank-zealot
name: "frank-archon"
# Dankserver: BOTH Radeon AI PRO R9700s (gfx1201, TP=2, wht6 wire) on
# the digest-pinned radiance image, plain `podman run` under a root
# unit. Payload, shape, eras, laws, rollback:
# serverAppConfigs-docs/LLM/frank-archon.md — and
# scripts/frank-archon.env is the authority for every number there.
# contextWindow MUST quote the engine's --max-model-len: radiance
# refuses a longer prompt and never truncates.
contextWindow: 200000
# maxTokens must survive the harness compaction gap AND the chars/4
# token-estimate under-run on code-heavy prompts. The clamp is
# max_tokens = min(maxTokens, contextWindow − estimate − 4096); the
# estimate under-runs by ~3 % on code. Compaction fires at 85 % of
# the window = 170,000 est; worst-case prompt + budget ≈
# 170,000 × 1.03 + 16,384 ≈ 191,500 ≤ 200,000 — the engine
# refuses a longer request, never truncates.
maxTokens: 16384
reasoning: true
# Text + image: the official FP8 checkpoint carries the vision
# tower (vision_config depth 27; the first blocks stay bf16 in
# modules_to_not_convert) and the plugin declares it
# (arch/common/rad_block_vit.h). Video preprocessing configs ship
# too; images are the contract that matters here.
input: [text, image]
compat:
# radiance's --reasoning-format defaults to auto: thinking
# comes back in `reasoning_content` (config.cpp). No parser
# flags exist or are needed.
reasoningContentField: "reasoning_content"
# The froggeric template does not gate reasoning_effort the way
# Qwen's shipped template did, and radiance special-cases only
# none/minimal (core/server/oai.cpp:609). The map stays as the
# zero-cost safety net, same as frank-zealot's.
reasoningEffortMap:
minimal: low
low: low
medium: medium
high: xhigh
max: xhigh
# Qwen recommended sampling. extraBody is merged last and wins.
# Every key is inside radiance's known-parameter list
# (core/server/oai.cpp:194-205); unknown keys are refused 400.
extraBody:
temperature: 1.0
top_p: 0.95
top_k: 20
min_p: 0.0
presence_penalty: 0.0
repetition_penalty: 1.0
chat_template_kwargs:
enable_thinking: true
preserve_thinking: true
"llamacpp (dankclaw)":
baseUrl: http://192.168.0.143:7770/v1
api: openai-completions
auth: none
models:
- id: frank-dragoon
# Model id renamed from frank-dragoon on 2026-10-08 (official
# unit-name scheme; the service/unit/scripts keep the frank-dragoon
# name — service names are unchanged).
name: "frank-dragoon (dankclaw-gpu)"
# Server-side compaction runs on the compaction.remoteEndpoint in
# config.yml (192.168.0.143:7771 — frank-zealot's 3090); this steers the
# compaction model candidate so the wire model id stays valid
# there even from a frank-dragoon session.
compactionModel: llamacpp (dankclaw-3090)/frank-zealot
# halogen flash-server on the Strix Halo iGPU. Payload, shape, eras,
# laws, rollback: serverAppConfigs-docs/LLM/frank-dragoon.md — and
# scripts/frank-dragoon.env is the authority for every number there.
# contextWindow sits deliberately BELOW the engine ceiling
# (HALOGEN_CTX): the clamp below leaves the gap that absorbs the
# harness's chars/4 under-count, so a window equal to the ceiling
# would make every long request a guaranteed 400.
contextWindow: 155648
# The clamp is max_tokens = min(maxTokens, contextWindow − est −
# 4096); the chars/4 est UNDER-counts the rendered prompt by ~3 %
# on code/agent traffic (measured 2026-10-07: est 152,938 ->
# server 157,388). Worst-case request = window − 4096 + 3 % est
# error ≈ 156.2k, inside the engine ceiling with ~44k of margin
# (robust to a ~25 % under-count). Compaction fires at 85 % of the
# window and rides on frank-zealot: input ≈ threshold −
# keepRecent(20k), comfortably inside its per-slot window.
# HALOGEN_MAX_TOKENS_CAP in frank-dragoon.env must stay >= this.
maxTokens: 45056
reasoning: true
# VISION ON as of 2026-10-06: the v2 vision tower loads beside the
# checkpoint (HALOGEN_VISION_TOWER; red-PNG probe verified on the
# card). image_url content parts only — the legacy top-level
# images field is the frank-zealot trap, do not repeat it here.
input: [text, image]
compat:
# flash-server emits thinking as `reasoning_content` — same
# field as every engine this endpoint has run, no harness
# change needed.
reasoningContentField: "reasoning_content"
# Same Qwen3.8 template family (it ships inside the tokenizer
# bundle): any reasoning_effort outside {xhigh, medium, low} is
# rejected, not clamped — the fold stays mandatory.
reasoningEffortMap:
minimal: low
low: low
medium: medium
high: xhigh
max: xhigh
# The card's thinking recipe, on the wire. The flash-server
# engine HAS a server-side sampler (HALOGEN_TEMPERATURE/TOP_P/
# TOP_K = 1.0 / 0.95 / 20 in frank-dragoon.env) — these match it,
# so per-request values are consistent, not load-bearing.
extraBody:
temperature: 1.0
top_p: 0.95
"llamacpp (dankclaw-3090)":
baseUrl: http://192.168.0.143:7771/v1
api: openai-completions
auth: none
models:
- id: frank-zealot
# Model id renamed from frank-zealot on 2026-10-08 (official
# unit-name scheme; the service/unit/scripts keep the
# frank-zealot name — service names are unchanged).
name: "frank-zealot (dankclaw-3090)"
# Server-side compaction routes to compaction.remoteEndpoint in
# config.yml (192.168.0.143:7771 — this endpoint); the
# compactionModel candidate keeps the wire model id valid there.
compactionModel: llamacpp (dankclaw-3090)/frank-zealot
# Dankclaw's RTX 3090 llama.cpp endpoint (PrismML fork build — the only
# loader for this payload's custom tensor type). Shape, payload, eras,
# laws, rollback: serverAppConfigs-docs/LLM/frank-zealot.md, and
# scripts/frank-zealot.env is the authority for every number there.
# contextWindow is the PER-SLOT window: llama.cpp divides --ctx-size
# across slots and answers a longer prompt with a 400, never a
# truncation, so this value must follow every reslice (live now:
# 2 x 262,144 over exact f16 KV, 68afc6d).
contextWindow: 262144
# Prompt + budget must fit inside the slot window; thinking counts
# against the budget. Compaction fires at 85 % of the window =
# 222,822 est; worst-case prompt + budget ≈ 222,822 × 1.03 +
# 16,384 ≈ 245,891 ≤ 262,144. This endpoint is the fleet's
# compaction hub: the widest window in the fleet.
maxTokens: 16384
reasoning: true
input: [text, image]
compat:
# llama.cpp --reasoning-format deepseek emits thinking as
# `reasoning_content` — the same field the MiMo/Ornith eras used;
# harness reads unchanged.
reasoningContentField: "reasoning_content"
# Bonsai-2's template DOES read reasoning_effort (the Qwen3.5-9B
# template did not — the map used to be inert here): it accepts ONLY
# xhigh (default), medium, low and calls raise_exception on anything
# else, so an unmapped harness level is a hard HTTP 500 on the role's
# first request, naming Jinja and not the model. The fold below is
# therefore load-bearing, identical to the frank-archon/dragoon law.
# llama.cpp passes chat_template_kwargs through to Jinja.
reasoningEffortMap:
minimal: low
low: low
medium: medium
high: xhigh
max: xhigh
# The payload's OWN sampling metadata (general.sampling.* in the
# GGUF): temperature 1.0 / top_p 0.95 / top_k 20 — thinking-mode
# recipe, the same trio the other Qwen3.8-family endpoints carry.
# (The old 0.6 was the Qwen3.5-9B publisher's card, not this file.)
# extraBody is merged last and wins over the harness default.
extraBody:
temperature: 1.0
top_p: 0.95
top_k: 20
min_p: 0.0
presence_penalty: 0.0
chat_template_kwargs:
enable_thinking: true
# The template DOES read preserve_thinking: when false it drops
# prior assistants' <think> blocks from history. Keep them —
# multi-turn tool traffic on this endpoint is the majority.
preserve_thinking: true
# Speech endpoint — the fleet's TTS, NOT a chat provider. `api:
# openai-speech` is a runner API (catalog kind `tts`), so this row never
# enters the chat picker, the Ctrl+P cycle, or any chat role: it is
# reachable only through the `speech` model role and the tts device.
# frank-tts (host port 7772) is the OpenAI /v1/audio/speech façade that
# resolves a voice BY NAME; its engine (frank-tts-engine, container-internal
# 8880, never published) is arm A qwentts.cpp 5916bf7 — measured 0.55-0.67
# RTF warm and 86-451 ms to the first audio byte on Dankclaw's CPU, with
# mainline llama-tts (TTS_BACKEND=llama-tts-cli) kept as the rollback.
# Transport contract, read out of the harness itself: the request body is
# {model, input, response_format, voice?, speed?}; `voice` is forwarded ONLY
# when explicitly set, and sampleRate/bitRate are REJECTED outright (the
# transport throws "openai-speech does not support sampleRate"), so the
# codec comes from the output_path suffix and the only tunable that matters
# is the voice name — and it comes from ONE place: the tool's `voice_id`
# argument. No setting feeds it (`speech.voice` is the speak-aloud Kokoro enum,
# `tts.localVoice` is the local backend's), so a call that omits voice_id arrives
# at 7772 with no `voice` key and the endpoint answers 400 "unknown voice None;
# available voices: narrator1, narrator2, narrator3". Say the voice in the call.
# WIRED 2026-10-18: `config.yml` `modelRoles.speech` is this row, flipped only
# after the service was deployed and answered real synthesis (two packs,
# different bytes, 24 kHz PCM16, RTF 0.57). Why the gate existed: `auth: none`
# makes this provider read as AVAILABLE even while the container is down, and an
# explicit speech role has NO fallback candidate, so a dead 7772 fails the device
# loudly instead of quietly narrating in Kokoro. Reverting is ONE key:
# `modelRoles.speech: local/kokoro`. `speech.voice` stays a Kokoro name either
# way — it was never this endpoint's voice.
# SCHEMA LAW, learned the hard way (2026-10-18): provider-level `api` must be
# a CHAT transport — the models.yml schema accepts only the chat/judge APIs
# there, and naming a runner API (`openai-speech`) at provider level fails the
# file's validation, which DISABLES EVERY custom provider: all three fleet
# endpoints vanish from the registry, not just this one (`omp models` prints
# "models.yml validation failed — custom providers disabled" and lists only
# local/kokoro). The runner api belongs on the MODEL entry only, which is what
# the block below does — `auth: none` covers the credential requirement, and
# `contextWindow`/`maxTokens` stay unset because the check only fires when they
# are provided (the bundled Kokoro row is null on both). `omp models --kind tts`
# still prints 128K/16K for this row — the registry fills display defaults — and
# the speech transport never reads them: its whole request body is the five
# fields named above. Verified 2026-10-18 with `omp models --kind tts` (row
# present) and `omp models` (frank-tts absent from the chat roster, all three
# fleet providers still listed).
"frank-tts (dankclaw)":
baseUrl: http://192.168.0.143:7772/v1
auth: none
models:
- id: frank-tts
name: "frank-tts (dankclaw) — cloned voices"
api: openai-speech
input: [text]