Přeskočit obsah

Phase D + E — Plánované

Phase D — Chat s RAG injection

Stav: ⏳ Plánováno Cíl: Přepsat /chat endpoint aby používal /retrieve interně místo full report textu

Aktuální stav (Phase B/C)

/chat endpoint (app/routers/chat.py):

  • Načte report row → parsed_markdown (v2) nebo clean_text (v1-import legacy)
  • Volá Pydantic AI Agent s plným textem reportu v system promptu (~10-40K tokens)
  • Streamovaný SSE response

Problém: full text = drahý kontext + vendor model může mít problém s "needle in haystack" pro velké reporty.

Co Phase D změní

  1. /chat interně volá /retrieve pro každý turn
  2. top_k = 8 chunks
  3. scope = folder (current report context)
  4. Inject chunks do system promptu místo full textu
  5. 8 chunks × ~500 tokens = ~4K vs 40K full text
  6. 10× tokens saving
  7. AI cituje per chunk (source_label + attachment_filename denormalized v chunks)
  8. "Z přílohy 'Vyjádření ČEZ' vyplývá..."
  9. "V sekci 'Riziko povodní' najdete..."
  10. Streaming odpověď zachovat (SSE)
  11. Multi-turn conversation historyrewrite_standalone v Phase C MVP no-op, Phase D dostane real history → použije LLM rewrite

Plánovaný flow

User → ChatWindow → POST /chat {message, conversation_id}
  → Backend retrieve interně /retrieve {query, scope=folder, top_k=8}
  → top-K chunks
  → Build system prompt:
    "Jsi asistent pro hodnocení nemovitostí. Odpovídej z následujícího kontextu:
     [1] Sekce 'Riziko povodní': Pozemek je v zóně Q100...
     [2] Příloha 'Vyjádření ČEZ': Nad parcelou nejsou nadzemní vedení...
     [3] Figura 'map_zoning' (sekce Územní plán): Mapa ukazuje...
     ..."
  → Pydantic AI Agent stream response
  → SSE chunks → Frontend

Změny per komponenta

Backend: - app/routers/chat.py — rewrite use /retrieve interně - app/retrieval/rewrite.py — implement rewrite_standalone s history (currently no-op) - Možná nový chat_context_formatter.py — assemble system prompt z chunks

Frontend: - ChatWindow.tsx — nezbytně malé změny (response shape stejný) - Možná zobrazit cited chunks v UI ("Z těchto pasáží:" + linky na sekce)

Schema: - messages table možná přidat cited_chunk_ids uuid[] pro UI render

Open questions Phase D

  1. Jak handle-ovat reporty bez chunks? (D7 soft-fail) → fallback na full-report dump, ale zminit user "bez RAG, basic fallback"
  2. Multi-report chat support? Aktuálně 1 conversation = 1 report. Phase D může umožnit cross-report queries.
  3. Streaming + chunks injection — Pydantic AI patterns pro streamovaný response

Časový odhad

~1-2 dny implementace + 1 den testing + golden eval (Phase C.12 deferred → mohlo by se hodit zde).

Phase E — Nette integration

Stav: ⏳ Plánováno (gate: Nette tým ready) Cíl: Embed chat do Nette aplikace, JWT bridge, HMAC webhooks, DNS cutover

Co bylo připraveno v Phase A/B

  • verify_nette_jwt() ready hook v app/auth.py — RS256 + iss/aud/exp enforcement, neaktivní v A
  • POST /reports/{id}/attachments/system — HMAC-authed endpoint pro Nette automatické attachment uploady (Phase B B.11)
  • Embed-first frontend — chat je vždy iframe, jen parent origin se změní

Plánovaný flow

Nette user logged in
  → Nette signs RS256 JWT { sub: nette_user_id, email, aud: "nemoreport-ai", iss: "nemoreport.cz", exp: now+15min }
  → postMessage { type: "nemoreport-ai:init", authToken: "<JWT>" }
Chat iframe (https://review.algaweb.cz/chat?id=...)
  → POST /auth/nette-exchange { jwt }
Backend
  → verify_nette_jwt(token) — RS256 přes NETTE_JWT_PUBLIC_KEY
  → lookup or create Supabase user via auth.identities(provider='nette')
  → generate Supabase session → return { access_token, refresh_token }
Frontend uses Supabase session, chatuje bez druhého loginu

Komponenty

Backend: - POST /auth/nette-exchange — verify Nette JWT → mint Supabase session - ENV NETTE_JWT_PUBLIC_KEY (PEM) — pro RS256 verify - ENV NETTE_AUDIENCE = "nemoreport-ai", NETTE_ISSUER = "nemoreport.cz"

Frontend: - iframe child listener pro postMessage event nemoreport-ai:init - apiFetch exchange Nette JWT → Supabase session - Adjust CORS / origins pro Nette domain

Infra: - DNS cutover: NemoReport AI app on review.algaweb.cz (currently on nemoreport-ai-frontend-v2.algaweb.workers.dev) - CF Workers route bind

Časový odhad

~1 týden implementace + integration testing s Nette tým + DNS cutover.

Další plánované funkce (mimo phase plan)

Token credit system (přeprodej)

Per project memory project_nemoreport_admin_section:

Až přijde, bude další admin sekce — token mint/refund, user balances, transaction log. Cost tracking se přepíše z raw halíře na "tokens spent". Pro Phase C zatím držet raw cost v ingestion_cost_cents.

User explicit decision 30.4: bude "přeprodej tokenů jako platební systém — uživatelé kupují kredity, utrácejí na platformě". Frontend cost zobrazení teď interní, pro produkci se přepíše.

Admin analytics dashboard

/admin/retrieval/* endpointy nad retrieval_log: - Top queries / scope distribution - A/B variant comparison - Per-tenant retrieval stats - Latency p50/p95/p99 trends

/admin/cost/* UI v admin frontu (zatím jen JSON endpointy).

Multi-report scope retrieval

Phase C MVP supports jen scope.type='folder' (single report). Multi-report scope:

  • scope.type='multi_report', report_ids=[...]
  • HNSW with WHERE report_id IN (...) — pgvector iterative_scan='relaxed_order'
  • Use case: cross-report comparison ("porovnej tyto 3 nemovitosti")

Resend production domain

Pro reálné testery (mimo owner email). Verifikace auth.algaweb.cz nebo auth.nemoreport.cz.

Cohere production key

Trial limit ~1000 calls/měsíc. Pilot OK, scale potřebuje upgrade.