Как текст превращается в точку в многомерном пространстве. Почему «оплата картой» и «билинг» становятся близкими. Что такое чанкинг и почему от его выбора зависит, найдёт RAG ответ или нет.
Эмбеддинг — это превращение куска текста в вектор из сотен-тысяч чисел. Эти числа подобраны так, чтобы тексты с близким смыслом давали близкие векторы. Это позволяет искать «по смыслу», а не по буквам. Чанкинг — это разбиение твоих документов на куски подходящего размера, которые будут индексироваться отдельно. Эти два этапа — фундамент любого RAG: ошибся тут — никакая хитрость дальше не поможет.
Эмбеддинг — это превращение текста в вектор (массив чисел фиксированной длины). Например, «как настроить SSO» может стать таким вектором:
Размерность вектора — обычно от 384 до 3072 чисел (зависит от модели). Это и есть «многомерное пространство»: тексты — точки в этом пространстве, и близкие по смыслу — реально близкие как точки (по евклидову расстоянию или косинусу).
Эмбеддинг-модели обучены на огромных корпусах текстов так, чтобы тексты в похожих контекстах получали похожие векторы. Когда в обучающих данных «SSO», «авторизация», «вход в систему» постоянно встречаются в схожих контекстах — модель учится размещать их близко.
Эмбеддинг — это математическое выражение смысла. Не идеальное, не абсолютное, но достаточное, чтобы построить поиск, который работает по смыслу, а не по буквам.
Поиск ближайших векторов в БД работает быстро — векторные БД (Pinecone, Weaviate, Chroma, Qdrant, pgvector) специально оптимизированы под эту задачу. На 1 миллион документов поиск занимает миллисекунды.
Эмбеддинг-моделей много. От выбора зависят: качество поиска, цена, скорость, размер вектора. Разделить их можно так:
OpenAI text-embedding-3-small / text-embedding-3-large, Cohere embed-v3, Voyage AI. Платный API, простой вызов.
Когда выбрать: на старте, для прототипов, когда не хочешь возиться с инфраструктурой. Очень дёшево: ~$0.02 за 1M токенов на маленьких моделях.
Минусы: зависишь от провайдера, данные уходят в облако (важно для приватных), плата за каждый запрос (накапливается при больших базах).
Стандарт по умолчанию: для большинства проектов хватает text-embedding-3-small от OpenAI. Хорошее качество, очень дёшево.
BGE, E5, GTE, Nomic-embed, Jina. Бесплатные, можно запустить локально или у себя на сервере. Размеры — от 100M до 7B параметров.
Когда выбрать: приватные данные (нельзя в облако), большая база (миллионы документов — облако дорого), нужна полная независимость.
Минусы: своя инфраструктура (GPU/CPU нужен), обновление модели — твоя забота, выбор сложнее (моделей десятки).
Если выбираешь: смотри MTEB Leaderboard на HuggingFace — там реальные сравнения моделей по задачам.
Большинство эмбеддинг-моделей преимущественно обучены на английском. Если у тебя русские документы — нужны специальные многоязычные.
Что есть: multilingual-e5, BGE-M3, jina-embeddings-v2-multilingual. Облачные — text-embedding-3-large от OpenAI хорошо работает с русским, Cohere multilingual.
Что важно: проверяй именно на своём языке. «Multilingual» в названии — не гарантия одинакового качества на всех языках. Бывает что модель хорошо работает на испанском и плохо на русском.
Главная грабля: взять английскую модель для русских документов. Будет работать, но плохо — все смысловые связки будут «через английский».
Модели, дообученные под конкретный домен: код, медицинские тексты, юридические документы, научные статьи.
Когда нужны: когда твоя база очень узкоспециализирована и общие модели плохо ловят оттенки смысла. Например, CodeBERT для эмбеддингов кода, BioBERT для медицины.
Когда не нужны: в большинстве бизнес-случаев. Общие модели от OpenAI и Cohere покрывают 90% задач. Не лезь сюда раньше времени.
Главный фильтр на старте. Если работаешь на русском — бери модель, в которой русский явно поддержан.
Больше — обычно лучше качество, но дороже хранить и медленнее искать. Для большинства задач 768-1536 — оптимум.
Сколько токенов модель принимает на вход. Влияет на чанкинг: чанки не должны превышать этот предел.
Если меняешь модель — нужно переиндексировать всю базу (старые векторы несовместимы). Выбирай надолго.
Вторая половина индексации — что именно мы эмбеддим. У тебя 4000 страниц документации — нельзя сделать один огромный эмбеддинг (превысит max input у модели, потеряет специфику). Нельзя сделать один на абзац (потерян широкий контекст). Где середина?
Это и есть чанкинг — разбиение документов на куски (chunks) подходящего размера, каждый из которых индексируется отдельно.
Типичные размеры — от 200 до 1000 токенов. Балансирует две противоположные силы:
Эмпирически: 400-800 токенов — хороший дефолт для большинства типов документов. Для длинных формальных текстов (юридические, технические) — ближе к 800-1000. Для коротких диалогов, FAQ — ближе к 200-400.
Тупо берём документ и режем каждые N символов или токенов. Простейший подход, но часто рвёт смысл посередине предложения.
Эмбеддинг такого «куска» получается странный — модель видит обрезанный текст и плохо ловит смысл.
Разбиваем по естественным границам: абзацам, разделам, заголовкам. Каждый чанк — это законченная смысловая единица.
Эмбеддинг такого чанка — точный, потому что текст — целостный. На markdown / HTML структурированных документах работает отлично.
Начинаем с крупных границ (главы → разделы), если чанк выходит большой — режем дальше по более мелким (абзацы → предложения). Сохраняем смысл везде, где можно.
Это стандарт в библиотеках типа LangChain (RecursiveCharacterTextSplitter). На разнотипных документах работает лучше всего.
Распространённый приём — делать чанки с перекрытием: следующий чанк начинается на 50-100 токенов раньше, чем закончился предыдущий. Это значит, что какой-то фрагмент текста попадает в два чанка.
Зачем: важная информация на границе между чанками не «теряется». Если ответ требует одновременно конца одного раздела и начала следующего — он будет в обоих чанках, и хотя бы один из них найдётся.
Цена: индекс растёт на 10-15%, дублирование в результатах. На практике овэрлап в 10-20% от размера чанка — норма.
Помимо самого текста и эмбеддинга, в чанк полезно записывать метаданные:
Метаданные не используются в эмбеддинге (не влияют на похожесть), но огромно важны на этапе фильтрации и реранкинга. Об этом — День 24.
На старте — облачные. text-embedding-3-small от OpenAI или Cohere embed v3. Это бесплатно по эффорту (одна функция API), почти бесплатно по деньгам (~$0.02 за миллион токенов).
На локальные переходишь, когда: (а) приватные данные нельзя в облако, (б) база огромна и облачный счёт начинает кусаться, (в) нужно low-latency и сетевой запрос за эмбеддингом слишком дорог.
Никогда не начинай с локальных «потому что круче». 80% проектов остаются на облачных и это окей.
Не существует «правильного» размера. Подход — экспериментировать на своих данных:
Готового ответа нет, и это нормально. Эта эмпирика — часть инженерной работы с RAG.
«Переключусь с small на large для лучшего качества». Векторы от разных моделей несовместимы. Меняешь модель → нужно переиндексировать всю базу. Для маленькой это окей. Для миллиона документов это часы работы и заметные деньги на эмбеддингах.
Выбирай модель надолго. Если вынужден менять — закладывай миграцию: переиндексация ночью, версионирование эмбеддингов в БД, плавный переход.
Запрос пользователя должен пройти через ту же модель, что индексировала документы. Иначе их векторы — в разных пространствах, поиск не работает.
Это очевидно, но часто ломается при «случайных» переходах: разработчик A проиндексировал, разработчик B читает старый код, добавляет фичу, использует более новую модель в search. RAG разом перестаёт работать.
«Режу по 2000 символов». На русском это ~500-700 токенов, на английском — ~400-500, на коде ещё иначе. Чанки получаются разной «информационной плотности».
Хороший подход — резать по токенам через ту же токенизацию, что используется в эмбеддинг-модели. Большинство библиотек (LangChain, LlamaIndex) умеют это из коробки.
«Сохраню только текст и вектор, остальное потом». Через 3 месяца понимаешь, что нужны фильтры: «только из политик», «только за последний год», «только для разработчиков». А метаданные не сохранены — переиндексируй всё заново.
Привычка с первого дня: каждый чанк сохраняем с метаданными — источник, дата, тип, аудитория, разделы. Это копейки места, и спасает от больших переделок потом.
В OpenAI Playground есть Embeddings, в Cohere — Embed. Введи 5-10 коротких фраз: половину про одно (например, «настройка авторизации», «как залогиниться», «вход в систему»), половину про другое («рецепт пирога», «как испечь хлеб», «кулинарные советы»). Получи эмбеддинги. Посчитай косинусное расстояние (или просто посмотри глазами на числа). Заметишь: первые пять близки между собой, вторые — между собой, две группы — далеки. Это и есть «поиск по смыслу» в действии.
Возьми любой свой длинный документ (заметку, статью, доку). Раздели его в уме на чанки тремя способами: (а) каждые 500 символов; (б) по абзацам; (в) по подзаголовкам. Сравни — какой из вариантов даёт осмысленные куски, каждый из которых имеет ценность по отдельности? Это покажет, почему semantic chunking почти всегда лучше fixed-size.
Если у тебя есть документация, по которой ты хочешь сделать RAG — посчитай: сколько в ней документов? средняя длина в токенах? есть ли заголовки/разделы (значит подходит semantic chunking) или сплошной текст (потребуется fixed-size с overlap)? есть ли метаданные (дата, автор, тип)? Этот аудит — то, что определит твой выбор стратегий на следующих шагах.