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

6.3 KiB

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.pyBrainClient

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.pyBrainIngestSink

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:

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:

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):

-- 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.