diff --git a/public/architecture.html b/public/architecture.html new file mode 100644 index 0000000..6b08b30 --- /dev/null +++ b/public/architecture.html @@ -0,0 +1,14935 @@ + + + + + + + Poimen Memory System Diagram + + + + + + + + +
+ +
+
+
+

Poimen Memory System

+
+
+ + + + + + + +
+ + Poimen Memory System + An architecture diagram generated by Archify. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AI Agent · LLM client · Architecture component + + + + AI Agent + LLM client + + + + Memory API · actix-web :8080 · K8s: poimen · Rust + + + + Memory API + actix-web :8080 + Rust + + + + Authentik · OIDC / JWT · K8s: poimen + + + + Authentik + OIDC / JWT + + + + Ingest Worker · LLM pipeline · K8s: poimen + + + + Ingest Worker + LLM pipeline + + + + LLM · ornith:35b · Architecture component + + + + LLM + ornith:35b + + + + pgvector · CNPG cluster · K8s: poimen · HNSW + + + + pgvector + CNPG cluster + HNSW + + + + Embeddings · nomic-embed · K8s: poimen + + + + Embeddings + nomic-embed + + + + + + HTTP + + + + verify JWT + + + + enqueue + + + + extract + + + + persist + + + + embed + + + + search + + + + + + K8s: poimen + + + + + Legend + + + Backend + + + + Database + + + + Security + + + + External + + + +

+ + + + + + + + + +
+ + +
+
+
+
+

Ingest

+
+
    +
  • • Conversations ingested via HTTP
  • +
  • • LLM extracts entities + relationships
  • +
  • • Temporal graph persisted to pgvector
  • +
+
+ +
+
+
+

Retrieval

+
+
    +
  • • HNSW cosine similarity search
  • +
  • • BFS graph traversal for context
  • +
+
+ +
+
+
+

Auth

+
+
    +
  • • Authentik OIDC JWT verification
  • +
  • • SOPS-encrypted K8s secrets
  • +
+
+
+ +
+ + + + diff --git a/public/architecture.json b/public/architecture.json new file mode 100644 index 0000000..2f4295c --- /dev/null +++ b/public/architecture.json @@ -0,0 +1,35 @@ +{ + "schema_version": 1, + "diagram_type": "architecture", + "meta": { + "title": "Poimen Memory System", + "quality_profile": "showcase", + "viewBox": [1060, 560] + }, + "components": [ + { "id": "agent", "type": "external", "label": "AI Agent", "sublabel": "LLM client", "pos": [40, 220], "size": [130, 60] }, + { "id": "api", "type": "backend", "label": "Memory API", "sublabel": "actix-web :8080", "pos": [270, 220], "size": [140, 60], "tag": "Rust" }, + { "id": "auth", "type": "security", "label": "Authentik", "sublabel": "OIDC / JWT", "pos": [270, 60], "size": [140, 60] }, + { "id": "worker", "type": "backend", "label": "Ingest Worker", "sublabel": "LLM pipeline", "pos": [540, 220], "size": [140, 60] }, + { "id": "llm", "type": "external", "label": "LLM", "sublabel": "ornith:35b", "pos": [540, 380], "size": [140, 60] }, + { "id": "pgvector", "type": "database", "label": "pgvector", "sublabel": "CNPG cluster", "pos": [540, 60], "size": [140, 60], "tag": "HNSW" }, + { "id": "embed", "type": "external", "label": "Embeddings", "sublabel": "nomic-embed", "pos": [810, 220], "size": [140, 60] } + ], + "boundaries": [ + { "kind": "region", "label": "K8s: poimen", "wraps": ["api", "auth", "worker", "pgvector", "embed"] } + ], + "connections": [ + { "id": "c1", "from": "agent", "to": "api", "label": "HTTP", "variant": "emphasis" }, + { "id": "c2", "from": "api", "to": "auth", "label": "verify JWT", "variant": "security" }, + { "id": "c3", "from": "api", "to": "worker", "label": "enqueue", "labelAt": [445, 178] }, + { "id": "c4", "from": "worker", "to": "llm", "label": "extract", "labelAt": [630, 356] }, + { "id": "c5", "from": "worker", "to": "pgvector", "label": "persist" }, + { "id": "c6", "from": "worker", "to": "embed", "label": "embed", "variant": "dashed" }, + { "id": "c7", "from": "api", "to": "pgvector", "label": "search", "variant": "emphasis" } + ], + "cards": [ + { "dot": "emerald", "title": "Ingest", "items": ["Conversations ingested via HTTP", "LLM extracts entities + relationships", "Temporal graph persisted to pgvector"] }, + { "dot": "cyan", "title": "Retrieval", "items": ["HNSW cosine similarity search", "BFS graph traversal for context"] }, + { "dot": "rose", "title": "Auth", "items": ["Authentik OIDC JWT verification", "SOPS-encrypted K8s secrets"] } + ] +} diff --git a/public/dataflow.html b/public/dataflow.html new file mode 100644 index 0000000..8af4cb3 --- /dev/null +++ b/public/dataflow.html @@ -0,0 +1,14933 @@ + + + + + + + Poimen Ingest Pipeline Diagram + + + + + + + + +
+ +
+
+
+

Poimen Ingest Pipeline

+
+
+ + + + + + + +
+ + Poimen Ingest Pipeline + A data-flow diagram generated by Archify. + + + + + + + + + + + + + + + + + + + + + + + + + 01 / Input + + + 02 / Extract + + + 03 / Store + + + 04 / Serve + + + + + + + + + + + + Episode · conversation text · 01 / Input · messages + + + + Episode + conversation text + messages + + + + Entity Extractor · LLM + reflection · 02 / Extract · person / tool + + + + Entity Extractor + LLM + reflection + person / tool + + + + Fact Extractor · LLM relationships · 02 / Extract · edges + + + + Fact Extractor + LLM relationships + edges + + + + Temporal Graph · pgvector · 03 / Store · HNSW + + + + Temporal Graph + pgvector + HNSW + + + + Query API · hybrid search · 04 / Serve · BFS + cosine + + + + Query API + hybrid search + BFS + cosine + + + + Visualization · React Flow · 04 / Serve · graph UI + + + + Visualization + React Flow + graph UI + + + + + + text + ingest + + + + text + ingest + + + + persist nodes + write + + + + persist edges + write + + + + search + read + + + + graph data + read + + + + + Legend + + + primary data + + + + async batch + + + + data store + + + + data flow + + + +

+ + + + + + + + + +
+ + +
+
+
+
+

Extraction

+
+
    +
  • • LLM extracts entities with type + summary
  • +
  • • Second LLM call extracts edges between entities
  • +
  • • Reflection filters hallucinated entities
  • +
+
+ +
+
+
+

Storage

+
+
    +
  • • Temporal graph with bi-temporal edges
  • +
  • • 768-dim HNSW embeddings for similarity
  • +
+
+ +
+
+
+

Retrieval

+
+
    +
  • • BFS traversal + cosine similarity
  • +
  • • React Flow JSON for interactive graph
  • +
+
+
+ +
+ + + + diff --git a/public/dataflow.json b/public/dataflow.json new file mode 100644 index 0000000..cbaaaf6 --- /dev/null +++ b/public/dataflow.json @@ -0,0 +1,36 @@ +{ + "schema_version": 1, + "diagram_type": "dataflow", + "meta": { + "title": "Poimen Ingest Pipeline", + "quality_profile": "showcase", + "viewBox": [1020, 540] + }, + "stages": [ + { "label": "Input" }, + { "label": "Extract" }, + { "label": "Store" }, + { "label": "Serve" } + ], + "nodes": [ + { "id": "episode", "type": "external", "label": "Episode", "sublabel": "conversation text", "stage": 0, "row": 1, "tag": "messages" }, + { "id": "entities", "type": "backend", "label": "Entity Extractor", "sublabel": "LLM + reflection", "stage": 1, "row": 0, "tag": "person / tool" }, + { "id": "facts", "type": "backend", "label": "Fact Extractor", "sublabel": "LLM relationships", "stage": 1, "row": 2, "tag": "edges" }, + { "id": "graph", "type": "database", "label": "Temporal Graph", "sublabel": "pgvector", "stage": 2, "row": 1, "tag": "HNSW" }, + { "id": "query", "type": "backend", "label": "Query API", "sublabel": "hybrid search", "stage": 3, "row": 0, "tag": "BFS + cosine" }, + { "id": "viz", "type": "frontend", "label": "Visualization", "sublabel": "React Flow", "stage": 3, "row": 2, "tag": "graph UI" } + ], + "flows": [ + { "id": "f1", "from": "episode", "to": "entities", "label": "text", "classification": "ingest", "variant": "emphasis" }, + { "id": "f2", "from": "episode", "to": "facts", "label": "text", "classification": "ingest", "variant": "default" }, + { "id": "f3", "from": "entities", "to": "graph", "label": "persist nodes", "classification": "write", "variant": "emphasis" }, + { "id": "f4", "from": "facts", "to": "graph", "label": "persist edges", "classification": "write", "variant": "emphasis" }, + { "id": "f5", "from": "graph", "to": "query", "label": "search", "classification": "read", "variant": "emphasis" }, + { "id": "f6", "from": "graph", "to": "viz", "label": "graph data", "classification": "read", "variant": "dashed" } + ], + "cards": [ + { "dot": "emerald", "title": "Extraction", "items": ["LLM extracts entities with type + summary", "Second LLM call extracts edges between entities", "Reflection filters hallucinated entities"] }, + { "dot": "cyan", "title": "Storage", "items": ["Temporal graph with bi-temporal edges", "768-dim HNSW embeddings for similarity"] }, + { "dot": "orange", "title": "Retrieval", "items": ["BFS traversal + cosine similarity", "React Flow JSON for interactive graph"] } + ] +} diff --git a/public/sequence.html b/public/sequence.html new file mode 100644 index 0000000..6d31f5e --- /dev/null +++ b/public/sequence.html @@ -0,0 +1,15025 @@ + + + + + + + Poimen Ingest Request Lifecycle Diagram + + + + + + + + +
+ +
+
+
+

Poimen Ingest Request Lifecycle

+
+
+ + + + + + + +
+ + Poimen Ingest Request Lifecycle + A sequence diagram generated by Archify. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + POST /memory/ingest + + + + + + + + enqueue job + + + + + + + + 202 pending + + + + + + + + poll job + + + + + + + + episode records + + + + + + + + extract entities + + + + + + + + JSON entities + + + + + + + + extract facts (entity pairs) + + + + + + + + JSON edges + + + + + + + + INSERT memory_entity + + + + + + + + INSERT memory_edge + + + + + + + + store embeddings + + + + + + + + mark done + + + + + + + Ingest + + + + Extraction + + + + Persist + + + + + AI Agent · client · Sequence participant + + + + AI Agent + client + + + + Memory API · actix-web · Sequence participant + + + + Memory API + actix-web + + + + Queue · ingest jobs · Sequence participant + + + + Queue + ingest jobs + + + + Worker · pipeline · Sequence participant + + + + Worker + pipeline + + + + LLM · Ollama · Sequence participant + + + + LLM + Ollama + + + + pgvector · postgres · Sequence participant + + + + pgvector + postgres + + + + + Legend + + + request + + + + return + + + + async trace + + + + default message + + + +

+ + + + + + + + + +
+ + +
+
+
+
+

Async Ingest

+
+
    +
  • • Agent gets 202 immediately, no blocking
  • +
  • • Worker polls jobs from queue independently
  • +
  • • Decoupled ingest from extraction latency
  • +
+
+ +
+
+
+

LLM Extraction

+
+
    +
  • • First call: extract named entities with types
  • +
  • • Second call: extract relationships between entity pairs
  • +
  • • JSON response cleaned of thinking tags and fences
  • +
+
+ +
+
+
+

Persistence

+
+
    +
  • • Entities saved with type, summary, confidence
  • +
  • • Edges saved with temporal fields (t_valid, t_invalid)
  • +
  • • Embeddings stored for vector similarity search
  • +
+
+
+ +
+ + + + diff --git a/public/sequence.json b/public/sequence.json new file mode 100644 index 0000000..6f551da --- /dev/null +++ b/public/sequence.json @@ -0,0 +1,51 @@ +{ + "schema_version": 1, + "diagram_type": "sequence", + "meta": { + "title": "Poimen Ingest Request Lifecycle", + "quality_profile": "showcase", + "viewBox": [1020, 620], + "column_fit": "spread" + }, + "participants": [ + { "id": "agent", "type": "external", "label": "AI Agent", "sublabel": "client" }, + { "id": "api", "type": "backend", "label": "Memory API", "sublabel": "actix-web" }, + { "id": "queue", "type": "messagebus", "label": "Queue", "sublabel": "ingest jobs" }, + { "id": "worker", "type": "backend", "label": "Worker", "sublabel": "pipeline" }, + { "id": "llm", "type": "external", "label": "LLM", "sublabel": "Ollama" }, + { "id": "db", "type": "database", "label": "pgvector", "sublabel": "postgres" } + ], + "segments": [ + { "from": 150, "to": 240, "label": "Ingest" }, + { "from": 250, "to": 440, "label": "Extraction" }, + { "from": 450, "to": 560, "label": "Persist" } + ], + "messages": [ + { "id": "ingest-req", "from": "agent", "to": "api", "y": 160, "label": "POST /memory/ingest", "variant": "emphasis" }, + { "id": "enqueue", "from": "api", "to": "queue", "y": 185, "label": "enqueue job", "variant": "default" }, + { "id": "accept", "from": "api", "to": "agent", "y": 210, "label": "202 pending", "variant": "return" }, + { "id": "poll", "from": "worker", "to": "queue", "y": 258, "label": "poll job", "variant": "default" }, + { "id": "job", "from": "queue", "to": "worker", "y": 290, "label": "episode records", "variant": "return" }, + { "id": "extract-entities", "from": "worker", "to": "llm", "y": 315, "label": "extract entities", "variant": "emphasis" }, + { "id": "entities-resp", "from": "llm", "to": "worker", "y": 345, "label": "JSON entities", "variant": "return" }, + { "id": "extract-facts", "from": "worker", "to": "llm", "y": 375, "label": "extract facts (entity pairs)", "variant": "emphasis" }, + { "id": "facts-resp", "from": "llm", "to": "worker", "y": 405, "label": "JSON edges", "variant": "return" }, + { "id": "save-entities", "from": "worker", "to": "db", "y": 460, "label": "INSERT memory_entity", "variant": "default" }, + { "id": "save-edges", "from": "worker", "to": "db", "y": 490, "label": "INSERT memory_edge", "variant": "default" }, + { "id": "embed", "from": "worker", "to": "db", "y": 520, "label": "store embeddings", "variant": "dashed" }, + { "id": "done", "from": "worker", "to": "queue", "y": 535, "label": "mark done", "variant": "return" } + ], + "activations": [ + { "participant": "api", "from": 155, "to": 220, "type": "backend" }, + { "participant": "queue", "from": 180, "to": 295, "type": "messagebus" }, + { "participant": "worker", "from": 255, "to": 555, "type": "backend" }, + { "participant": "llm", "from": 310, "to": 350, "type": "external" }, + { "participant": "llm", "from": 370, "to": 410, "type": "external" }, + { "participant": "db", "from": 455, "to": 530, "type": "database" } + ], + "cards": [ + { "dot": "emerald", "title": "Async Ingest", "items": ["Agent gets 202 immediately, no blocking", "Worker polls jobs from queue independently", "Decoupled ingest from extraction latency"] }, + { "dot": "cyan", "title": "LLM Extraction", "items": ["First call: extract named entities with types", "Second call: extract relationships between entity pairs", "JSON response cleaned of thinking tags and fences"] }, + { "dot": "orange", "title": "Persistence", "items": ["Entities saved with type, summary, confidence", "Edges saved with temporal fields (t_valid, t_invalid)", "Embeddings stored for vector similarity search"] } + ] +}