Реліз векторної бази даних 0.7.0: IVF-RaBitQ, DiskANN на io_uring і бібліотека на 40% менша
Огляд релізу 0.7.0 вбудовуваної векторної бази даних: локальний пошук по робочому простору, інтеграція з ReMe, квантовані та дискові індекси, wheels для musllinux і DocIterator.
Версія 0.7.0 — великий реліз цієї вбудовуваної векторної бази даних. Зміни зачепили чотири сфери: екосистему навколо неї, алгоритми індексів, способи розгортання бібліотеки та зручність у щоденній роботі. Головне: CLI для пошуку по робочому простору zvec-grep, інтеграція з ReMe, IVF-RaBitQ, доведений до продакшену DiskANN з io_uring і підтримкою ARM64, вибір AVX2 та AVX512 для RaBitQ під час виконання, динамічна бібліотека приблизно на 40% менша, wheels для musllinux, готові бінарники SDK із CI, DocIterator і N-грамний токенізатор для повнотекстового пошуку. Повні нотатки до релізу є на сторінці GitHub-релізу проєкту для тегу v0.7.0.
Екосистема
zg: локальний пошук по робочому простору
Нова консольна утиліта zvec-grep шукає по робочому простору повністю на вашій машині. За одним інтерфейсом стоять три шари:
- ripgrep — для швидкого пошуку за рядками й регулярними виразами
- BM25 з jieba — для лексичного ранжування
- векторний пошук HNSW — для смислових запитів
Користуватися нею мають і люди, і ШІ-агенти, а під'єднати до агентських процесів її можна через MCP. Хто будує RAG по кодовій базі, пам'яті агента чи документації, отримує одну команду zg замість кількох склеєних докупи інструментів.
Інтеграція з ReMe
База тепер працює як файловий бекенд для ReMe — набору інструментів для керування пам'яттю агентів. ReMe використовує її для наближеного пошуку найближчих сусідів на HNSW усередині процесу по файлах пам'яті агента, тож застосунки отримують векторний пошук із низькою затримкою без запуску окремого процесу бази.
Алгоритми індексів
IVF-RaBitQ
RaBitQ уперше з'явився для індексів HNSW і Flat у попередніх версіях. У 0.7.0 він дістався індексів IVF і дав ще один спосіб пожертвувати невеликою часткою повноти заради великої економії пам'яті на даних масштабу мільярдів векторів.
Індекс IVF-RaBitQ розбиває вектори на кластери в інвертовані списки, і кожен список квантується через RaBitQ приблизно до одного біта на вимір. Індекс лишається компактним, але підтримує переранжування через refiner і скалярну фільтрацію та використовує той самий API Query, що й раніше. Для навантажень, які підходять під профіль IVF, тобто великих пакетних задач або пошуку з обмеженою пам'яттю, це часто найдешевший варіант.
SIMD-диспетчеризація для RaBitQ
RaBitQ тепер обирає найшвидший шлях коду під час виконання. На процесорі з AVX512 працюють ядра AVX512, інакше AVX2, а скалярний код лишається останнім варіантом. Один бінарник може користуватися новим залізом без окремих збірок і прапорців компілятора.
DiskANN готовий до продакшену
DiskANN був головною новинкою v0.5.0. Цей реліз робить його швидшим, надійнішим і доступним на більшій кількості платформ.
Бекенд io_uring. На Linux 5.3 і новіших DiskANN віддає перевагу io_uring перед libaio. Він звертається до ядра напряму, тому для збірки не потрібен liburing. Порядок відкату такий: io_uring, потім libaio, потім pread, і за відсутності бекенда все акуратно деградує.
Асинхронне введення-виведення з перекриттям і динамічний beam. Променевий пошук тепер поєднує роботу процесора з читанням із диска й на льоту підлаштовує ширину променя, щоб диск був завантажений, але не засипаний запитами. У навантажень, що впираються в диск, падає затримка. Пов'язане виправлення дедуплікації у visit-фільтрі прибирає зайві вставки кандидатів.
ARM64. DiskANN збирається й працює на Linux ARM64 і на Mac з Apple Silicon. На macOS використовується синхронний pread з F_NOCACHE і вимкненим випереджальним читанням, а CI на Linux проганяє всі бекенди. Граничні випадки на кшталт часткового чи короткого читання, EINTR і переходу між бекендами обробляються безпечно.
Інтроспекція. Активний бекенд введення-виведення кешується й видимий через API на C, C++ і Python, тож під час роботи можна перевірити, чи йдуть запити через io_uring, libaio або pread.
Якість графа зросла
Vamana отримала необов'язкову двопрохідну збірку. Швидкий перший прохід будує грубий граф, другий його уточнює — вдалий обмін, коли повнота важливіша за час збірки.
HNSW також уміє будувати граф за вихідними сирими векторами від провайдера індексу, навіть якщо сам індекс зберігає для пошуку квантовану чи перетворену копію. Побудова графа йде з повною точністю, якість зростає, а пам'ять під час запитів лишається невеликою.
Розгортання
Схудла динамічна бібліотека
Готові спільні бібліотеки на C і C++ на macOS ARM64 стали приблизно на 40% меншими. Наприклад, libzvec_c_api.dylib зменшилася приблизно з 37 до 22 МБ. Публічні API не змінилися, швидкість запитів теж, а основний код пошуку, як і раніше, компілюється з -O3.
Економія вийшла завдяки трьом змінам:
- компіляція з
-ffunction-sections -fdata-sections, щоб лінкер викидав невикористаний код - експорт лише власних публічних символів бібліотеки через
-exported_symbols_listабо--version-script - повна відмова від protobuf у дереві залежностей
Маніфести колекцій побайтово сумісні з попереднім форматом protobuf. Серіалізацією тепер займаються невеликі внутрішні кодувальник і декодер.
Wheels для musllinux
З'явилися офіційні wheels для musllinux на x86_64 і ARM64, тож бібліотека без проблем встановлюється на Alpine Linux та інші системи на musl. Для цього знадобилося кілька виправлень під musl. Великі SIMD-буфери прибрали зі стандартного стеку потоку на 128 КБ, а логер став синглтоном Маєрса, щоб уникнути повторних реєстрацій __cxa_atexit у різних спільних бібліотеках.
Конвеєр готових SDK
Workflow GitHub Release тепер збирає готові до використання пакети SDK для C і C++. Теги alpha, beta та RC автоматично позначаються як пререлізи. Перед завантаженням кожен пакет проходить smoke-тест. Ранери для десктопа й musl компілюють маленькі тестові програми на C і C++ та запускають їх проти підготовленого SDK. Для Android перевірка — це крос-збірка, яка має злінкуватися, а для iOS — огляд обох зрізів XCFramework і розкладки заголовків.
Зручність
DocIterator
Тим, хто працює з пам'яттю агентів та ETL, часто треба пройти всі документи колекції без вектора запиту. Для цього є DocIterator. Під час створення він робить знімок поточних сегментів і бітової карти видалень, тож подальші записи й видалення обходу не заважають. Він працює з C++, C і Python, а контроль доступу не дає обходу й операціям обслуговування перетинатися.
На Python:
with collection.iter_docs(
output_fields=["title"], # only fetch needed scalar fields; primary key is always returned
include_vector=False,
) as docs:
for doc in docs:
print(doc.id, doc.fields["title"])
N-грамний токенізатор для FTS
У повнотекстовому пошуку з'явився N-грамний токенізатор. Він індексує послідовності символів довжиною n, що перекриваються, і не зважає на межі слів. Це підходить для пошуку фраз і підрядків у коротких текстах, ідентифікаторах у коді та рядках логів, а також для мов, де межі слів визначити складно. Значення n задається через extra_params під час створення FTS-індексу.
Продуктивність
- DiskANN поєднує роботу процесора й диска в променевому пошуку, а динамічна ширина променя тримає паралелізм на розумному рівні.
- RaBitQ обирає ядра AVX512 або AVX2 під час виконання, без єдиної жорстко заданої цілі збірки.
- Видалення мертвого коду в динамічній бібліотеці дає менші бінарники, які швидше завантажуються й займають менше резидентної пам'яті, а ядра пошуку лишаються на
-O3.
Інші зміни та виправлення
- Python API: новий
collection.close(), перевірка порожніх FTS-запитів,topkі невідомих імен полів, охайніша робота з векторами NumPy. - C++ API: публічні імена тепер у стилі
snake_case. - C API: більше немає фіктивного рядка версії
0.2.1, коли git-теги відсутні. - Коректність пошуку: фільтри перевіряються, застарілий стан фільтра скидається, а інваріанти купи неможливо обійти.
- K-Means: виправлено ваги вибірки у сферичному K-MC2 і нормалізацію центроїдів.
- Сховище: обробляються розбіжні межі скалярних пакетів, останній IPC-фрагмент у mmap-сховищі обробляється правильно, записувані сегменти лише з видаленнями зберігаються, а осиротілі й списані каталоги сегментів очищуються під час відновлення після збою та на Windows.
- Колекції: читання й запис тривають, поки працює
Optimize. - Vamana: враховуються асиметричні метрики запитів.
- Збірка та CI: менше експортів із DLL на Windows, прибрано застарілі маркери патчів сабмодулів, оновлено залежності GitHub Actions, а перевірки запускаються, коли чорновий PR стає готовим.
Подальша робота над масштабованістю сховища, новими алгоритмами та SDK для інших мов відстежується в публічній задачі з дорожньою картою, номер 309 у GitHub-репозиторії проєкту.