mindnet/docs/archiv/mindnet_v2_implementation_playbook.md
2025-12-09 17:11:03 +01:00

17 KiB
Raw Blame History

mindnet v2 Implementierungs-Playbook & Handover (SidebySide zu v1)

Stand: 2025-11-10 08:03
Autor: ChatGPT (ProjektHandover)
Zweck: Vollständige, ausführbare Anleitung zur Weiterentwicklung von mindnet auf eine versionierte, testbare v2Architektur (neben v1), inklusive Prompt für den Folgethread, Akzeptanzkriterien, Dateiliste, Test und RollbackPläne.


0) Kontext & Zielbild (kurz)

  • Mission: Persönliches Wissensnetz, das langfristig die eigene Persönlichkeit, Erfahrungen und Entscheidungslogik abbildet; später nachvollziehbare Erklärungen für Familie/Nachwelt.
  • Heutiger Stand (v1): mindnet_notes in Qdrant vorhanden; Chunks und Edges bisher nur teilweise/nicht konsistent; EdgeDefaults („1 Dot“) vorhanden, aber Ziele teils nicht materialisiert. Importskripte: import_markdown.py, edges.py (historisch).
  • Ziel (v2):
    • Collections: mindnet_notes_v2, mindnet_chunks_v2, mindnet_edges_v2 (saubere PayloadSchemata + Indizes).
    • Chunker v2: Block/Headingaware, Ziel 9001200 Zeichen, Überlappung 120180, deterministische chunk_ids.
    • EdgeBuilder v2: Reihenfolge: explicit → rule → default_resolved → default; saubere provenance.
    • ImporterPipeline v2: Parse → Chunk → Edge → Embeddings → BatchUpsert + PayloadIndexpflege + Snapshots.
    • Policies: Privacy/Recency/TypeGewichte als Konfiguration (YAML + JSONSchema), nicht hart im Code.
    • Observability: FastAPI + OpenTelemetry (Tracing/Metrics); ImportReports (CSV/JSON).
    • SidebySide: v2 parallel zu v1; kein BigBang.

Warum so? QdrantPayloadIndizes/Filter → schnelle, erklärbare Selektionen; Snapshots → betriebssicheres Rollback; OTel → Nachvollziehbarkeit; YAML/JSONSchema → Validierbarkeit & Stabilität.

0.1 Aktueller Implementierungsstand (2025-11-18)

  • Es existiert eine produktive mindnet-Instanz mit den Collections:
    • ${prefix}_notes
    • ${prefix}_chunks
    • ${prefix}_edges
  • Import-Pipeline:
    • scripts/import_markdown.py erzeugt Notes, Chunks und Edges vollständig.
    • types.yaml definiert per Note-Typ:
      • retriever_weight
      • chunk_profile
      • edge_defaults (z. B. depends_on, related_to).
  • Edges:
    • Strukturkanten: belongs_to, next, prev
    • Explizite Kanten aus Wikilinks: kind="references", rule_id="explicit:wikilink"
    • Typbasierte Default-Kanten aus edge_defaults: rule_id="edge_defaults:<type>:<relation>"
    • Inline-Kanten im Format [[rel:<relation> <Zielnote>]] mit rule_id="inline:rel"
    • alle Edges tragen eine confidence im Bereich [0,1] als Hinweis für spätere Ranking-Logiken.
  • Tests:
    • tests/test_edges_smoke.py, tests/test_edges_all.py und scripts/edges_full_check.py validieren Counts, Konsistenz (belongs_to == chunks, next/prev-Ketten, keine Duplikate) und Provenienz-Zählungen (explicit, defaults, inline, structure).
  • Offene Punkte:
    • Mehrere Ziele in einer Inline-Relation (rel: similar_to [[A]] [[B]]) sind noch nicht implementiert.
    • Retrieval-Service nutzt die neuen Edges und Weights bisher nur teilweise; ein edge-bewusster Retriever ist als nächster Schritt geplant.

1) Datenmodelle (Schemata, v2)

Die tatsächlichen JSONSchemata (202012) werden im Repo abgelegt und in CI validiert.

1.1 note.schema.json

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.org/mindnet/note.schema.json",
  "type": "object",
  "required": ["id", "title", "type", "privacy", "created", "hash_body"],
  "properties": {
    "id":           { "type": "string", "pattern": "^[a-zA-Z0-9_-]+$" },
    "title":        { "type": "string", "minLength": 1 },
    "type":         { "type": "string" }, 
    "privacy":      { "type": "string", "enum": ["public","internal","private"] },
    "created":      { "type": "string", "format": "date-time" },
    "modified":     { "type": "string", "format": "date-time" },
    "tags":         { "type": "array", "items": { "type": "string" } },
    "lang":         { "type": "string", "default": "de" },
    "source_path":  { "type": "string" },
    "source_collection": { "type": "string" },
    "hash_body":    { "type": "string" },
    "hash_frontmatter": { "type": "string" },
    "token_count":  { "type": "integer", "minimum": 0 }
  }
}

1.2 chunk.schema.json

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.org/mindnet/chunk.schema.json",
  "type": "object",
  "required": ["chunk_id","note_id","text","ord"],
  "properties": {
    "chunk_id":      { "type": "string", "pattern": "^[a-zA-Z0-9_-]+#c\d{4}$" },
    "note_id":       { "type": "string" },
    "text":          { "type": "string" },
    "ord":           { "type": "integer", "minimum": 0 },
    "span_char_start": { "type": "integer", "minimum": 0 },
    "span_char_end":   { "type": "integer", "minimum": 0 },
    "heading_path":  { "type": "array", "items": { "type": "string" } },
    "section_title": { "type": "string" },
    "tokens_start":  { "type": "integer", "minimum": 0 },
    "tokens_end":    { "type": "integer", "minimum": 0 },
    "embeddings_version": { "type": "string" }
  }
}

1.3 edge.schema.json

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.org/mindnet/edge.schema.json",
  "type": "object",
  "required": ["edge_id","src_note_id","relation","provenance"],
  "properties": {
    "edge_id":       { "type": "string" },
    "src_note_id":   { "type": "string" },
    "src_chunk_id":  { "type": "string" },
    "dst_note_id":   { "type": "string" },
    "dst_chunk_id":  { "type": "string" },
    "relation":      { "type": "string" },
    "evidence_spans":{ "type": "array", "items": {"type":"object","properties":{"chunk_id":{"type":"string"},"span":[{"type":"integer"},{"type":"integer"}]]} },
    "provenance":    { "type": "string", "enum": ["explicit","rule","default_resolved","default"] },
    "rule_id":       { "type": "string" },
    "confidence":    { "type": "number", "minimum": 0, "maximum": 1 }
  }
}

1.4 default_edge.schema.json

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.org/mindnet/default_edge.schema.json",
  "type": "object",
  "required": ["src_note_id","relation","target_kind"],
  "properties": {
    "src_note_id":  { "type": "string" },
    "relation":     { "type": "string" },
    "target_kind":  { "type": "string" }, 
    "when":         { "type": "string" }, 
    "strength_hint":{ "type": "number", "minimum": 0, "maximum": 1 }
  }
}

2) Qdrant: Collections & Indizes (v2)

Anlegen neben v1:

  • mindnet_notes_v2 (PayloadIndex: type, privacy, created, modified, tags, source_path)
  • mindnet_chunks_v2 (PayloadIndex: note_id, ord, heading_path)
  • mindnet_edges_v2 (PayloadIndex: src_note_id, dst_note_id, relation, provenance)

Snapshots für Backups/Restore einplanen (Runbook siehe unten).


3) ImportPipeline v2 Module & Flags

  • Chunker v2 (chunking/block_chunker.py): target_len=1000, overlap=150, respect_headings=True, min_chunk_len=600, max_chunk_len=1400, chunk_id = f\"{note_id}#c{ordinal:04d}\"
  • EdgeBuilder v2 (graph/edge_builder_v2.py): Reihenfolge explicit → rule → default_resolved → default, provenance korrekt setzen.
  • Importer (scripts/import_markdown.py erweitern oder scripts/import_markdown_v2.py):
    Flags: --schema v2, --chunker v2, --edges v2, --dry-run, --apply, --prefix "$COLLECTION_PREFIX".

BeispielRun (dryrun):

python3 -m scripts.import_markdown_v2 --vault ./vault --schema v2 --chunker v2 --edges v2 --dry-run --prefix "$COLLECTION_PREFIX"

Apply:

python3 -m scripts.import_markdown_v2 --vault ./vault --schema v2 --chunker v2 --edges v2 --apply --prefix "$COLLECTION_PREFIX"

4) Policies (konfigurierbar, kein HardCode)

  • policies/retrieval.schema.json (JSONSchema) und policies/retrieval.yaml, z.B.:
privacy_order: [private, internal, public]
recency_boost_half_life_days: 90
type_priority:
  person: 1.2
  event: 1.1
  concept: 1.0
max_chunks_per_note: 8
edge_provenance_weights:
  explicit: 1.0
  rule: 0.8
  default_resolved: 0.6
  default: 0.2
rule_sets:
  - id: "rules:types-v1"
    enabled: true

5) Observability & Reports

  • FastAPI + OpenTelemetry: Traces um Phasen parse/chunk/edge/upsert; Metriken (Counter/Histogramme) pro Phase.
  • ImportReport je Lauf (CSV/JSON): counts für Notes/Chunks/Edges, Fehler, Dauer, EmbeddingVersion.

6) Teststrategie

  • GoldNotizen (35 repräsentative .md) mit erwarteten ChunkCounts und EdgeSets.
  • Regression: fixer SollCount (z.B. 171 ± 15%) über GesamtVault; keine Duplikate (src,relation,dst).
  • DryRun vs Apply: identische Counts, nur ohne Upserts.
  • FilterSmokeTests: QdrantFilter nach privacy, type, tags, created funktionieren performant.

7) Akzeptanzkriterien (KPI)

  1. ChunkQualität: ≥ 90% der Chunks enden an semantischen Grenzen; ZielLänge 9001200 Zeichen; deterministische IDs.
  2. EdgeKohärenz: Keine Duplikate gleicher (src,relation,dst); ≥ 95% der expliziten Links materialisiert; default nur, wenn kein Ziel existiert.
  3. Filterbarkeit: Queries nach privacy/type/tags/created performant (PayloadIndex vorhanden).
  4. Betriebsfestigkeit: Telemetrie aktiv; fehlertoleranter Import; QdrantSnapshot nach erfolgreichem Lauf.

8) Roadmap in kleinen, testbaren Schritten

Step 0 Safeguards

  • QdrantSnapshot v1 erstellen + RestoreProbe.
  • ENV: MINDNET_SCHEMA_VERSION=2 (Importer wird v2 schreiben, v1 bleibt unberührt).

Step 1 Schemata (nur Dateien)

  • Ablage: /schemas/note.schema.json, /schemas/chunk.schema.json, /schemas/edge.schema.json, /schemas/default_edge.schema.json
  • CIJob: make schema-validate (jsonschema).
  • Abnahme: Validator grün auf 3 GoldNotizen.

Step 2 Qdrant v2Collections (Optional)

  • Anlegen der 3 v2Collections + PayloadIndizes.
  • Abnahme: FilterQuery liefert erwartbare Ergebnisse.

Step 2a Edge-Pipeline v1 stabilisieren (ERLEDIGT)

  • Ziel: Vollständige Generierung von Struktur-, expliziten, typbasierten und Inline-Kanten in den bestehenden Collections ${prefix}_notes, ${prefix}_chunks, ${prefix}_edges.
  • Status: Implementiert und durch tests/test_edges_smoke.py, tests/test_edges_all.py und scripts/edges_full_check.py verifiziert.

Step 3 Chunker v2

  • Implementierung & Flag --chunker v2.
  • Abnahme: ChunkCounts ~ alt (≈171 ± 15%), semantische Schnitte.

Step 4 EdgeBuilder v2

  • Reihenfolge & provenance strikt umsetzen, default_resolved integrieren.
  • Abnahme: erwartete Relationensätze auf GoldNotizen, keine Duplikate.

Step 4a Edge-bewusster Retriever

  • Implementiere einen Retrieval-Service, der:
    • Chunks über Vektor-Suche aus ${prefix}_chunks holt,
    • dazu passende Nachbar-Chunks (next/prev) und typrelevante Notizen (edge_defaults, Inline-Relationen, Wikilinks) über ${prefix}_edges ergänzt,
    • retriever_weight und confidence beim Scoring berücksichtigt.
  • Liefere einen API-Endpoint /mindnet/query mit einem einfachen JSON-Response (Chunks + Begründung).
  • Akzeptanz:
    • mindestens ein Testfall mit dem Relations-Showcase-Vault,
    • sichtbarer Einfluss von edge_defaults und Inline-Relationen auf die Ergebnisliste.

Step 5 ImporterPipeline v2

  • --schema v2 SidebySide; BatchUpserts; vollständige Payloads; RecencyBoost Konfig nur in Policy.
  • Abnahme: DryRun/ApplyParität, Reports, TelemetrieEreignisse sichtbar.

Step 6 Observability

  • OTelInstrumentierung + /import/status + Reports.
  • Abnahme: Traces & Metriken vorhanden.

Step 7 Snapshots & Runbook

  • Snapshot nach Erfolg; RestoreDokument.
  • Abnahme: RestoreProbe erfolgreich.

Step 8 Policies

  • policies/retrieval.yaml + JSONSchema; A/BTest (Policy ändern → Retrieval ändert sich ohne Reimport).
  • Abnahme: Sichtbarer Effekt laut Testfall.

Step 9 Umschalten

  • AbnahmeDoku, KPIDelta dokumentiert; Alias/FlagSwitch auf v2.
  • Abnahme: Funktionale Gleichwertigkeit + Qualitätsgewinn.

9) Dateien (neu/ändern)

Neu:

  • schemas/note.schema.json
  • schemas/chunk.schema.json
  • schemas/edge.schema.json
  • schemas/default_edge.schema.json
  • policies/retrieval.schema.json
  • policies/retrieval.yaml
  • chunking/block_chunker.py
  • graph/edge_builder_v2.py
  • docs/OPERATIONS.md (Snapshots/Restore/Runbook)
  • tests/gold_notes/manifest.yaml (+ 35 Notizen Kopien)

Änderungen:

  • scripts/import_markdown.py oder scripts/import_markdown_v2.py neu (Flags --schema/--chunker/--edges).
  • edges.py (falls weiterverwendet): auf v2EdgeBuilder migrieren oder auslaufen lassen.
  • types.yaml: RegelDefinitionen klarisieren (IDs, Bedingungen), nicht hart in Code.

10) BeispielKommandos

# Step 2: Collections prüfen
curl -s http://127.0.0.1:6333/collections | jq

# Step 3: Chunker v2 (dry-run)
python3 -m scripts.import_markdown_v2 --vault ./vault --schema v2 --chunker v2 --edges v2 --dry-run --prefix "$COLLECTION_PREFIX"

# Step 5: Apply + Report
python3 -m scripts.import_markdown_v2 --vault ./vault --schema v2 --chunker v2 --edges v2 --apply --prefix "$COLLECTION_PREFIX" --report ./reports/import_$(date +%F_%H%M).json

11) Rollback

  • v2Collections droppen (wenn SidebySide).
  • Aus Snapshot wiederherstellen (v1).
  • Flags zurück auf v1.

12) Referenzen (offizielle Quellen)


13) PROMPT für den neuen Chat (bitte exakt so einfügen)

Rolle: Du bist mein SeniorEntwickler & Architekt für mindnet. Arbeite strikt in kleinen, testbaren Schritten (SidebySide v2 neben v1). Liefere komplette Dateien als Downloads. Frage immer zuerst nach den **aktuellsten** Projektdateien, wenn du sie brauchst (z.B. import_markdown.py, edges.py, types.yaml), ändere keine Systemfunktion „workaroundartig“ ohne die Gesamtwirkung zu prüfen.

Kontext (Kurzfassung):
- v1 hat nur mindnet_notes zuverlässig. Chunks/Edges sind inkonsistent/teilweise leer. Ziel: v2 mit drei Collections (notes/chunks/edges), neuem Chunker v2, EdgeBuilder v2 (explicit → rule → default_resolved → default), Policies (YAML), Observability (OTel), Snapshots. Kein BigBang; v2 parallel zu v1.
- Siehe angehängte Datei **mindnet_v2_implementation_playbook.md** (Pfad/Download im Chat). Alles daraus ist verbindlich.

Deine ersten Aufgaben (StepbyStep):
1) **Schemata anlegen (Step 1)**  
   - Erstelle die Dateien:  
     - schemas/note.schema.json  
     - schemas/chunk.schema.json  
     - schemas/edge.schema.json  
     - schemas/default_edge.schema.json  
   - Nutze die in der PlaybookDatei vorgegebenen Strukturen als Basis.  
   - Liefere zusätzlich ein einfaches `Makefile`Ziel `schema-validate` (jsonschema via Python), plus `requirements.txt`.  
   - Output: komplette Dateien als Downloads + kurze Testanleitung.

2) **Qdrant v2Collections (Step 2)**  
   - Erzeuge die Collections + PayloadIndizes.  
   - Liefere ein kleines PythonSkript `tools/qdrant_bootstrap_v2.py`, das diese Anlage idempotent durchführt (inkl. PrüfOutput).

3) **Chunker v2 (Step 3)**  
   - Implementiere `chunking/block_chunker.py` mit den im Playbook genannten Parametern.  
   - Teste gegen 3 GoldNotizen (liefere mini TestHarness in `tests/gold_notes/…`).

Arbeitsweise:
- Jede Aufgabe einzeln, mit klaren Akzeptanzkriterien (aus Playbook) und DownloadArtefakten.  
- Keine parallelen Großumbauten.  
- Immer deterministische IDs, idempotente Upserts.

Dateien, die ich dir anfänglich bereitstelle:
- **mindnet_v2_implementation_playbook.md** (diese Datei)  
- **import_markdown.py** (aktuelle Version aus dem Projekt)  
- **edges.py** (aktuelle Version aus dem Projekt)  
- **types.yaml** (aktuelle Version)

Sage mir jeweils, welche Datei du als Nächstes brauchst. Beginne jetzt mit Aufgabe 1 (Schemata).