Skip to main content
Текстовые эмбеддинги описывает, как вызывать API. На этой странице объясняется как правильно его использовать. Почти ни одна проблема с embedding не проявляется как неудачный вызов. endpoint возвращает 200, размеры верны, а качество retrieval незаметно падает. Каждая рекомендация ниже основана на измерениях, выполненных на шлюзе APIYI 2026-08-25 (UTC+8), — это не общие советы.
Метод: 20 китайских документов об интеграции LLM gateway и 20 соответствующих английских документов, 20 китайских и 20 английских запросов с ответами, размеченными вручную, при этом все три модели запускались на одном и том же корпусе в один и тот же временной интервал. Корпус небольшой, поэтому различия менее чем в 5 процентных пунктов не являются убедительными — воспроизведите результаты на своих данных, прежде чем считать что-либо окончательным.

1. Сначала выберите подходящую модель

Выбирайте bge-m3, когда

  • Ваш корпус в основном китайский (или японский / русский): качество retrieval соответствует 3-small,
    цена по прайсу вдвое ниже, а тот же текст использует лишь 42% tokens — примерно 1/5 фактических расходов
  • Вам нужен меньший объём хранилища: 1024 dims — это на 33% меньше, чем 1536, и на 66% меньше, чем 3072
  • Вам нужен охват редких языков (поддерживается 100+)
  • Вы хотите запускать ту же open-source модель локально, чтобы офлайн- и онлайн-векторы совпадали

Выбирайте OpenAI, когда

  • Ваш корпус в основном на английском или код: качество на ступень выше. bge-m3 действительно расходует 15%–50%
    больше tokens на таком контенте, но вдвое меньшая цена за единицу всё равно делает его дешевле в целом — поэтому в этом случае
    ориентируйтесь на качество, а не на цену
  • Ваша база знаний содержит материалы на разных языках, и вам нужен только один ответ
  • Вам нужен dimensions, чтобы сократить объём хранилища
  • У вас уже есть пороговые значения, настроенные по диапазонам оценок OpenAI, и вы не хотите перенастраивать их
Смешанный по языкам корпус — слабое место bge-m3 (Recall@1 65%). Не потому, что кросс-языковой retrieval плох —
как раз наоборот. Он почти одинаково оценивает китайскую и английскую версии одного и того же факта
(показатель 0.75–0.87, против 0.56–0.69 у OpenAI), поэтому китайский запрос часто ставит английскую копию выше
китайской.
Если ваш RAG возвращает только один ответ, разделите индекс по языкам или добавьте языковой фильтр во время запроса.
Если вам нужно собирать материал на разных языках, это скорее преимущество, чем недостаток.

2. Всегда разбивайте длинные документы на фрагменты

bge-m3 имеет контекстное окно на 8192 token, поэтому длинное руководство помещается в один вызов. Это не делает такой подход хорошей идеей. Измерено: 20 разделов, объединённых в одно длинное руководство, при этом 20 коротких документов (каждый соответствовал одному разделу) были добавлены как сильные отвлекающие варианты, а запросы задавались 20 вопросами — Для одного и того же вопроса правильный раздел в среднем получает оценку на +0.10 выше, чем весь документ: Единый вектор длинного документа — это среднее по всему, что в нём есть, поэтому любой короткий фрагмент с точной формулировкой его превосходит.
Рекомендации по разбиению на фрагменты
  • Разбивайте по смысловым границам на 200–500 token, с перекрытием 10%–15%
  • В китайском языке в среднем около 2.1 символа на token, поэтому 200–500 token — это примерно 420–1050 китайских символов
  • Не дробите на слишком мелкие фрагменты: каждый ввод содержит 2 фиксированных специальных token — накладные расходы 0.4% на 500-token фрагменте, но уже 12.5% чистой потери на 16-token фрагменте
  • Добавление заголовка раздела в начало каждого фрагмента заметно улучшает его распознаваемость

3. Пороги нужно калибровать заново для каждой модели

Именно здесь миграция с OpenAI на bge-m3 чаще всего даёт сбой. Два диапазона оценок полностью различаются. Одинаковые вручную размеченные пары, оценённые всеми тремя моделями:
У bge-m3 нижняя граница находится на 0.42; у OpenAI — на 0.09. Копирование правила вроде «отбрасывать всё ниже 0.3» означает, что для bge-m3 фильтрации вообще не будет; копирование правила «считать релевантными только значения 0.8 и выше» отбрасывает почти каждый корректный результат.
Лучшие одиночные пороги, измеренные для bge-m3: Для сравнения, лучший порог для китайского сценария — 0.45 для text-embedding-3-small и 0.33 для 3-large.
На практике: начните с 0.50, считайте 0.45–0.60 серой зоной, требующей подтверждения, и заново калибруйте на основе 50–100 размеченных примеров из вашего собственного корпуса перед запуском в рабочую среду.

4. Сходство не может сказать вам, правильно ли что-то

Это верно для любой эмбеддинг-модели — это не недостаток какой-то одной из них, но вам нужно знать об этом заранее: Все три не срабатывают. Косинусное сходство показывает, об одном ли и том же два текста, а не согласуются ли они. Отрицание, цены, номера версий и имена сущностей нельзя отделить на этапе поиска. Правильный запасной вариант:
1

Векторный поиск, Top 50–100

Используйте bge-m3, чтобы быстро сузить круг. Порог лишь отфильтровывает явно нерелевантное.
2

Переранжирование до Top 3–5

Отправьте кандидатов в bge-reranker-v2-m3. Это cross-encoder, который пропускает запрос и документ через модель вместе, и это именно тот инструмент, который нужен для таких тонких различий — и он относится к тому же семейству моделей, что и bge-m3.
3

Пусть LLM оценивает во время генерации

Передайте Top 3–5 вместе с исходным вопросом и явно укажите в prompt, что модель должна сказать, что ничего не найдено, если извлечённый контент не соответствует вопросу.

5. Размер батча и параллельные запросы

Пакетная обработка: точка перегиба — 64–128

После 128 стоимость на элемент почти не улучшается (58ms → 53ms), тогда как один запрос становится в 7 раз дольше. Длительность запроса напрямую влияет на риск тайм-аута клиента и на то, сколько работы будет потеряно при одном сбое.

Параллельные запросы: 8 для работы в реальном времени, 32–48 для массовой индексации

  • Используйте параллельные запросы 8 для получения в реальном времени: 200 requests без единого сбоя
  • Для массовой индексации можно поднять до 32–48: максимальная пропускная способность, но 429s начинают появляться, поэтому требуется экспоненциальный backoff
  • Не превышайте 64: при 96 уровень сбоев составляет 11.8%, а запросы начинают зависать примерно на 60 seconds
Ваш клиент должен выполнять повторные попытки. Даже при низкой параллельности примерно 0.8% запросов сталкиваются с разорванным соединением (Connection aborted / Remote end closed connection). Одна повторная попытка устраняет проблему; без повторной попытки в вашем индексе останется пробел.Установите тайм-аут клиента на 60–90 seconds для массовой индексации, а не на несколько сотен — с зависшим запросом сложнее работать, чем с неудавшимся.

6. Как фактически работает стоимость

Стоимость — это произведение двух вещей: цена за unit и сколько token получается из данного фрагмента текста. Здесь различаются оба параметра. bge-m3$0.01 / 1M tokens против $0.02 для text-embedding-3-small — то есть вдвое ниже unit price еще до всего остального. Дополнительно сказывается эффективность tokenizer: bge-m3 использует XLM-R SentencePiece и дает около 2.1 Chinese characters per token, тогда как cl100k от OpenAI — около 0.9: Китайские корпуса стоят примерно одну пятую от text-embedding-3-small. Английский текст и code потребляют больше token на bge-m3, но вдвое более низкая unit price все равно делает его дешевле OpenAI по общим расходам — так что для этих двух корпусов решение зависит от качества retrieval (English Recall@1 70% vs 80%), а не от цены. Хранение тоже отличается. Векторы уже L2-нормализованы, а возвращаемые значения имеют точность fp16, поэтому хранение vector bge-m3 в float16 не дает потерь в точности:
Векторы возвращаются нормализованными (измеренные нормы L2 — 0.99992–1.00029), поэтому dot product уже и есть cosine similarity. IP и COSINE types индекса дают идентичные результаты в вашей vector database, а IP экономит один проход нормализации.

7. Режимы отказа, которые остаются незаметными

7.1 Значение по умолчанию в LangChain снижает Recall с 80% до 15%

langchain_openai.OpenAIEmbeddings по умолчанию использует check_embedding_ctx_length=True, который сначала кодирует ваш текст в tiktoken token ids и отправляет массив целых чисел в /v1/embeddings.Это нормально для моделей OpenAI, чьим tokenizer и является tiktoken. bge-m3 использует tokenizer XLM-R, и эти два пространства id не имеют ничего общего.Вызов по-прежнему возвращает 200, вектор по-прежнему имеет размерность 1024, usage по-прежнему выглядит нормально — только качество поиска тихо обрушивается.
Измеренные затраты: Исправление:
Тот же риск применим к любому wrapper, который выполняет tokenization на стороне client перед отправкой. При подключении сторонней embedding-модели проверьте, отправляет ли ваш SDK исходный текст или token ids.

7.2 Пустая строка принимается как допустимый input

input: "" возвращает 200 на bge-m3 (OpenAI здесь возвращает 400), формируя вектор размерностью 1024 и тарифицируя 2 token. Скрипт chunking, который не отфильтровывает пустые chunks, заполнит ваш index бессмысленными векторами, которые будут случайно всплывать во время поиска. Фильтруйте пустой текст перед индексацией.

7.3 Параметр dimensions отклоняется

Возвращает 400: Model "bge-m3" does not support matryoshka representation, changing output dimensions will lead to poor results. bge-m3 не был обучен с Matryoshka representation, поэтому обрезание вектора заметно ухудшает качество. Используйте float16, чтобы уменьшить объем хранения, вместо того чтобы самостоятельно обрезать размерности.

7.4 Имя модели чувствительно к регистру, алиасов нет

Работает только bge-m3. BAAI/bge-m3 и BGE-M3 оба возвращают 503 «нет доступных каналов».

7.5 8192 — это лимит на один input

Один input длиной более 8192 token возвращает 400 и никогда не обрезается молча — что является более безопасным поведением: вы не получите вектор, который выглядит нормальным, но тихо потерял вторую половину вашего текста. Лимит применяется к каждому item, а не к запросу: один вызов, содержащий 1024 item / 102560 token, в тестировании возвращался нормально. Если любой один item превышает лимит, весь запрос завершается с ошибкой, а число token в ошибке относится именно к этому item, а не к общему итогу.

8. Минимальная реализация, которую вы можете скопировать

Связанная документация

API встраивания текста

Параметры, формат ответа, быстрый старт

Переранжирование

bge-reranker-v2-m3, подходящий инструмент для этапа повышения точности

Настройка RAG

Двухэтапное извлечение: сколько кандидатов извлекать

Тарификация моделей

Актуальная тарификация для каждой модели встраивания