Files

:vector-index-jvector — ANN-индекс поверх JVector (Datadog)

Что это

JVM-only реализация MutableVectorIndexStore поверх JVector — ANN-библиотеки Datadog (HNSW-подобный граф). Самый быстрый бэкенд в проекте для больших датасетов (10K+ записей).

Используется как замена brute-force SQLite-индекса, когда размер датасета перерастает ~10K записей или важна latency на search.

Где используется

Standalone-агентом в JVM-режиме, когда нужно эффективное семантическое поисковое хранилище. Прямо сейчас модуль не подключён в :standalone — это API-готовый компонент, ждущий интеграции.

Что внутри

class JVectorVectorIndexStore(
    override val dimension: Int,
    seedEntries: List<SeedEntry> = emptyList(),
) : MutableVectorIndexStore {

    data class SeedEntry(val id: String, val embedding: FloatArray, val payload: String?)

    override suspend fun getSize(): Long
    override suspend fun add(id: String?, embedding: FloatArray, payload: String?): VectorIndex
    override suspend fun delete(id: String): Boolean
    override suspend fun clear(): Long
    override suspend fun search(embedding: FloatArray, limit: Int): List<VectorSearchResult>
    override fun close()
}

Параметры графа (как в :memory-vector/JVectorMemoryIndex): M=16, efConstruction=100, neighborOverflow=1.2f, alpha=1.2f.

Thread-safety: ReentrantReadWriteLock — параллельные search() ок, add/delete/clear — эксклюзивно.

delete(): убирает id из idToOrdinal + помечает ordinal как удалённый в BitSet. Это позволяет повторный add(id) после delete (без этого упал бы с VectorIndexAlreadyExistsException).

Цели сборки

Только jvm() — JVector публикуется только как JVM-библиотека (нет KMP-таргетов). Для Apple-целей использовать :vector-index-ksqlite.

Persist

НЕ поддерживается в v1. JVector'у для записи на диск нужна Feature с INLINE_VECTORS, которая в JVector 3.x конфигурируется отдельно и нестабильна. Альтернатива — пара (JVectorVectorIndexStore, KVectorStore) с persistence embeddings в SQLite и graph-rebuild на старте. Если persist нужен — это будущая работа.

Как подключить

dependencies {
    implementation("pw.binom.agentik:vector-index-jvector:0.1.0")
    implementation("pw.binom.agentik:vector-index-api:0.1.0")
}

val store = JVectorVectorIndexStore(dimension = 768)
store.add(id = "doc-1", embedding = embeddingOf("hello"), payload = """{"src":"chat"}""")
val top = store.search(embedding = queryEmbedding, limit = 10)

Тесты

./gradlew :vector-index-jvector:jvmTest

Покрывают: explicit/auto id, duplicate throws, delete+idempotency, clear, top-K sort, payload round-trip, limit > size.

Зависимости

  • io.github.jbellis:jvector:3.0.6
  • pw.binom.agentik:vector-index-api
  • kotlinx-coroutines-core

Чего здесь НЕТ

  • Persist (см. выше).
  • Фильтрации в search() — чистый ANN.
  • Multi-target / native — только JVM.

Текущий статус

Реализация готова, тесты зелёные. Интеграция в :standalone отложена до момента, когда понадобится.