Spaces:
Paused
Paused
| 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í `<tool_call>` | **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/<repo_id>` (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 <model> --port 8001 … (4× A100, TP=4) │ | |
| │ ▲ modely: /repos/<repo_id> (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://<space>.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://<space>.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://<space>.hf.space/admin/settings | |
| # stav / reload / stop enginu, logy, presety | |
| curl -H "Authorization: Bearer $TOKEN" https://<space>.hf.space/admin/engine/status | |
| curl -X POST -H "Authorization: Bearer $TOKEN" https://<space>.hf.space/admin/engine/reload | |
| curl -H "Authorization: Bearer $TOKEN" "https://<space>.hf.space/admin/logs?source=engine&lines=100" | |
| curl -H "Authorization: Bearer $TOKEN" https://<space>.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 <owner>/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 `<think>` | | |
| | 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_<ROLE>_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_<role>_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_<role>_steps`), | |
| - **přepsat systémový prompt** (`subagent_<role>_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_<server>_<tool>` 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 | |