У каждого в шкафу лежит ноут из прошлой жизни. У нас это Acer Aspire 3830TG 2011 года: двухъядерный Sandy Bridge i3-2310M (без AVX2), 12 ГБ DDR3 и GeForce GT 540M на 1 ГБ (Fermi).
Выкидывать кремний жалко, а у нас под боком FlyingRAG на 1,34 млн чанков (нормативы, паспорта оборудования). Чтобы не греть основную машину фоновой векторизацией, решили сделать из ветерана микросервер эмбеддингов.
Свежий софт о таком железе не слышал. Готовые бинарники llama.cpp падают с
Illegal instruction, а CUDA забыла Fermi еще лет 10 назад. Вспомнили про OpenCL 1.1: собрали llama.cpp с CLBlast через MSVC, вырезали неподдерживаемые инструкции CPU и скинули часть слоев в 1 ГБ VRAM, разгрузив шину DDR3. Модель — Qwen3-Embedding-0.6B-Q8_0 (dim 1024).Запустили
llama-server --embedding. Вектор отдает, но сверка с PyTorch выдала кашу: косинусное сходство плывет, а на батчах начинается хаос. Полезли разбираться в код.Выяснилась дичь: в моделях с attention pooling движок llama.cpp зачем-то тащил вычисления через causal LM Head — голову проекции в словарь на 150k токенов. Вместо чистого пулинга последнего слоя софт гонял генеративную голову, которая при оффлоаде на GPU и батчинге перетирала выходные тензоры и ломала нормализацию векторов.
Вырезали в коде лишний LM Head для режима
--embedding и пустили тензоры напрямую в pooling. Собрали, проверили: косинусное сходство с PyTorch — 0.9999. Бит в бит.В сухом остатке: старичок Acer полностью разгрузил основной Asus на Ryzen AI 9 HX 370 (32 ГБ), забрав черновую возню с векторами, и породил PR в репозиторий llama.cpp. Патч убирает холостые вычисления и может ускорить/починить эмбеддинги в llama.cpp, Ollama и MLX по всему миру.
Пафосно? Да. Но ноут, купленный 14 лет назад ради Скайрима на минималках, крутит миллионную базу FlyingRAG и контрибьютит в мировой опенсорс. Некромантия, которую мы заслужили. Всем RAG🤞
