nordabiz/docs/superpowers/specs/2026-03-28-nordagpt-identity-memory-design.md
Maciej Pienczyn 92780fe4b6 docs: NordaGPT identity, memory & performance design spec
Four pillars: user identity awareness, persistent memory per user,
smart router for cost/speed optimization, streaming responses.
Target: 3,000 queries/day, 70-80% cost reduction, 3-5x faster responses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 05:00:34 +01:00

9.6 KiB

NordaGPT Identity, Memory & Performance — Design Spec

Data: 2026-03-28 Zgłaszający: Jakub Pornowski (prędkość, tożsamość), Maciej Pienczyn Status: Draft

Cel

Przekształcić NordaGPT z anonimowego chatbota w spersonalizowanego asystenta, który:

  1. Wie kim jest użytkownik i personalizuje odpowiedzi
  2. Pamięta poprzednie rozmowy i buduje profil użytkownika
  3. Odpowiada 3-5x szybciej dzięki smart routingowi i streamingowi
  4. Kosztuje 70-80% mniej przy skali 3,000 zapytań/dzień

Skala docelowa

  • 100-150 aktywnych użytkowników dziennie
  • 10-20 pytań na użytkownika
  • 1,500-3,000 zapytań/dzień
  • Budżet: sponsorowany przez INPI, w przyszłości przeniesiony na użytkowników

Filar 1: Tożsamość użytkownika

Dane wstrzykiwane do promptu

# AKTUALNY UŻYTKOWNIK
Rozmawiasz z: {user.name}
Email: {user.email}
Firma: {company.name} (ID {company.id}) — kategoria: {company.category}
Rola w firmie: {user.company_role}
Członek Izby: {tak/nie}
Rola w Izbie: {user.chamber_role lub "—"}
Powiązane firmy: {lista z UserCompanyPermissions}
Na portalu od: {user.created_at}

Zmiany w API

  • send_message() — nowy parametr user_context: dict (zamiast samego user_id: int)
  • Route chat_send_message() buduje user_context z current_user + current_user.company + UserCompanyPermissions

Zachowanie AI

  • Pierwsza wiadomość w konwersacji: "Cześć {imię}, w czym mogę pomóc?"
  • Na "co wiesz o mnie?": wypisuje dane z profilu + powiązania firmowe + fakty z pamięci
  • Kontekstowe odpowiedzi uwzględniające firmę i rolę użytkownika

Filar 2: Pamięć użytkownika

Nowe tabele

ai_user_memory

Kolumna Typ Opis
id SERIAL PK
user_id FK users.id (NOT NULL) Właściciel pamięci
fact TEXT (NOT NULL) Treść faktu
category VARCHAR(50) interests / needs / contacts / insights
source_conversation_id FK ai_chat_conversations.id Z której rozmowy
confidence FLOAT DEFAULT 1.0 Maleje z czasem
created_at TIMESTAMP DEFAULT NOW()
expires_at TIMESTAMP created_at + 12 miesięcy
is_active BOOLEAN DEFAULT TRUE Użytkownik może dezaktywować

Indeksy: (user_id, is_active, confidence DESC), (expires_at) dla cleanup crona.

ai_conversation_summary

Kolumna Typ Opis
id SERIAL PK
conversation_id FK UNIQUE ai_chat_conversations.id 1:1 z konwersacją
user_id FK users.id
summary TEXT Podsumowanie 1-3 zdania
key_topics JSONB ["budowlane", "TERMO", "PEJ"]
created_at TIMESTAMP DEFAULT NOW()
updated_at TIMESTAMP

Generowanie pamięci (asynchroniczne)

  1. Po wysłaniu odpowiedzi AI → Flash-Lite analizuje rozmowę w tle (nie blokuje response)
  2. Wyciąga nowe fakty → INSERT do ai_user_memory (deduplikacja po treści)
  3. Co 5 wiadomości w konwersacji → aktualizuje ai_conversation_summary
  4. Przy opuszczeniu konwersacji → finalne podsumowanie

Prompt do ekstrakcji faktów (Flash-Lite)

Na podstawie tej rozmowy, wyciągnij kluczowe fakty o użytkowniku.
Zwróć JSON array: [{"fact": "...", "category": "interests|needs|contacts|insights"}]
Zasady:
- Tylko nowe, nietrywialne fakty (nie "zapytał o firmę X")
- Fakty przydatne w przyszłych rozmowach
- Max 3 fakty na rozmowę
- Nie duplikuj istniejących faktów: {existing_facts}

Wstrzykiwanie do promptu

  • Top 10 najświeższych aktywnych faktów (~500 tokenów)
  • Podsumowania ostatnich 5 konwersacji (~750 tokenów)
  • Razem: ~1,250 tokenów

UI

  • Ustawienia czatu → "Co NordaGPT o mnie wie"
  • Lista faktów z datą i źródłem (link do konwersacji)
  • Przycisk "Usuń" przy każdym fakcie (soft delete: is_active=False)
  • Lista podsumowań konwersacji

RODO

  • Pamięć prywatna — dostępna TYLKO dla właściciela (filtr user_id na każdym query)
  • Użytkownik ma pełną kontrolę: podgląd, usuwanie
  • Przy usunięciu konta → CASCADE DELETE pamięci
  • Fakty nie zawierają danych wrażliwych (PESEL, konta bankowe) — ten sam filtr RODO co na wiadomościach

Filar 3: Smart Router

Przepływ zapytania

Użytkownik pisze pytanie
        ↓
   [1] Smart Router (3.1 Flash-Lite, ~1-2s)
       Input: pytanie + tożsamość + pamięć + lista kategorii danych
       Output JSON: {
         "complexity": "simple|medium|complex",
         "data_needed": ["companies:IT", "events", "user_memory"],
         "model": "flash-lite|flash|flash-high"
       }
        ↓
   [2] Context Builder
       Ładuje TYLKO potrzebne dane z bazy
        ↓
   [3] Main Model (dobrany przez Router)
       Prompt: tożsamość + pamięć + wybrane dane + historia (~15-25k tokenów)
        ↓
   [4] Streamed response → użytkownik
        ↓
   [5] Memory Extractor (Flash-Lite, async, w tle)

Prompt routera

Jesteś routerem zapytań NordaGPT. Przeanalizuj pytanie użytkownika i zdecyduj:

Użytkownik: {name} z firmy {company}
Pamięć: {facts_summary}
Pytanie: {user_message}

Zwróć JSON:
{
  "complexity": "simple|medium|complex",
  "data_needed": ["categories from list below"],
  "reasoning": "one sentence why"
}

Dostępne kategorie danych:
- companies_all: wszystkie 150 firm (30k tokenów) — porównania, przeglądy
- companies_filtered:{category}: firmy z danej kategorii (2-5k)
- companies_single:{slug}: jedna firma (0.5k)
- events: nadchodzące wydarzenia (2k)
- news: aktualności i PEJ (3k)
- classifieds: ogłoszenia B2B (2k)
- forum: tematy forum (5k)
- company_people: zarząd/KRS (5k)
- registered_users: użytkownicy portalu (3k)
- social_media: profile social media firm (2k)
- audits: SEO/GBP wyniki (2k)

ZAWSZE dodawane (nie musisz wybierać): tożsamość, pamięć, historia rozmowy.
Wybierz MINIMUM potrzebnych kategorii. Jeśli nie jesteś pewien, dodaj więcej.

Kategorie danych i triggerowanie

Kategoria Triggery (słowa kluczowe) ~Tokenów
companies_all "firmy", "porównaj", "wszystkie", "ile firm" ~30k
companies_filtered nazwa kategorii, "budowlane", "IT" ~2-5k
companies_single nazwa firmy, slug ~0.5k
events "spotkanie", "wydarzenie", "kalendarz" ~2k
news "aktualności", "nowości", "PEJ", "atom" ~3k
classifieds "ogłoszenie", "B2B", "zlecenie", "oferta" ~2k
forum "forum", "dyskusja", "temat", "wątek" ~5k
company_people "zarząd", "KRS", "właściciel", "udziały" ~5k
registered_users "kto jest", "użytkownicy", "profil" ~3k

Fallback

Jeśli router zwróci błąd lub timeout → ładuj wszystkie dane (obecne zachowanie). Bezpieczne, wolniejsze.

Dobór modelu

Complexity Model Thinking Oczekiwany czas
simple 3.1 Flash-Lite minimal 2-3s
medium 3 Flash low 4-6s
complex 3 Flash high 8-12s

Filar 4: Streaming + UI

Backend

  • Nowy endpoint SSE: POST /api/chat/<id>/message/stream
  • Używa gemini_service.generate_text(stream=True)
  • Zwraca text/event-stream z chunkami: data: {"type": "token", "content": "..."}\n\n
  • Events: token (tekst), thinking (model myśli), done (koniec + metadata), error
  • Stary endpoint /api/chat/<id>/message pozostaje jako fallback (non-streaming)

Frontend

  • fetch() z ReadableStream (szersza kompatybilność niż EventSource dla POST)
  • Tekst pojawia się słowo po słowie w bańce czatu
  • Animacja "myślenia" gdy model przetwarza (pulsujące kropki)
  • Po done → zapisz pełną odpowiedź do DOM, pokaż metadata (czas, model)

Wskaźniki w UI

  • Przy prostych pytaniach: brak wskaźnika myślenia, odpowiedź natychmiastowa
  • Przy złożonych: "NordaGPT analizuje..." z animacją (2-3s), potem streaming tekstu

Szacunek kosztów (3,000 zapytań/dzień)

Składnik Koszt/zapytanie Dziennie Miesięcznie
Router (Flash-Lite) ~$0.001 $3 $90
Main model (mix) ~$0.01-0.03 $30-90 $900-2,700
Memory extraction (async) ~$0.001 $3 $90
Suma $36-96 $1,080-2,880

vs. obecne podejście bez optymalizacji przy tej skali: ~$9,000-13,500/mies. Oszczędność: 70-80%


Szacunek prędkości po zmianach

Metryka Obecna Po zmianach
Średni czas odpowiedzi 20.5s 3-6s
Perceived latency (streaming) 20.5s 1-2s
P95 34.5s 8-12s
Najwolniejsze (complex) 46s 12-15s

Migracje SQL

  1. 091_create_ai_user_memory.sql — tabela + indeksy
  2. 092_create_ai_conversation_summary.sql — tabela + indeksy

Pliki do zmiany

Plik Zmiana
database.py Nowe modele: AIUserMemory, AIConversationSummary
nordabiz_chat.py Smart Router, Context Builder, Memory Extractor, user_context
gemini_service.py Streaming support w generate_text (już częściowo jest)
blueprints/chat/routes.py Nowy endpoint streaming, user_context budowanie
templates/chat.html Streaming UI, animacja myślenia
static/js/chat.js lub inline ReadableStream handler
Nowy: smart_router.py Logika routera (prompt, parsing, fallback)
Nowy: memory_service.py Ekstrakcja faktów, podsumowania, CRUD pamięci
Nowy: context_builder.py Selektywne ładowanie danych na podstawie decyzji routera

Kolejność wdrażania

  1. Tożsamość użytkownika — najprostsza, natychmiastowy efekt "wow"
  2. Smart Router + Context Builder — redukcja kosztów i poprawa prędkości
  3. Streaming — perceived latency drop
  4. Pamięć użytkownika — wymaga nowych tabel, async pipeline, UI