Cum se colectează datele
Agenții rulează local, pe modele Ollama. Site-ul doar afișează rezultatele.
research — modulul „Carne: producători locali vs. supermarket"
Contextul complet și regulile obligatorii sunt în ../CLAUDE.md. Citește-l înainte de orice rulare.
Ordinea de rulare
Agenții se rulează în ordine: 01 → 02 → 03 → 04 → 05. Prompturile sunt în agents/.
| Agent | Ce face | Scrie |
|---|---|---|
01-colector-producatori.md | găsește producători autorizați SV în județul pilot | data/processed/producers.json |
02-colector-preturi-retail.md | colectează prețurile din supermarketuri | data/processed/prices-retail.json |
03-colector-preturi-producatori.md | colectează prețurile producătorilor | data/processed/prices-producers.json |
04-verificator.md | verifică sursele și marchează statusurile (modifică in place cele 3 fișiere) | cele 3 fișiere + logs/YYYY-MM-DD_verificare.md |
05-raportor.md | generează raportul comparativ | reports/YYYY-MM_<judet>_carne.md |
Loguri și snapshot-uri
- Fiecare rulare se loghează în
logs/YYYY-MM-DD_run.md(ce a rulat, ce a găsit, ce a eșuat). - Textul fiecărei pagini sursă se salvează în
data/raw/caYYYY-MM-DD_domeniu_slug.txt. Snapshot-urile se commit-ează, ca datele să rămână verificabile.
Configurare
- Schimbare județ: editează
config/regions.json. - Schimbare coș: editează
config/basket.json(și reflectă schimbarea în prompturile 02 și 03). - Surse și URL-uri de pornire:
config/sources.json.
research/runners — rularea locală a agenților cu Ollama
run-agent.mjs rulează agenții din research/agents/ pe modele locale (Ollama). Promptul agentului + regulile din CLAUDE.md secțiunea 4 devin system prompt-ul modelului.
Prerechizite
- Node.js 20+ și dependențele proiectului (
npm installla rădăcină — includecheerioșizod). - Ollama pornit, cu modelele:
ollama pull qwen3.5:9b # extragere (agenții 01, 02, 03, 05) ollama pull gpt-oss:20b # verificare (agentul 04) - Județul pilot setat în
research/config/regions.json:{ "judet_pilot": { "nume": "Cluj", "cod_siruta": "..." } }
Rulare
npm run research # usage + lista agenților
npm run research:01 # producători -> data/processed/producers.json
npm run research:02 # prețuri retail -> data/processed/prices-retail.json
npm run research:03 # prețuri producători -> data/processed/prices-producers.json
npm run research:04 # verificator (in place) -> logs/YYYY-MM-DD_verificare.md
npm run research:05 # raport -> reports/YYYY-MM_<judet>_carne.md
Fiecare rulare adaugă o secțiune în logs/YYYY-MM-DD_run.md. Fiecare pagină descărcată e salvată în data/raw/.
Rulare din site (job queue)
Pagina /research/control pune job-uri în MongoDB (DB rodebate, colecția jobs, șterse automat după 60 de zile). Pollerul de pe laptop le preia și rulează agenții local:
npm run research:watch # pornește pollerul (CTRL+C pentru oprire)
node research/runners/poller.mjs --check # doar verifică conexiunea și coada
nohup npm run research:watch > research/logs/poller.out 2>&1 & # în background, 24/7
- Necesită în
.env.localla rădăcina proiectului:MONGODB_URIșiRESEARCH_CONTROL_TOKEN(aceleași valori ca în Vercel). - Pollerul ia câte un job o dată (cel mai vechi
pending), ruleazărun-agent.mjs <agent>și trimite fiecare linie de output în logurile job-ului; site-ul le afișează live. - Pagina arată „Poller local online/offline" după ultimul semnal al pollerului (la fiecare 3 secunde).
- Datele noi (
data/processed/,reports/) rămân pe laptop: apar pe site abia după commit + deploy. - La repornire, job-urile rămase
runningdintr-o rulare întreruptă sunt marcatefailed.
Ce face runner-ul în afară de model (garanții deterministe)
- Orice înregistrare al cărei
extrasnu apare literal în pagina descărcată e respinsă (contează la „respinse" în log). - CUI, număr autorizare SV, localitate și contacte care nu apar în pagină devin
null. - Prețul trebuie să apară în extras; normalizarea la lei/kg e calculată în cod (
formula_normalizare), nu de model. - Producătorii fără număr de autorizare SV primesc
neautorizat_sau_neconfirmat; agentul 01 nu marchează niciodatăverificat— doar 04 o face. - 05 calculează min/medie/max și diferențele în cod; modelul scrie doar un rezumat opțional, marcat ca generat.
Surse cu mai multe pagini
url_start din config/sources.json e de obicei o pagină de pornire. Runner-ul acceptă opțional, pe fiecare sursă:
"urls": ["...", "..."]— listă de pagini concrete de procesat (în loc de / pe lângăurl_start);"url_carne": "..."(doar retail) — pagina categoriei de carne a lanțului.
Schimbarea modelului
Editează research/runners/config.json:
default_model— agenții 01, 02, 03, 05;verifier_model— agentul 04;timeout_ms— timeout per apel la model;max_text_chars— paginile mai lungi se împart în fragmente de această mărime (un apel per fragment).
Orice model din ollama list funcționează; modelele mai mici extrag mai prost (mai multe respingeri).
Troubleshooting
| Problemă | Mesaj | Soluție |
|---|---|---|
| Ollama oprit | Pornește Ollama: ollama serve & | ollama serve & sau brew services start ollama |
| Model lipsă | ollama pull <model> | rulează comanda afișată sau schimbă modelul în config.json |
| Județ nesetat | Setează județul în research/config/regions.json | completează judet_pilot |
| HTTP 403 / pagină goală | în log: HTTP 403 (posibil protecție anti-bot) sau randată din JavaScript | site-ul blochează boții sau încarcă prețurile din JS; salvează pagina manual în data/raw/ sau adaugă un URL alternativ în urls |
| PDF / XLS (ex.: liste DSVSA) | content-type neprocesat | runner-ul nu citește PDF/XLS; descarcă și convertește manual |
| Timeout model | ... aborted due to timeout | crește timeout_ms sau scade max_text_chars |
Un URL care eșuează nu oprește rularea — eroarea apare în log și se trece la următorul.