Neuro Graph Memory
Neuro Graph Memory is a Flask-based, graph-native continual memory workspace configured around the AIVillage world and its lore.
It models learning as connected experiences (paths), reinforces repeated links, decays weak memories over time, discovers memory regions, and supports recall + associative inference from a persistent .ngm brain file.
What Neuro Graph Memory is (and is not)
- Is: a memory graph workspace for AIVillage, including its places, people, history, and stories.
- Is not: an LLM chat model.
Everything is represented as concept paths drawn from AIVillage, for example:
AIVillage -> Oakwood -> Town FountainAIVillage -> Mount Anne -> 796m ClimbOakwood -> Blake -> Village Quests
NGM → CLM: prototype to product
Continual Language Model (CLM) is the intended language-system product. Neuro Graph Memory (NGM) is prototyping its explicit, persistent memory foundation and may remain a component of that product, rather than a name to replace. NGM is not yet a complete CLM: language understanding, generation, and their integration with continual memory remain to be implemented and verified. Updating graph memory is not the same as training language-model weights.
The following is a working handoff list, not a settled CLM architecture. Revisit it as experiments establish which behaviours are useful:
| Disposition | NGM behaviours | CLM direction |
|---|---|---|
| Inherit unchanged where validated | Explicit, inspectable memory; learning new experiences without recreating the brain; reinforcement of repeated associations; persistent save/load. | Preserve these memory behaviours, with regression tests demonstrating that language integration does not break them. This does not require preserving the current file format or implementation. |
| Redesign candidates | Weight-only direct recall ranking and weight-driven spreading activation; heuristic text-to-path extraction. | Evaluate context-aware retrieval and structured language-to-memory extraction. Do not treat association strength as factual confidence or an extracted path as a verified semantic relationship. |
| Prototype-only by default | Hand-entered demo paths, artificial import-anchor stitching, and the current Flask/3D inspection workflow. | Keep these as experiments and diagnostic tools unless evidence justifies a product role; do not make them requirements of the CLM architecture. |
| Evaluate before deciding | Sleep/decay rules, dormant/forgotten states, and region consolidation. | Test retention and retrieval effects before carrying the current heuristics into CLM unchanged. |
Decision for the next workspace
Start the CLM in a clean workspace; use this repository as its behavioral reference, not as a codebase to copy wholesale. Carry forward these decisions:
- CLM is the language system; NGM is a prototype of its explicit, persistent memory capability, not the CLM itself.
- Keep learned knowledge separate from language-model weights in the first milestone. Learning new material should update persistent memory, not silently claim to train or update the language model.
- Preserve inspectable memory, incremental learning, persistence across reloads, and retrieval of earlier as well as newly learned material as requirements to test.
- Treat the graph/path memory as the initial memory baseline to evaluate, not a guaranteed final representation. Keep memory operations behind a replaceable interface so retrieval or storage can evolve without coupling them to the UI or language component.
- Make the first end-to-end milestone small: add a piece of knowledge, ask a natural-language question about it, return an answer grounded in retrieved memory, restart/reload, and verify both the new knowledge and representative earlier knowledge remain retrievable. Include missing-evidence and ambiguous query cases; do not present association strength as factual confidence.
- Bring forward NGM's tests and sample data only as fixtures and regression cases where they support that milestone. Reimplement or adapt the useful behavior deliberately rather than inheriting the current Flask app, 3D explorer, heuristic importer, artificial anchor, file format, or unvalidated decay/consolidation rules as CLM requirements.
The prototype has done its job when the handoff list is backed by measured results: retained behaviours pass regression tests, redesign candidates have evaluated replacements or documented limitations, and prototype-only shortcuts are not required for the product to work. End-to-end CLM evaluation should demonstrate that newly added knowledge persists across reloads, can be retrieved and used in language responses, and does not unacceptably degrade earlier knowledge. Success criteria and acceptable regression thresholds must be defined before claiming that outcome.
Core capabilities
1) Memory formation
- Learns new experiences as paths.
- Creates nodes/connections if missing.
- Reinforces existing connections when paths repeat.
- Tracks node activation and importance.
2) Memory maintenance (sleep)
- Synaptic decay over time.
- Node importance decay over time.
- State transitions across active/inactive/dormant/forgotten.
- Archives forgotten memories instead of hard-deleting.
- Rebuilds and consolidates clusters (regions).
3) Recall and inference
- Recall: strongest direct associations for a concept.
- Think: spreading activation over multiple hops.
- Recall supports exact matching with fuzzy assist suggestions.
4) Persistence
- Save/load full brain state to
.ngm. - The workspace's AIVillage brain is stored at
brains/aivillage.ngm.
Tech stack
- Python + Flask
- NetworkX (graph model + region detection)
- 3D Force Graph / Three.js (interactive 3D graph UI)
- PyVis support in backend graph rendering paths
Project structure (key paths)
- App entry: app.py
- Memory engine: neurograph/
- Templates: templates/
- Static styles: static/css/style.css
- AIVillage brain: brains/aivillage.ngm
- AIVillage source data: datasets/AIVillageBackgroundHistoryComplete.txt
- AIVillage dataset files: datasets/
- Launcher: launch.sh
Quick start
Prerequisites
- Python 3.10+ recommended
- macOS/Linux shell (or equivalent environment)
Install
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
Run
./launch.sh start
Open:
http://0.0.0.0:5025http://localhost:5025
Stop / restart / status
./launch.sh stop
./launch.sh restart
./launch.sh status
Logs:
Reuse visit logging in another Flask app
See visitlog.md for installation, configuration, IP forwarding, and verification details.
Copy the visitlog/ package directory into the other project, then register
the blueprint:
from visitlog import register_visitlog
register_visitlog(app)
Registration automatically forwards successful HTML GET page visits from
Flask, using the original page request's Referer header. No browser tracking
script is needed. Do not include visitlog.js in page templates: combining the
legacy browser trigger with automatic server-side logging creates duplicate visits.
API responses, static assets, downloads, redirects, errors, HEAD requests, and
POST requests are not automatically logged.
By default, visit events are forwarded to
http://127.0.0.1:5020/api/visit-trigger. Override the destination with
app.config["VISITLOG_SERVICE_URL"]; set VISIT_TRIGGER_SECRET in the app
configuration or environment to forward the optional shared secret. The client
IP is taken from X-Forwarded-For using the configured trusted proxy count
(default 1), then from X-Real-IP, and finally from the direct connection.
Set VISITLOG_TRUSTED_PROXY_COUNT in app config or the environment to match
the number of trusted proxies that append addresses to X-Forwarded-For.
Configure those proxies to overwrite or correctly append forwarding headers;
do not trust client-supplied forwarding headers when the app is directly
internet-facing.
End-to-end usage guide
1) Dashboard
Page: /
Use it to:
- View top-level memory stats:
- active nodes/synapses
- regions
- experiences
- dormant/forgotten counts
- Run a memory maintenance cycle (
Sleep). - Load the AIVillage brain.
On first startup, when no valid previous brain selection is saved, the app
loads brains/aivillage.ngm if it is available. Later startups restore the
saved selection. The active brain is shared by all visitors to the app.
2) Learn new experiences
Page: /learn
Enter a path (one concept per line or delimited flow), plus optional experience name and importance.
This writes directly into the active brain and reinforces graph structure.
3) Recall associations
Page: /recall
- Query a concept.
- Returns strongest direct neighbors ranked by synapse weight.
- Supports exact/fuzzy-assist behavior for concept resolution.
4) Infer related concepts (Think)
Page: /think
- Runs spreading activation from a concept.
- Adjustable depth.
- Returns indirectly related concepts ranked by propagated activation.
5) Manage experiences
Page: /experiences
- Inspect recorded experiences.
- Edit or delete experiences.
- Uses rebuild-safe behavior to avoid orphaned graph artifacts.
AIVillage memory chat and before/after experiments
Page: /chat
- Send a concept name or a message such as
Tell me about Mount Anne. - The message input has a neutral placeholder, with no generated example prompts.
- Fuzzy search is Off by default. Its On/Off selection persists across page
refreshes using the existing browser page-state storage. When enabled, exact
matches still take priority. Otherwise, chat removes common question prefixes
(such as
who isortell me about) and compares the remaining text with active concept names. It requires at least three normalized characters and 80% text similarity; close competing matches are suggested rather than silently chosen. A fuzzy match is labelled explicitly. This is typo assistance, not semantic question understanding. Replays retain the original prompt's search mode; changing the selector applies to new prompts. - Chat produces deterministic, template-based responses from active graph experience paths mentioning the matched concept (including mentions within imported text fragments). Up to three distinct paths are shown, prioritizing fragments that start with the subject, then exact path concepts. Source paths are available under Source experience paths. These excerpts preserve stored context, not a generated semantic answer; conflicting memories are not resolved. Without relevant paths, chat falls back to associations. Direct weights and spreading-activation evidence remain visible. The default artificial text-import anchor is excluded from chat retrieval and traversal, preventing unrelated paths being connected through that anchor. Dormant, forgotten, or disconnected portions of experience paths are not quoted. Chat does not use an LLM, learn from messages, update access counters, or save memory.
- Matching uses normalized concept names within the message, not semantic question understanding. When several names match, the longest is used (alphabetical tie-break); other mentioned names are displayed. Unknown names return an explicit no-match response with suggestions, not guessed facts.
- Edit or learn memory in another page, then return and select Ask again / Compare on the original prompt. The original response stays fixed; the latest response appears alongside it with added/removed associations and changes to scores or ranks. A changed memory revision can still yield an unchanged response when the edit does not affect that query.
- Saving a node rename with Graph → Save Node updates that concept in the active brain and its experience paths. A replay can therefore show the renamed text in Latest response and Source experience paths. This renames that graph node; it does not rewrite similar wording in separate text-fragment nodes.
- Each replay uses the same prompt and inference depth but the currently active brain. Brain switches are labelled in the comparison. Edits must be loaded into the active brain to affect responses; editing a dataset alone does not update NGM memory.
- Up to 20 original prompts and their latest comparisons are stored in browser-tab session storage, surviving navigation/reload but not tab closure. Clear history removes them. Prompts are independent, with no conversational context or pronoun resolution.
Association weights and activation scores are not factual confidence. This
feature is an inspection experiment, not a complete CLM or a factual-answering
system. The read-only JSON endpoint is POST /chat/respond with
{"message": "Tell me about Mount Anne", "depth": 3, "fuzzy_search": false} (depth 1–8, message at most
1000 characters). Each response includes a SHA-256 memory revision for comparison.
Password-protected deletion
Every Delete button (experiences, regions, NGM brain files, and datasets) opens a confirmation dialog styled to match the app. Enter the password to delete, or use Cancel / Escape to leave the item unchanged. The eye icon toggles password visibility; each new prompt starts with the password hidden.
The server reads actions["agent.delete"]["password"] from
passwords.json for each deletion. All four delete types require
this password when that entry's enabled flag is true. Setting it to false
disables password protection for deletion. Password changes take
effect immediately without restarting. Missing, empty, or invalid configuration
blocks deletion and displays an error, as does an incorrect password.
The configured password is never sent to the browser; entered passwords are not saved in page-state storage. Keep the configuration file private and use HTTPS when accessing the app over a network.
Password-protected editing
Edit/open-editor controls and saves, and graph Save Node, use the themed prompt
with actions["agent.edit"]["password"] in
passwords.json.
Set this initially empty password to enable editing. Server checks also protect
direct edit requests. See Password prompts for coverage
and authorization lifetime. Opening the dataset editor and saving a dataset use
separate authorization grants: actions["agent.dataset_save"]["password"]
protects dataset saves, so granting editor access alone does not authorize a
save. Saving an edited experience uses its own
actions["agent.experience_save"]["password"] entry. Brain-file Rename uses
the separate actions["agent.rename"]["password"] entry, and saving edited
regions uses actions["agent.region_save"]["password"].
Creating a new NGM brain uses actions["agent.create"]["password"].
6) Manage regions (clusters)
Page: /regions
- Inspect discovered regions.
- Edit/delete region metadata safely.
- Region changes trigger consistent rebuild behavior where applicable.
Dashboard maintenance password
The dashboard's Run brain.sleep() maintenance action uses actions["agent.sleep"]
in passwords.json. When enabled is true, the button prompts
for that entry's password and the server blocks unauthorized maintenance requests.
Setting enabled to false skips the prompt. Changes take effect without restarting;
missing or invalid settings block maintenance.
Learn password
The Learn page remains accessible. Its Learn Path submit button uses the
separate actions["agent.learn"] entry in passwords.json.
When enabled is true, the button prompts for the learn password, and the server
protects learning submissions. Setting enabled to false skips the prompt.
7) 3D graph explorer
Page: /graph
Features:
- Rotate/pan/zoom interactive 3D graph
- Click node to open inspector
- Node search (supports fuzzy matching)
- Save edited node metadata (name/type/state/importance/activation)
- Move view arrows
- Reset View fits the node spheres to the available canvas with a small edge margin, preserving the current viewing angle and accounting for node size. It keeps the model fitted as the force layout settles or the canvas resizes; rotating, panning, zooming, moving the view, or focusing a node cancels this automatic fitting.
- Export GLB with node spheres and connecting tubes. Export loads Three.js independently when the graph renderer does not expose it globally.
- Strongest connection list for selected node
- Built-in node color legend
Node color semantics:
- Active: green
- Inactive: gray
- Dormant: amber
- Forgotten: muted gray
- Start Concept: purple (concept appears as first item in one or more experiences)
8) AIVillage brain file
Page: /files
The workspace uses brains/aivillage.ngm as its AIVillage memory. The page
provides the controls for loading and managing the active brain file.
9) Dataset pipeline
Page: /datasets
The dataset workflow is intended for AIVillage source material and memory.
Export AIVillage memory → raw JSONL
- Export graph memory to JSONL for downstream dataset workflows.
- Supports min synapse weight + dormant/forgotten inclusion toggles.
Build training dataset v1
Produces:
*.raw.jsonl*.tasks.jsonl*.manifest.json
Manifest viewer is built in for split/task diagnostics.
Password scope:
actions["agent.export_dataset"]controls Export Datasetactions["agent.build_training_v1"]controls Build Training Dataset v1actions["agent.export"]controls Export GLB
Import AIVillage text → memory (TXT only)
Current import constraints:
- Input must be
.txt - Heuristic path extraction is used
- Anchor stitching is applied to reduce disconnected components
Importance controls:
sourceorautostrategy- Importance sensitivity slider (0–100)
- Presets:
- Conservative
- Balanced
- Aggressive
- Custom
Import UX:
- Upload progress bar
- Cancel import button
- Inline success/error feedback
10) Inline dataset editor
Pages:
- selector:
/datasets/edit - editor:
/datasets/edit/<filename>
Editor capabilities for JSONL datasets:
- save
- validate JSONL
- data quality analysis
- strict Q&A transformation
- strict sentence transformation
- conversion outputs (
qa,sentence,tinyllama) - training consumption preview
- line navigation + undo/redo + formatting helpers
.ngm memory model summary
Brains persist:
- nodes
- synapses
- regions
- experiences
- dormant memories
- forgotten memories
State lifecycle is designed around:
active -> inactive -> dormant -> forgotten
Forgotten memories are archived, not immediately erased.
Programmatic API (engine-level)
The brain engine supports:
brain.learn(path, experience_name, importance)brain.sleep()brain.recall(concept)brain.think(concept, depth)brain.save(path)brain.load(path)
Implementation references:
Optional: seed starter brains
python seed_brains.py
This seeds included starter domains (if available) for immediate exploration.
Troubleshooting
- If the app does not start, check:
- logs/neurograph.log
.venvdependencies installed- If dataset import fails:
- confirm file extension is
.txt - inspect import feedback on
/datasets(it reports parse/import outcomes) - If a brain file seems locked in workflow:
- ensure it is not currently the active brain before deleting/renaming operations that require non-active status
Notes on reasoning quality
Recall and spread inference are currently weight-driven (synapse-centric).
Node importance still matters for lifecycle and visualization, but ranking behavior is dominated by edge weights and reinforcement history.