Search
Write a publication
Pull to refresh

Comments 18

квантованная версия может использовать 8 бит или даже 1 бит.

Как понимать 1 бит? - вектор существует / вектор не существует?

скорее всего речь про количество бит на элемент вектора: [0.1, 123, 34, 155] -> [0, 1, 0, 1]

В векторе должны быть только существующие элементы, иначе можно ещё снизить размерность, просто удалив пустые элементы. Ну по крайней мере так пишут в книгах; я сейчас много с этим экспериментирую, -- такое снижение размерности на практике даёт очень плохие результаты и увеличение количества эпох это не лечит. Может быть ошиблись и имелось в виду понижение до 2 байт или даже до 8 бит?

Действительно, слишком сильное квантование приводит к снижению полноты и это ожидаемо.
Выход - делать реранкинг, то есть в найденном поискать с помощью исходных несжатых векторов. После этого полнота сильно улучшается.
Пример запроса приведен в разделе "Приближённый векторный поиск без индекса"

скорее всего речь про количество бит на элемент вектора

Наверное нет, от этого долго и упорно уходят на другие варианты. Это можно сказать последнее лекарство для неизученных материй.

Изначально вектор использует 32 бита для каждого числа (размерности), можно применять статическое квантование и использовать 1 бит на размерность.

1 бит на размерность

Как раз такое кодирование используется в One Hot encoding, сейчас (давно уже) предпочитают ембединг, как раз такой способ уменьшает размерность и убирает разреженность матриц. 32 бита используется в tensorflow и PyTourch по умолчанию, только можно сразу инициировать другие размерности не дожидаясь квантования. Использовать 1 бит не имеет смысла, это просто потеря информации, или у вас более сложная модель которая читает данные в другой нейронке или уже в готовых данных, конкатенирует эти значения и выдаёт результат.

Да, согласен. Просто так использовать 1 бит на размерность нет смысла, слишком низкое качество. Но с реранкингом все гораздо лучше, как по скорости, так и полноте.

Для векторов логично использовать не обычное, а векторное квантование. Или использовать плотные n-мерные решетки..

Большое спасибо за статью! я так понимаю для RAG важно вытащить правильные документы из базы, что бы потом скормить их ЛЛМ для контекста с промнтом. И тут важна гибридная модель, когда можно и полнотекстовый поиск (желательно с возможностью задавать коэффициенты - ну например встречается в заголовке 0.9, встречается в теле 0.5 ).

Вопросы: 1. Полнотекстовый поиск поддерживается в YDB?
2. Гибридная модель поиска как скажем в Milvus есть в YDB?

Правильное замечание про RAG!
Мы уже работаем на полнотекстовым поиском. Ну а следующий этап - соединить полнотекстовый и векторный, получив гибридный поиск. Это хорошо ложится на нашу модель выполнения запросов.

RAG позволяет найти похожие тексты. Т.е. мы должны заранее знать, о чем идет речь (хотя бы примерно).

Но, например, если нам доступно только название фильма и мы просим проанализировать отзывы?
Он найдет все отзывы, добавит в контекст? Или найдет ближайшие к названию фильма? А если это просто общеупотребительное слово или есть одноименные фильмы / книги / сериалы?

Как RAG дает именно то, что надо? Или просто накидываем в контекст все, что есть, а там модель сама разберется?

Грубо говоря я не понимаю, как RAG позволит организовать что-то вроде толкового словаря или той же википедии, чтобы по слову вытаскивать целую статью.

RAG ищет тексты, близкие по смыслу к запросу, но если название неоднозначное, то результаты могут быть неточными. Чтобы избежать мусора в ответах, нужна фильтрация по метаданным (тип, год) или гибридный поиск (векторный + полнотекстовый).
Плюс никто не мешает строить такие запросы к LLM, чтобы она могла запросить дополнительные детали.

Вот я про это и говорю. RAG просто "обогащает" запрос по похожим данным. Это не память для модели, это не "ассоциативные цепочки" для модели, не база знаний или еще что. Это просто "что-то похожее было, вот оно".

Просто я недавно поработал с WIT-описанием для WebAssembly Component Model. И допустил ошибку в описании - описал resource в world. И самое интересное, что кодогенерация по описанию работала, но невозможно было использовать сгенерированные классы. Да, в спецификациях сказано, что в world допустимы только импорт/экспорт функций и интерфейсов. Но упустить этот нюанс не сложно (особенно если спецификацию не наизусть знаешь).

Когда уже разобрался, в чем проблема - мне стало интересно, а ИИ найдет эту ошибку в WIT (про решение исходной проблемы, с кодом, даже не говорю)? Топовые модели не справляются (как минимум deepseek-r1, grok-4, kimi-k2, gemini-2.5-pro, gpt-4.1, может что еще пробовал), хотя и знают что это WIT, Component Model и т.д. (к слову, это знали все опробованные модели, в том числе и локальные).

Но если в контекст добавить спецификации WIT (благо, что это просто один относительно объемный файл), то локальный Qwen3-30A-A3B успешно справляется с нахождением проблемы.

Пробовал в RAG загрузить (в OpenWebUI, параметры по умолчанию, кроме модели эмбеддинга - использовал nomic-embed-text) - он находит какие-то похожие куски (3 штуки, как задано в параметрах по умолчанию), но нужной фразы туда не попадает - и он не находит ничего полезного.

Вот я и думаю - а как вообще можно решать подобные кейсы, чтобы спецификации руками не кидать каждый раз. Хорошо, если модель явно несет ерунду - сразу видно, что спецификации не помешают. Но что делать, если ответ более качественный или ты в вопросе совсем не разбираешься (чтобы понять, что в ответе ерунда)?

Так что умная модель - это хорошо. Но не всегда есть модель, которую обучали на твоих сценариях использования и на твоих данных. Но модели способны "понять" новый материал и по нему сформировать ответ. Только нужно добавить нужные данные в контекст. RAG тут может и помогает, но явно не лучшим образом. А вот как это сделать лучшим образом - вопрос открытый.

Мы смотрели в сторону разных алгоритмов.
Конкретно HNSW не подошел именно для нас.

Произвольный доступ к памяти – замедление дискового IO.
Увеличенное потребление памяти 2x–8x в зависимости от числа слоёв.
Сложно сделать граф эластичным, перешардироваться на лету.

Ну и наконец, мы целимся в миллиарды векторов.

В HNSW нет никакого 2x-8x, вы храните центроиды в отдельной базе, а в HNSW используется настраиваемый аналог списков с пропусками, которые менее 100% займут от количества векторов.

Собственно само ваше описание это уже и есть тот же аналог HNSW:

в первой из них, Level Table, хранится иерархия центроидов для быстрого поиска по кластерам. Данные в этой таблице организованы в древовидную структуру, и YDB может быстро найти идентификатор кластера нижнего уровня для вектора, по которому происходит поиск.

В том же Qdrant справились с перешардированием - https://qdrant.tech/documentation/cloud/cluster-scaling/

А сама структура HNSW не ограничивает количество векторов. Миллиарды правда еще не пробовал, но на 60 миллионах векторов поиск занимает миллисекунды.

Спасибо за уточнение. Действительно, в ряде реализаций HNSW вектора хранятся прямо в графе, а в ряде реализаций - вне графа. Тут уже баланс между объемом памяти и временем поиска.

А по поводу перешардирование Qdrant - у них небольшая приписка: "Resharding is exclusively available on multi-node clusters across our cloud offering".
В случае YDB - немного иначе. СУБД, изначально рожденная в Яндексе, открыта в публичный доступ в OpenSource.

Sign up to leave a comment.