Личный рассказ о том, как мы с моим ИИ-агентом Саркисом подключили pimenov.ai к Яндекс.Метрике, Яндекс.Вебмастеру и Google Search Console, собрали SEO-дашборд и превратили сайт в ж…
База знаний
EmbeddingGemma (Gemma 3) — компактная embedding-модель от Google для on-device RAG
Открытая embedding-модель от Google на базе Gemma 3: 308M параметров, 100+ языков, контекст 2048 токенов, 768-мерные векторы с MRL-усечением до 128. Работает на 200 МБ RAM, считает эмбеддинг на CPU за десятки миллисекунд. Когда брать вместо BGE-M3, как поднять локально и во что упереться.
Если BAAI/bge-m3 — это «большой добротный грузовик» для self-hosted RAG, то EmbeddingGemma от Google — это маленький электрический скутер. Грузит меньше, едет быстрее, помещается в карман и работает там, где сервер поставить негде вовсе. В этом справочнике разбираемся, что это за модель, когда она реально уместна и как собрать с ней рабочий embedding-контур.
Что это вообще такое
EmbeddingGemma — open-source embedding-модель от Google DeepMind, выпущенная в сентябре 2025 года. Под капотом — архитектура Gemma 3 на 300M параметров, адаптированная из decoder-only в encoder-only по рецепту T5Gemma. Проще говоря, взяли мозги Gemma 3, отрезали генеративную голову и оставили только ту часть, которая умеет превращать текст в вектор.
Модель построена на той же исследовательской базе, что и Gemini, и занимает первое место на бенчмарке MTEB среди открытых мультиязычных моделей размером до 500M параметров.
Главная идея — on-device. EmbeddingGemma спроектирована так, чтобы запускаться на телефоне, ноутбуке или дешёвом VPS без GPU. Эмбеддинг на EdgeTPU считается меньше чем за 22 мс, а вся модель с квантизацией помещается в 200 МБ RAM. Это совсем другой класс задач, чем у BGE-M3 или OpenAI — там, где не было RAG, теперь он возможен.
Ключевые характеристики
| Параметр | Значение |
| Разработчик | Google DeepMind |
| Лицензия | Gemma Terms of Use (коммерческое использование разрешено) |
| Архитектура | Encoder-only на базе Gemma 3 (T5Gemma-инициализация) |
| Параметров | 308M (≈100M backbone + ≈200M embeddings) |
| RAM при инференсе | ~200 МБ с квантизацией, ~1.2 ГБ в full precision |
| Размерность dense-вектора | 768 (с MRL-усечением до 512, 256 или 128) |
| Максимальный контекст | 2048 токенов |
| Языки | 100+, тренировалась на данных Gemini-уровня |
| Latency на EdgeTPU | ~22 мс на запрос |
| Latency на среднем CPU | ~30–80 мс на чанк |
Matryoshka Representation Learning — главная фича
MRL — это технология, при которой внутри большого вектора уже «живут» меньшие. У EmbeddingGemma полный эмбеддинг — 768-мерный, но вы можете честно обрезать его до первых 512, 256 или 128 измерений — и это по-прежнему будет качественное представление текста, а не обрубок.
Во время тренировки лосс считается не только на полном векторе, но и на всех вложенных подпространствах. Модель как бы заранее соглашается «работать на четверть мощности» — и делает это достойно.
| Размерность | Размер индекса (на 1M чанков) | Типичный сценарий |
| 768 | ~3 ГБ | Максимальное качество, серверный RAG |
| 512 | ~2 ГБ | Баланс качества и места |
| 256 | ~1 ГБ | Мобильный RAG, быстрый поиск |
| 128 | ~0.5 ГБ | Прекоммутация, кеш, дешёвый retrieval |
Практический приём — двухэтапный поиск: сначала по 128-мерным векторам быстро отбираете top-200 кандидатов, потом пересчитываете их 768-мерными и ранжируете. Индекс в 6 раз меньше, а качество на выдаче — как у полного вектора.
Когда EmbeddingGemma — правильный выбор
- Мобильные приложения с RAG — поиск по заметкам, чатам, документам прямо на телефоне. Без интернета, без облака, без утечек.
- Приватный офлайн-поиск на ноутбуке или корпоративном десктопе, где данные не должны покидать устройство.
- Слабый VPS без GPU, где BGE-M3 уже начинает кряхтеть. EmbeddingGemma на 200 МБ RAM и CPU — это другая экономика хостинга.
- Высоконагруженные API с дешёвой инфраструктурой — когда надо считать миллионы эмбеддингов в сутки, и каждые 10 мс на запрос превращаются в реальные деньги.
- Короткие запросы и короткие документы — сниппеты, сообщения, заголовки, подписи. Контекст 2048 токенов здесь избыточен, а скорость решает.
Когда лучше взять что-то другое
- Длинные документы. Контекст 2048 против 8192 у BGE-M3 — это реальный разрыв. Если вы эмбеддите статьи или PDF целиком, EmbeddingGemma заставит вас резать на чанки агрессивнее.
- Максимальное качество на русском в сложных задачах. BGE-M3 на MIRACL по-прежнему сильнее в нишевых мультиязычных бенчмарках. Для RAG по русско-английской базе знаний BGE-M3 остаётся дефолтом.
- Гибридный поиск dense + sparse в одной модели. У EmbeddingGemma только dense-режим. Sparse придётся брать отдельной моделью или BM25.
- Эмбеддинги для кода. Специализированные модели (
voyage-code-2,jina-embeddings-v2-code) дадут заметно лучший результат.
Сравнение с альтернативами
| Модель | Параметров | Контекст | Размерность | RAM |
| EmbeddingGemma | 308M | 2048 | 768 (MRL до 128) | ~200 МБ |
| BAAI/bge-m3 | 567M | 8192 | 1024 | ~1 ГБ |
| bge-small-en | 33M | 512 | 384 | ~150 МБ |
| multilingual-e5-large | 560M | 512 | 1024 | ~1 ГБ |
| OpenAI text-embedding-3-small | — (API) | 8191 | 1536 (truncatable) | — (API) |
Если сравнивать «в лоб» с BGE-M3: EmbeddingGemma проигрывает в размере контекста, но выигрывает в скорости, размере индекса и пригодности для on-device. Это не конкуренты — это инструменты под разные задачи.
Поднимаем локально
Минимальные требования
- CPU: любой современный x86_64 или ARM (в т.ч. Apple Silicon, Raspberry Pi 5).
- RAM: от 512 МБ с квантизацией, от 2 ГБ в full precision.
- Диск: ~1 ГБ под веса.
- Python 3.10+.
- GPU не нужен. Это принципиально: модель проектировалась для CPU.
Вариант 1: Ollama (самый быстрый старт)
ollama pull embeddinggemma
ollama serveПроверка:
curl http://localhost:11434/api/embeddings \
-d '{"model": "embeddinggemma", "prompt": "Привет, мир"}'Ollama поднимает OpenAI-совместимый endpoint на /v1/embeddings — можно сразу подключать к LiteLLM, LangChain, LlamaIndex без единой строки кода.
Вариант 2: sentence-transformers (для тонкого контроля)
pip install -U sentence-transformers# server.py — OpenAI-compatible embeddings server на EmbeddingGemma
from fastapi import FastAPI
from pydantic import BaseModel
from sentence_transformers import SentenceTransformer
from typing import List, Union, Optional
# Загружаем модель один раз при старте
model = SentenceTransformer("google/embeddinggemma-300m")
app = FastAPI()
class EmbeddingRequest(BaseModel):
input: Union[str, List[str]]
model: str = "embeddinggemma"
dimensions: Optional[int] = None # 128, 256, 512 или 768
@app.post("/v1/embeddings")
def embeddings(req: EmbeddingRequest):
texts = [req.input] if isinstance(req.input, str) else req.input
# EmbeddingGemma ожидает task-специфичные префиксы
vectors = model.encode(
texts,
prompt_name="Retrieval-document",
normalize_embeddings=True,
)
# MRL-усечение: берём первые N измерений и ренормализуем
if req.dimensions and req.dimensions < 768:
import numpy as np
vectors = vectors[:, :req.dimensions]
vectors = vectors / np.linalg.norm(vectors, axis=1, keepdims=True)
return {
"object": "list",
"model": req.model,
"data": [
{"object": "embedding", "index": i, "embedding": v.tolist()}
for i, v in enumerate(vectors)
],
"usage": {"prompt_tokens": 0, "total_tokens": 0},
}
@app.get("/health")
def health():
return {"status": "ok", "model": "embeddinggemma-300m"}Запуск:
uvicorn server:app --host 127.0.0.1 --port 8080Retrieval-query: , для документов — title: none | text: . В sentence-transformers они подставляются через prompt_name. Если эмбеддить всё голым текстом — потеряете несколько процентов качества.Systemd-юнит для автозапуска
# /etc/systemd/system/embeddinggemma.service
[Unit]
Description=EmbeddingGemma Embeddings Server
After=network.target
[Service]
Type=simple
User=embeddings
WorkingDirectory=/opt/embeddinggemma
Environment="PATH=/opt/embeddinggemma/.venv/bin"
ExecStart=/opt/embeddinggemma/.venv/bin/uvicorn server:app --host 127.0.0.1 --port 8080
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetАктивация:
sudo systemctl daemon-reload
sudo systemctl enable --now embeddinggemma
sudo systemctl status embeddinggemma127.0.0.1 или на интерфейс Tailscale. Лицензия Gemma разрешает коммерческое использование, но не разрешает сторонним ботам жечь ваш CPU. Авторизация из коробки не встроена.Практические сценарии
On-device RAG в мобильном приложении
- Модель в квантизации до 200 МБ помещается в iOS/Android бандл.
- База знаний пользователя (заметки, чаты, файлы) индексируется локально, один раз.
- Запрос → эмбеддинг за 30 мс → поиск в локальной SQLite+vector-extension → ответ. Интернет не нужен.
- Данные никуда не утекают — вся приватность соблюдена технически, а не на бумаге.
Двухэтапный поиск на большой базе
- Индексируете документы в 128-мерных векторах (экономия памяти в 6 раз).
- На запрос считаете 128-мерный эмбеддинг, достаёте top-500 кандидатов.
- Пересчитываете эти 500 текстов в 768-мерных векторах и ранжируете ещё раз.
- Получаете качество 768-мерного поиска при затратах памяти 128-мерного.
Семантический дедуп входящих сообщений
- Порог cosine > 0.90 — дубль.
- 0.75–0.90 — похожая тема, кандидат на объединение.
- Считается настолько быстро, что можно запускать inline при каждом новом сообщении.
Классификация без разметки (zero-shot)
- Создаёте эмбеддинг для каждой категории (описываете её короткой фразой).
- Входящий текст эмбеддите тоже.
- Побеждает та категория, у которой cosine с текстом максимальный.
- Работает удивительно хорошо для типовых задач вроде «спам / не спам», «запрос / жалоба / благодарность».
Типичные ошибки и как их чинить
| Симптом | Причина | Решение |
| Низкое качество retrieval | Не используются task-специфичные префиксы | Передавать prompt_name="Retrieval-query" для запросов и "Retrieval-document" для документов |
| MRL-эмбеддинги не сравниваются между собой | После обрезки забыли ренормализовать вектор | После vectors[:, :N] делать vectors / np.linalg.norm(...) |
| Тексты длиннее 2048 токенов молча обрезаются | Контекст модели — всего 2048 | Резать на чанки 300–800 токенов с overlap, эмбеддить по отдельности |
| Cross-lingual similarity низкая | Смешаны префиксы для query и document | Для query и document использовать разные prompt-имена, это важно |
| Модель медленно стартует | Cold start с загрузкой весов | Прогревать фиктивным запросом при старте сервиса |
Антипаттерны
- ❌ Брать EmbeddingGemma для документов по 10 000 токенов. Контекст 2048 — это реальный потолок. Для длинных текстов либо чанкуйте агрессивно, либо берите BGE-M3.
- ❌ Эмбеддить запросы и документы одинаковым prompt-именем. Модель тренировалась на асимметричных префиксах, и она это помнит. Симметрия ломает качество.
- ❌ Мешать в одном индексе векторы от EmbeddingGemma и любой другой модели. Даже одинаковая размерность не делает их сопоставимыми. Поиск сломается тихо и бесповоротно.
- ❌ Хранить 768-мерные векторы, когда хватает 256. Индекс раздувается в 3 раза без повода. MRL существует ровно для того, чтобы этого не делать.
- ❌ Тестировать качество на английском и переносить выводы на русский. Мультиязычность у модели есть, но языки ведут себя по-разному. Меряйте на своих данных.
Полезные ссылки
- Модель на HuggingFace: huggingface.co/google/embeddinggemma-300m
- Обзор на ai.google.dev: ai.google.dev/gemma/docs/embeddinggemma
- Анонс от Google DeepMind: developers.googleblog.com/en/introducing-embeddinggemma
- Разбор архитектуры: developers.googleblog.com/en/gemma-explained-embeddinggemma-architecture-and-recipe
- Технический отчёт (arXiv:2509.20354): arxiv.org/abs/2509.20354
- Ollama: ollama.com/library/embeddinggemma
- Лидерборд MTEB: huggingface.co/spaces/mteb/leaderboard
По теме
- База знаний: BAAI/bge-m3 — мультиязычная embedding-модель для self-hosted RAG
- База знаний: OpenAI Codex — облачный coding-агент для параллельной разработки
Если выбираете embedding-модель под свою задачу и не уверены, чем EmbeddingGemma отличается от BGE-M3 на практике — давайте обсудим, что лучше сядет под вашу нагрузку и инфраструктуру.