--- title: CodeAgent emoji: 🛠️ colorFrom: indigo colorTo: purple sdk: docker app_port: 7860 pinned: false --- # CodeAgent v5 — AI kódovací agent s lokální vLLM inference a nastavením za běhu Agentní chat běžící na HF Space **4× NVIDIA A100 80GB (320 GB VRAM, 568 GB RAM, 48 vCPU)**. Inference probíhá **lokálně ve Space** přes vLLM — žádné externí LLM API není potřeba (volitelně hybrid fallback přes HF router). ## Co je nové ve v5 | Oblast | v4 | v5 | |---|---|---| | Inference | in-process `vllm.LLM` | **`vllm serve` subprocess** (OpenAI server) řízený aplikací | | Tool calling | ruční parsování `` | **nativní** (`--enable-auto-tool-choice` + parser dle modelu) | | Změna nastavení | HF Variables ⇒ **restart Space** | **tab ⚙️ Nastavení / `/admin/settings` — za běhu, bez restartu** | | Výměna modelu | rebuild/restart | **hot-swap**: engine se přenačte na pozadí, UI/API běží dál | | Modely | download při buildu (limit disku) | **read-only volume mounty** `/repos/` (bez stahování) | | Pád enginu | pád celé aplikace | **watchdog** — automatický restart enginu (max 3×) | | Stack | vLLM 0.23, Gradio 5 | **vLLM 0.25, Gradio 6, huggingface_hub 1.x, hf_transfer** | | Režimy | single / dual / hybrid | single / hybrid (dual odstraněn — na 4×A100 je lepší 1 velký model) | ## Architektura ``` ┌────────────────────────── HF Space (Docker) ──────────────────────────┐ │ uvicorn app:app (port 7860) │ │ ├─ Gradio 6 UI: 💬 Chat · ⚙️ Nastavení (runtime) · 📜 Logy │ │ ├─ FastAPI: /health · /v1/* (OpenAI-kompatibilní) · /admin/* │ │ ├─ SettingsManager ⇒ /data/settings.json (bucket) | .agent/ │ │ └─ VLLMEngine (subprocess manager + watchdog) │ │ └─ vllm serve --port 8001 … (4× A100, TP=4) │ │ ▲ modely: /repos/ (RO volume) | HF download │ └───────────────────────────────────────────────────────────────────────┘ ▲ nástroje (run_command, read_file, …) přes tunel Open Terminal / runner na uživatelově Macu (LOCAL_RUNNER_URL) ``` - **Aplikace startuje okamžitě** — UI a `/health` jsou dostupné hned, model se načítá na pozadí (stav vidíš v UI i v `/health.engine`). - **Změna enginových polí** (model, kvantizace, TP, kontext…) spustí reload subprocessu na pozadí. **Space se nerestartuje.** - **Ostatní pole** (limity agenta, runner URL, cache, log level…) platí okamžitě. ## Nastavení za běhu ### UI Tab **⚙️ Nastavení**: presety pro 4×A100, formulář všech polí, stav enginu (auto-refresh 5 s), tlačítka Uložit/Reload/Stop. Tab **📜 Logy**: tail logu vLLM i aplikace. ### API (Bearer `AGENT_API_TOKEN`) ```bash # přečíst aktuální nastavení curl -H "Authorization: Bearer $TOKEN" https://.hf.space/admin/settings # změnit model za běhu (spustí reload enginu na pozadí) curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"model": "Qwen/Qwen3-235B-A22B-Instruct-2507-FP8", "max_model_len": 65536}' \ https://.hf.space/admin/settings # jen instant pole — bez reloadu curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"max_steps": 40, "temperature": 0.1}' \ https://.hf.space/admin/settings # stav / reload / stop enginu, logy, presety curl -H "Authorization: Bearer $TOKEN" https://.hf.space/admin/engine/status curl -X POST -H "Authorization: Bearer $TOKEN" https://.hf.space/admin/engine/reload curl -H "Authorization: Bearer $TOKEN" "https://.hf.space/admin/logs?source=engine&lines=100" curl -H "Authorization: Bearer $TOKEN" https://.hf.space/admin/presets ``` Persistence: `/data/settings.json`, pokud je připojen storage bucket (doporučeno — přežije restart), jinak `.agent/settings.json` (ephemeral). Env Variables slouží jen jako výchozí hodnoty při úplně prvním startu. ## Modely na 4×A100 (320 GB VRAM) A100 = Ampere: FP8 checkpointy běží přes **FP8-Marlin** (weight-only). Ephemeral disk je jen ~50 GB ⇒ velké modely **mountuj jako volume**: ```bash python3 scripts/space_ctl.py mount Qwen/Qwen3-Coder-30B-A3B-Instruct python3 scripts/space_ctl.py mount Qwen/Qwen3-235B-A22B-Instruct-2507-FP8 python3 scripts/space_ctl.py volumes # výpis ``` (Mount změní konfiguraci Space ⇒ jednorázový restart. Poté už přepínáš modely za běhu v Nastavení.) ### Persistentní stahování vah: Storage Bucket (read-write) Alternativa k RO mountům — **HF Storage Bucket** připojený read-write. Stažené váhy pak přežijí restart Space a neomezuje je ~50GB ephemeral disk: ```bash python3 scripts/space_ctl.py create-bucket codeagent-data python3 scripts/space_ctl.py mount-bucket /codeagent-data /data ``` - Bucket na `/data` se **detekuje automaticky**: váhy se stahují do `/data/models` (vLLM `--download-dir`, Xet high-performance transfer), `settings.json` do `/data`, a navíc se tam persistují **`VLLM_CACHE_ROOT`** (torch.compile artefakty — další starty Space přeskočí kompilaci) a **`HF_HOME`** (tokenizery, configy, remote-code moduly). - Adresář lze změnit **za běhu** polem **`download_dir`** (tab Nastavení nebo `POST /admin/settings {"download_dir": "/muj-bucket/models"}`); prázdná hodnota = auto-detekce. Env default: `MODEL_DOWNLOAD_DIR`. - Kdy co: **RO model mount** = okamžitá dostupnost bez stahování (oficiální repo váhy); **RW bucket** = univerzální cache pro libovolné modely vč. vlastních fine-tunů, platí se za uložená data (viz hf.co/storage). | Preset | Váhy | Poznámka | |---|---|---| | **Qwen3-Coder-Next-FP8** (80B-A3B) | ~80 GB | **výchozí** — SWE-bench Verified ~70 %, 256K ctx, jen 3B aktivních | | Qwen3-Coder-Next (BF16) | ~159 GB | plná přesnost téhož | | MiniMax-M2.7 (FP8, 229B-A10B) | ~230 GB | nejsilnější agentic coder, co se vejde; ctx ~96K, nutný mount | | Qwen3.5-122B-A10B-FP8 | ~127 GB | nejnovější generace (04/2026), hybridní thinking | | Qwen3.5-397B-A17B-GPTQ-Int4 | ~236 GB | oficiální Int4 vlajkové lodi; nutný mount | | Devstral-2-123B (dense) | ~256 GB | Mistral SWE specialista; ctx ~48K, nutný mount | | GLM-4.7-Flash (31B) | ~62 GB | rychlý malý agentní model (01/2026) | | Qwen3-Coder-30B-A3B (BF16) | ~61 GB | prověřená stabilní jistota | | Qwen3-Coder-30B-A3B-FP8 | ~31 GB | minimum VRAM, plný 256K kontext | | Qwen3-235B-A22B-Instruct-2507-FP8 | ~236 GB | starší vlajková loď; ctx ~64K, nutný mount | | GLM-4.5-Air-FP8 | ~110 GB | silný agentní model s thinking | | Qwen3-32B | ~66 GB | dense reasoning s `` | | gpt-oss-120b | ~63 GB | Harmony formát; optimalizován pro Hopper | Nevejdou se (07/2026): GLM-5.x (756 GB), GLM-4.7 (362 GB), MiniMax-M3 (444–854 GB), Kimi-K2.x (595+ GB), DeepSeek-V3.x — pro ně slouží hybrid režim. > **Kimi-K2.7-Code lokálně neběží**: 1.06T parametrů, nativní INT4 checkpoint > má 595 GB (> 320 GB VRAM i po jakékoli další kvantizaci). Je dostupný jako > výchozí `kimi_model` v **hybrid** režimu — volá se přes HF router API > (tag `[kimi]`, auto-routing těžkých dotazů, fallback při pádu enginu). ## Proměnné prostředí (jen výchozí hodnoty + secrets) | Proměnná | Popis | Výchozí | |---|---|---| | `HF_TOKEN` *(secret)* | token pro gated modely + HF router | — | | `AGENT_API_TOKEN` *(secret)* | Bearer pro `/v1/*` a `/admin/*` | — | | `GRADIO_AUTH` *(secret)* | `user:heslo` pro UI | — | | `LOCAL_RUNNER_TOKEN` *(secret)* | Bearer pro runner | — | | `MODEL_PRIMARY` | výchozí model | `Qwen/Qwen3-Coder-Next-FP8` | | `AGENT_MODE` | `single` / `hybrid` | `single` | | `ROUTER_MODE` | hybrid routing: `ai` / `keywords` | `ai` | | `TENSOR_PARALLEL_SIZE` | počet GPU | `4` | | `GPU_MEMORY_UTILIZATION` | podíl VRAM | `0.92` | | `MAX_MODEL_LEN` | kontext | `131072` | | `QUANTIZATION` | `auto`/`none`/`fp8`/`awq`… | `auto` | | `MODEL_DOWNLOAD_DIR` | adresář pro stahované váhy (prázdné = auto `/data/models` → `/app/cache/models`) | — | | `MODEL_REVISION` | pin na commit/tag HF repa (doporučeno u `trust_remote_code`) | — | | `TOOL_CALL_PARSER` / `REASONING_PARSER` | `auto` = dle modelu | `auto` | | `KIMI_MODEL` | hybrid fallback (HF router) | `moonshotai/Kimi-K2.7-Code` | | `LOCAL_RUNNER_URL` | URL Open Terminal tunelu | — | | `PRELOAD_MODEL` | načíst model hned po startu | `1` | | `ENGINE_STARTUP_TIMEOUT` | limit načítání modelu (s) | `2700` | | `CHAT_VERBOSITY` | `full` / `compact` / `final` | `full` | | `CONTEXT_COMPACTION` | `trim` / `off` | `trim` | | `SUBAGENT__ENABLED` / `_PROMPT` | konfigurace sub-agentů | zapnuto / výchozí | | `MAX_STEPS` a další limity | viz `settings.py` | | Kompletní seznam runtime polí: `GET /admin/settings` nebo `settings.py`. ## Hybrid režim: AI routing složitých úloh V `agent_mode=hybrid` rozhoduje o každé zprávě router, zda ji řeší rychlý **lokální model**, nebo velký **API model** (`kimi_model` přes HF router, výchozí Kimi-K2.7-Code — 1T model, který se na 320 GB VRAM nevejde lokálně): 1. **Explicitní tagy** mají absolutní přednost: `[kimi]`/`[api]` ⇒ API, `[local]`/`[qwen]` ⇒ lokální. 2. **Délka kontextu** nad `local_context_limit` ⇒ API. 3. **AI klasifikace** (`router_mode=ai`, výchozí): sám lokální model dostane krátký klasifikační prompt (~8 output tokenů, temperature 0) a rozhodne LOCAL vs API — API jen pro architekturu/design, deep debugging, security audity, velké refaktory a nejednoznačná zadání vyžadující těžké plánování. Při chybě/nejednoznačné odpovědi fallback na keywords. 4. **Keywords** (`router_mode=keywords`): statická pravidla bez AI. API model slouží zároveň jako **failover** — když lokální engine spadne nebo se právě reloaduje, smyčka automaticky přepne na API a pokračuje. ## Sub-agenti: plná runtime konfigurace `delegate_task` deleguje na role `explorer` / `coder` / `reviewer`. V tabu **🤝 Sub-agenti** (nebo přes `/admin/settings`) lze **za běhu** u každé role: - **zapnout/vypnout** (`subagent__enabled`) — vypnutá role zmizí z nabídky nástroje `delegate_task` (enum se generuje dynamicky; bez zapnutých rolí se nástroj vynechá úplně), - nastavit **max kroků** (`max__steps`), - **přepsat systémový prompt** (`subagent__prompt`, prázdné = výchozí). Tokeny sub-agentů se počítají do statistik nadřazeného běhu. ## Výřečnost chatu (`chat_verbosity`) | Hodnota | Chování | |---|---| | `full` (výchozí) | nástroje + argumenty + JSON výsledky + 📊 token patička | | `compact` | jen jednořádkové záznamy nástrojů + patička | | `final` | pouze finální odpověď (během práce nenápadný ⏳ heartbeat) | Platí okamžitě, ovlivňuje i obsah odpovědí `/v1/chat/completions` (agentní režim). ## Tokeny a inteligentní správa kontextu **Počítání tokenů** — přesná čísla z `usage` každé odpovědi (vLLM i HF router), žádné odhady: per-turn patička v chatu (volání, vstup/výstup, aktuální velikost kontextu) a globální součty od startu v `/health.tokens` a v UI statusu, rozpad podle zdroje (`local` / `api` / `router` / `passthrough`). Cache hity se nepočítají. `/v1` odpovědi vracejí skutečné `usage` za celý agentní běh. **Kompakce kontextu** (`context_compaction=trim`, výchozí) — drží kontext pod budgetem (`context_budget_tokens`, 0 = auto z `max_model_len − max_output_tokens − 2048`) a šetří KV cache: 1. **Stárnutí**: staré výsledky nástrojů (mimo posledních `context_keep_last_steps` bloků) se zkrátí na `tool_result_aged_chars` znaků — plné výpisy ztrácejí hodnotu, jakmile na ně agent zareagoval. 2. **Vypouštění**: pokud se stále nevejde, nejstarší celé kroky konverzace se nahradí souhrnnou poznámkou (model ví, že historie byla zkrácena). Nikdy se nekompaktuje: systémový prompt, zadání úlohy a posledních N bloků. Kompakce nikdy nerozbije tool-calling strukturu (vypouští jen celé bloky) a v chatu se hlásí řádkem `🧹 Kontext zhutněn (~X tokenů ušetřeno)`. ## Externí tool servery (MCP) Tab **🧰 Externí nástroje** připojuje za běhu libovolný **MCP server** (Model Context Protocol, Streamable HTTP) — jeho nástroje dostane hlavní agent okamžitě jako `ext__` funkce, bez restartu: - **Přidání/editace/odebrání** serverů (jméno, URL, Bearer token, timeout), per-server **zapnout/vypnout** a filtr `allowed_tools` (čárkami). - **Hledání v oficiálním registru** (registry.modelcontextprotocol.io — metaregistr Anthropic/GitHub/Microsoft/PulseMCP) přímo z UI/API; vrací servery s hotovým HTTP endpointem. - **Katalog ověřených veřejných serverů**: Context7 (dokumentace knihoven), DeepWiki (Q&A nad GitHub repy), Hugging Face Hub, Microsoft Learn, Cloudflare docs — připojitelné na jeden klik, bez klíčů. - Transport dle spec 2025-06-18: JSON i SSE odpovědi, `Mcp-Session-Id` session handling s automatickou re-inicializací. - API: `GET/POST /admin/toolservers`, `POST /admin/toolservers/delete|refresh`, `GET /admin/toolservers/registry?q=…`, `GET /admin/toolservers/catalog`. - Persistence `/data/toolservers.json` (bucket) nebo `.agent/`. - Bezpečnost: výstupy externích nástrojů jsou **nedůvěryhodná data**; externí nástroje má jen hlavní agent (sub-agenti ne), výsledky ořezává `tool_result_max_chars`. Připojuj jen servery, kterým věříš. Další zdroje serverů: [PulseMCP](https://www.pulsemcp.com/servers) (10k+), [Smithery](https://smithery.ai) (hosting + HTTP endpointy), [Glama](https://glama.ai/mcp/servers), [mcp.so](https://mcp.so), [Awesome MCP Servers](https://github.com/punkpeye/awesome-mcp-servers). ## OpenAI-kompatibilní API - `POST /v1/chat/completions` s `model="code-agent"` ⇒ plná agentní smyčka (nástroje, sub-agenti, paměť). - `model="code-agent-llm"` (nebo `"raw"`) ⇒ **passthrough přímo na lokální model** bez agentní smyčky — pro OpenWebUI jako čistý chat model. - `GET /v1/models`, `GET /health` (bez auth). ## Nasazení ```bash cd agent # 1) nastav Variables/Secrets (jen první inicializace) python3 scripts/init_space.py # 2) namountuj modely, které chceš mít k dispozici python3 scripts/space_ctl.py mount Qwen/Qwen3-Coder-30B-A3B-Instruct # 3) push kódu do Space (build ~10 min; modely se nestahují) git push # 4) tunel na runner (Mac) ./scripts/tunnel.sh ``` Ovládání: `space_ctl.py start|stop|status|stats|logs|price|volumes|mount|unmount`. ## Testy ```bash pip install -r requirements.txt pytest pytest tests/ -v ``` Testy běží bez GPU — vLLM subprocess je nahrazen mock OpenAI serverem (`tests/mock_vllm.py`), takže se ověřuje i celý flow „změna nastavení ⇒ hot-swap enginu bez restartu aplikace". ## Sub-agenti a nástroje (beze změny) - `delegate_task(role="explorer"|"coder"|"reviewer")` s vlastními limity kroků. - Nástroje přes Open Terminal API na `LOCAL_RUNNER_URL`: `run_command`, `git_command`, `read_file`, `write_file`, `replace_in_file`, `search_code`, `list_files` + trvalá paměť `remember`/`recall` (`.agent/memory.md`). Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference