Правила публикуются раньше,
чем цифры.
Telys — версия 0.1.0b4: это показатели, подтверждённые на прототипе на раскрытом стенде, а не продакшен-цифры. Результат засчитывается только тогда, когда он измерен при совпадающем recall на совпадающем железе, с исходными выборками и скриптом, который их получил. Правила ниже по-прежнему обязательны для каждого числа: что мы измеряем, с кем сравниваем и в чём обязаны проигрывать.
Правила, закреплённые в стенде, — не оговорки в сносках.
Каждое из приведённых ниже правил закодировано как машинная проверка в бенчмарк-стенде. Прогон, нарушивший правило, не получает сноску — он помечается как недействительный и исключается из всех таблиц результатов.
“Любой множитель остаётся гипотезой, пока не измерен при совпадающем recall и совпадающем железе — с исходными выборками и опубликованным скриптом воспроизведения.”
Доктрина бенчмарков TelysБенчмарк, в котором нельзя проиграть, ничего не стоит
Сгенерированная таблица результатов содержит обязательный раздел «Где мы проигрываем», заполняемый автоматически по каждой ячейке, которую выигрывает конкурент. Если раздел пуст, сборка отчёта завершается ошибкой — чистая победа трактуется как сломанный стенд, а не как триумф.
Embedded против embedded — честное сравнение
Мы никогда не выносим в заголовок вызов in-process против конкурента, отвечающего по TCP. Для встраиваемых библиотек честный транспорт — in-process против in-process. Для серверов транспорт сопоставляется один к одному, иначе цифра аннотируется и в заголовки не попадает.
Совпадающие уровни — или нет сравнения
Прогон in-memory никогда не сравнивается с конкурентом, выполняющим fsync при каждом коммите. Каждый результат декларирует свой уровень надёжности — in_mem, wal_async или wal_fsync — и стенд жёстко отклоняет любое сравнение между уровнями.
Мы никогда не намекаем, что обходим FAISS, когда сами вызываем FAISS
FAISS — это ANN-ядро, встроенное в Telys: фундамент, а не соперник. В каждой векторной таблице первой идёт ячейка с результатом чистого обхода FAISS; там, где результат совпадает, это явно указывается. Честные победы заявляются в другом: ядра переранжирования, фильтрованное планирование и движок вокруг индекса.
Каждый сравниваемый изолирует одно утверждение.
Единственная цифра в таблице лидеров смешивает алгоритм, транспорт, надёжность и формат хранения. Набор подобран так, чтобы каждое сравнение изолировало ровно одну переменную — с контрольным замером на том же узле под каждым заголовком.
| Система | Тип | Что изолирует сравнение |
|---|---|---|
| FAISS (тот же узел) | Контрольный базис | Нижняя граница, а не соперник. Telys встраивает FAISS, поэтому цифра чистого FAISS — это и есть наш базис; публикуемая дельта — то, что движок добавляет вокруг него при той же строке индекса и том же измеренном recall. |
| Postgres + pgvector | Реляционная + векторная | Фильтрованный гибридный запрос: выигрывает ли проталкивание скалярного предиката в путь кандидатов у индекса, вынужденного делать over-fetch или post-filter, при равном recall по разным селективностям фильтра. |
| LanceDB / Chroma | Встраиваемая библиотека | Ближайшие конкуренты, in-process против in-process — единственный случай, когда цифра in-process честна в заголовке. Одинаковый ANN-базис; сравнение изолирует движок вокруг него: единое пространство row-id, cold-open, объём памяти. |
| Qdrant / Milvus | Сервер | Качество алгоритма — recall при фиксированном k — отделённое от сетевых round-trip. Задержка публикуется с аннотацией о серверном хопе и никогда не выносится в заголовок рядом с вызовом in-process. |
| Pinecone | Управляемый сервис | Recall при фиксированном k и пропускная способность на единицу вычислительных ресурсов. Сырая задержка относительно встроенного движка не используется как заголовочный показатель; вместо этого контрольный узел на том же хосте подтверждает качество. |
| DuckDB / ClickHouse | Аналитический движок | Сканирование и агрегация по одному физическому файлу Parquet — так преимущество формата хранения отделяется от преимущества движка. Векторизованные аналитические движки здесь превосходны; их победы публикуются. |
Что измеряется.
Матрица определяет измерения, а не предполагаемые победы. Каждая ячейка задержки отражает полное распределение — никогда только среднее — при нагрузке в режиме открытого цикла. Каждая ячейка скорости привязана к порогу recall, вычисляемому стендом по эталонным данным; ячейка, не прошедшая порог, помечается недействительной и не попадает в итоговую таблицу.
| Нагрузка | Конфигурация | Что измеряется |
|---|---|---|
| cold-open | Сброс page cache, запуск нового процесса | Время от запуска процесса до первого успешного запроса — mmap сегментов и подключение index-sidecar в сравнении с загрузкой сервера и восстановлением. Измеряется отдельно от установившегося режима, никогда не объединяется с ним. |
| exact FLAT | Точный поиск перебором, f32 и int8 | Нижняя граница ядра расстояний при recall 1.0 по построению, относительно точного базового уровня на том же узле и тех же буферах. Каждая ячейка int8 сообщает дельту recall относительно f32 — потери от квантования не скрываются. |
| фильтрованный гибрид | Скалярный предикат + top-k, перебор по трём уровням селективности | Задержка при равном recall по мере сужения фильтра, а также выбранная планировщиком стратегия для каждой ячейки — pre-filter затем exact, pre-filter затем IVF или поиск с последующим post-filter — так адаптивное решение поддаётся аудиту. |
| full scan | Полное сканирование столбца и агрегация | Сырая колоночная пропускная способность по общему Parquet — движок против движка на идентичных байтах. |
| выборочное сканирование | Сканирование по предикату при низкой доле совпадений | Действительно ли footer min-max и zone-map pruning пропускают лишнюю работу — отчёт в байтах прочитанных данных и затронутых строках, а не только в wall clock. |
python -m bench.orchestrator.run \
--suite vector --rig m-laptop
# one command: pinned comparators, content-addressed
# datasets, warmup, steady-state measurement
# reviewer mode: the same run with Telys excluded# every run emits a machine-checked ResultEnvelope; # a run that cannot fill every field is invalid index_string = "IVF4096,PQ16" # same for Telys and the FAISS control omp_num_threads = 8 # FAISS threading pinned, disclosed transport = "in_process" # headlined only vs in-process durability_tier = "wal_fsync" # cross-tier comparison hard-fails recall_at_k = 1.000 # harness-measured, never self-reported samples_path = "bench/results/filtered_impact.txt"
Прогоны повторяются не менее пяти раз при каждом свежем запуске процесса, на зафиксированных аппаратных профилях, по одной системе за раз. Датасеты адресуются по содержимому; наборы запросов — замороженные файлы, не генерируются во время выполнения. Спецификация стенда зафиксирована сегодня; стенд публикуется вместе с результатами.
Измерено, обусловлено, воспроизводимо.
Каждая строка — реальный прогон на указанном выше стенде при напечатанном рядом пороге recall. Источник выигрыша — физическая раскладка: на идентичном непрерывном подмножестве наш Mojo-скан не уступает сырому FAISS — дельта ниже показывает, что даёт раскладка с партиционированием по ключу, а не более быстрое ядро расстояний. Это показатели прототипа, которые переизмеряются в рамках полного контракта честности по мере развития стенда.
| Нагрузка | Конфигурация + порог recall | Измеренный результат (M4 Max, однопоточный, in-process) |
|---|---|---|
| Фильтрованный срез · сел. 0,1% | N=1 000 000 D=128 K=10, прогрев, recall 1,000 (точный) | partition-slice p50 0,013 мс — выигрыш раскладки vs полный скан ~373×, vs scatter-gather ~19×. FAISS Flat на идентичном подмножестве: 0,040 мс (ничья — доказывает, что выигрыш даёт раскладка, а не ядро). |
| Фильтрованный срез · сел. 0,4% | N=1 000 000 D=128 K=10, прогрев, recall 1,000 (точный) | p50 0,032 мс — ~128× vs полный скан, ~10,8× vs scatter-gather. Контроль FAISS Flat 0,035 мс (ничья). |
| Фильтрованный срез · сел. 1,6% | N=1 000 000 D=128 K=10, прогрев, recall 1,000 (точный) | p50 0,112 мс — ~42× vs полный скан, ~10,3× vs scatter-gather. Контроль FAISS Flat 0,120 мс (ничья). |
| Спасение гигантской партиции | 247k строк при N=400 000 D=128, nprobe откалиброван, recall 0,9915 (порог 0,98) | IVF внутри партиции восстанавливает выигрыш раскладки там, где точный срез деградирует: точный срез 1,71 мс → IVF 0,033 мс. Без IVF одна гигантская партиция даёт лишь ~4–5×. |
| Управляемый auto-nprobe | N=1 000 000 D=128 Q=500 nlist=1000, recall удерживается 0,998 (порог 0,98) | FIND 0,28–0,31 мс при базовом nprobe=32 → 0,081–0,088 мс при управляемом auto-nprobe=8. Recall остаётся выше порога — без скрытого обмена recall на скорость. |
| FIND vs контроль FAISS | Iso-recall, одинаковый транспорт, оба in-process, N=1 000 000 D=128 | Telys 0,073–0,074 мс @0,998 vs сырой FAISS 0,080 мс @0,999 — паритет или незначительное преимущество. Зависит от масштаба: отставание (0,74×) при N=200k, до ~1,6× только при большом memory-bound N. Качество FAISS, ускоренное Mojo. |
| Конкурентность без GIL | N=200 000 D=128, 12 производительных ядер, in-process Mojo IVF kernel | Пропускная способность FIND масштабируется ×6,9 на 8 потоках (15 128 → 104 756 qps). Масштабирование пропускной способности, а не задержки на запрос; без сравнения с серверными движками. |
| Актуальность вставки | Базовый N=100 000, M=300 вставок, D=128, in-process | Только что вставленный вектор занимает top-1 уже на следующем запросе: recall@1-of-new = 1,000. Insert p50 0,3 мкс. Это проверка корректности, а не заголовок о пропускной способности. |
Каждая ячейка выше прослеживается до именованного скрипта и сохранённого исходного вывода в bench/results/ (filtered_impact.txt, partitioned.txt, partition_acceptance.txt, opt.txt, telys.txt, concurrency.txt, freshness.txt). Показатель повторного открытия после персистентности удержан до получения нового измеренного исходного образца. Любой множитель — гипотеза за пределами условий, указанных в каждой строке.
Создан для кода — и оценён на кодовом бенчмарке.
Telys ищет по коду, поэтому планка качества — CoIR, а не набор для общего текста. LexicalCodeIndex обёрнут как mteb SearchProtocol и оценивается через mteb.evaluate по тому же пути, что и базовые линии bm25s, — никакого разрыва в методологии, никакой самооценки. Базовые линии — воспроизводимые запуски от 2026-07-21, а не опубликованные цифры из статьи CoIR (часть из них не воспроизводится). Метрика: nDCG@10.
| Задача CoIR | multigram | bm25-ref | bm25-code | код-лексический · выпущен | vs лучшего базового |
|---|---|---|---|---|---|
| CodeTransOceanContest | 0.160 | 0.478 | 0.600 | 0.718 | ✅ |
| CodeTransOceanDL | 0.340 | 0.344 | 0.351 | 0.366 | ✅ |
| CosQA | 0.048 | 0.188 | 0.213 | 0.218 | ✅ |
| SyntheticText2SQL | 0.265 | 0.249 | 0.372 | 0.441 | ✅ |
| CodeFeedbackMT | 0.288 | 0.592 | 0.591 | 0.674 | ✅ |
| CodeFeedbackST | 0.162 | 0.682 | 0.682 | 0.722 | ✅ |
| StackOverflowQA | 0.223 | 0.703 | 0.687 | 0.733 | ✅ |
| AppsRetrieval | 0.001 | 0.048 | 0.014 | 0.034 | ❌ |
| Среднее | 0.186 | 0.445 † | 0.488 | 7/8 | |
Семь побед из восьми; среднее 0.488 против 0.445 у сильнейшей базовой линии по каждой задаче († лучшее из bm25-ref / bm25-code, по задаче) — и в 2.6× выше среднего multigram. Единственное поражение, AppsRetrieval, близко к нулю для всех лексических методов: длинные условия задач против кода — это территория эмбеддингов.
Токены для кода + BM25
Идентификаторы разбиваются так, как пишется код — camelCase, snake_case, пути через точку — и подаются в обычный IDF/BM25. Одно это выигрывает большинство задач: CodeTransOceanContest вырастает с 0.478 до 0.600 без какой-либо настройки.
Стоп-слова убраны, лёгкий стемминг
Английские стоп-слова удалены, лёгкий суффиксный стеммер выравнивает запросы на естественном языке с токенами кода — рычаг, который превращает SyntheticText2SQL из поражения в 0.441.
k1 = 1,8 · b = 1,0
Значения по умолчанию в поставке, настроенные Algenta на CoIR: более сильное насыщение по частоте термина и полная нормализация длины — рычаг, который переворачивает StackOverflowQA.
Каждая ячейка воспроизводится из одного скрипта — bench/mteb_code_lexical.py — прогоняющего обе стороны через один вызов mteb.evaluate (запуски от 2026-07-21). code-lexical — это индекс, поставляемый Telys, с его значениями по умолчанию.
Победы, ничьи и поражения — в открытом доступе.
Формат публикации фиксируется до появления первого числа — числа не могут его изменить.
Где мы проигрываем — в печати
Каждая итоговая таблица содержит раздел «Где мы проигрываем» и раздел «Где мы лишь сравниваемся с FAISS» — оба заполняются автоматически из ячеек. Отчёт не собирается, если хотя бы один из них пуст.
Воспроизведите результаты без нас
Стенд запускается без Telys, так что скептик может самостоятельно воспроизвести числа сравниваемых систем и контрольного узла и убедиться, что каждый конкурент настроен по собственному руководству — конфиги зафиксированы и сравнены с дефолтами вендора.
Каждая ячейка ведёт к сэмплам
Каждая опубликованная ячейка ссылается на сырые сэмплы по операциям и точный скрипт, их породивший. Результаты только дополняются — с привязкой к ревизии движка и версиям статически слинкованных зависимостей.
Это показатели прототипа, каждый сопровождается своими условиями. Держите нас за этот контракт — и за цифры по мере того, как мы переизмеряем их в рамках полного стенда.