Skip to main content

DuxxDB — the database built for AI agents. Hybrid (vector + BM25 + structured) retrieval, agent-native primitives (MEMORY / TOOL_CACHE / SESSION), embedded-or-server, RESP / gRPC / MCP.

Project description

duxxdb — Python bindings

Native Python bindings for DuxxDB, the agent-native hybrid database. Built with PyO3 + maturin against the stable Python ABI (abi3-py38) so a single wheel supports Python 3.8 through 3.13.

Install

From a wheel (recommended)

pip install duxxdb-0.1.0-cp38-abi3-<platform>.whl

(For now, build the wheel locally — see the next section. Public PyPI release lands with v0.1.0.)

Build from source

# Prerequisites: Rust toolchain, Python ≥ 3.8.
pip install --user maturin
cd bindings/python
maturin build --release
pip install --force-reinstall ../../target/wheels/duxxdb-0.1.0-cp38-abi3-*.whl

On Windows + Git Bash the workspace uses the GNU toolchain — see ../../docs/SETUP.md for the WinLibs MinGW prerequisite.

Quickstart

import duxxdb

store = duxxdb.MemoryStore(dim=4)

def embed(text):
    """Replace this with a real embedder (OpenAI / Cohere / local BGE)."""
    import hashlib
    h = int(hashlib.sha1(text.lower().encode()).hexdigest()[:16], 16)
    v = [(h >> (i*4)) & 0xff for i in range(4)]
    norm = sum(x*x for x in v) ** 0.5 or 1.0
    return [x / norm for x in v]

store.remember(key="alice", text="I lost my wallet at the cafe", embedding=embed("wallet"))
store.remember(key="alice", text="My favorite color is blue",     embedding=embed("blue"))

hits = store.recall(key="alice", query="wallet",
                    embedding=embed("wallet"), k=3)
for hit in hits:
    print(f"{hit.score:.4f}  {hit.text}")

Output:

0.0328  I lost my wallet at the cafe
0.0161  My favorite color is blue

API surface

Embedded (native, no server required)

Class Constructor Methods
MemoryStore dim, capacity=100_000 remember(key, text, embedding) -> id, recall(key, query, embedding, k=10) -> [MemoryHit], len(), dim
MemoryHit (returned by recall) id, key, text, score
ToolCache threshold=0.95 put(tool, args_hash, args_embedding, result, ttl_secs=3600), get(tool, args_hash, args_embedding) -> ToolCacheHit | None, purge_expired(), len()
ToolCacheHit (returned by get) kind ("exact" or "semantic_near_hit"), similarity, result
SessionStore ttl_secs=1800 put(session_id, data), get(session_id) -> bytes | None, delete(session_id) -> bool, purge_expired(), len()
PromptRegistry dim=32, storage=None put(name, content, metadata=None) -> version, get(name, version_or_tag=None) -> Prompt | None, list(name) -> [Prompt], names() -> [str], tag(name, version, tag), untag(name, tag) -> bool, delete(name, version) -> bool, search(query, k=10) -> [PromptHit], diff(name, v_a, v_b) -> str
Prompt (returned by get / list) name, version, content, tags, metadata (decoded JSON), created_at_unix_ns
PromptHit (returned by search) prompt, score

Module-level: duxxdb.__version__.

Server (typed Python facade over RESP)

When you're running duxx-server as a daemon and want a typed Python surface over every Phase 7 agent-ops primitive (traces, prompts, datasets, evals, replay, cost ledger), install the server extra:

pip install 'duxxdb[server]'
from duxxdb.server import ServerClient

client = ServerClient(url="redis://:<token>@localhost:6379")

# Phase 7.2 — prompt registry
v1 = client.prompts.put("classifier", "you are a refund agent")
prompt = client.prompts.get("classifier", v1)

# Phase 7.3 — dataset registry
client.datasets.create("refunds")
ds_v = client.datasets.add("refunds", [
    {"id": "r1", "text": "I want a refund", "split": "train"},
    {"id": "r2", "text": "Where is my package?", "split": "test"},
])

# Phase 7.4 — evals with summary stats + failure clustering
run_id = client.evals.start(
    dataset_name="refunds",
    dataset_version=ds_v,
    model="gpt-4o-mini",
    scorer="llm_judge",
    prompt_name="classifier",
    prompt_version=v1,
)
client.evals.score(run_id, row_id="r1", score=0.9, output_text="REFUND")
client.evals.score(run_id, row_id="r2", score=0.1, output_text="REFUND")
summary = client.evals.complete(run_id)
print(summary.mean, summary.pass_rate_50)

# Phase 7.6 — cost ledger
client.cost.record(tenant="acme", model="gpt-4o-mini",
                   tokens_in=120, tokens_out=80, cost_usd=0.0023)
print(client.cost.total("acme"))
Namespace Wraps Methods (highlights)
client.trace TRACE.* (6 cmds) record, close, get, subtree, thread, search
client.prompts PROMPT.* (9 cmds) put, get, list, names, tag, untag, delete, search, diff
client.datasets DATASET.* (13 cmds) create, add, get, sample, size, splits, search, from_recall, …
client.evals EVAL.* (9 cmds) start, score, complete, get, scores, list, compare, cluster_failures
client.replay REPLAY.* (12 cmds) capture, start, step, record, complete, diff, list_runs, …
client.cost COST.* (10 cmds) record, query, aggregate, total, set_budget, status, alerts, cluster_expensive

All return types are plain dataclasses decoded from the server's JSON responses. The raw redis.Redis client is exposed as client.raw for anything not yet wrapped.

PromptRegistry (embedded, native bindings): versioned prompts with semantic search

New in v0.2.0: native PyO3 bindings for the prompt registry, so you can use it embedded — no server, no redis-py — straight from a notebook or batch script. The same Rust crate that powers duxx-server's PROMPT.* commands is exposed directly.

import duxxdb

# In-memory (default; matches v0.1.x in-memory feel).
r = duxxdb.PromptRegistry(dim=16)
v1 = r.put("classifier", "You are a refund agent.", metadata={"author": "alice"})
v2 = r.put("classifier", "You are a friendly refund agent.")
r.tag("classifier", v2, "prod")

p = r.get("classifier", "prod")     # resolves the tag
print(p.version, p.content, p.metadata)

# Durable (rows + tags + monotonic counter survive process exit).
r = duxxdb.PromptRegistry(dim=16, storage="redb:./prompts.redb")
r.put("greeting", "Hello! How can I help today?")
# ... process dies ...
r = duxxdb.PromptRegistry(dim=16, storage="redb:./prompts.redb")
assert r.get("greeting").content == "Hello! How can I help today?"

# Semantic search across the catalog.
for hit in r.search("hello", k=3):
    print(hit.score, hit.prompt.name, hit.prompt.content)

The HNSW vector index is rebuilt on open by re-embedding every persisted prompt — fine for the typical prompt-catalog scale (<1000 rows). Larger Phase 7 primitives (datasets, evals) keep shipping through duxxdb.server.ServerClient for now; native PyO3 bindings for them land progressively through v0.2.x.

ToolCache: semantic-near-hit demo

cache = duxxdb.ToolCache(threshold=0.95)

# Cache the result of an expensive web_search call.
cache.put(tool="web_search", args_hash=hash("what is rust?"),
          args_embedding=embed("what is rust?"),
          result=b"A systems programming language ...",
          ttl_secs=600)

# Later, a paraphrased query — different hash, similar embedding.
hit = cache.get("web_search",
                args_hash=hash("describe rust"),
                args_embedding=embed("describe rust"))

if hit and hit.kind == "semantic_near_hit":
    print(f"cache hit by paraphrase, similarity={hit.similarity:.3f}")
    answer = hit.result.decode() if isinstance(hit.result, bytes) else bytes(hit.result).decode()

What's missing today

  • The other five Phase 7 primitives (TraceStore, DatasetRegistry, EvalRegistry, ReplayRegistry, CostLedger) — sequenced in docs/V0_2_0_PLAN.md. Today they're reachable via the RESP facade (duxxdb.server.ServerClient); native bindings land progressively through v0.2.x.
  • Subscriptions (MemoryStore.subscribe()) — Phase 4.5; the Rust / RESP servers already support this, the Python wrapper just needs to bridge tokio::broadcast::Receiver into a Python iterator.
  • Async API — currently sync only. async def wrappers are planned.
  • Numpy / typed-array fast path — embeddings are currently list[float]. Phase 3.5 will accept np.ndarray[float32] directly via numpy::PyArrayLike.

See ../../docs/ROADMAP.md for the broader plan.

License

Apache 2.0. See ../../LICENSE.

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

duxxdb-0.2.0.tar.gz (102.4 kB view details)

Uploaded Source

Built Distributions

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

duxxdb-0.2.0-cp38-abi3-win_amd64.whl (3.6 MB view details)

Uploaded CPython 3.8+Windows x86-64

duxxdb-0.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.8 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

duxxdb-0.2.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.7 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

duxxdb-0.2.0-cp38-abi3-macosx_11_0_arm64.whl (3.3 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

File details

Details for the file duxxdb-0.2.0.tar.gz.

File metadata

  • Download URL: duxxdb-0.2.0.tar.gz
  • Upload date:
  • Size: 102.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for duxxdb-0.2.0.tar.gz
Algorithm Hash digest
SHA256 fbb501abaeef11052e004690eae368740dc607c758d0ef96d8d65c17a6276e5f
MD5 2af8f3ae6adb68f1e2b711a0830b27b1
BLAKE2b-256 fcb358669ed682d43284e1f64de1ace30dcc1f5c36e6eba7d4680235e386e0e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for duxxdb-0.2.0.tar.gz:

Publisher: pypi.yml on bankyresearch/duxxdb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duxxdb-0.2.0-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: duxxdb-0.2.0-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 3.6 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for duxxdb-0.2.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 4222b0047b351d66c732b281e184422f9e4903f299b1eb9e3dbd7acf08fed18a
MD5 655a3939f3c7aced94bf4a3d9aab38f1
BLAKE2b-256 bf87a4b56aa63d25a9d378fe03c8e880063eff7574c74e2d6f12ad310218b937

See more details on using hashes here.

Provenance

The following attestation bundles were made for duxxdb-0.2.0-cp38-abi3-win_amd64.whl:

Publisher: pypi.yml on bankyresearch/duxxdb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duxxdb-0.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for duxxdb-0.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 675c309b1e53114a715f0634ef0fc607e09936513c425eb540a2e8ebaf9946e1
MD5 eab87fa7723403eabc3859e22d24fb70
BLAKE2b-256 d26ca8495b77f9f4fe5321d78d1805891c13a2252b9141592d0cf5811768058d

See more details on using hashes here.

Provenance

The following attestation bundles were made for duxxdb-0.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: pypi.yml on bankyresearch/duxxdb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duxxdb-0.2.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for duxxdb-0.2.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d92e9732596cbe9f2f926a1da6ae5f5a01d7f89c8f3173e1bc863e888cb0eef5
MD5 5c1767e4a7fbbf6c3943021790c44b8c
BLAKE2b-256 60b5f3e82f42afcb36dccb2a959b408e7fdba2c6a0cfc6ccfae3258215cfcabc

See more details on using hashes here.

Provenance

The following attestation bundles were made for duxxdb-0.2.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: pypi.yml on bankyresearch/duxxdb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duxxdb-0.2.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for duxxdb-0.2.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 84f3ba28ada4f4b751a29fcd2d3c8481578e6d4be53a413b29f83884f012b5ad
MD5 5ebdb163fe60def40270ca7770c04c6f
BLAKE2b-256 00b4b873a3dbda32d6204bb289d07ea76451e4eaff07e9ca9194441f545c7b43

See more details on using hashes here.

Provenance

The following attestation bundles were made for duxxdb-0.2.0-cp38-abi3-macosx_11_0_arm64.whl:

Publisher: pypi.yml on bankyresearch/duxxdb

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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