Skip to main content

Epistemic grounding substrate for LLMs — knows what it knows, what it doesn't, and why

Project description

Nouse

Nouse

Structured memory for LLM agents that knows not only what it knows, but how confidently it knows it and where knowledge runs out.

Epistemic grounding for any model.

PyPI Python 3.11+ MIT Benchmark

Quick Start · Why It Matters · What You Get · Benchmark

Nouse demo

Repo social preview asset: IMG/nouse-social-preview.svg


Try NoUse In 60 Seconds

pip install nouse
python - <<'PY'
import nouse

brain = nouse.attach()
result = brain.query("What does this project know about epistemic grounding?")

print(result.context_block())
print("confidence:", round(result.confidence, 2))
PY

If NoUse already knows something relevant, you get back a grounded context block with validated relations, uncertainty, and explicit boundaries instead of a generic answer blob.

If that output feels more useful than plain chat history or chunk retrieval, then the project is doing its job.


Why It Matters

NoUse gives an LLM agent a persistent epistemic memory layer.

  • It stores relations, not just retrieved chunks.
  • It carries confidence, rationale, and uncertainty with the memory itself.
  • It makes the boundary between known, probable, and unknown visible to the model.

That changes agent behavior in the place that actually matters: when a model is close to hallucinating but still sounds fluent.

The Result That Triggered This

Model                               Score   Questions
─────────────────────────────────────────────────────
llama3.1-8b  (no memory)            46%     60
llama-3.3-70b  (no memory)          47%     60
llama3.1-8b  + Nouse memory  →      96%     60

An 8B model with Nouse outperforms a 70B model without it.

The effect is not about retrieval. It is about epistemic grounding — a small, precise knowledge signal redirects the model's existing priors onto the correct frame, with confidence and evidence attached. We call this the Intent Disambiguation Effect.

LLMs are stateless formal systems: they process symbol strings without epistemic commitment. They cannot distinguish what they know from what they hallucinate. Nouse is the missing layer: it gives any LLM a persistent, structured account of what is known, why, with what confidence, and — critically — what is not yet known.

→ Full benchmark: eval/RESULTS.md


What You Get

Capability What it does
Structured memory Stores typed relations between concepts instead of plain text chunks
Confidence-aware retrieval Returns what is known, with evidence and uncertainty attached
Gap awareness Surfaces where knowledge ends instead of bluffing through it
Continuous learning Strengthens or weakens graph paths over time via Hebbian plasticity
Local-first runtime Runs as a local graph and daemon, then injects context into any LLM

What Nouse is

Nouse (νοῦς, Gk. mind) is a persistent, self-growing epistemic substrate that attaches to any LLM.

It is informed by brain-inspired plasticity, cognitive research, and the practical failure modes of LLM memory.

Your documents, conversations, research
           ↓
    Nouse knowledge graph
    (KuzuDB + Hebbian learning + evidence scoring)
           ↓
    brain.query("your question")
           ↓
    Structured context injected into any LLM prompt:
      — what is known (relations + confidence)
      — why it is known (evidence chain)
      — what is NOT known (gap map from TDA)

It is not a RAG system. RAG retrieves chunks. Nouse extracts relations — typed, weighted, evidence-scored connections between concepts — and injects a compact, structured context block.

It is not just a memory system. Memory stores and retrieves. Nouse maintains an epistemic account: every relation carries a trust tier (hypothesis / indication / validated), a rationale, and a contradiction flag. The system knows the difference between what it has evidence for and what it is guessing.

It learns continuously. Every interaction strengthens or weakens connections (Hebbian plasticity). There is no retraining. No gradient descent. The graph grows — and the gaps become visible.


Why It Feels Different From RAG

System Main unit Knows confidence Knows what is missing Learns structurally over time
Basic RAG text chunk No No No
Vector memory embedding Partial No No
NoUse typed relation + evidence Yes Yes Yes

NoUse is not trying to replace the model. It gives the model a brain-like memory substrate it can query before speaking.


Quick start

pip install nouse
import nouse

# Auto-detects the local daemon if it is running.
# Otherwise falls back to direct local graph access.
brain = nouse.attach()

result = brain.query("transformer attention mechanism")

print(result.context_block())
print(result.confidence)
print(result.strong_axioms())

If the daemon is already running, attach() talks to it over HTTP instead of opening KuzuDB directly. That means the same quickstart works whether the user is in local-only mode or daemon mode.

Works with any provider — OpenAI, Anthropic, Groq, Cerebras, Ollama:

# You handle the LLM call. Nouse handles the memory.
context = brain.query(user_question).context_block()
response = openai.chat(messages=[
    {"role": "system", "content": context},
    {"role": "user",   "content": user_question},
])

Use With OpenAI, Anthropic, Or Ollama

OpenAI

from openai import OpenAI
import nouse

client = OpenAI()
brain = nouse.attach()

question = "How does residual attention affect token relevance?"
context = brain.query(question).context_block()

response = client.chat.completions.create(
       model="gpt-4.1-mini",
       messages=[
              {"role": "system", "content": context},
              {"role": "user", "content": question},
       ],
)

print(response.choices[0].message.content)

Anthropic

from anthropic import Anthropic
import nouse

client = Anthropic()
brain = nouse.attach()

question = "What does this repo know about topological plasticity?"
context = brain.query(question).context_block()

response = client.messages.create(
       model="claude-3-7-sonnet-latest",
       max_tokens=800,
       system=context,
       messages=[
              {"role": "user", "content": question},
       ],
)

print(response.content[0].text)

Ollama

import ollama
import nouse

brain = nouse.attach()

question = "Summarize what is known about epistemic grounding."
context = brain.query(question).context_block()

response = ollama.chat(
       model="qwen3.5:latest",
       messages=[
              {"role": "system", "content": context},
              {"role": "user", "content": question},
       ],
)

print(response["message"]["content"])

The pattern is always the same: brain.query(...) first, provider call second.


Managed NoUse

NoUse is local-first today. A natural next step is a managed cloud brain:

brain = nouse.attach(api_key="nouse_sk_...")

That would give users a hosted NoUse brain with larger managed memory graphs, shared project memory across agents and teams, and less local setup.

For individual users, it is a simpler paid upgrade. For researchers, it is persistent shared memory across runs and collaborators. For larger companies, it is a path to API access, team memory, and managed deployment.


What A Grounded Answer Looks Like

When you query NoUse, the model does not just get a blob of context. It gets an epistemic frame:

[Nouse memory]
• transformer attention: mechanism for routing token influence across context
       claim: attention modulates token relevance based on learned relational patterns

Validated relations:
       transformer —[uses]→ attention  [ev=0.92]
       attention —[modulates]→ token relevance  [ev=0.81]

Uncertain / under review:
       attention —[is_equivalent_to]→ memory routing  [ev=0.41] ⚑

That is the real product surface: not storage, but a more honest and better-calibrated answer path.


Run the benchmark yourself

git clone https://github.com/base76-research-lab/NoUse
cd NoUse
pip install -e .

# Generate questions from your own graph
python eval/generate_questions.py --n 60

# Run benchmark (requires Cerebras or Groq API key, or use Ollama)
python eval/run_eval.py \
  --small cerebras/llama3.1-8b \
  --large groq/llama-3.3-70b-versatile \
  --n 60 --no-judge

The current benchmark is domain-specific and intentionally small. Its purpose is to test whether a grounded memory signal can redirect the model onto the right frame, not to claim a universal leaderboard win.


How the graph grows

Read a document / have a conversation
           ↓
    nouse daemon (background)
           ↓
    DeepDive: extract concepts + relations
           ↓
    Hebbian update: strengthen confirmed paths
           ↓
    NightRun: consolidate, prune weak edges
           ↓
    Ghost Q (nightly): ask LLM about weak nodes → enrich graph

The daemon runs as a systemd service. It watches your files, chat history, browser bookmarks — anything you configure. You never manually curate the graph.


Good Fits

  • Coding agents that need stable project memory across sessions
  • Research copilots that must preserve terminology, evidence, and uncertainty
  • Domain-specific assistants where bluffing is worse than saying "unknown"
  • Local-first AI workflows where you want observability instead of hidden memory state

Architecture

nouse/
├── inject.py          # Public API: attach(), NouseBrain, Axiom, QueryResult
├── field/
│   └── surface.py     # KuzuDB graph interface
├── daemon/
│   ├── main.py        # Autonomous learning loop
│   ├── nightrun.py    # Nightly consolidation (9 phases)
│   ├── node_deepdive.py  # 5-step concept extraction
│   └── ghost_q.py     # LLM-driven graph enrichment
└── search/
    └── escalator.py   # 3-level knowledge escalation

The hypothesis (work in progress)

small model + Nouse[domain]  >  large model without Nouse

We have evidence for this in our benchmark. The next step is to test across more domains, more models, and with an LLM judge instead of keyword scoring.

Contributions welcome — especially domain-specific question banks.


Install & run daemon

pip install -e ".[dev]"

# Start the learning daemon
nouse daemon start

# Interactive REPL with memory
nouse run

# Check graph stats
nouse status

Requires Python 3.11+. Graph stored in ~/.local/share/nouse/field.kuzu.


License

MIT — Björn Wikström / Base76 Research Lab


Contact

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nouse-0.2.3.tar.gz (351.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nouse-0.2.3-py3-none-any.whl (389.3 kB view details)

Uploaded Python 3

File details

Details for the file nouse-0.2.3.tar.gz.

File metadata

  • Download URL: nouse-0.2.3.tar.gz
  • Upload date:
  • Size: 351.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for nouse-0.2.3.tar.gz
Algorithm Hash digest
SHA256 2f7f0a2b466d5bedb35b65769b9c37ddad0d879f6db4a9c40e9404c71aae8822
MD5 785271b2009937fd9c454561cf7225ab
BLAKE2b-256 7520050b27c9b8b70476cca52d1564473730c9c27baf662e577a0ca3c6a32a62

See more details on using hashes here.

File details

Details for the file nouse-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: nouse-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 389.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for nouse-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 17efcd4b5212519f37986b6c9c4cb034081af434f084b8f25fe1179b7c1438e6
MD5 5a2883c68fc1fd290821fa0f1c8356c5
BLAKE2b-256 b77b7716fdaaf5e8ef2f535e8ba9efcb47dbd3581b8bb859e601e3f99c1f3607

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page