193 lines
6.3 KiB
Markdown
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`.
|