This commit is contained in:
lachtan
2026-09-16 08:56:28 +02:00
parent b0827177d2
commit 5407931bdc
4 changed files with 550 additions and 29 deletions

View File

@@ -260,12 +260,21 @@ Modely se přidávají jako položky do `model_presets` v `~/.nanobot/config.jso
4. **V chatu** (Telegram/WebUI) přepneš příkazem `/model <preset-name>`.
**Konvence pojmenování presetů:** krátký alias podle modelu — `kimi`, `kimi27`, `kimi3`, `glm`, `glm52`, `sonnet`, `haiku`, `gemini-flash`. (Dřív tu stálo `<model>-<provider>` jako `kimi-k2.6-openrouter`; reálný stav na serveru je od nějaké doby krátká forma, ověřeno 2026-07-27.)
**Konvence pojmenování presetů:** krátký alias podle modelu. Aktuální sada (ověřeno 2026-09-16): `glm`, `flash`, `glm52`, `glm51`, `kimi`, `kimi26`, `kimi3`, `sonnet`, `haiku`, `gemini-flash`, `gemini-flash-lite`. **Nepojmenovaný alias = aktuální generace** (`glm` = glm-5.3, `kimi` = kimi-k2.7-code), číslovaný = zamrzlá starší verze. (Dřív tu stálo `<model>-<provider>` jako `kimi-k2.6-openrouter`, pak `glm53`/`kimi27`; 2026-09-16 přejmenováno na současnou formu.)
**Parametry presetu:** `maxTokens` 16384 a `temperature` 0.1 napříč všemi presety. `contextWindowTokens` se drží na **~97 % reálného okna modelu** (rezerva na výstup), reálné okno se čte z `curl http://nvidia.hell:11434/api/show -d '{"model":"<id>"}'` → `model_info["<family>.context_length"]`. `reasoningEffort: null` = zachovat default providera (`schema.py:141`), explicitní hodnota jen kde ji chceme vynutit (`glm52: high`).
**Ollama gotcha:** `providers.ollama.apiBase` musí končit `/v1` (`http://nvidia.hell:11434/v1`) — viz [[Ollama provider potřebuje `/v1` suffix v `apiBase`]].
**Gotcha — přejmenování presetu validace nechytí.** `Config._validate_model_preset` (nanobot `config/schema.py`, model_validator mode="after") ověřuje při startu **jen** `agents.defaults.modelPreset` a `fallbackModels`. Preset předaný ad-hoc do `Nanobot.from_config(model_preset=...)` neprojde žádnou statickou kontrolou a spadne až za běhu v `Config.resolve_preset()` — u nočních cron jobů tedy ve 2:00 do logu a Telegramu, ne při editaci configu. **Po každém přejmenování presetu projdi tahle místa:**
- `skills/reflect/scripts/reflect_auto.py` → `MODEL_PRESET`
- `skills/compact-memory/scripts/compact_memory_auto.py` → `MODEL_PRESET`
- serverový `~/.nanobot/workspace/knowledge/models.md` — tabulka presetů, podle které si agent vybírá `/model`; neplatný alias tam je tichá chyba (agent zkusí neexistující preset)
- `skills/detach/` řešit nemusíš — preset resolvuje dynamicky přes `load_preset_names()`/`resolve_preset()`
Jednorázový check: `ssh nanobot@nanobot.hell 'grep -rn -e <starý-alias> ~/.nanobot/workspace/skills/ ~/.nanobot/workspace/knowledge/ ~/.nanobot/config.json'` (pozor na `__pycache__` — zastaralý `.pyc` matchne, ale nic neovlivní). Automatický validátor uživatel 2026-09-16 explicitně zamítl: Telegram alert z nočního běhu je jako detekce dostatečný. Plný záznam: history 2026-09-16.
## Ollama Cloud: některé modely jsou „extra usage only" (kimi-k3)
`kimi-k3:cloud` je v `api/tags` vidět a `/model kimi3` v nanobotu se přepne bez chyby, ale **každé volání skončí HTTP 402**:
@@ -792,7 +801,7 @@ Nanobot má **hardcoded default `context_window_tokens = 65_536`** pro `ModelPre
Nastaveno 2026-06-02 per-preset na reálné limity modelů (kimi-k2.6 / qwen3.5 / nemotron-3-super 262144, minimax-m2.7 204800, glm-5.1 196608, deepseek-v4-flash 1048576) + `maxTokens` 16384. **Bez restartu** — `modelPresets` se hot-reloadují (viz sekce „Kdy je a není potřeba restart"). U `:cloud` modelů hostí kontext Ollama cloud, takže `contextWindowTokens` reálně rozšíří budget — není to lokální `num_ctx` žeroucí RAM. Plný záznam: history 2026-06-02.
**Gotcha — `agents.defaults.contextWindowTokens` je zavádějící číslo.** V serverovém `config.json` je `65536`, ale to platí jen když preset vlastní hodnotu nemá. Reálné okno aktuálního defaultu (**`glm53`: 976 000**, `glm52`/`glm-flash` 976 000, `kimi3` 1 020 000, `sonnet`/`gemini-flash` 256 000) je ~15× větší, než `defaults` napovídá. **Než z 65k něco odvodíš, přečti `model_presets`, ne `agents.defaults`** — na tomhle jsem 2026-09-02 postavil celý (zamítnutý) rozpočet velikosti pro `/project`. Limit, který v praxi kouše, je `maxToolResultChars: 16000`, ne okno.
**Gotcha — `agents.defaults.contextWindowTokens` je zavádějící číslo.** V serverovém `config.json` je `65536`, ale to platí jen když preset vlastní hodnotu nemá. Reálné okno aktuálního defaultu (**`glm`: 976 000**, `flash`/`glm52` 976 000, `kimi3` 1 020 000, `sonnet`/`gemini-flash` 256 000) je ~15× větší, než `defaults` napovídá. **Než z 65k něco odvodíš, přečti `model_presets`, ne `agents.defaults`** — na tomhle jsem 2026-09-02 postavil celý (zamítnutý) rozpočet velikosti pro `/project`. Limit, který v praxi kouše, je `maxToolResultChars: 16000`, ne okno.
**Důsledky (trade-off, ne čistá výhra):**
@@ -1137,7 +1146,7 @@ Naměřeno na reálném destilátu (90 kB promptu → 75 135 tokenů podle tikto
## `contextWindowTokens` presetu přebíjí `agents.defaults`
`agents.defaults.contextWindowTokens` je 65536, ale preset `glm53` má 976000 a **vyhrává**`agent/loop.py:476` (`context_window_tokens = extra.pop(...) or resolved.context_window_tokens`). Efektivní input budget = `contextWindowTokens - maxTokens - 1024` (`SNIP_SAFETY_BUFFER`, `agent/context_governance.py:105`), tedy ~958k tokenů pro glm53.
`agents.defaults.contextWindowTokens` je 65536, ale preset `glm` má 976000 a **vyhrává**`agent/loop.py:476` (`context_window_tokens = extra.pop(...) or resolved.context_window_tokens`). Efektivní input budget = `contextWindowTokens - maxTokens - 1024` (`SNIP_SAFETY_BUFFER`, `agent/context_governance.py:105`), tedy ~958k tokenů pro `glm`.
## Velká zpráva projde, `snip_history` krátí jen historii
@@ -1302,3 +1311,54 @@ per model. Ověřeno 2026-09-15.
→ Atribuce spotřeby na session jde jen **časovou korelací** (timestampy v `sessions/*.jsonl`
a `Processing message from …` v journalu) proti řadě vzorků z `db/ollama_usage.sqlite`.
Ověřeno 2026-09-15, zdroj: [[plans/ollama-usage-poller.md]] sekce Revize.
---
## Ollama session okno: 5 h kotvených prvním requestem, ne pevná mřížka
Okno **nezačíná na pevné mřížce** — začíná prvním requestem po vypršení
předchozího (jako 5h sessions v Claude Code). Naměřeno 2026-09-15: usage
zůstala na `0.077`/21 req přes 05:00 UTC (pevná mřížka by ji tam vynulovala
a poller by to zapsal) a resetovala se až s requestem v 06:00, po 93minutové
pauze. Rekonstrukce aktivity z `sessions/*.jsonl` dává souvislý řetězec
00:0005:00, pak 06:0011:00 UTC.
Délka 5 h je z primárního zdroje
[transparent-pricing](https://ollama.com/blog/transparent-pricing) („no 5-hour
or weekly limits" je to, co **nové** plány zrušily; tenhle klíč je pořád má).
Že jde o okno a ne rolling counter je taky měřené — pokles `0.077`/21 → `0.0`/`{}`
naráz, rolling by se rozpadal postupně.
**Praktický důsledek:** konec okna = poslední pozorovaný přechod v `samples`
+ 5 h. Za konec se nesmí extrapolovat — další okno začne až dalším requestem,
takže čas neexistuje, dokud request nepřijde. Detail: history 2026-09-15 10:15.
**Pozor na past:** crony nanobota běží na celé hodiny (Dream po 2 h atd.), takže
první request po pauze často padne na celou hodinu. Hranice pak *vypadají* jako
pevná mřížka, i když nejsou.
**Zamítnuto:** kalibrace fáze průnikem kandidátů modulo 300 min. Stála na
předpokladu pevné mřížky a navíc potřebovala víc pozorování, než začala hlásit
cokoli. Nahrazeno výše. Vedlejší poznatek, který z ní zbyl: **5 h nedělí 24 h**,
takže „mřížka 00/05/10/15/20 UTC" nemůže být stálá tak jako tak.
## `limits.session.usage` == procento na dashboardu; countdown na webu ne
API `2.3 %` sedělo přesně s tím, co uživatel viděl na webu. **Countdown na webu
je ale ke kalibraci nepoužitelný** — zaokrouhluje neznámo jak: v 06:58 UTC
ukazoval „4 hodiny" a v 07:05 „3 hodiny". Proto skill tiskne i konkrétní čas,
ne jen „resets in X".
## Zamítnuto: heartbeat v usage polleru
Nápad zapisovat vzorek i beze změny (aby mezera v `samples` znamenala výpadek)
je **zbytečný** — interval `(poslední před, první po]` kolem resetu je pravdivý
bez ohledu na to, jestli poller běžel; výpadek ho jen rozšíří. Uživatel ho
zamítl a měl pravdu: DB zůstává čistě změnová.
## `uv` není v PATH při neinteraktivním SSH
`ssh nanobot@nanobot.hell 'uv run …'` selže na `uv: command not found` — je
v `~/.local/bin`, který se nenačte. Crontab to řeší vlastním řádkem
`PATH=/home/nanobot/.local/bin:/usr/bin:/bin`. Při ručním spuštění přes SSH
předřadit `export PATH=/home/nanobot/.local/bin:$PATH`.