Skip to main content

llm_kernel/graph/
mod.rs

1//! AI agent memory graph — SQLite/PostgreSQL-backed long-term memory with FTS5
2//! search, smart recall, and graph-structured relevance boosting.
3//!
4//! The module is tuned for agent *memory*: nodes carry importance and decaying
5//! recency/access signals, and are recalled by composite scoring (recency +
6//! importance + access + FTS + graph boost), with CSR algorithms ([`algo`])
7//! surfacing structurally central memories. The niche is comparable to
8//! **Zep / Mem0 / Letta**, but local-first and vault-based rather than a hosted
9//! service.
10//!
11//! From v0.19 the trait also serves **general directed-graph workloads** —
12//! citation networks, document backlinks, dependency graphs — via batch edge
13//! writes ([`GraphBackend::append_edges`]), directional / relation-filtered
14//! lookups ([`GraphBackend::edges_for_node_dir`],
15//! [`GraphBackend::neighbors_weighted`]), and filtered BFS
16//! ([`GraphBackend::related_nodes_filtered`]); [`EdgeDirection`] selects
17//! out / in / both. For pure topology with no memory semantics, `petgraph` or
18//! a graph database remains a better fit.
19//!
20//! Provides a complete knowledge graph layer on top of SQLite:
21//!
22//! - **Types**: [`GraphNode`], [`GraphEdge`], [`ScoredNode`], [`GraphStats`]
23//! - **Schema**: [`init_graph_schema`] — creates tables, FTS5, indexes
24//! - **CRUD**: node/edge insert, read, update, delete
25//! - **Search**: FTS5 full-text search and dynamic filtering
26//! - **Recall**: [`smart_recall`] — composite scoring with recency, importance, access, FTS, graph boost
27//! - **Traversal**: [`graph_neighbors`] (1-hop), [`related_nodes`] (BFS via recursive CTE)
28//! - **Algorithms**: pure-Rust CSR algorithms in [`algo`] — [`pagerank()`], [`connected_components()`], [`label_propagation()`], [`dijkstra()`], [`jaccard_similarity()`]
29//! - **Lifecycle**: [`decay_importance`], [`tag_stale_nodes`], [`compute_stats`]
30//!
31//! All functions take `&rusqlite::Connection` — no hardcoded paths.
32//!
33//! ```no_run
34//! use rusqlite::Connection;
35//! use llm_kernel::graph::{init_graph_schema, upsert_node, smart_recall, GraphNode};
36//!
37//! let conn = Connection::open_in_memory().unwrap();
38//! init_graph_schema(&conn).unwrap();
39//!
40//! upsert_node(&conn, &GraphNode {
41//!     id: "rust-ownership".into(),
42//!     node_type: "concept".into(),
43//!     title: "Rust Ownership Model".into(),
44//!     body: "Ownership, borrowing, and lifetimes...".into(),
45//!     tags: vec!["rust".into(), "memory-safety".into()],
46//!     projects: vec!["my-project".into()],
47//!     agents: vec![],
48//!     created: "2026-01-01T00:00:00Z".into(),
49//!     updated: "2026-01-01T00:00:00Z".into(),
50//!     importance: 0.8,
51//!     access_count: 0,
52//!     accessed_at: String::new(),
53//! }).unwrap();
54//!
55//! let results = smart_recall(&conn, Some("my-project"), Some("ownership"), 5).unwrap();
56//! for scored in &results {
57//!     println!("{:.2} — {}", scored.score, scored.node.title);
58//! }
59//! ```
60
61pub mod algo;
62pub mod backend;
63pub mod dedup;
64pub mod lifecycle;
65pub mod recall;
66pub mod schema;
67pub mod search;
68pub mod store;
69pub mod traversal;
70pub mod types;
71
72/// CJK-aware graph search (Rust-side segmentation; no schema change).
73#[cfg(feature = "graph-cjk")]
74pub mod cjk;
75
76/// PostgreSQL `GraphBackend` (feature `graph-pg`).
77#[cfg(feature = "graph-pg")]
78pub mod pg;
79
80#[cfg(feature = "graph-async")]
81pub mod async_graph;
82
83#[cfg(feature = "graph-pool")]
84pub mod async_pool;
85#[cfg(feature = "graph-pool")]
86pub use async_pool::AsyncPoolGraph;
87
88// Re-export primary types and functions
89pub use algo::{
90    CsrGraph, LABEL_PROPAGATION_ITERS, PAGERANK_DAMPING, PAGERANK_EPS, PAGERANK_ITERS,
91    SHORTEST_PATH_W_MIN, adamic_adar, common_neighbors, connected_components, dijkstra,
92    jaccard_similarity, label_propagation, label_propagation_default, link_prediction, pagerank,
93    pagerank_default, pagerank_scores, shortest_path, shortest_path_ids,
94};
95pub use backend::{GraphBackend, SqliteGraph};
96pub use dedup::{find_duplicate, upsert_node_dedup};
97pub use lifecycle::{compute_stats, decay_importance, tag_stale_nodes, touch_node, touch_nodes};
98pub use recall::smart_recall;
99pub use schema::{GRAPH_SCHEMA_VERSION, init_graph_schema, migrate_graph, schema_version};
100pub use search::{query_nodes, search_nodes};
101pub use store::{
102    append_edge, delete_edge, delete_node, read_edges, read_node, read_nodes, upsert_node,
103};
104pub use traversal::{build_graph, graph_neighbors, related_nodes};
105pub use types::{
106    EdgeDirection, Graph, GraphEdge, GraphNode, GraphNodeSummary, GraphStats, ScoredNode,
107    validate_uuid,
108};
109
110#[cfg(feature = "graph-cjk")]
111pub use cjk::{search_nodes_cjk, segment_cjk};
112
113#[cfg(feature = "graph-pg")]
114pub use pg::PgGraph;