v0.1.0 published preview

Three local query paths · one Rust core

Search locally.
Keep the evidence.

Use exact vector, BM25, or hybrid retrieval; query relationships without embeddings; or rank only the records selected by a graph. Everything runs inside your app on your user’s own machine. Native Swift, Node.js, Kotlin, and Python APIs plus dedicated browser Worker packages.

Python preview revision 09cb2d8f9e56 · SHA-256 11e35cc0764ebc62fd1c10708588d525843bc396cd11669e27689891daced246

graph_scoped.search
QUERY

Why did we choose Swift?

01
Scope

Project Apollo · approved notes

02
Rank

semantic 0.6 · BM25 0.4

TOP HITdecision-swift
0.96
Local-firstNo retrieval server
ExplainableScores and traces
DeterministicStable exact search
ComposableGraph-only or combined

Fast, private retrieval for edge AI

Private is a boundary, not a badge.

Privacy is a property of the whole pipeline you assemble, so the boundary is worth stating exactly instead of asserting it loudly.

After first loadA query requires no network request. Model files are fetched once, then the query path stays on the machine.
Embeddings stay yoursNo retrieval database downloads, selects, or invokes an embedding model. The embedding packages are separate and optional.
Relationships stay yoursRetrievalKit never extracts or invents a graph. Your application supplies the records and the relationships between them.
The honest limitIf your application sends text to a remote embedding service, that step is not private — even though RetrievalKit still indexes and searches locally.

Choose the smallest product that fits

Retrieval, graph search, or both.

Graph search is not an add-on that requires vectors. Use it alone, or use a graph selection as the candidate scope for the same exact vector, BM25, and hybrid ranker.

01

Vector · BM25 · hybrid

Retrieval search

Search a flat corpus with an embedding, query text, or both. Query-time alpha selects vector-only, BM25-only, or hybrid ranking.

RetrievalDatabase
.search(text?, embedding?, alpha?)
02

Traversal · projection

Graph search

Follow relationships, match graph fields, and project stable candidates. No retrieval configuration, vector index, or embeddings.

GraphDatabase
.graph.query(...)
03

Relationships → ranked hits

Graph-scoped retrieval

Let the graph choose the candidate neighborhood, then run exact vector, BM25, or hybrid ranking only inside that scope.

GraphRetrievalDatabase
graph.query(...) → retrieval.search(... within)

Published preview

One signed release, four distribution channels.

v0.1.0 is available through SwiftPM, PyPI, npm, and Maven Central. The immutable GitHub preview release contains the signed source and qualified artifacts. Platform limits still apply; publication is not a claim of universal device support. View the v0.1.0 release.

SDKSelectPublicationAvailable now
SwiftRetrievalKit, RetrievalKitGraph, EmbeddingKit, PipelinePublished preview from signed tag and release XCFrameworkSwiftPM 0.1.0
Pythonretrievalkit, retrievalkit-graph, retrievalkit-embeddingThree macOS arm64 distributions publishedPyPI 0.1.0
Node.jsBase, graph, and independent embeddingThree macOS arm64 packages publishednpm 0.1.0
BrowserWorker retrieval + independent Worker embeddingTwo portable/SIMD128 WASM packages publishednpm 0.1.0
Kotlinretrievalkit, retrievalkit-graph, retrievalkit-embeddingThree macOS arm64 artifacts publishedMaven Central 0.1.0
Androidretrievalkit-android, retrievalkit-graph-android, retrievalkit-embedding-androidThree arm64-v8a AARs published; live device unqualifiedMaven Central 0.1.0

Scoped evidence

Measured workloads, named hardware, no universal claims.

Speed, retrieval quality, and device qualification are separate kinds of evidence, so they are reported separately. Retrieval and embedding are separated unless a result explicitly says end to end. Mobile browser performance and all live Android-device performance remain unqualified.

Frozen observations for revision 9c784d2, reported 2026-07-21, expiring 2027-07-21. They describe that revision, not the current checkout.

Read the benchmark methodology and evidence →

Speed

Named Apple M1 Max contracts. Retrieval timings exclude embedding generation.

Native exact retrieval · P50

7.17–7.60×

Lower latency than sqlite-vec 0.1.9

Apple M1 Max, exact F32 384d top-10: 7.17× at 10K, 7.60× at 25K, and 7.29× at 50K. With the frozen filter: 10.38×, 9.08×, and 8.43×. Each lane used 20 warmups and 100 measured queries; embedding was excluded.

Browser pipeline · P95

12.460 ms

Chrome WebGPU at 50K

Apple M1 Max, 50K×384d I8, 32-token query, separate embedding and retrieval Workers: Chrome 150 WebGPU + SIMD128 reached 12.460 ms end to end. Firefox 150's deterministic WASM compatibility tier reached 21.660 ms; Safari 26.5.2 WebGPU reached 18.380 ms. Those two are measurements only — Safari, Firefox, and physical mobile browsers are not qualified support.

Kotlin/JVM · P95

8.393 ms

Separately measured embedding + retrieval

The packaged macOS arm64 JAR measured 8.175 ms warm embedding p95 and 0.218 ms native I8 retrieval p95 on Apple M1 Max. Their 8.393 ms sum is not an end-to-end measurement and is not an Android result.

Retrieval quality

Frozen 296-query HotpotQA linked-abstracts comparison, weighted I8, over a 12,670-chunk workload.

Graph-scoped vs whole-corpus · NDCG@10

0.928

Scoping by relationships ranked better than searching everything

Graph-scoped retrieval raised NDCG@10 from 0.858036 to 0.927909, with 121 wins, 157 ties, and 18 losses. Recall@10 rose from 0.871622 to 0.957770 and complete-evidence Recall@10 from 0.743243 to 0.922297; sixteen queries lost on each recall measure. A scoped quality result on one workload, not a universal graph winner.

Candidate stage · mean per query

972.65×

Far fewer candidates, evidence still retained

The frozen candidate stage cut the mean per-query candidate set by 972.65× while retaining 96.79% candidate recall and 94.26% candidate complete evidence across 296 valid graph queries, with zero empty scopes. Candidate reduction is not a retrieval-latency speedup, and retention was not perfect.

Physical-device qualification

Supported-workload qualification on one named device, with embedding excluded.

iPhone 17 Pro Max · median-session P95

6 / 6

Supported workflows passed on a real iPhone

On a physical iPhone 17 Pro Max (iPhone18,2, V54AP), the supported 10K, 25K, and 50K F32/I8 product workflows passed, and all six graph-free candidate-to-baseline median-session P95 ratios landed at or below the frozen 1.03 gate. Query and prepare evidence used iOS 26.5.1; remaining lifecycle evidence used iOS 26.5.2. This qualifies that device and workload set — it is not a claim about other hardware.

From first result to integration

One mental model, native in every language.

9 of 9 sections

Published preview

Install v0.1.0 from the public registries

The signed v0.1.0 preview is available through SwiftPM, PyPI, npm, and Maven Central, including independent embedding packages and the two browser Worker packages.

Choose exactly one base or graph native retrieval aggregate per process; graph already includes base retrieval. The embedding packages are independent. Browser retrieval combines base, graph-only, and graph-scoped retrieval in one Worker/WASM package, with browser embedding in a second Worker package.

API example

# Python: choose base or graph; embedding is optional
python -m pip install retrievalkit==0.1.0
python -m pip install retrievalkit-graph==0.1.0
python -m pip install retrievalkit-embedding==0.1.0

# Node.js: choose base or graph; embedding is optional
npm install @gungorbasa/retrievalkit@0.1.0
npm install @gungorbasa/retrievalkit-graph@0.1.0
npm install @gungorbasa/retrievalkit-embedding@0.1.0

# Browser: two independent Worker packages
npm install @gungorbasa/retrievalkit-browser@0.1.0
npm install @gungorbasa/retrievalkit-browser-embedding@0.1.0

// Package.swift
.package(
  url: "https://github.com/gungorbasa/RetrievalKit.git",
  from: "0.1.0"
)

// build.gradle.kts — JVM
implementation("io.github.gungorbasa:retrievalkit-graph:0.1.0")
implementation("io.github.gungorbasa:retrievalkit-embedding:0.1.0")

// build.gradle.kts — Android
implementation("io.github.gungorbasa:retrievalkit-graph-android:0.1.0")
implementation("io.github.gungorbasa:retrievalkit-embedding-android:0.1.0")

Run from source

git clone https://github.com/gungorbasa/RetrievalKit.git
cd RetrievalKit
Expected: Next: choose a language quickstart below.

Swift / Apple platforms

One package, selectable retrieval and graph products

Choose RetrievalKit for local search or RetrievalKitGraph for graph traversal and scoped retrieval. Both products share one graph-capable native artifact.

The signed v0.1.0 tag and versioned XCFramework are public through SwiftPM. The qualified package target is macOS 14+ arm64 and iOS 15+ arm64 devices and Apple-silicon simulators. Add the package once, then select RetrievalKit, RetrievalKitGraph, EmbeddingKit, or RetrievalKitPipeline as needed.

Read the complete Swift / Apple platforms guide →

API example

import RetrievalKit

@main
struct ApolloSearch {
  static func main() async throws {
    let builder = try RetrievalDatabase.Builder(
      corpusID: "apollo",
      encoding: .f32
    )
    try await builder.upsert(
      Document(
        id: "decision-swift",
        text: "Apollo chose Swift for its Apple client."
      ),
      embedding: [1, 0]
    )
    let database = try await builder.build()
    let hits = try await database.search(
      text: "Why did we choose Swift?",
      embedding: [1, 0],
      alpha: 0.6,
      limit: 1
    )
    print(hits[0].documentID)
  }
}

// Build first:
// scripts/build-xcframework.sh --macos-only

Run from source

scripts/build-xcframework.sh --macos-only
scripts/run-swift-quickstart.sh base-retrieval
Expected: hybrid=decision-swift

TypeScript / Node.js

Typed async APIs for Node.js LTS

Promise-based N-API calls keep native work off the event loop and preserve Float32Array, bigint, and typed graph values.

The base, graph, and independent embedding packages are published for macOS arm64 with Node.js 22.13+ LTS or Node.js 24 LTS. Browser retrieval and browser embedding are separate published Worker packages with portable and SIMD128 WASM tiers; they are not Node.js fallbacks. Windows, Linux, and other native Node architectures are not claimed.

Read the complete TypeScript / Node.js guide →

API example

import { RetrievalDatabaseBuilder }
  from "@gungorbasa/retrievalkit";

const builder = new RetrievalDatabaseBuilder({
  corpusId: "apollo"
});
await builder.add([{
  id: "decision-swift",
  text: "Apollo chose Swift.",
  embedding: new Float32Array([1, 0, 0])
}]);

const database = await builder.build();
try {
  const hits = await database.search({
    mode: "hybrid",
    text: "Why Swift?",
    embedding: new Float32Array([1, 0, 0]),
    alpha: 0.6
  });
  console.log(hits[0]?.documentId);
} finally {
  await database.close();
}

Run from source

cd wrappers/typescript
npm ci
npm run preflight
npm run build
node base/examples/retrieval.mjs
Expected: The top hit contains documentId: 'two'.

Browser / WebAssembly

Two Worker packages, one local browser pipeline

Browser retrieval owns base, graph-only, and graph-scoped WASM databases; browser embedding is an independent Worker package.

Both v0.1.0 npm packages are public. Retrieval loads either the portable or SIMD128 WASM tier inside its Worker. Embedding uses a separate Worker and selects WebGPU or deterministic WASM at load time. They do not replace or fall back to the native Node.js packages, and browser persistence remains deferred.

Read the complete Browser / WebAssembly guide →

API example

import { RetrievalKitBrowser }
  from "@gungorbasa/retrievalkit-browser";
import { BrowserEmbedder }
  from "@gungorbasa/retrievalkit-browser-embedding";

const kit = await RetrievalKitBrowser.create({
  worker: () => new Worker(
    new URL("./retrievalkit.worker.js", import.meta.url),
    { type: "module" },
  ),
});

const embedder = await BrowserEmbedder.load({
  worker: () => new Worker(
    new URL("./embedding.worker.js", import.meta.url),
    { type: "module" },
  ),
  execution: "auto",
});

Kotlin / Android

Blocking, typed JNI with deterministic lifetime

Kotlin uses FloatArray, sealed value types, typed exceptions, and AutoCloseable resources over the shared Rust core.

All six JVM and Android v0.1.0 artifacts are published on Maven Central: base, graph, and independent embedding variants for each platform. The JVM package uses a macOS arm64 native library, builds with JDK 17, and its bytecode runs on Java 11+. Android API 24+ arm64-v8a is an explicit packaging-qualified preview; live-device inference, compatibility, and performance remain unqualified.

Read the complete Kotlin / Android guide →

API example

import ai.retrievalkit.Document
import ai.retrievalkit.RetrievalDatabase
import ai.retrievalkit.VectorEncoding

fun main() {
    RetrievalDatabase.Builder(
        "apollo",
        encoding = VectorEncoding.F32,
    ).use { builder ->
        builder.upsert(
            Document("decision-swift", "Apollo chose Swift."),
            floatArrayOf(1f, 0f),
        )
        builder.build().use { database ->
            val hits = database.search(
                text = "Why Swift?",
                embedding = floatArrayOf(1f, 0f),
                alpha = 0.6f,
                limit = 1,
            )
            println(hits.first().documentId)
        }
    }
}

Run from source

export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export PATH="$JAVA_HOME/bin:$PATH"
cd wrappers/kotlin
./scripts/preflight.sh jvm
./scripts/build-native.sh jvm
./gradlew :example-retrieval:run
Expected: kotlin: Kotlin calls the local Rust retrieval core. (1.0)

Graph-only Python

Traverse relationships without embeddings

GraphDatabase is a complete standalone product for graph queries and stable candidate projection.

Use the graph-enabled distribution but build GraphDatabase when relationships are the result—not a scope for retrieval. The builder accepts no metric, vector encoding, embedding dimension, or embeddings. Rust owns validation, traversal, filtering, ordering, and generation safety.

Read the complete Graph-only Python guide →

API example

from retrievalkit_graph import (
    GraphDatabaseBuilder,
    GraphRecordNode,
    GraphSchema,
)

builder = GraphDatabaseBuilder(
    corpus_id="topics",
    schema=GraphSchema(
        record_nodes=[
            GraphRecordNode("Topic", "Topic", ["title"])
        ]
    ),
)
builder.upsert({
    "id": "retrieval",
    "record_type": "Topic",
    "fields": {"title": "Local retrieval"},
})
database = builder.build()

selection = database.graph.query_equals(
    node_type="Topic",
    field="title",
    values="Local retrieval",
)
print(selection.matches[0]["node"]["record_id"])

Run from source

PYTHON_BIN=python3 scripts/check-python-graph-wrapper.sh
target/python-graph-wrapper-check-venv-py*/bin/python \
  wrappers/python-graph/examples/graph_quickstart.py
Expected: graph-only=retrieval

Python

Scope by relationships, then rank

Graph-scoped retrieval selects candidates before exact vector, BM25, or hybrid ranking. Rust owns identity, filtering, ranking, traces, and persistence.

Install retrievalkit-graph for graph-only or graph-scoped search, retrievalkit for a flat corpus, and retrievalkit-embedding when you want the independent local FP32 MiniLM provider. All three v0.1.0 distributions are published for macOS arm64 on CPython 3.10–3.14. Install exactly one retrieval distribution per process.

Read the complete Python guide →

API example

from retrievalkit_graph import (
    GraphNode,
    GraphRecordNode,
    GraphRelationship,
    GraphRetrievalDatabaseBuilder,
    GraphSchema,
    GraphTraversal,
)

schema = GraphSchema(
    record_nodes=[
        GraphRecordNode("Project", "Project", ["title"]),
        GraphRecordNode("Note", "Note", ["title"]),
    ],
    relationships=[
        GraphRelationship(
            "contains", "Project", "Note", "note_ids", "many"
        )
    ],
)
builder = GraphRetrievalDatabaseBuilder(
    corpus_id="project-notes",
    graph=schema,
    encoding="f32",
)
builder.upsert({
    "id": "apollo",
    "record_type": "Project",
    "fields": {
        "title": "Project Apollo",
        "note_ids": ["decision-swift"],
    },
})
builder.upsert(
    {
        "id": "decision-swift",
        "record_type": "Note",
        "fields": {"title": "Apple client decision"},
        "content": "Apollo chose Swift for its Apple client.",
        "metadata": {"status": "approved"},
    },
    embedding=[1.0, 0.0],
)
database = builder.build()

selection = database.graph.query(
    seeds=[GraphNode("Project", "apollo")],
    traversals=[GraphTraversal("contains")],
)
hits = database.retrieval.hybrid_search(
    "Why did we choose Swift?",
    [1.0, 0.0],
    within=selection,
    where={"status": "approved"},
    alpha=0.6,
    limit=1,
)
print(hits[0]["document_id"])  # decision-swift

Run from source

PYTHON_BIN=python3 scripts/check-python-graph-wrapper.sh
target/python-graph-wrapper-check-venv-py*/bin/python \
  wrappers/python-graph/examples/graph_retrieval_quickstart.py
Expected: graph-hybrid=decision-swift

Debugging

Errors explain the correction

Stable language-specific exception types retain actionable messages from the Rust core.

A query with the wrong embedding dimension identifies the expected and actual values and tells the caller to use the same embedding model. Invalid alpha values explain the allowed range and the vector-only and BM25-only endpoints.

API example

invalid vector dimension: expected 384, got 768;
use the same embedding model for indexing and queries

invalid query parameter 'alpha':
alpha must be finite and between 0 and 1;
use 1 for vector-only or 0 for BM25-only

Compatibility

Know what is qualified today

Portability checks and released-platform support are tracked separately so CI evidence never becomes an accidental product promise.

The published preview remains deliberately narrow: Swift covers arm64 macOS and iOS, Python and native Node target macOS arm64, browser packages use dedicated Workers, and Kotlin/JVM targets macOS arm64. Android packaging covers API 24+ arm64-v8a, but no physical-device inference or performance pass exists. Other targets remain unclaimed until their full package and consumer matrices pass.

Platform truth, not platform theater

Qualified targets stay narrow until the evidence expands.

CI portability is useful evidence, but it is not a release claim. Every public target must pass package construction, installed-consumer smoke tests, lifecycle tests, and artifact inspection first.

Size is part of the same honesty. V1 is built for 1K to fewer than 50K chunks, 384- or 768-dimensional vectors, and top_k 5–10. Exact search is the deliberate choice at that scale: HNSW and other ANN indexes are deferred, not missing.

SwiftmacOS 14+ arm64Published preview
SwiftiOS 15+ arm64 device / simulatorPublished preview
PythonmacOS arm64 / CPython 3.10–3.14Published preview
PythonUbuntu / WindowsPortability CI only
Node.jsmacOS arm64 / Node 22.13+ or 24 LTSPublished preview
BrowserDedicated Workers / portable + SIMD128 WASMPublished preview; named desktop contracts
Kotlin/JVMmacOS arm64 / JDK 17 buildPublished preview
AndroidAPI 24+ / arm64-v8aPublished preview; live-device unqualified

Commercial licensing

The licence is settled. The commercial tier is not.

RetrievalKit is Apache-2.0 and stays that way. A commercial tier is planned, but nothing about it is decided — not the scope, not the pricing, not the date. If your team needs something the open licence does not cover, describing it now is what shapes it.

Tell us what you need →