У меня есть сервер. AMD Ryzen 5 3600, 64 гига оперативки, без видеокарты. И задача: перестать платить OpenRouter за эмбеддинги и запустить своё.
Зачем? Пару дней назад я гонял бенчмарк LTM-фреймворков — Hindsight, Cognee, Graphiti — и OpenRouter стал причиной номер один всех проблем. Ошибки 422 на embeddings, кривой routing через LiteLLM, несовместимость encoding_format. Спалил $20 на Sonnet, пока разбирался, что баг не во фреймворках, а в моей конфигурации провайдера. После этого стало понятно: свой embedding API на своём железе — это не прихоть, а необходимость.
Кого рассматривал
Начал с семи кандидатов. Две модели убил ещё до тестов:
- jina-embeddings-v3 — лицензия CC-BY-NC-4.0. Для коммерческого использования нужно покупать лицензию у Jina AI. Нет.
- multilingual-e5-large-instruct — максимум 512 токенов на вход. Мои чанки — 800-1500 символов. Не влезут.
Осталось пять:
| Модель | Параметры | Размерность | Лицензия |
|---|---|---|---|
| BAAI/bge-m3 | 568M | 1024 | MIT |
| Alibaba-NLP/gte-multilingual-base | 305M | 768 | Apache-2.0 |
| nomic-ai/nomic-embed-text-v1.5 | 137M | 768 | Apache-2.0 |
| nomic-ai/nomic-embed-text-v2-moe | 137M (active) | 768 | Apache-2.0 |
| ai-sage/Giga-Embeddings-instruct (Сбер) | ~600M | 1024 | MIT |
Как тестировал
Написал скрипт на Python. 100 текстовых чанков: 50 на русском, 50 на английском. Для каждой модели мерил:
- Скорость — сколько миллисекунд на один чанк (single) и сколько чанков в секунду пакетами по 32.
- Качество на мультиязыке — взял 5 пар «один и тот же текст на русском и на английском» и посчитал cosine similarity. Если модель хорошо понимает оба языка, эмбеддинги одного и того же смысла будут близки.
- Потребление памяти — сколько RAM съедает загруженная модель.
Запускал прямо на сервере, без GPU, чистый CPU inference через sentence-transformers.
Что получилось
Две модели (GTE и GigaEmbeddings) не смогли запуститься — проблемы совместимости с текущей версией библиотек. GTE падала с ошибкой индексации, GigaEmbeddings — с ошибкой ROPE-инициализации. Можно было чинить, но три оставшихся дали чёткую картину.
| Модель | p50 мс | Чанков/сек (batch) | Кросс-лингв. сходство | RAM |
|---|---|---|---|---|
| bge-m3 | 118 | 23.7 | 0.887 | 914 МБ |
| nomic-v1.5 | 60 | 16.8 | 0.610 | 893 МБ |
| nomic-v2-moe | 86 | 45.8 | 0.782 | 3286 МБ |
nomic-v1.5 быстрее всех (60 мс на чанк), но на русском — слабо. Cosine similarity 0.61 между русским и английским вариантом одного и того же текста. Для проекта, где контент двуязычный, это не годится.
nomic-v2-moe лучше по качеству (0.78), но жрёт 3.3 гига RAM — на сервере, где крутится ещё PostgreSQL и Vault, это многовато.
bge-m3 победил. Cosine similarity 0.887 — почти вполовину выше nomic-v1.5. Скорость 118 мс на чанк. RAM — 914 МБ, укладывается в бюджет. MIT-лицензия. Размерность 1024 — совместима со всеми LTM-фреймворками, которые я тестирую.
Что в итоге поставил
FastAPI-сервер на 90 строк Python. Три файла: main.py (API), model.py (загрузка модели), config.py (настройки). OpenAI-compatible endpoint /v1/embeddings — любой фреймворк, который умеет работать с OpenAI API, подключится без изменений.
Привязал к Tailscale IP — сервис доступен только внутри mesh-сети, не видно из интернета. Systemd unit с MemoryMax=8G и автозапуском. На весь деплой ушло минут пятнадцать.
Финальный smoke test: 100 чанков (50 RU + 50 EN) пакетами по 10. Все прошли, 135 мс на чанк в среднем. С публичного IP — таймаут. Всё как задумано.
Итого
Потратил 45 минут от начала до работающего сервиса. Никаких per-request платежей облачным API — модель крутится на моём железе, которое и так оплачено. 135 мс на чанк — быстрее, чем OpenRouter давал на платных моделях. И главное — никаких 422 ошибок, никакого LiteLLM routing, никакой зависимости от чужой инфраструктуры.
Если у вас есть сервер с 1+ ГБ свободной RAM и Python — bge-m3 через sentence-transformers работает из коробки. Ставится за 15 минут, не нужна видеокарта. Для проектов с русским и английским контентом — лучший open-source выбор, что я нашёл.
Расскажите, какие embedding-модели вы используете? Если гоняли что-то на CPU с большими нагрузками — напишите, это очень интересно.