Skip to content

feat: GraphMemory — knowledge-graph backend using NetworkX #20

@Neal006

Description

@Neal006

Background

MemoryLens currently benchmarks 7 memory backends (naive, rag, rag_chunked, cascading, summary, entity — graph is missing). A graph-based backend models facts as nodes in a directed graph, making fact-update tracking structurally explicit rather than regex-patched. Relationships like "city changed from Bangalore to Mumbai" become first-class graph edges, which enables richer traversal-based retrieval.

Key files to read first:

  • memory/base.py — the 3-method interface every backend must implement
  • memory/entity.py — the closest existing example (regex extraction + key-value store)
  • evaluation/benchmark.py_make_memory() and VALID_BACKENDS (where to register the backend)
  • docs/adding-a-new-backend.md — the full 4-step contributor guide

What to build

memory/graph.py — new file

class GraphMemory(BaseMemory):
    name = "graph"
  • add_message(role, content, turn):

    • Extract (subject, value) pairs via regex matching injection ("my <key> is <value>") and update ("my <key> has changed to <value>") patterns
    • On injection: add a node {subject, value, role, turn, valid=True, valid_from=turn}
    • On update: set valid=False, valid_until=turn on all existing nodes with the same subject, then add a fresh node
    • Add directed edge: entity:<subject><node_id> with predicate="has_value"
  • get_context(query, current_turn):

    • Tokenise query into word set
    • Return all valid nodes whose subject overlaps with query tokens
    • Fallback: return all valid nodes if no overlap found
    • Return format: [{"role": "system", "content": "[Graph Memory] my X is Y; ..."}]
  • reset(): self.graph.clear()

evaluation/benchmark.py

  • Add "graph" to VALID_BACKENDS
  • Add GraphMemory() case in _make_memory()

main.py

  • Update --backends help text to include graph
  • Add graph usage example in the module docstring

requirements.txt + pyproject.toml

  • Add networkx>=3.0

Acceptance criteria

  • memory/graph.py exists and from memory.graph import GraphMemory works
  • GraphMemory implements add_message, get_context, reset matching BaseMemory
  • After a fact update, the old node has valid=False in the graph
  • python main.py --backends naive graph cascading --turns 50 runs without error
  • "graph" present in VALID_BACKENDS
  • 3 new tests added to tests/test_pipeline.py:
    • test_graph_memory_recall_early() — recall ≥ 75% at T=15
    • test_graph_memory_no_stale_after_update() — old node has valid=False
    • test_graph_benchmark_registration()_make_memory("graph") doesn't raise
  • All 24 existing tests still pass (pytest tests/ -v)

Technical hints

  • Use networkx.DiGraph() — add it explicitly to requirements even if it's a transitive dep
  • Node ID pattern: f"{subject}:{value}:{turn}" (same style as entity.py)
  • The entity.py regex patterns are almost identical — adapt them directly
  • get_context must not make any LLM calls — pure graph traversal only
  • Return type of get_context must be List[Dict] with "role" and "content" keys

Getting started

git clone https://github.com/Neal006/memorylens
pip install -e ".[dev]"
pip install networkx
pytest tests/ -v   # make sure all 24 pass before you start

# Create memory/graph.py, then test:
python main.py --backends naive graph --turns 30

See docs/adding-a-new-backend.md for the full 4-step checklist.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions