homelab-codex-ws/docs/kb/kb-00-overview.md

8.2 KiB
Raw Blame History

Baza wiedzy — przegląd i log decyzji (homelab-codex · KB)

Master-dokument inicjatywy. Stoi ponad dokumentami per-projekt (kb-01-email-design.md, …). Cel: każda kolejna sesja / Claude Code startuje z pełnym kontekstem ustaleń. Status: faza docs. Implementacja jeszcze nie ruszyła.


Czym to jest

Nie sama „baza wiedzy" — de-Google'izacja życia + warstwa wiedzy na wierzchu. Każde źródło ma dwie twarze:

  • migracja off-cloud — gdzie dane fizycznie lądują u Ciebie,
  • archiwum + ingest — warstwa wiedzy.

Architektura: 4 warstwy × 4 filary + rdzeń

Dwa spojrzenia, ta sama rzecz:

  • Pionowo — 4 filary źródeł, każdy = ingest + index (per-filar, wymienny): maile · dokumenty · zdjęcia · transakcje.
  • Poziomo — 4 warstwy przepływu:
    1. Ingest — per filar (adaptery przeciw protokołom).
    2. Preprocess + Index — per filar (parse/chunk/embed → pgvector; transakcje → SQL).
    3. Join + Enrichwspólny rdzeń: entity resolution, graf encji, klucz czasoprzestrzenny.
    4. Advanced analytics + NL querywspólny: agent interdyscyplinarny, zapytania w języku naturalnym, analityka LLM.

Dwa dolne tiery są per-filar i neutralne. Dwa górne są wspólne dla wszystkich źródeł. OwnTracks = nie piąty filar, lecz klucz czasoprzestrzenny w warstwie 3 (ciągła funkcja czas→miejsce, bez własnego ingestu/agenta).

        [ 4. Agent interdyscyplinarny ]   NL query + analityka (LLM)
                      ↑  (wspólne)
        [ 3. Join + Enrich ]   entity resolution · graf · OwnTracks (czas+miejsce)
            ↑       ↑        ↑          ↑  (wspólne)
        [ 2. Preprocess + Index ]   → pgvector / → SQL
            ↑       ↑        ↑          ↑  (per filar)
        [ 1. Ingest ]
          Maile  Dokumenty  Zdjęcia  Transakcje

Zasady przekrojowe (obowiązują każdy projekt)

  1. Archiwum ≠ indeks. Archiwum surowe/niezmienne (asset, wieczne); indeks pochodny i odtwarzalny (wyrzucalny). Re-indeks z archiwum przy lepszym modelu.
  2. Koperta = jedyny kontrakt zamrożony z góry. Addytywna. Zamrożone: id · source · ts(UTC) · geo · raw_ref + otwarte pole entities[]. Cała semantyka (typy encji, resolution, graf) płynie — rośnie z danych.
  3. Czas + miejsce jako byty pierwszej klasy od dnia zero. Uniwersalny klucz złączeń między źródłami, karmiony OwnTracks. Nie da się retrofitować bez re-ingestu — stąd w kopercie od startu.
  4. Local-first / privacy. Korpus (bank + prywatne zdjęcia + maile) → wszystko lokalnie. Embeddingi i modele na SOLARIA (GPU + ollama). Zero chmury dla danych wrażliwych.
  5. Protokół, nie provider. Ingest pisany przeciw standardom (JMAP, IMAP, WebDAV), nie przeciw firmie → przenośność.
  6. Jeden spine: Postgres + pgvector. Koperta + wektory (+ później encje + punkty OwnTracks) w jednym store. Mniej ruchomych części.
  7. Warstwa 4 nie jest waterfallem. Kontrakt encji (warstwa 3) definiujemy wcześnie — przy 2 źródłach; po drugim źródle stawiamy cienką wersję warstwy 4, by udowodnić cross-source linking; dopiero potem dokładamy resztę.

Kolejność projektów (z uzasadnieniem)

  1. Maile — urgency historyczna (Gmail), czysty text RAG (najprostszy), stawia wzorce reużywalne przez resztę (archiwum, embeddingi na SOLARIA, szkielet agenta, deploy). Wzorzec referencyjny.
  2. Dokumenty — reużywają ~80% maili (text RAG + OCR), niosą własną migrację Drive → self-host.
  3. Zdjęcia — silnie zde-ryzykowane: Immich już robi multimodal. Projekt = cienki agent nad API Immicha. Może iść w parze z dokumentami.
  4. Transakcje — inny paradygmat (strukturalny/analityka, nie RAG); najmniej danych, najtrudniejszy acquisition. Na koniec.
  5. Interdyscyplinarny — capstone; ale jego szkielet (schema encji) powstaje już przy 12.

Stan per źródło

  • Mailedwa żywe źródła: Fastmail (JMAP, primary) + Gmail (IMAP, bo konto zostaje jako śmieciowe/loginy/2FA). Plus jednorazowy bulk historyczny Gmaila. Reguła: archiwizuj wszystko, indeksuj selektywnie (filtr odrzuca login/2FA/notyfikacje z wektorów). Design: kb-01-email-design.md. Następny do realizacji.
  • Dokumentyzdecydowane: Nextcloud (zamiennik Drive, dowolne pliki + sync) i Paperless-ngx (podzbiór: skany/faktury/umowy z OCR). Dwa deploye; w ingeście jeden adapter na każdy (Nextcloud WebDAV + Paperless API).
  • ZdjęciaImmich już działa (storage + sync z telefonu + CLIP + twarze + EXIF). Projekt = cienki agent nad API Immicha + job: twarze→osoby, EXIF→miejsca do warstwy encji.
  • TransakcjeOPEN ISSUE. Banki: gł. mBank + Revolut (+ reszta PL). Cel: maks automatyzacja. Kandydat: agregator PSD2 (GoCardless Bank Account Data / Tink) — jedno wejście zamiast N adapterów. Ograniczenie regulacyjne: zgoda PSD2 wygasa co 90 dni (SCA) — pełnego bezobsługowego sync nie da się zrobić legalnie. Fallback zero-API: import CSV/MT940. Pokrycie mBanku, koszt agregatora, Revolut → do weryfikacji przy starcie filaru #4.
  • OwnTracksdziała; feed do middleware jako warstwa spatio-temporalna (warstwa 3).

Middleware — co zamrożone, co płynne

  • Zamrożone (cienkie, addytywne): koperta (id/source/ts/geo/raw_ref) + mechanizm entities[].
  • Płynne (rośnie z danych): typy encji, entity resolution, graf tożsamości, linki cross-source.
  • Powód: koperta jest retrofit-hostile ale data-independent (można ustalić „na ślepo"); semantyka odwrotnie — wymaga prawdziwych danych, więc jej nie usztywniamy.

Decyzje — zamknięte vs otwarte

Zamknięte:

  • Spine: Postgres + pgvector (nie Qdrant).
  • Embed: bge-m3 (multilingual, długi kontekst — pod polski lepszy niż multilingual-e5).
  • Załączniki: indeksowane w II turze (MVP najpierw czysty tekst).
  • Warstwa 3 startuje jako cienki graf encji; federacja przy zapytaniu dochodzi później (docelowo hybryda).
  • Dokumenty: Nextcloud + Paperless-ngx.

Otwarte:

  • Transakcje: agregator vs CSV, pokrycie mBanku, Revolut, koszt (filar #4).
  • Maile §design: sizing archiwum / node (ile waży Gmail), unifikacja adaptera (jeden IMAP dla obu vs JMAP+IMAP osobno).

Tor równoległy (nie tutaj)

Hardening homelabu / stabilizacja control-plane — osobny wątek.


Konwencje katalogów Python

Katalog Co tu trafia
packages/<lib>/ Reużywalne biblioteki (nie deployowane samodzielnie). Instalacja: pip install /repo/packages/<lib>/. Nie mają docker-compose.yml ani service.yaml.
services/<svc>/ Długo żyjące serwisy Docker z docker-compose.yml + service.yaml.
jobs/<job>/ Jednorazowe i periodyczne joby CLI — bez Dockera, odpalane bezpośrednio na węźle (pip install -e).

Pierwsza biblioteka: packages/kb-mail/ — model koperty, helpery DB (asyncpg), helper archiwum. Pierwszy job: jobs/gmail-bulk-import/ — jednorazowy bulk importer Gmail Takeout.


Stan etapów

Etap 1 maili: zamroź kopertę + postaw Postgres+pgvector + szkielet repo. ZROBIONE (2026-06-17).

  • services/kb-postgres — pgvector/pgvector:pg16 na PIHA (:5433, always-on), init/001_envelope.sql
  • Zamrożona koperta — tabela envelope + @dataclass Envelope (tz-aware)
  • packages/kb-mailenvelope / db (asyncpg) / archive (append-only .eml)
  • 15 testów unit + 5 integration (mark integration, wymaga KB_TEST_DSN)

Etap 2: jednorazowy bulk importer Gmail (mbox/Takeout → archiwum). KOD GOTOWY (2026-06-24) — nie uruchomiony.

  • jobs/gmail-bulk-import/ — CLI importer bez Dockera (pip install -e na PIHA)
  • entities[]: manifest załączników (filename, content_type, size, sha256) od dnia zero
  • batch inserty, idempotentny, --limit, epoch_fallback, statystyki załączników
  • 24 testy jednostkowe, wszystkie zielone
  • Google Takeout ~27 GB mbox — do transferu SOLARIA→PIHA + uruchomienia

Następny krok: transfer Takeout SOLARIA→PIHA (rsync Tailscale) → dry-run → próbka --limit 200 → pełny wlew ionice -c 3 nice -n 19. Szczegóły kolejności: kb-01-email-design.md §8.