didi-lot1-ai/ai_platform/modules/web/BRAIN_INTEGRATION.md

193 lines
6.3 KiB
Markdown

# Web-API ↔ didi-brain integration
Web-api folosește didi-brain ca **layer de cache cu 2 fețe**:
1. **Cache read** (ambele tiers — free și premium) — înainte să cheme SearXNG
sau paid providers, web-api întreabă brain. Dacă brain are evidence
relevante cached, le servește direct; clientul primește răspuns în ~1-2s
în loc de 10-30s.
2. **Cache write** (doar tier premium, quality-gated) — după o cerere premium
care a trecut pragurile de calitate, web-api pompează evidence în brain
fire-and-forget. Brain face extraction async. Viitoarele cereri pe claim-uri
similare vor hit-ui cache-ul.
Ideea de bază: **free users primesc quality-ul plătit de premium users**, dar
doar premium plătește pentru popularea cache-ului.
---
## Flow-ul per request
```
POST /v1/gather { claim, tier }
┌─────────────────────────────────────────┐
│ 1. Cache READ (brain /v1/gather) │
│ (ambele tiers, dacă brain configured│
│ și brain_cache_read_enabled=true) │
└────────┬────────────────────────────────┘
├─ brain HIT cu quality OK
│ → returnează direct răspunsul (skip orchestrator)
└─ brain MISS sau quality slab
┌────────────────────────────────┐
│ 2. Orchestrator normal │
│ free → SearXNG + Qwen │
│ premium → Paid + OpenRouter│
└────────┬───────────────────────┘
┌────────────────────────────────┐
│ 3. Cache WRITE (doar premium) │
│ dacă quality_ok_for_cache │
│ fire-and-forget ingest │
│ (nu blochează response) │
└────────────────────────────────┘
Return to client
```
---
## Componente
### `src/web/brain/client.py` — `BrainClient`
Client HTTP minimal pentru brain:
- `gather(claim, max_evidence, run_nli, ...)` — cache read, returnează JSON sau None pe eroare
- `ingest(payload)` — cache write, fire-and-forget via sink de obicei
Timeout-uri separate (gather e rapid, ingest poate fi mai lent).
### `src/web/brain/sink.py` — `BrainIngestSink`
Queue bounded (1000 items max) processat de un single worker task.
Overflow → drop oldest. Eșecuri → log DEBUG, swallowed. Zero impact
pe latența web-api.
### `src/web/brain/quality.py` — Quality gates
- `quality_ok_for_cache(response)` — decide dacă un gather result e worth-caching
(3+ evidence, cel puțin 1 sursă credibilă dacă sunt scored, toate stages OK,
execution > 2s)
- `brain_hit_acceptable(brain_raw)` — decide dacă un brain HIT e suficient
de bun (HIT = da; PARTIAL = da doar dacă 3+ items cu relevance ≥ 0.7)
### `src/web/brain/adapter.py` — Schema conversion
- `brain_response_to_web(brain_raw, request_id)` — convertește response-ul
brain în `GatherResponse` web (datetime → ISO string, provenance dict,
`brain_meta` flatten în provenance per evidence item)
- `web_response_to_ingest_payload(response, claim)` — convertește
`GatherResponse` în `IngestRequest` pentru brain (ISO dates, safe defaults
pentru field-urile required brain-side: title/retrieved_at/score defaults)
---
## Configurare
În `deploy/.env`:
```bash
WEB_BRAIN_URL=http://didibrain-api:8090
# Feature toggles (default true dacă brain_url setat)
WEB_BRAIN_CACHE_READ_ENABLED=true
WEB_BRAIN_INGEST_ENABLED=true
# Quality thresholds pentru ingest
WEB_BRAIN_INGEST_MIN_EVIDENCE=3
WEB_BRAIN_INGEST_MIN_CREDIBILITY=0.7
WEB_BRAIN_INGEST_MIN_EXECUTION_MS=2000
# Acceptance thresholds pentru PARTIAL cache hit
WEB_BRAIN_HIT_MIN_EVIDENCE=3
WEB_BRAIN_HIT_MIN_RELEVANCE=0.7
# Timeouts
WEB_BRAIN_GATHER_TIMEOUT=8.0
WEB_BRAIN_INGEST_TIMEOUT=15.0
```
Toate sunt optional. Dacă `WEB_BRAIN_URL` e gol, integrarea e dezactivată
complet (fallback la orchestrator normal pentru tot).
---
## Networking Docker
Web-api trăiește pe rețeaua `deploy_default` (cu dashboard, video, audio,
searxng). Brain trăiește pe rețeaua proprie `didibrain`.
Web-api e atașat la **ambele** rețele în `deploy/docker-compose.yml`:
```yaml
networks:
deploy_default:
external: true
didibrain:
external: true
services:
web-api:
networks:
- deploy_default
- didibrain
```
Asta îi permite să rezolve `didibrain-api` prin DNS-ul Docker.
---
## Fail-open
Brain down ≠ web-api down. Toate apelurile spre brain sunt wrapped cu
try/except generos:
- Gather cache read eșuează → continuă la orchestrator normal
- Ingest eșuează → log și drop event (queue-ul va reumple)
Clientul nu vede niciodată o eroare datorită brain.
---
## Cum monitorizezi HIT rate
Log-urile web-api emit `Brain cache HIT [tier=X, N items]: <claim>` pe fiecare
hit. Pentru producție, integrarea cu dashboard face count-uri în tabela
`request_history` (câmp `raw_response.stages` conține `retrieval`/`rerank` când
e din brain vs `search`/`fetch` când e direct).
Query exemplu (post-deploy):
```sql
-- HIT rate per tier pe ultimele 24h
SELECT
tier,
COUNT(*) FILTER (
WHERE raw_response::jsonb -> 'stages' @> '[{"stage":"retrieval"}]'
) AS brain_hits,
COUNT(*) AS total_gathers,
ROUND(100.0 * COUNT(*) FILTER (
WHERE raw_response::jsonb -> 'stages' @> '[{"stage":"retrieval"}]'
) / NULLIF(COUNT(*), 0), 1) AS hit_rate_pct
FROM request_history
WHERE endpoint = '/v1/gather'
AND created_at > now() - interval '24 hours'
GROUP BY tier;
```
---
## Ce NU face integrarea
- Nu scrie la brain pe tier `free` (doar citește) — tip premium gold standard
- Nu face fallback la premium când brain MISS pe free (menține tier isolation)
- Nu retry — un singur request la brain, orice eșec → fallback silent
Pentru detaliile contractului verification_cache (backend ↔ brain),
vezi `modules/didi_brain/CONTRACT_VERIFICATION_CACHE.md`.