Maven Central

Kotlin and Android local retrieval guide

Install the JVM or Android artifact, run typed JNI retrieval, scope with graph selections, and manage deterministic lifetimes.

JVM macOS arm64; Android API 24+ arm64-v8a previewView the v0.1.0 source guide →
On this page

Install

Choose exactly one base or graph retrieval artifact. Graph already includes retrieval. Embedding is independent.

dependencies {
    // JVM graph plus retrieval
    implementation("io.github.gungorbasa:retrievalkit-graph:0.1.0")
    implementation("io.github.gungorbasa:retrievalkit-embedding:0.1.0")

    // Android equivalents
    implementation("io.github.gungorbasa:retrievalkit-graph-android:0.1.0")
    implementation("io.github.gungorbasa:retrievalkit-embedding-android:0.1.0")
}

The JVM artifact contains a macOS arm64 native library. JDK 17 builds the wrapper and the produced bytecode runs on Java 11+. Android artifacts target API 24+ on arm64-v8a.

Android packaging is qualified. Live-device inference, lifecycle, compatibility, thermal behavior, and performance remain unqualified.

Kotlin exposes blocking JNI calls. Run build, persistence, and search work on an application-selected background executor or coroutine dispatcher on Android.

import ai.retrievalkit.Document
import ai.retrievalkit.MetadataValue
import ai.retrievalkit.RetrievalDatabase

val database = RetrievalDatabase.Builder(corpusId = "apollo").use { builder ->
    builder.upsert(
        Document(
            id = "decision-swift",
            text = "Apollo chose Swift for native platform integration.",
            metadata = mapOf(
                "project" to MetadataValue.Text("apollo"),
            ),
        ),
        floatArrayOf(1f, 0f, 0f),
    )
    builder.build()
}

database.use {
    val hits = it.search(
        text = "Why did we choose Swift?",
        embedding = floatArrayOf(1f, 0f, 0f),
        alpha = 0.6f,
        limit = 5,
    )
    println(hits.firstOrNull()?.documentId)
}

The first upsert fixes dimension in Rust. FloatArray carries embeddings; metadata integers and timestamps use exact signed Long values.

Choose a search mode

  • search(embedding = ...) performs exact vector search.
  • search(text = ...) performs BM25-only search.
  • search(text = ..., embedding = ..., alpha = ...) performs hybrid search.

Metadata filters are hard constraints and are applied before the final top-k.

Scope with a graph

Graph selections are opaque AutoCloseable resources.

graphRetrievalDatabase.query(
    GraphQuery(
        GraphSeed.Nodes(listOf(GraphNodeId("Project", "apollo"))),
        traversals = listOf(GraphTraversal("contains")),
    ),
).use { selection ->
    val hits = graphRetrievalDatabase.search(
        text = "native integration",
        embedding = floatArrayOf(1f, 0f, 0f),
        alpha = 0.6f,
        within = selection,
    )
    println(hits.firstOrNull()?.documentId)
}

Rust owns schema validation, traversal, typed path provenance, projection filtering, stale-selection rejection, and ranking.

Run the JVM source quickstart

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

Source builds require Rust cargo. Android builds additionally require NDK 26 and the Rust aarch64-linux-android target.

Choose the database boundary

Three query paths

Compare the same job in Kotlin. These are separate APIs, not modes hidden behind one query.

01

Hybrid vector + BM25

RetrievalDatabase

Rank the whole corpus with exact vector similarity and BM25.

Kotlin
val hits = retrievalDatabase.search(
    text = "What did we decide about offline sync?",
    embedding = queryEmbedding,
    alpha = 0.6f,
    limit = 5,
)
02

Graph query alone

GraphDatabase

Select records by relationship. No embedding or retrieval ranker is involved.

Kotlin
graphDatabase.query(
    GraphQuery(
        seed = GraphSeed.Nodes(
            listOf(GraphNodeId("Notebook", "product-research")),
        ),
        traversals = listOf(GraphTraversal("references")),
    ),
).use { selection ->
    selection.snapshot.matches.forEach(::println)
}
03

Graph + vector + BM25

GraphRetrievalDatabase

Select candidates with the graph, then rank only that scope with vector + BM25.

Kotlin
graphRetrievalDatabase.query(
    GraphQuery(
        GraphSeed.Nodes(
            listOf(GraphNodeId("Project", "mobile-app")),
        ),
        traversals = listOf(GraphTraversal("contains")),
    ),
).use { selection ->
    val hits = graphRetrievalDatabase.search(
        text = "Why is cold start slow on Android?",
        embedding = queryEmbedding,
        alpha = 0.6f,
        within = selection,
        limit = 5,
    )
}