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?)Three local query paths · one Rust core
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.
Why did we choose Swift?
Project Apollo · approved notes
semantic 0.6 · BM25 0.4
Fast, private retrieval for edge AI
Privacy is a property of the whole pipeline you assemble, so the boundary is worth stating exactly instead of asserting it loudly.
Choose the smallest product that fits
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.
Vector · BM25 · hybrid
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?)Traversal · projection
Follow relationships, match graph fields, and project stable candidates. No retrieval configuration, vector index, or embeddings.
GraphDatabase
.graph.query(...)Relationships → ranked hits
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
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.
Scoped evidence
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.
Named Apple M1 Max contracts. Retrieval timings exclude embedding generation.
Native exact retrieval · P50
7.17–7.60×Browser pipeline · P95
12.460 msKotlin/JVM · P95
8.393 msFrozen 296-query HotpotQA linked-abstracts comparison, weighted I8, over a 12,670-chunk workload.
Graph-scoped vs whole-corpus · NDCG@10
0.928Candidate stage · mean per query
972.65×Supported-workload qualification on one named device, with embedding excluded.
iPhone 17 Pro Max · median-session P95
6 / 6From first result to integration
9 of 9 sections
Published preview
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 RetrievalKitExpected: Next: choose a language quickstart below.Swift / Apple platforms
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-onlyRun from source
scripts/build-xcframework.sh --macos-only
scripts/run-swift-quickstart.sh base-retrievalExpected: hybrid=decision-swiftTypeScript / Node.js
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.mjsExpected: The top hit contains documentId: 'two'.Browser / WebAssembly
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
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:runExpected: kotlin: Kotlin calls the local Rust retrieval core. (1.0)Graph-only Python
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.pyExpected: graph-only=retrievalPython
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-swiftRun 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.pyExpected: graph-hybrid=decision-swiftDebugging
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-onlyCompatibility
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
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.
Commercial licensing
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 →