Skip to main content

Python SDK for the Dasein managed vector index service

Project description

Dasein

Python SDK for the Dasein managed vector index service.

Low-latency vector search with hybrid retrieval as a one-line toggle. Send raw text and get back ranked results — Dasein handles embedding, indexing, and serving.

See our VectorDBBench results for latency and recall benchmarks.

Install

pip install dasein-ai

Quick Start

from dasein import Client

client = Client(api_key="dsk_...")

# Create an index — we embed your text automatically
index = client.create_index("my-docs", model="bge-large-en-v1.5")

# Upsert documents
index.upsert([
    {"id": "doc1", "text": "Machine learning is a subset of AI", "metadata": {"topic": "ai"}},
    {"id": "doc2", "text": "Python is great for data science", "metadata": {"topic": "code"}},
    {"id": "doc3", "text": "The stock market rallied today", "metadata": {"topic": "finance"}},
])

# Dense search — returns id, score, metadata (all from RAM, no SSD)
results = index.query("what is machine learning?", top_k=5)

# Flip to hybrid — combines dense vectors with BM25 in a single call
results = index.query("what is machine learning?", top_k=5, mode="hybrid")

# Need the original text back? Opt in (adds SSD read per result)
results = index.query("what is machine learning?", top_k=5, include_text=True)

for r in results:
    print(f"{r.id}: {r.score:.4f}{r.metadata}")

Hybrid Search

Toggle between dense-only and hybrid retrieval per query — no config changes, no reindexing, no separate BM25 pipeline.

# Dense: pure semantic similarity
results = index.query("financial derivatives risk models", top_k=10, mode="dense")

# Hybrid: semantic + BM25 keyword matching, fused and re-ranked
results = index.query("AAPL earnings Q3 2025", top_k=10, mode="hybrid")

# Exact keyword matching — only docs that contain all your terms
results = index.query("AAPL earnings Q3 2025", top_k=10, mode="hybrid", exact=True)

# Phrase matching — only docs containing "machine learning" as an exact phrase
results = index.query("machine learning", top_k=10, mode="hybrid", phrase=True)

# Fuzzy matching — handles typos (edit distance 1)
results = index.query("machin lerning", top_k=10, mode="hybrid", fuzzy=True)

# Tune the dense vs BM25 balance (0.0 = all dense, 1.0 = all BM25, default 0.5)
results = index.query("AAPL earnings", top_k=10, mode="hybrid", alpha=0.7)  # lean keyword-heavy

Hybrid mode is strongest on queries with specific keywords, entity names, or codes where pure semantic search loses signal. Dense mode is better for abstract, conceptual queries. You choose per query. The keyword features (exact, phrase, fuzzy) refine hybrid results — use them when you need precise keyword control. The alpha parameter lets you tune the balance between dense and BM25 ranking in the fusion step.

Get an API Key

Web: Sign up with GitHub at daseinai.ai/auth — no credit card required. You'll get an API key instantly.

CLI / Agents:

import httpx, time

resp = httpx.post("https://api.daseinai.ai/auth/device/start").json()
print(f"Go to {resp['verification_uri']} and enter code: {resp['user_code']}")

while True:
    time.sleep(resp.get("interval", 5))
    poll = httpx.post(
        "https://api.daseinai.ai/auth/device/poll",
        json={"device_code": resp["device_code"]},
    ).json()
    if poll.get("api_key"):
        print(f"API key: {poll['api_key']}")
        break

Features

Managed embedding — Pass raw text, we embed with open-source models (BGE, Nomic, E5, GTE). No embedding infrastructure to manage.

Bring your own vectors — Already have embeddings? Pass them directly with any dimension.

Hybrid search as a toggle — Switch between dense and hybrid retrieval per query. No reindexing, no separate BM25 infrastructure.

Metadata filtering — Attach key-value metadata to documents and filter at query time.

Automatic retries — The SDK retries with exponential backoff:

Error Read / query Upsert Build / delete
429 (rate limit) Retried (up to max_retries) Retried Retried
503 (transient) Retried Retried (upserts are idempotent by doc ID) Not retried
504 (gateway timeout) Retried Retried Not retried
Connection error Retried Retried Not retried

Embedding Models

Model Dimensions Matryoshka dims Notes
bge-large-en-v1.5 1024 512, 256, 128, 64 Strong general-purpose English model
nomic-embed-text-v1.5 768 512, 384, 256, 128, 64 Good balance of speed and quality
e5-large-v2 1024 Microsoft's E5 family (no MRL support)
gte-large-en-v1.5 1024 512, 256, 128, 64 Alibaba's GTE family

Or skip the model parameter and pass your own vectors of any dimension.

Matryoshka Dimension Truncation

Models trained with Matryoshka Representation Learning (MRL) can be truncated to lower dimensions with minimal recall loss, cutting RAM and storage proportionally. Pass dim at index creation:

index = client.create_index("my-docs", model="bge-large-en-v1.5", dim=256)

Embeddings are generated at full dimension and truncated + L2-renormalized before indexing. Queries are truncated the same way automatically. The first build for a truncated dimension uses on-the-fly PQ training (slightly slower) since pretrained codebooks are only available for native dimensions.

API Reference

Client

from dasein import Client

client = Client(
    api_key="dsk_...",       # required
    base_url=None,           # override API URL (default: Dasein Cloud)
    timeout=30.0,            # request timeout in seconds
    max_retries=3,           # retries on 429/503
)

Create Index

index = client.create_index(
    name="my-index",
    model="bge-large-en-v1.5",  # None for bring-your-own-vectors
    plan="dense",                # "dense" or "hybrid"
    dim=None,                    # truncate to lower dim for MRL models (e.g., 256)
)

List Indexes

indexes = client.list_indexes()
for idx in indexes:
    print(idx["index_id"], idx["name"], idx["status"], idx["vector_count"])

Get Existing Index

index = client.get_index("index_id")

Delete Index

client.delete_index("index_id")

Upsert Documents

index.upsert([
    {"id": "doc1", "text": "Hello world"},
    {"id": "doc2", "vector": [0.1, 0.2, ...], "metadata": {"type": "example"}},
])

Max 5,000 documents per call for model-backed indexes (10,000 for bring-your-own-vectors). The SDK automatically batches larger lists.

You can also use the typed UpsertItem class instead of raw dicts:

from dasein import UpsertItem

index.upsert([
    UpsertItem(id="doc1", text="Hello world", metadata={"type": "greeting"}),
    UpsertItem(id="doc2", vector=[0.1, 0.2, ...]),
])

Query

results = index.query(
    text="search query",         # or vector=[0.1, 0.2, ...]
    top_k=10,
    mode="dense",                # "dense" or "hybrid"
    filter={"key": "value"},     # optional metadata filter
    exact=False,                 # exact keyword matching (hybrid only)
    phrase=False,                # exact phrase matching (hybrid only)
    fuzzy=False,                 # typo-tolerant matching (hybrid only)
    alpha=0.5,                   # dense vs BM25 balance (0=dense, 1=BM25)
    include_text=False,          # return stored text (off by default)
    include_metadata=True,       # return stored metadata (on by default)
)

What you get back depends on your settings:

Setting Returns I/O cost
Default id, score, metadata RAM only (dense) or RAM only (hybrid)
include_text=True + text Adds SSD read per result
include_metadata=False id, score only Fastest — pure RAM, zero SSD
# Maximum QPS — IDs and scores only, pure RAM
results = index.query("quarterly earnings", top_k=10, include_metadata=False)
for r in results:
    print(r.id, r.score)

# Standard — IDs, scores, and metadata (default)
results = index.query("quarterly earnings", top_k=10)
for r in results:
    print(r.id, r.score, r.metadata)

# Full hydration — include original text
results = index.query("quarterly earnings", top_k=10, include_text=True)
for r in results:
    print(r.id, r.score, r.text, r.metadata)

Text is stored on SSD and only fetched when you ask for it. This means the default dense and hybrid search paths are entirely RAM-resident — no disk I/O in the query hot path.

Delete Documents

index.delete(["doc1", "doc2"])

Upsert and Wait

result = index.upsert_and_wait(documents, timeout=120.0)

Upserts documents and polls until the index becomes queryable. Useful for scripts where you want to upsert and immediately query.

Build (BYOV only)

index.build()

Only needed for bring-your-own-vectors with unrecognized models. Known-model indexes build automatically after the first upsert.

Compact

index.compact()

Triggers a compaction rebuild that removes deleted document tombstones from the graph. Run this after large batch deletions to reclaim performance.

Index Status

info = index.status()
print(info.status)        # created, building, built, active, etc.
print(info.vector_count)

Exceptions

from dasein.exceptions import (
    DaseinError,             # base — catch-all for any Dasein error, including plain 403 Forbidden
    DaseinAuthError,         # 401, or 403 mentioning credentials / API key / revoked
    DaseinQuotaError,        # 403 — billing/plan/trial/subscription/embed limit
    DaseinNotFoundError,     # 404 — index doesn't exist
    DaseinRateLimitError,    # 429 — transient rate limit exceeded (has retry_after)
    DaseinUnavailableError,  # 503/504 — service temporarily unavailable (has retry_after)
    DaseinBuildError,        # build failed
)

DaseinAuthError is raised only for credential issues (bad API key, revoked key, authentication failure). DaseinQuotaError covers trial limits, plan vector caps, expired/past-due subscriptions, and embed token quotas (including 429s that indicate a non-transient monthly embed cap). DaseinRateLimitError is raised for transient per-second rate limits that the SDK retries automatically. A generic 403 (e.g., accessing a resource you don't own) raises DaseinError — catch it separately if you need to distinguish resource authorization from credential errors.

License

MIT

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

dasein_ai-0.3.1.tar.gz (18.1 kB view details)

Uploaded Source

Built Distribution

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

dasein_ai-0.3.1-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file dasein_ai-0.3.1.tar.gz.

File metadata

  • Download URL: dasein_ai-0.3.1.tar.gz
  • Upload date:
  • Size: 18.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for dasein_ai-0.3.1.tar.gz
Algorithm Hash digest
SHA256 8ebec5efa240f27c0d99b6eb764e8f1d081b8f444dc0c964c4d97dca4c046d41
MD5 3e72af4f3466310d00c0d7ba4c607e1c
BLAKE2b-256 fe794ffdbaf19c15a047cf32f94c5187e3b0da9368f17175a716b73c94c7feae

See more details on using hashes here.

File details

Details for the file dasein_ai-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: dasein_ai-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for dasein_ai-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f5fc90713989c50a02b64e4774673081fd484c0391d79e1e085fd53560efa6d8
MD5 4109aa12c5efe6be50dcb3f0f37394ad
BLAKE2b-256 48041487121c077b3f02dfe11341274bb43c8b230882822c159dfa8e4895fa93

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