config.yml: vision -> llamacpp (dankclaw)/frank-large:auto, tiny -> llamacpp (dankserver)/frank-small:off, task -> llamacpp (dankclaw)/frank-large:medium (was flm dankclaw-npu), matching the flm (dankclaw-npu) provider removal in models.yml. Memories/managed skills: rollouts and learned notes from the frank-large KV-pool + sampler work and the noctalia recolor; merged the duplicate noctalia-palette-recolor skill into noctalia-custom-palette-recolor (adds the dotfiles-tracking step and the +show-config delta gotcha) and dropped the superseded legacy memory skills whose ghostty USR1 reload recipe is wrong for this fleet.
3.1 KiB
name, description
| name | description |
|---|---|
| omp-per-model-sampler-config | Set per-model sampler params and preserve_thinking in OMP's models.yml via compat.extraBody, and verify the exact wire body with an echo-capture profile. |
OMP Per-Model Sampler Config (compat.extraBody)
~/.omp/agent/models.yml has no per-model sampler keys. Sampling is global (config.yml: temperature, topP, topK, minP, presencePenalty, repetitionPenalty; default -1 = not sent). The per-model hook is compat.extraBody.
Why it works
applyOpenAIExtraBody runs last in the openai-completions builder — after applyChatCompletionsCompatPolicy — via Object.assign(params, extraBody). So extraBody overrides global settings and compat-policy output.
Recipe
Use wire names, not OMP camelCase:
- id: frank-large
compat:
reasoningEffortMap:
max: xhigh
extraBody:
temperature: 1.0
top_p: 0.95
top_k: 20
min_p: 0.0
presence_penalty: 0.0
repetition_penalty: 1.0
preserve_thinking: true
Two traps
preserve_thinkingis not user-settable.qwenPreserveThinkingis auto-derived inbuildOpenAICompatfrom the auto-detectedthinkingFormat+ local baseUrl, beforeapplyCompatOverrides. Settingcompat.thinkingFormat: qwenin models.yml does not enable it. Custom-named models (frank-large) match no Qwen id pattern → useextraBody: {preserve_thinking: true}.- Never put
chat_template_kwargsinextraBody.Object.assignis shallow — it replaces the whole object and silently drops thereasoning_effortkwarg the compat policy set. Top-levelpreserve_thinkingis honoured by halogen; use that.
Gotcha: silent greedy decode
halogen-flash-server has no server-side sampler defaults — temperature absent or 0 = greedy. If OMP sends nothing, the endpoint decodes greedy while looking configured.
Verify the exact wire body (echo-capture)
Don't trust the YAML — capture what OMP actually emits.
- Echo server on
127.0.0.1:18099that dumps the JSON body to a file and returns a cannedchat.completion(includereasoning_contentso thinking paths exercise). - Copy the real models.yml into a throwaway profile with only the baseUrl swapped:
sed 's|http://<host>:7770/v1|http://127.0.0.1:18099/v1|' \ ~/.omp/agent/models.yml > ~/.omp/profiles/wiretest/agent/models.yml - Run and inspect:
Confirm every intended field is present with the right value.
omp --profile wiretest --model "<provider>/<model>" -p "hi" \ --no-tools --no-session --no-extensions --no-skills --no-rules jq 'del(.messages, .tools)' last-body.json
Verify a field is honoured, not just accepted
Unknown fields often return 200 anyway. Prove behavior with a prompt-token delta: replay an assistant turn carrying a long reasoning_content, then compare usage.prompt_tokens with the flag true vs false. A large delta means the field changed template rendering; zero delta means it was ignored.
Cleanup
Trash the probe profile and echo server (profiles/.AGENTTRASH), never rm.