Skip to main content

SynapticDB

A single-file memory store that gives AI agents hybrid search, learned associations, and confidence-aware recall.

PyPI · Benchmark · Report a bug


Why

AI agents need to retrieve useful context and recognize when no useful context exists. SynapticDB combines keyword search, vector search, and a graph of associations in one SQLite file. Each result includes an absolute confidence value, so an agent can reject weak matches instead of treating every ranked result as an answer.

SynapticDB v0.1 is alpha software. Hybrid search and confidence scoring are measured and working. The association graph is implemented, but current benchmark results do not show that the graph improves recall on its own.

Install

Install the built-in local embedding model:

pip install "synapticdb[embeddings]"

Install the smaller core package when you provide an embedding function:

pip install synapticdb

Requires Python 3.10 or newer. The embeddings extra downloads the 384-dimensional all-MiniLM-L6-v2 model on first use.

Quick start

from synapticdb import SynapticDB

with SynapticDB("synaptic.db") as memories:
    memories.store("Client X requires SOC2 for vendor deployments")
    result = memories.recall("deployment requirements for Client X")
    print(result.memories[0].content)
Client X requires SOC2 for vendor deployments

The database, full-text index, embeddings, associations, and recall history all live in synaptic.db. Use ":memory:" instead for a temporary in-process database.

Features

  • Run without a service — SQLite stores the complete memory system in one portable file.
  • Match words and meaning — BM25 keyword search and cosine vector search are fused into one ranking.
  • Reject weak answers — absolute confidence values support one threshold across different queries.
  • Learn relationships — temporal, co-retrieval, feedback, and manual links build an association graph.
  • Bring your own embeddings — a custom local or hosted embedding function can replace the built-in model.

Usage

Add memory to an OpenAI response

Install the OpenAI Python SDK and set OPENAI_API_KEY in your environment:

pip install "synapticdb[embeddings]" openai
export OPENAI_API_KEY="your-api-key"

The example retrieves memory for user_input, adds the memory to the OpenAI request, and stores the completed exchange:

from openai import OpenAI
from synapticdb import SynapticDB

client = OpenAI()
user_input = "What does Client X require for vendor deployments?"

with SynapticDB("agent-memory.db") as memories:
    memories.store("Client X requires SOC 2 for vendor deployments.")
    recalled = memories.recall(user_input, top_k=3)
    context = "\n".join(memory.content for memory in recalled.memories)

    response = client.responses.create(
        model="gpt-5.6",
        input=(
            "Use the memory below to answer the user.\n\n"
            f"Memory:\n{context}\n\n"
            f"User: {user_input}"
        ),
    )
    answer = response.output_text
    print(answer)

    memories.store(f"User: {user_input}\nAssistant: {answer}")

The OpenAI client reads OPENAI_API_KEY from the environment. See the OpenAI API quickstart for key setup.

Return nothing when evidence is weak

min_confidence filters results before SynapticDB records retrieval learning. A recall can return fewer than top_k memories, including none.

result = memories.recall(
    "deployment requirements for Client X",
    top_k=5,
    min_confidence=0.6,
)
relevant = result.memories

if not relevant:
    print("No reliable answer found")

score ranks memories within one recall. confidence measures query-to-memory similarity and can be compared across recalls.

Store metadata and filter results

memories.store(
    "Client X requires SOC 2 for vendor deployments",
    metadata={"client": "x", "topic": "compliance"},
)

result = memories.recall(
    "deployment requirements",
    where={"client": "x"},
)

Teach explicit relationships

requirement = memories.store("Client X requires SOC 2")
deployment = memories.store("Project Atlas deploys to Client X")

memories.connect(requirement.id, deployment.id)

result = memories.recall("What affects the Atlas deployment?")
memories.feedback(result.query_id, positive=True)

Positive feedback strengthens the relationships used by a recall. Negative feedback weakens them without creating new links.

Export results as JSON

payload = result.to_dict()
json_text = result.to_json()

Every public result model retains typed Python fields. JSON exports convert UUIDs and timestamps to strings. get(), connect(), forget(), and feedback() accept UUID objects or their string forms.

How it works

One recall() follows five bounded steps:

  1. FTS5 BM25 ranks keyword matches, and cosine similarity ranks embedding matches.
  2. Reciprocal rank fusion combines both result lists.
  3. The highest-ranked memories seed spreading activation across the association graph.
  4. Graph maturity controls how much activation contributes to the final ranking.
  5. SynapticDB returns each memory with its ranking score, confidence, and retrieval source.

A cold or empty graph falls back to hybrid search. Edge weights decay over time, and periodic maintenance prunes weak edges.

Benchmark

The committed chained benchmark compares SynapticDB with a locked BM25, FAISS, and cross-encoder baseline. SynapticDB answers 17 of 25 associative queries, compared with 10 of 25 for the baseline. Both answer all 25 direct queries.

A confidence floor of 0.6 keeps 41 of 42 correct answers and rejects all 12 unanswerable questions in the benchmark. Confidence AUC is 0.994.

Reproduce the results after the first model download:

uv sync --extra bench
uv run --extra bench python -m bench --profile chained --retriever synaptic

The run takes about 35 seconds on the development machine. See the benchmark documentation for profiles, measurements, and stored records.

What an associative answer looks like

For one associative holdout query, the locked baseline misses the answer. SynapticDB returns it at rank 6 with confidence 0.640.

Query: Why does the observatory dome trigger wind protection during calm weather?

Answer: Converting knots before publishing reduced false closure alerts while preserving every genuinely windy shutdown.

The query and answer share almost no words. The association graph connects them through two intermediate memories:

  1. Wind data reaches the controller through the Boreal weather adapter.
  2. Boreal labels readings as meters per second but forwards knot values unchanged.

The graph records a useful reasoning path, but it did not create this benchmark win. SynapticDB's hybrid search already returned the answer before the graph existed.

What does not work yet

  • Semantic seeding is disabled. A threshold sweep produced no unique wins. At 0.60, only 4 of 1,069 semantic edges landed on a real associative chain.
  • Co-retrieval and feedback are not measured end to end. Both update edges, but benchmark warm-up topics do not overlap the holdout paths. Adding overlap would leak training data into evaluation.
  • Decay and pruning are not measured end to end. Future-dated ingestion and write-only maintenance prevent the benchmark from aging edges. Unit tests cover both behaviors.
  • Confidence depends on embedding quality. Measure a threshold on your own data before using confidence as a production decision boundary.

Alternatives

If you only need vector search, start with a mature tool such as Chroma, LanceDB, or sqlite-vec. Choose SynapticDB when you want fused keyword and vector search in one SQLite file, plus a confidence value that can suppress weak answers. Treat the association graph as an experimental research feature.

Development

git clone https://github.com/xhillman/synapticdb.git
cd synapticdb
uv sync --extra dev
uv run --extra dev ruff format --check .
uv run --extra dev ruff check .
uv run --extra dev mypy
uv run --extra dev python -W error -m pytest
uv run --extra dev python -W error -m bench --profile smoke --retriever fixture --check --no-write
uv run --extra dev python -W error -m bench --profile smoke --retriever synaptic --check --no-write

Build the wheel and source distribution with uv run --extra dev python -m build.

Contributing

Contributions are welcome. Open an issue before starting a large change so the proposed scope can be reviewed first.

License

MIT © Xavier Hillman. See LICENSE.

Metadata

Release files for synapticdb 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for synapticdb 0.1.1
File Size Uploaded Provenance Actions
synapticdb-0.1.1.tar.gz 171.8 kB With provenance Details for synapticdb-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for synapticdb 0.1.1
File Interpreter ABI Platform Actions
synapticdb-0.1.1-py3-none-any.whl Python 3 none any Details for synapticdb-0.1.1-py3-none-any.whl

Total release size: 213.9 kB

Release files / synapticdb-0.1.1.tar.gz

Download URL synapticdb-0.1.1.tar.gz
Size 171.8 kB
Tags Source
SHA-256 checksum
How to use checksums
79723da5086f0f23b6d464ed9b0f94514732ceb3c7816a8d7f9dbc886098243b
BLAKE2b-256 checksum
How to use checksums
60ef111c97773f9c3768aa43da881d1325365feb17f340822739eb5392498d2e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 21, 2026.

Transparency log

Release files / synapticdb-0.1.1-py3-none-any.whl

Download URL synapticdb-0.1.1-py3-none-any.whl
Size 42.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d1a7683dae10b95f65b1f28f72d24f4cd49138136ea52f5aaa7d039fff24753f
BLAKE2b-256 checksum
How to use checksums
d9a04fb016db9ea1eba99208f8df0d3d77b82d4cb0e4b01a27e3f9ff3145c69c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 21, 2026.

Transparency log

Security for synapticdb 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for synapticdb-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 21, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page