chore: auto-commit from dashboard

This commit is contained in:
2026-07-12 19:28:42 +00:00
parent 80eb8034b3
commit 4d2dbfb8a7
22 changed files with 582 additions and 520 deletions

View File

@@ -0,0 +1,85 @@
# Cactus Needle — evaluare model de function calling pentru pre-routing local (2026-07-12)
Spike de testare: se poate folosi un model mic de function calling (rulat local pe CPU) ca pre-router înaintea `claude_session.py`, ca să interceptăm intenții simple (weather, add task, note, query roa2web) fără să consumăm din rate limit-ul Claude?
## Context — de ce s-a pornit testul
`router.py` rutează doar pe prefix (`/`, text-keywords) — orice mesaj care nu e slash-command pornește un turn Claude CLI complet, inclusiv întrebări triviale ("ce vreme e", "cât e în casă"). Asta consumă rate limit pe Anthropic subscription (nu cost — vezi [[user_anthropic_subscription]]) chiar și pe intenții simple, repetitive. Video sursă care a declanșat testul: [Cactus Needle — The 26M Function Calling Model](https://youtu.be/tt9UJ0NiOzU) (notă: [[2026-07-12_cactus-needle-26m-function-calling-model]]).
## Ce s-a testat
Model: [`Cactus-Compute/needle`](https://huggingface.co/Cactus-Compute/needle) — 26M parametri, "Simple Attention Network" (attention+gating, fără FFN/MLP), distilat din Gemini 3.1 Flash Lite. Repo: [cactus-compute/needle](https://github.com/cactus-compute/needle).
- Instalare izolată în `/tmp/needle-test` (venv separat, nu a atins `.venv` de producție din echo-core). JAX/Flax/Optax, CPU-only.
- Checkpoint `needle.pkl` (~50MB fp32) descărcat direct de pe HF, fără antrenare/fine-tuning suplimentar.
- Tools JSON definite manual, mimând funcții reale Echo: `get_weather`, `add_task`, `create_note`, `get_treasury_balance` (analog roa2web), `set_timer`.
- 10 query-uri de test, engleză + română, incluzând și mesaje conversaționale banale (fără tool corespunzător).
## Rezultate
- **Recunoaștere corectă pe intenții clare, inclusiv română** (deși modelul e antrenat mai ales pe engleză): "Ce vreme e la Cluj?" → `get_weather(location=Cluj)`, "Cât e în casă?" → `get_treasury_balance(account=casa)`, "Pune un timer de 10 minute" → `set_timer(duration="10 minutes")`.
- **Fals pozitiv critic pe conversație casual**: "Bună, ce mai faci?" a declanșat `get_treasury_balance(account="bun")` — tool call inventat pe un salut banal. Traficul Echo e majoritar conversație, nu comenzi, deci acest failure mode lovește direct fluxul principal.
- Query ambiguu ("Cât e în bancă?") a generat două tool calls duplicate cu argumente diferite, nu un răspuns curat.
- Extragere de conținut incompletă pe note mai lungi (a păstrat doar titlul, a pierdut restul textului).
- Pe query clar conversațional/tehnic ("Explică-mi recursivitatea în Python") a răspuns corect cu listă goală — fără tool call inventat.
- **Latență reală pe CPU: 3-9s per query** (nu ms-urile din marketing) — setup-ul default din repo nu are encoder JIT-cache-uit/warm, ar necesita inginerie suplimentară (padding fix + server ținut pornit) ca să se apropie de cifrele oficiale (1200 tok/s pe device).
## Comparație cu alternative
- **Qwen3-0.6B** (benchmark extern, [heyneo.com](https://heyneo.com/blog/needle-26m-vs-qwen3-0.6b-cpu-function-call-benchmark), 4-core CPU, 50 query-uri / 5 nivele de dificultate, netestat local): acuratețe mai bună decât Needle cu prompt bun (84% vs 72% overall), dar **4-6x mai lent** (~40-56s/query vs ~7-17s Needle) și cu **exact același failure mode** — pe query "What's 2+2?" a inventat un tool call `run_command`.
### Hammer2.1-0.5b — testat local (2026-07-12)
[`MadeAgents/Hammer2.1-0.5b`](https://huggingface.co/MadeAgents/Hammer2.1-0.5b) — **0.5 miliarde parametri, ~19x mai mare decât Needle** (26M). Fine-tune pe Qwen2.5-Coder-0.5B-Instruct, folosește "function masking" pentru robustețe la tool calling (arxiv 2410.04587). Rulat local pe CPU (torch+transformers, venv izolat `/tmp/hammer-test`), **exact aceleași 10 query-uri și tool-uri** ca la testul Needle, pentru comparație directă.
- **Fixează problema critică de la Needle**: pe ambele mesaje conversaționale ("Bună, ce mai faci?" și "Explică-mi recursivitatea") a răspuns corect cu listă goală — zero fals-pozitive pe chit-chat, spre deosebire de Needle care a inventat un tool call pe salut.
- Dar are propriile probleme:
- **Fals-negativ pe RO**: "Ce vreme e la Cluj?" (română) → listă goală, deloc recunoscut — deși Needle a rezolvat corect exact acest query. Query-ul englezesc echivalent a mers corect.
- **Halucinație de conținut, nu doar omisiune**: la `create_note` pentru "intalnirea de azi cu Andrei", a generat `content: "Please check the weather report tomorrow."` — text complet inventat, fără nicio legătură cu query-ul. Mai grav decât Needle, care măcar a păstrat conținut relevant (incomplet, dar corect tematic).
- **Nu extrage argumentul `account`** la `get_treasury_balance` — "Cât e în casă?" și "Cât e în bancă?" au produs exact același output gol (`arguments: {}`), pierzând distincția casă/bancă pe care Needle o prindea corect.
- **Dimensiune pe disc**: checkpoint ~950MB (fp32) vs ~50MB la Needle — proporțional cu raportul de parametri.
- **Latență**: 2.4-5.6s/query (comparabil cu Needle, 3-9s), plus ~24s load inițial al modelului (Needle: 2.4s).
### Qwen2.5-0.5B-Instruct — testat local (2026-07-12)
[`Qwen/Qwen2.5-0.5B-Instruct`](https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct) — 0.5B parametri, model general-purpose foarte popular (nu specializat pe function calling), cu suport tool calling nativ prin chat template. Testat cu același set de 10 query-uri.
- Corect pe weather RO **și** EN (mai bine ca Hammer, care rata varianta RO).
- **Fals-negativ pe task RO**: "Adaugă un task să sun clientul mâine" → nu a emis niciun tool call, a răspuns cu o întrebare de clarificare în engleză. Varianta EN a mers corect.
- `create_note` RO: nume+titlu corecte, dar a omis complet argumentul `content` (obligatoriu) — tool call incomplet.
- **Cel mai prost rezultat din tot testul**: "Cât e în casă?" → refuz ("I can't assist with that"); "Cât e în bancă?" → răspuns complet halucinat și incoerent, **"NO, CAT IS NOT IN THE BANK"** — a confundat "cât" (românește) cu "cat" (pisică, engleză) și a ieșit din orice logică de tool calling.
- Pe conversație casual, nu a inventat tool calls (bine), dar calitatea răspunsului conversațional în română a fost slabă/agramat pe salut, deși explicația tehnică despre recursivitate (tot RO) a ieșit surprinzător de coerentă.
- Concluzie: sigur pe fals-pozitive, dar robustețea pe română e inconsistentă și imprevizibilă — de la perfect (weather) la incoerent total (treasury).
### FunctionGemma-270M — testat local (2026-07-12)
[`google/functiongemma-270m-it`](https://huggingface.co/google/functiongemma-270m-it) (testat via mirror-ul `unsloth/functiongemma-270m-it`, ~520MB) — bazat pe Gemma 3 270M, model Google specializat explicit pe function calling, cel menționat și în videoclipul sursă ca fiind depășit de Needle pe single-shot function calling. README-ul modelului avertizează clar: "not intended for use as a direct dialogue model... designed to be highly performant **after further fine-tuning**" — adică e gândit ca bază de fine-tuning per-domeniu, nu ca model gata de folosit zero-shot.
- **Cel mai rapid dintre toate**: 1-2.7s/query (comparabil cu Needle, mai rapid decât Hammer/Qwen).
- Folosește sintaxă proprietară de function call (`<start_function_call>call:nume{...}<end_function_call>`), nu JSON standard — ar necesita parser custom pe partea de Echo.
- **Confirmă empiric ce spunea videoclipul**: e clar mai slab decât Needle zero-shot pe cazurile noastre.
- Halucinează date/conținut: la `add_task` a inventat date fixe greșite ("2024-05-23", "2026-07-27" — nici "mâine" real) și a înlocuit titlul cu text generic ("add task to task board") în loc de conținutul real al cererii, pe **ambele** variante RO și EN.
- La `create_note` a generat un paragraf întreg fabricat, fără legătură cu "Andrei" sau întâlnirea.
- **Fals-pozitiv periculos**: "Cât e în casă?" → a interpretat "cat" ca pisică (aceeași confuzie ca la Qwen) și a generat `create_note(content="Noticed cat in casa")` — o notă complet inventată dintr-o interogare financiară, exact tipul de acțiune nedorită de care ne temeam.
- Pe conversație casual a refuzat corect (fără tool call), dar cu mesaje generice de eroare, nu conversație reală — așteptat, dat fiind avertismentul din README.
## Concluzie
**Niciun model din cele patru testate/cercetate nu e suficient de fiabil ca să înlocuiască un pas din `router.py` fără un prag de încredere + fallback obligatoriu la Claude.** Tabel rezumat (CPU, aceleași 10 query-uri RO+EN):
| Model | Parametri | Fals-pozitiv pe chit-chat | Robustețe RO | Halucinație conținut/argumente | Latență/query |
|---|---|---|---|---|---|
| Needle 26M | 26M | **Da** (salut → tool call inventat) | Bună | Extragere incompletă, nu inventată | 3-9s |
| Hammer2.1-0.5b | 0.5B | Nu | Parțială (ratează weather RO) | Da (content fabricat la note) | 2.4-5.6s |
| Qwen2.5-0.5B-Instruct | 0.5B | Nu | Inconsistentă (weather OK, treasury total incoerent) | Da (răspuns halucinat pe "bancă") | 2.4-8.5s |
| FunctionGemma-270M | 270M | **Da** (interpretare literală "pisică" → notă inventată) | Slabă | Da, sever (date/conținut fabricate) | 1-5.7s (cel mai rapid) |
Cele mai rapide (Needle, FunctionGemma) sunt și cele cu fals-pozitive periculoase pe interogări normale/financiare — corelație clară între "modele hiper-specializate pe function calling, foarte mici" și tendința de a forța un tool call chiar și când nu e cazul. Modelele mai generaliste (Hammer, Qwen) sunt mai reținute pe chit-chat, dar au propriile goluri pe română și pe extragerea corectă a argumentelor.
**Decizie:** nicio schimbare de cod în echo-core. Nu s-a integrat niciun pre-router local.
**Dacă se reia pe viitor:** niciunul dintre cele patru nu e gata "as-is". Dacă tot se alege un candidat de rafinat, Hammer2.1-0.5b rămâne cel mai sigur punct de plecare (singurul fără fals-pozitiv periculos și cu extragere de argumente parțial corectă), dar are nevoie de: (a) validare/fine-tuning explicit pe română (fals-negativul pe weather RO e blocant dat fiind traficul majoritar RO), (b) prompt/system message mai strict pentru a reduce halucinația pe câmpuri text libere (title/content). Nu merită reluat testul cu FunctionGemma-270M zero-shot — README-ul propriu spune clar că are nevoie de fine-tuning per-domeniu ca să fie utilizabil.
## Artefacte
Foldere de test (`/tmp/needle-test`, `/tmp/hammer-test`) sunt în `/tmp`, se pierd la reboot. Cache-uri de modele rămase în `~/.cache/huggingface/hub/` (**nu** se pierd la reboot): `models--MadeAgents--Hammer2.1-0.5b` (~950MB), `models--Qwen--Qwen2.5-0.5B-Instruct` (~950MB), `models--unsloth--functiongemma-270m-it` (~520MB) — total ~2.4GB, de șters manual dacă nu se reia testarea (disc la 85% ocupare în timpul testului, atenție la spațiu).