Skip to content
YoruxyvPublic

About

Contract-first semantic caching for Python. Async APIs, pluggable storage, confirmed cache hits, and inspectable decisions.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

Β 

History

295 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧠 Semantix

Async semantic caching for Python.

Memory, SQLite, MySQL, PostgreSQL, Redis or Valkey storage. Your generation flow stays yours.

Python 3.11–3.14 MIT license

EN Β· ID

Quick start Β· How it works Β· Compatibility Β· Dashboard Β· Documentation

semantix-cache is the primary embedded Python library and the intended first public PyPI product. Its 0.1.0 API is async-only and runs in your Python process. No Semantix server, web UI, Docker or PostgreSQL is required.

Use Semantix Start here
Embedded Python (primary) Source quick start; no Docker or official server
Backend/dashboard (optional) Dashboard quick start; optional local application
PostgreSQL persistence Embedded setup or dashboard setup; explicit initialization required

Install and run

Note

0.1.0 is not yet published to PyPI. Use the GitHub source or a locally built wheel. The distribution is named semantix-cache; Python imports semantix_cache.

Install Git, Python 3.11–3.14 and uv. Start from a new checkout, or use your existing checkout and enter packages/cache.

Bash (Linux/macOS):

git clone https://github.com/Yoruxyv/semantix.git
cd semantix/packages/cache

Windows PowerShell:

git clone https://github.com/Yoruxyv/semantix.git
Set-Location semantix/packages/cache

Then run these commands in either shell:

uv sync --locked
uv run --no-sync python -m examples.custom_integration

The maintained custom integration example uses AsyncSemanticCache, EmbeddingSpace and MemoryStore with no API key, Docker, server or database. It exits silently on success and raises if the first resolve does not generate/write or the second does not confirm a hit and skip generation. Its deterministic two-dimensional vectors verify API wiring, not semantic understanding or match quality. provider_called means the local application generation callable ran; this example makes no provider API calls. Setup downloads Python dependencies; the example itself runs offline.

For an independent Python project, see local source and wheel installation. The minimal package depends on NumPy and Pydantic; provider networking and persistent store drivers are optional. The backend/dashboard is a separate optional application; embedded usage does not pass through it.

This credential-free example runs as a script. The toy vectors demonstrate the integration, not language understanding or semantic-match quality. Replace the embedder and generation function with your application's existing async integrations.

import asyncio
from semantix_cache import AsyncSemanticCache, EmbeddingSpace, MemoryStore

class DemoEmbedder:
    embedding_space = EmbeddingSpace(identity="demo-v1", dimensions=2)

    async def embed(self, text: str) -> tuple[float, float]:
        return (1.0, 0.0) if "weather" in text.lower() else (0.0, 1.0)

async def generate(prompt: str) -> str:
    return "Completed answer for: " + prompt

async def main() -> None:
    embedder = DemoEmbedder()
    async with MemoryStore(embedding_space=embedder.embedding_space) as store:
        async with AsyncSemanticCache(embedder=embedder, store=store) as cache:
            prompt = "weather today"
            miss = await cache.resolve(prompt, namespace="demo", generate=generate)
            hit = await cache.resolve(prompt, namespace="demo", generate=generate)
            assert miss.provider_called and miss.cache_written
            assert hit.cache_hit and hit.generation_skipped
            print(hit.response, "cache_hit=", hit.cache_hit)

asyncio.run(main())

The first resolve generates and writes; the second reports a confirmed cache hit and skips generation. Reuse the store/cache across requests: creating a new MemoryStore loses its process-local entries. Context managers close the facade and store; the application owns any other injected resources.

At a glance

Aspect Summary
Runtime Async, in-process Python
Storage MemoryStore, local SQLite, optional MySQL, PostgreSQL/pgvector, Redis or Valkey
Generation Your own async callable

Compatibility and supported backends

The embedded semantix-cache package supports CPython 3.11–3.14. Backend links below lead to setup requirements and complete certification details.

Backend Supported server/runtime Python driver Availability
MemoryStore In-process, non-durable; no external database Included in the minimal core; no database driver Embedded + optional server/dashboard
SQLiteStore Thread-capable linked SQLite >=3.51.3, except withdrawn 3.52.0, or exact upstream WAL-patched 3.44.6 / 3.50.7 Python's standard-library sqlite3; no extra driver package Embedded + single-process server
MySQLStore Runtime: MySQL Community 8.4.x; CI-certified: 8.4.11 / 8.4.12 [mysql]: exact PyMySQL 1.2.1, 1.2.2 or 1.2.3 Embedded + official server
PgVectorStore Verified PostgreSQL / pgvector: 16.15 / 0.8.7, 17.10 / 0.8.5, 18.6 / 0.8.7 [pgvector]: asyncpg>=0.31,<=0.32.0; certified 0.31.0 / 0.32.0 in different CI combinations Embedded + optional server/dashboard
RedisStore β€” Redis Open Source Admitted minor families and patch floors: 7.4.x >=7.4.11; 8.2.x >=8.2.10; 8.4.x >=8.4.7; 8.6.x >=8.6.7; 8.8.x >=8.8.3; 8.10.x >=8.10.2 [redis]: exact redis-py 7.4.1, exact 8.0.1, or stable 8.1.x Embedded + optional server/dashboard
RedisStore β€” Valkey Separate server product; exact Valkey 9.1.2 Same RedisStore and [redis] extra; verified redis-py 8.1.0, no Valkey-specific dependency Embedded + validated official server/dashboard path (see below)

Runtime-admitted versions pass the implementation's compatibility policy. CI-verified combinations are the exact targets exercised in maintained tests, listed in the linked guides. Admission does not mean every server, extension, driver, Python, architecture, OS or managed-service combination has been tested. The PostgreSQL targets above are not runtime minimum versions.

Development locks retain asyncpg 0.31.0, PyMySQL 1.2.3 and redis-py 8.1.0. The Redis dependency resolver range is broader than runtime admission; see the driver policy. redis-py 8.0.1 does not imply Redis 8.0 server support. MySQL 8.0/9.x, MariaDB and managed variants are outside the MySQL verified boundary.

For SQLite, use trusted upstream builds or verify the vendor's WAL-fix provenance: a version number alone does not authenticate a binary. Valkey certification pairs 9.1.2 / redis-py 8.1.0 / Linux x86-64 / CPython 3.14, with additional local Windows-client evidence. Other Valkey releases, drivers and platforms are not individually certified. TLS, managed-service and failover limits remain specific to each guide; Redis/Valkey data-file migration remains unverified.

The optional server/dashboard accepts only CACHE_BACKEND=memory, pgvector, redis, sqlite or mysql. SQLite requires a native single-process server on trusted local disk with explicit setup; bundled Compose is unsupported. MySQL requires explicit setup, restricted runtime credentials and verified TLS; see server MySQL configuration. Valkey uses the existing redis path, with no separate ValkeyStore or valkey selector. The official FastAPI, Python HTTP SDK and production-built React dashboard were validated against the pinned Linux x86-64 Valkey container with a Windows CPython 3.14.6 client/server host and redis-py 8.1.0. See the bounded validation record and operational limits; this does not certify TLS, HA/failover, production load or other application host platforms.

Why Semantix?

Reuse completed responses inside an existing async application while keeping prompt construction, model selection, RAG, tools and approval logic in your code. Choose a similarity threshold and retention policy explicitly, inspect the returned hit/miss evidence, and add persistence when your application needs it.

How it works

For the default NORMAL policy, the embedded path is:

flowchart LR
    A[Your app] --> B[AsyncSemanticCache]
    B --> C[Embed]
    C --> D{Confirmed cache hit?}
    D -->|Yes| H[Return hit]
    D -->|No| G[Generate, validate and write]
    G --> R[Return miss]
Loading

Eligible candidates pass validation and atomic TTL/revision confirmation before a hit is returned.

The application owns the embedder, generator and store lifetimes. A CacheStore can be MemoryStore, SQLiteStore, optional MySQLStore/PgVectorStore/RedisStore or your custom implementation. Other policies control reads/generation/writes; opt-in coalescing adds waiting and each follower's own confirmed lookup. See the cache contract.

Semantic cache behavior

Matching uses validated embeddings and cosine similarity, rather than requiring identical strings. The inclusive threshold defaults to 0.92; evaluate false matches for your own model and workload. Even a repeated prompt goes through embedding and lookup. Namespace and EmbeddingSpace isolate compatible cache data; they do not replace application authorization.

Version the namespace when response context, model, permissions or approval policy changes. Keep embedding identity stable for a particular model/revision/dimensions/ preprocessing combination. Matching dimensions alone do not establish compatibility. TTL starts at the write and does not extend on hits. See policies, TTL and matching.

See context identity and migration for model/tenant/knowledge/output scopes, embedding revisions and safe migration recipes.

Prompt normalization

Normalization transforms text for embedding-based lookup and newly computed write embeddings. Generation and cache entries retain the application prompt under the existing canonicalization rules. This can help matching; it does not verify answer correctness.

The optional server corrects common English typos and accidental word splits with SymSpell, disabled by default. Enable it at startup with PROMPT_TYPO_CORRECTION_ENABLED=true and configure distance with PROMPT_TYPO_MAX_EDIT_DISTANCE=2. It generally preserves capitalization: typo correction is not case-insensitive matching, and capitalization alone guarantees neither a hit nor a miss. These settings are not editable from the dashboard.

The standalone semantix-cache package exposes a synchronous prompt_normalizer callable; installing it alone does not install SymSpell or enable the server's correction behavior. See the package hook and normalization guide for examples, configuration and limitations. Preprocessing changes require compatible storage isolation and a coordinated transition; follow the identity and migration guide.

Key capabilities

  • Async API β€” AsyncSemanticCache with explicit CachePolicy, CacheResult and CacheHit evidence.
  • Memory β€” Bounded MemoryStore with exact float64 cosine scoring, TTL and confirmed-hit LRU.
  • Persistence β€” Optional PostgreSQL/pgvector with explicit schema initialization.
  • Extensions β€” Maintained embedding/generation adapters and structural custom integration ports.
  • Coalescing β€” Opt-in NORMAL cold misses within one cache instance and event loop.

Performance

Historical development measurements compared the optimized base ee915140 with opt-in coalescing in three fresh alternating control/treatment pairs per store. The workload used 256 requests, concurrency 128, two compatible prompts and a 200 ms deterministic generation delay. Generation calls fell from 256 to 2; embedding calls remained 256.

Store Burst P50, disabled β†’ enabled Burst P95, disabled β†’ enabled
MemoryStore 294.095 β†’ 434.127 ms 316.949 β†’ 458.839 ms
PgVectorStore 916.670 β†’ 941.012 ms 1366.900 β†’ 1087.602 ms

These are median per-trial burst percentiles, not isolated follower timings.

Provider-work reduction can increase cold-follower latency, as the MemoryStore numbers show. Sharing requires equivalent attested inputs, bounded admission and successful persistence/confirmation. It is disabled by default and does not promise universal latency, duplicate elimination or dollar savings. See the complete tradeoff. Optional server measurements are retained below and describe a different workload.

Measurement environment and methodology

Conditions: Windows 11, Ryzen 9 5900HX/16 logical CPUs/about 32 GiB RAM; Python 3.14.6, NumPy 2.4.6, Pydantic 2.13.5; 384 dimensions, 500 seeded candidates, capacity 5,000, threshold 0.92, TTL 3,600 s; child BLAS threads=1. PostgreSQL 17.10/pgvector 0.8.5 used a local four-CPU/2-GiB container, asyncpg 0.31.0 and pool eight. Setup/warmup/cleanup were excluded; measured requests had no errors.

Reproduce with the coalescing experiments and runtime benchmark methodology.

Production behavior

The facade borrows injected resources. Adapters borrow their HTTP clients; PgVectorStore.connect owns its pool, while an injected pool is borrowed. Drain or cancel active work before closing: busy resources raise CacheBusyError. Total deadlines are finite, cancellation propagates, and no automatic generation retry is added. Caller-configured transports/callbacks remain the caller's responsibility.

Lookup/write failures raise; generated output followed by a failed write is not a successful resolve. Typed errors and bounded result evidence are documented in the package guide. Coalescing needs explicit coalescing_key attestation; it does not infer equivalent ContextVars/closures or coordinate across processes. Followers confirm their own hits. Changing that key alone does not invalidate stored answers. Read the coalescing safety rules.

Optional numeric coalescing evidence is collected only with collect_coalescing_metrics=True. General instrumentation remains application-owned.

Documented AsyncSemanticCache usage is covered by the package's 0.1.x compatibility policy.

Verified AI Providers

Hosted provider examples are optional, require your own credentials and may incur charges. Start with the credential-free MemoryStore workflow above.

The maintained OpenAI, Gemini, and Hugging Face adapters were exercised against real provider APIs on 2026-10-05, including embedding, generation, and an AsyncSemanticCache + MemoryStore miss β†’ generate β†’ write β†’ confirmed-hit flow. Generation was skipped on the repeated-prompt hit; the checks cover the models listed in the provider guide.

Provider Embeddings Generation Verification
OpenAI Yes Yes βœ… Live verified
Gemini Yes Yes βœ… Live verified
Hugging Face Yes Yes βœ… Live verified
Ollama Yes Yes Previously exercised locally; current release evidence incomplete
Anthropic No native embedding API Yes ⚠️ Contract-tested; first-party live verification pending

Public extension path verified. Independent HTTPX integrations for OpenAI, Gemini, and Hugging Face used only Semantix's public AsyncSemanticCache extension interfaces, without built-in provider adapters or private helpers. Each completed a live miss β†’ generate β†’ write β†’ confirmed-hit flow.

Anthropic: The generation adapter is covered by deterministic contract and regression tests, but was not live-verified against the first-party Anthropic API for 0.1.0. It has no native embedding API; pair generation with any supported embedding adapter. Contributions using your own first-party Anthropic API access are welcome for verification, reproducible compatibility reports, and focused fixes with regression coverage when a defect is reproduced.

Built-in adapters live in semantix_cache.adapters, outside minimal root imports. Choose models and embedding-space identity explicitly and supply a borrowed HTTPX client. The optional HTTP extras do not install provider SDKs. See embedded providers and custom integrations for configuration and the custom-provider path.

Provider APIs evolve independently of Semantix. I intend to keep the maintained integrations current; reproducible compatibility reports and focused fixes are welcome. Never include API keys, credentials, or raw provider responses in issues, commits, logs, or fixtures.

Storage

Start with MemoryStore for bounded process-local state. See the compatibility table for admitted versions, verified targets and embedded versus server availability.

For local persistence, semantix_cache.stores.sqlite.SQLiteStore owns a dedicated file and worker with explicit setup. Check the thread-capable linked runtime and WAL-fix provenance; Python's version alone is insufficient. Run uv run --no-sync python -m examples.sqlite_cache from packages/cache for a credential-free miss/write/hit and reopen check. See SQLite setup and limits for the bounded complete float64 scan, file ownership and cancellation restrictions.

Optional semantix_cache.stores.mysql.MySQLStore uses the local wheel's [mysql] extra, an owned worker, verified TLS and explicit setup on a dedicated MySQL Community 8.4.x database. Hosted CI covers both certified server releases and all three admitted PyMySQL versions in the combinations listed in the MySQL guide. See that guide for least-privileged grants, the locked schema verifier, exact float64 search, deadlines, uncertain COMMIT and bounded failed-construction recovery.

semantix_cache.stores.redis.RedisStore uses [redis] for Redis Open Source or exact Valkey 9.1.2. Both require explicit binding initialization and a directly addressed writable standalone primary with noeviction. Operators own persistence, backups, TLS and recovery; Cluster, Sentinel, replica reads and automatic failover are unsupported. See Redis and Valkey setup and limits.

Optional semantix_cache.stores.pgvector.PgVectorStore persists across processes/restarts using an application-controlled PostgreSQL database. Provision the vector extension and initialize its separate marked cache schema explicitly; normal cache operations perform no DDL. Runtime operations enforce ownership markers, version and migration checksums, not a complete catalog fingerprint. Protect out-of-band schema changes.

PgVectorStore.connect() can raise typed errors and returns no usable store on failure. Applications own recovery or fail-startup decisions; see PostgreSQL connection failures.

See embedded storage and user databases for least-privileged runtime access, pool ownership, migrations and custom stores. pgvector stores float32 vectors; near-threshold scores can differ from MemoryStore's float64 scoring.

Extension points

Supply a structural EmbeddingAdapter (embedding_space and async embed), an async GenerationCallable returning approved completed text, or a structural CacheStore. No subclass or registry is required. Streaming/RAG/tool flows can use get/set around their final approved text; Semantix does not run those application workflows.

Examples

Repository components

Path Component
packages/cache/ Primary semantix-cache embedded library; first intended PyPI product
apps/server/ Optional official self-hosted FastAPI server
apps/web/ Optional official web/workbench for inspecting and evaluating server cache decisions
packages/client/ Maintained optional/reference semantix-client HTTP client; not a first-release PyPI target

The optional server/workbench is a full-stack laboratory for inspecting cache decisions, evaluating thresholds and measuring provider work. Its namespace-scoped authorization and hardened two-replica deployment are server features, not embedded prerequisites. Operational tooling lives in ops/; developer tooling in scripts/.

Optional Dashboard β€” Quick Start

Install Git, Python 3.11–3.14, and Docker Desktop or Docker CLI/Engine 23+ (API 1.42+) with Compose 2.20+. Start the local Docker engine. Host Python is only needed for the development launcher; backend dependencies stay in Docker.

Use the checkout above and run from the repository root (cd ../.. if you are still in packages/cache). For a new configuration, copy the example; if apps/server/.env already exists, keep it and edit it instead:

cp apps/server/.env.example apps/server/.env

In PowerShell, use Copy-Item apps/server/.env.example apps/server/.env.

Set these values in the untracked apps/server/.env, keeping the other example defaults, for a credential-free MemoryStore dashboard:

EMBEDDING_PROVIDER=mock
GENERATION_PROVIDER=mock
MOCK_EMBEDDING_DIMENSIONS=384
CACHE_BACKEND=memory
EVALUATION_DATASET_STORAGE=session
EVALUATION_RUN_HISTORY_STORAGE=disabled
COORDINATION_BACKEND=memory
AUTH_MODE=disabled
AUTH_PRINCIPALS=[]
TRUSTED_PROXY_CIDRS=[]
MAX_REQUEST_BODY_BYTES=65536

Then start the dashboard:

python scripts/dev.py up

Or use uv run --no-project scripts/dev.py up. The launcher waits for backend readiness before starting the frontend; this configuration needs no database or provider API key. The first build can download images and dependencies.

Open http://localhost:4173 (or the URL printed for your configured ports). Mock responses are deterministic examples; memory cache/session data disappear when the backend restarts. Authentication is disabled for trusted local use only; never expose this development stack publicly.

For other providers, persistent storage, or direct Docker-only startup, follow Getting started, including PostgreSQL credentials/setup and advanced direct Compose.

Optional server/workbench: tour, Docker setup and deployment evidence

Semantix Monitor showing a cache hit, similarity evidence, and the skipped provider call

Actual Semantix UI with Hugging Face providers and example prompts.


✨ Optional server workspaces

Workspace Purpose
Monitor Submit namespace-scoped policy probes and inspect cache hits, misses, latency, matched prompts, and similarity evidence
Cache Inspector Search entries, inspect metadata, delete records, clear namespaces safely
Evaluations Measure precision, recall, false hits, false misses, inspect filtered case evidence, and export reproducible runs
Observability Track process metrics and inspect safe, read-only runtime diagnostics for evaluation reproducibility

Product tour

The optional server workbench inspects its connected server cache, evaluates ordered runs, and diagnoses that server. It does not observe arbitrary embedded application caches. The local Hugging Face demo exposes the same workspaces. The screenshots below show the current UI; select any image to open the original resolution.

Cache Inspector

Search stored prompts and inspect entry age, hit counts, expiry, and cache metadata without exposing raw embeddings.

Cache Inspector showing safe example cache entries with hit counts and TTL

Evaluations

Run an isolated dataset and inspect measured cache behavior, provider calls, latency, and classification outcomes. Bookmark /evaluations?view=runs, ?view=datasets, ?view=history, or ?view=reuse-quality to reopen the selected view. Reuse quality displays reviewed static library evidence and methodology, with calibration and held-out results separate from ordered server runs. These synthetic results do not establish production quality or a universally safe threshold.

Evaluations showing results for the built-in semantic safety dataset

Observability

Inspect safe runtime diagnostics, provider categories, matching fingerprints, storage readiness, and other reproducibility signals.

Observability showing runtime diagnostics and provider readiness

Core capabilities:

  • independent embedding and generation providers;
  • MemoryStore, SQLiteStore, MySQLStore, PostgreSQL/pgvector or RedisStore storage (including the exact supported Valkey target), within the server deployment restrictions;
  • TTL, LRU eviction, namespaces, private requests, and read/write policies;
  • role-aware Monitor controls, private trace minimization, and live-hit links to authorized Cache detail;
  • request coalescing for identical concurrent misses;
  • optional typo-aware prompt normalization;
  • global-admin-only runtime diagnostics with safe provider categories, fingerprints, readiness, and evaluation limits;
  • token roles and namespace authorization for hardened deployments;
  • deterministic mock providers for safe local testing;
  • run-local evaluation caches, complete confusion-matrix accounting, and configurable bounded frozen-candidate threshold sweeps;
  • versioned session-local JSON evaluation datasets with provider-free preview, strict validation, and no browser persistence;
  • optional namespace-authorized PostgreSQL evaluation dataset catalog with explicit save, bounded retention, and no stored run results.

Dashboard endpoints and operations

Service Address
Frontend http://localhost:4173
Backend http://localhost:8000
API documentation http://localhost:8000/docs
Liveness http://localhost:8000/health
Readiness http://localhost:8000/ready
Runtime metrics http://localhost:8000/api/v1/metrics
Runtime diagnostics http://localhost:8000/api/v1/diagnostics
PostgreSQL from the host (persistent profile only) 127.0.0.1:5433

Submit a unique Monitor prompt twice: expect a miss followed by a confirmed hit. Mock responses are deterministic examples, not hosted model output.

Useful commands:

docker compose -f docker-compose.dev.yml ps
docker compose -f docker-compose.dev.yml logs -f backend
docker compose -f docker-compose.dev.yml down

down keeps named volumes. Adding --volumes deletes the local PostgreSQL data.

Optional: PostgreSQL persistence

For persistent cache entries and saved evaluation datasets, keep the mock-provider settings above and change these values in apps/server/.env. Replace the URL placeholders with the separate runtime login provisioned below; URL-encode its credentials when necessary. Keep the existing volume and back up any existing database before setup.

CACHE_BACKEND=pgvector
DATABASE_URL=postgresql://semantix_runtime:replace-runtime-password@postgres:5432/semantix
DATABASE_MIGRATION_MODE=external
EVALUATION_DATASET_STORAGE=postgres
EVALUATION_DATASET_DEFAULT_RETENTION_DAYS=30

For a fresh launcher-managed volume, generate/configure the runtime password as explained in PostgreSQL credentials, then run python scripts/dev.py up. It provisions the missing restricted login with that password and runs separate setup; existing roles/data are never repaired or overwritten. No external provider supplies this password.

Advanced direct Compose setup: the remaining steps require explicit operator authority. Start only PostgreSQL and wait for its health check:

docker compose -f docker-compose.dev.yml --profile pgvector up -d --wait --wait-timeout 60 postgres

The development database creates only the local bootstrap role semantix. Do not use that privileged role in the backend's DATABASE_URL. Securely load these operator variables into your shell, without putting migration credentials in apps/server/.env, tracked files, shell history, or logs:

  • DATABASE_RUNTIME_ROLE: the restricted login name from DATABASE_URL;
  • MIGRATION_DATABASE_URL: the bootstrap/migration connection for this development database, with authority to enable pgvector, initialize schemas, and grant access.

Inside containers, both URLs use postgres:5432/semantix. A host tool instead uses 127.0.0.1:5433 by default (POSTGRES_PORT can change the published port). For an existing volume, use its actual credentials and back it up before setup.

For a genuinely missing runtime role, open psql using local bootstrap authority:

docker compose -f docker-compose.dev.yml --profile pgvector exec postgres psql -X --set ON_ERROR_STOP=1 --username semantix --dbname semantix

Inside psql, create the restricted role and enter the password from DATABASE_URL at the hidden \password prompts. If the role already exists, stop and verify its privileges and credentials separately; do not reset its password.

CREATE ROLE semantix_runtime LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS NOINHERIT;
GRANT CONNECT ON DATABASE semantix TO semantix_runtime;
\password semantix_runtime
\q

The password prompt avoids plaintext password SQL and process arguments. The migration command grants schema/table access; it does not create the login. In PowerShell, supply migration authority through a masked prompt:

$env:DATABASE_RUNTIME_ROLE = 'semantix_runtime'
$env:MIGRATION_DATABASE_URL = [pscredential]::new(
    'migration', (Read-Host 'Migration database URL' -AsSecureString)
).GetNetworkCredential().Password

In other shells, securely load the same two operator variables without putting their secret values in shell history or arguments.

Run explicit setup in a one-shot backend container and continue only if it exits successfully:

docker compose -f docker-compose.dev.yml --profile pgvector run --rm --no-deps --build -e DATABASE_MIGRATION_MODE=external -e MIGRATION_DATABASE_URL -e DATABASE_RUNTIME_ROLE backend python -m app.infrastructure.migrate

The backend image supplies Python, dependencies, and /apps/server as its working directory. It inherits cache schema/prefix and evaluation settings from apps/server/.env; keep them identical to runtime. The -e flags pass operator variables from your shell only to this job. Clear the operator variables afterward.

Ordinary cache startup validates the official schema and never initializes it. DATABASE_MIGRATION_MODE=auto applies only to other enabled PostgreSQL features, including evaluation storage. Development Compose reads the mode from apps/server/.env; keep it external when using the restricted runtime role. After successful setup, start the persistent stack with one command on either OS:

docker compose -f docker-compose.dev.yml --profile pgvector up --build -d --wait --wait-timeout 120 postgres backend frontend

This starts the React frontend with Vite hot reload and FastAPI with Uvicorn reload after explicit database setup. Check that /ready returns HTTP 200, then submit a unique Monitor prompt twice: expect a miss followed by a hit and a readable Cache Inspector entry. Empty official cache tables immediately after setup are valid; setup does not copy preserved legacy cache rows. See server storage setup for ownership and schema validation. This procedure remains for trusted local development; use hardened deployment before sharing with untrusted users.

πŸ”Œ Providers

Embedding and generation providers are selected independently.

Provider Embeddings Generation Credentials
Hugging Face Yes Yes Required
OpenAI Yes Yes Required
Anthropic No native embedding API Yes (contract-tested; live pending) Required
Gemini Yes Yes Required
Ollama Yes Yes Not required locally
Mock Yes Yes Not required

Only settings required by the selected capabilities are validated. See Providers for configuration examples and networking notes.

πŸ›‘οΈ Development and hardened deployment

Mode Intended use Main behavior
Development One trusted local developer Hot reload, loopback ports, disabled authentication, explicit setup for persistent cache
Hardened Shared or public two-replica deployment Token authentication, namespace roles, internal backend/database networks, external migrations, TLS proxy required

Create .env.production from .env.production.example only when preparing a hardened deployment:

docker compose --env-file .env.production -f docker-compose.prod.yml up --build -d

Do not start it until every placeholder has been replaced. See Hardened deployment for token generation, trusted proxies, database roles, TLS, and validation.

πŸ“ˆ Performance and scalability

The hardened stack balances backend replicas over shared PostgreSQL + pgvector state. PostgreSQL also coordinates deployment-wide rate limits, session lockout, and cache threshold changes. Replica failover, draining, and controlled scaling have been exercised.

In a local Docker test on the documented hardware, the two-replica stack completed a 10-minute cache-heavy run with 1,000 virtual users: 195,961 requests (about 324 RPS), P95 latency 186 ms, and zero HTTP 4xx, HTTP 5xx, transport, or sampled readiness failures. The workload used deterministic mock providers and 2–4 seconds of think time per virtual user. These figures are specific to that machine and workload, not a production capacity guarantee.

Controlled generation-heavy tests at 1,000 virtual users improved from about 167 RPS and 4.86 s P95 with one replica to 270 RPS and 1.95 s P95 with two. PostgreSQL connection and lock pressure limits extrapolation to more replicas. See Capacity testing for hardware, methodology, all profiles, failures, and limitations. The Python SDK was also exercised through the load-balanced gateway.

πŸ“Š Semantic cache benchmark

A local run on July 19, 2026 used the eight-query Quick semantic safety set, Hugging Face providers, typo normalization, an empty isolated cache, and a 0.92 threshold:

Provider calls avoided Average hit Average miss Precision / Recall / F1
4 of 8 (50%) 330.3 ms 3772.7 ms 1.0 / 1.0 / 1.0

This is one dated measurement, not a performance guarantee. See Benchmarking for the dataset, run details, and limitations.

⚠️ Important limitations

  • Semantic similarity is probabilistic and must be evaluated for each model and workload.
  • Hosted providers may receive prompts and can introduce cost, latency, and external data-handling requirements.
  • Runtime metrics, diagnostics, and request coalescing are process-local; production rate limiting uses shared PostgreSQL coordination.
  • The hardened stack balances two backend replicas; it is not a complete multi-tenant platform or a general-purpose autoscaling system.
  • Mock providers are for tests, demonstrations, and UI development.
  • Evaluation sweeps reuse one measured run; alternate thresholds are projections, not ordered replays or automatic threshold recommendations.

Use semantix-client only with an already-running compatible Semantix server. It remains maintained, is not a first-release PyPI target, and does not provide the embedded engine.

Reference HTTP client

External Python applications can use the independently installable semantix-client distribution through the public HTTP API. Python code imports it as semantix_client. It provides typed synchronous and asynchronous clients without installing or importing Semantix backend internals.

The package is not currently published to PyPI; install it from a built wheel or directly from the repository as described in the full guide.

from semantix_client import SemantixClient

with SemantixClient(base_url="http://localhost:8000") as client:
    result = client.query("Explain semantic caching", namespace="default")

print(result.response, result.cache_hit)

Full Python SDK guide β†’

Documentation

The documentation index separates embedded and server guides.

Start here Use it for
Cache package guide Embedded quick start, policies, ownership and canonical compatibility
Embedded providers Maintained adapters and custom embedding/generation
Context identity and migration Explicit scopes, embedding revisions and safe migration
Embedded storage Memory, SQLite, MySQL, PostgreSQL, Redis, Valkey and user-owned databases
Examples Application-controlled generation and stores
Reviewed reuse quality Semantic baseline, lexical controls, calibration/held-out split and evidence limitations
Benchmark methodology Reproducible local runtime workloads and limitations
Server getting started Optional server environment files and Docker workflows
HTTP client guide Typed client for an already-running compatible server
Server architecture Feature ownership and request flow
Hardened deployment Server auth, TLS, database roles and validation

Contributing

See CONTRIBUTING, cache contributor checks and server/web development.

Repository layout and server/web development checks

πŸ—‚οΈ Project structure

semantix/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ server/
β”‚   └── web/
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ cache/
β”‚   β”‚   β”œβ”€β”€ src/semantix_cache/
β”‚   β”‚   └── tests/
β”‚   └── client/
β”‚       β”œβ”€β”€ src/semantix_client/
β”‚       └── tests/
β”œβ”€β”€ ops/
β”‚   β”œβ”€β”€ ci/
β”‚   β”œβ”€β”€ load-testing/
β”‚   β”œβ”€β”€ postgres/
β”‚   └── supply-chain/
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ linux/
β”‚   └── windows/
β”œβ”€β”€ docs/
β”œβ”€β”€ .github/
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ docker-compose.dev.yml
β”œβ”€β”€ docker-compose.prod.yml
└── README.md

apps/server is the official self-hosted FastAPI application; apps/web is the official web/workbench. packages/cache contains the primary reusable semantix-cache library, the intended first public PyPI distribution. packages/client contains the maintained optional/reference semantix-client HTTP client, which is not currently required for that first release. ops holds operational tooling and scripts holds repository/developer tooling.

The backend and frontend use feature-first ownership. See Architecture for the runtime flow and package boundaries.

βœ… Quality checks

Backend cache setup

Backend tool caches are centralized under apps/server/.cache/. Enable the Python bytecode cache redirect before running backend commands.

From the repository root:

Windows PowerShell:

. .\apps\server\scripts\windows\enable_cache.ps1

Linux or macOS:

source apps/server/scripts/linux/enable_cache.sh

When already inside apps/server/:

Windows PowerShell:

. .\scripts\windows\enable_cache.ps1

Linux or macOS:

source scripts/linux/enable_cache.sh

The leading dot in PowerShell and source in Bash are required so PYTHONPYCACHEPREFIX remains active in the current terminal. Ruff, mypy, and pytest use their cache paths from apps/server/pyproject.toml.

To remove generated caches and editable-install metadata:

.\apps\server\scripts\windows\clean_artifacts.ps1

For Linux or macOS:

bash apps/server/scripts/linux/clean_artifacts.sh

Platform-specific automation lives in windows/ and linux/ directories. Shared Compose overlays remain beside those directories under ops/ci/. For example, the development health smoke has matching entry points:

Windows PowerShell:

.\ops\ci\windows\dev-healthcheck-smoke.ps1

Linux or macOS:

bash ops/ci/linux/dev-healthcheck-smoke.sh

The smoke entry points generate ephemeral database passwords and authentication tokens for each run unless the corresponding environment variables are already set. Credentials are not stored in the scripts.

Repository-wide developer reports are available through paired platform helpers:

.\scripts\windows\get_total_lines.ps1
.\scripts\windows\find_undocumented_files.ps1
bash scripts/linux/get_total_lines.sh
bash scripts/linux/find_undocumented_files.sh

They inspect Git-tracked and unignored project files, so ignored dependencies, caches, virtual environments, and build output are excluded automatically.

Backend:

cd apps/server
uv sync --locked --extra dev
uv run --locked pytest
uv run --locked ruff check .
uv run --locked ruff format --check .
uv run --locked mypy app tests scripts

Frontend:

cd apps/web
npm ci
npm run lint
npm run format:check
npm run imports:check
npm run test:coverage
npm run build
npm run bundle:check

See Development for local toolchains, architecture rules, and contribution steps.

Security

Applications own authorization, generation context, credentials, transport security and provider data handling. Namespace separation is not authorization. See SECURITY for reporting and server deployment boundaries, plus the embedded provider and storage guides for caller-owned resource and database responsibilities.

πŸ“„ License

Licensed under the MIT License.

About

Contract-first semantic caching for Python. Async APIs, pluggable storage, confirmed cache hits, and inspectable decisions.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages