Files
2026-09-23 03:48:38 +03:00

99 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `:vector-index-jvector` — ANN-индекс поверх JVector (Datadog)
## Что это
JVM-only реализация `MutableVectorIndexStore` поверх
[JVector](https://github.com/jbellis/jvector) — ANN-библиотеки Datadog
(HNSW-подобный граф). Самый быстрый бэкенд в проекте для больших
датасетов (10K+ записей).
Используется как замена brute-force SQLite-индекса, когда размер
датасета перерастает ~10K записей или важна latency на search.
## Где используется
Standalone-агентом в JVM-режиме, когда нужно эффективное семантическое
поисковое хранилище. Прямо сейчас модуль **не подключён** в
`:standalone` — это API-готовый компонент, ждущий интеграции.
## Что внутри
```kotlin
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 нужен — это будущая работа.
## Как подключить
```kotlin
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`
отложена до момента, когда понадобится.