homelab-codex-ws/docs/kb/kb-01-email-design.md

3.9 KiB

Filar maili — projekt (homelab-codex · KB · projekt #1)

Pierwszy filar. Wzorzec referencyjny dla pozostałych (archiwum, embeddingi na SOLARIA, szkielet agenta, deploy). Zasady przekrojowe: patrz kb-00-overview.md.


1. Rdzeń: archiwum, nie RAG

Realna potrzeba to najpierw archiwum, nie „RAG nad mailami". Dwie warstwy, fundamentalnie różne:

  • Archiwum — surowe, niezmienne, kompletne .eml / Maildir, append-only. To, co chcesz mieć u siebie na zawsze, niezależnie od jakiegokolwiek AI. Asset.
  • Indeks — pochodny, odtwarzalny, wyrzucalny. Parse → chunk → embed → pgvector. Re-budowalny z archiwum przy lepszym modelu.

2. Dwa żywe źródła (zmiana względem pierwotnego planu)

Gmail nie jest porzucany — zostaje jako konto śmieciowe / loginy / 2FA. Stąd maile mają dwa żywe wejścia:

  • Fastmailsource: fastmail, adapter JMAP (read-only token). Primary: tu ląduje sensowna poczta na przyszłość.
  • Gmailsource: gmail, adapter IMAP (protokół, nie Gmail API → przenośność). Ciągły sync żywej skrzynki.

Plus jednorazowy bulk historyczny Gmaila (eksport „All Mail" / Takeout → surowy dump do archiwum). Operacja odwracalna i niezależna od reszty pipeline'u — robimy pierwsza. Urgency spadła (konto żyje), ale historia warta zassania od razu.


3. Koperta (kontrakt zamrożony)

id        — stabilny identyfikator wiadomości
source    — fastmail | gmail
ts        — UTC (data wiadomości)
geo       — null dla maili (uzupełniane cross-source w warstwie 3)
raw_ref   — wskaźnik do .eml w archiwum
entities[] — otwarte, wypełniane przy ingeście/enrich

Addytywna. Nic poza tym nie usztywniamy.


4. Filtr archiwum → indeks

Archiwizuj wszystko. Indeksuj selektywnie. Gmail śmieciowy (login/2FA/notyfikacje/newslettery) to szum — wpuszczony do wektorów zaśmieca wyszukiwanie i pali GPU na SOLARII. Filtr na wejściu do indeksu:

  • whitelist/blacklist nadawców i nagłówków (List-Unsubscribe, Auto-Submitted, typowe domeny powiadomień),
  • progi (np. odrzuć czysto automatyczne),
  • surowiec zawsze leży w archiwum — filtr nie kasuje, tylko decyduje co trafia do embeddingów.

Filtr jest częścią indeksu (odtwarzalny), nie archiwum.


5. Indexer

parse (.eml) → chunk → embed (bge-m3 na SOLARIA/ollama) → pgvector Retrieval hybrydowy: wektor + filtry metadanych (nadawca, zakres dat, etykieta, source). Załączniki: II tura (MVP = czysty tekst + nagłówki).


6. Agent maili (dedykowany, cienki)

  • Hybrydowy retrieval: wektor + filtry metadanych.
  • Wystawia tool/API, które agent interdyscyplinarny (warstwa 4) woła — wzorzec federacji.
  • Reużywa szkieletu agenta z control-plane (to samo DNA).

7. Deploy

  • Wszystko w homelab-codex, przez Git na SATURN, konwencja override hosts/<node>/runtime/<svc>/.
  • Usługi: jmap-poller (Fastmail), imap-poller (Gmail), indexer, embed (ollama na SOLARIA), postgres+pgvector, mail-agent; bulk importer jako one-shot job.
  • Deploy skryptem czytającym inventory/topology.yaml.

8. Kolejność budowy (w obrębie projektu)

  1. Zamroź kopertę + postaw Postgres+pgvector.
  2. Bulk Gmail historyczny → archiwum (pierwsze, niezależne).
  3. Fastmail JMAP live ingest → archiwum.
  4. Gmail IMAP live sync → archiwum.
  5. Filtr archiwum→indeks.
  6. Indexer (parse → chunk → embed bge-m3) → pgvector.
  7. Cienki agent maili + tool dla warstwy 4.

9. Decyzje otwarte (do przyklepania przed/w trakcie startu)

  • Sizing Gmaila — ile realnie waży „All Mail"? (przesądza node/dysk archiwum).
  • Unifikacja adaptera — jeden wspólny IMAP dla Fastmail + Gmail (mniej kodu) vs JMAP dla Fastmail + IMAP dla Gmail (JMAP bogatszy)?
  • Reguły filtra — startowa lista blacklist domen/nagłówków.
  • Vector store: pgvector przyklepane (spine).
  • Embed model: bge-m3 przyklepane.