Перейти к содержимому
12 нояб. 2025 г.·7 мин чтения

Смешанные русско-английские запросы в продакшене

Смешанные русско-английские запросы ломают поиск, RAG и tool calling. Разберем набор тестов, метрики, типовые сбои и проверку перед релизом.

Смешанные русско-английские запросы в продакшене

Где возникает проблема

Смешанные русско-английские запросы ломаются не там, где их обычно ищут. Пользователь видит нормальный ответ на русском и думает, что все в порядке. Но внутри цепочки модель могла неточно понять термин, поиск мог поднять не тот документ, а инструмент мог получить аргумент не на том языке.

Типичный пример: человек пишет "Не могу открыть отчет по revenue за прошлый квартал". Для человека это один вопрос. Для системы это уже смесь русского намерения и английского термина. Если модель переведет revenue как "выручка", а индекс хранит документы с исходным английским словом, поиск и ранжирование начнут расходиться.

В RAG это видно особенно быстро. Пользователь ждет ответ на русском, а retriever находит лучший документ на английском, потому что именно там есть точная формулировка ошибки, название поля или API-метод. Дальше система легко промахивается: вставляет английский фрагмент без перевода, пересказывает его слишком свободно или вообще отбрасывает полезный документ, потому что reranker хуже сравнил русский вопрос с английским текстом.

С инструментами проблема еще неприятнее. Модель может правильно понять задачу, но передать в tool calling смесь языков: status: "отменен" вместо cancelled, period: "last month" рядом с русским описанием, currency: "рубли" там, где схема ждет RUB. Ответ потом выглядит правдоподобно, хотя инструмент либо вернул пустой результат, либо сработал не на тех данных.

Ошибка часто прячется в маршруте запроса, а не в финальной фразе. Это особенно заметно в системах, где один запрос проходит через несколько слоев: классификацию, поиск, выбор модели, вызов инструмента и постобработку. Снаружи интеграция может выглядеть одинаково, но после смены модели поведение на смешанном языке уже другое.

Проблему усиливают короткие англоязычные слова. "Lead", "issue", "chargeback", "billing", "case" часто имеют два смысла. Модель должна не просто перевести слово, а понять, оставить его как термин или передать в поиск без изменений. На тестовых примерах это кажется мелочью. В проде из таких мелочей складываются пустые выдачи, неверные фильтры и ответы "вроде по теме", которые трудно отладить по одному логу.

Что считать одним сценарием

Один сценарий - это не просто пара "вопрос -> ответ". Для mixed-language проверки этого мало. Сценарий должен описывать весь путь запроса: на каком языке пишет пользователь, на каком языке лежат документы, какой язык понимает инструмент и на каком языке система должна ответить в конце.

Для смешанных русско-английских запросов это особенно важно. Один и тот же вопрос может пройти поиск по английским документам, затем вызвать инструмент с английскими параметрами, а потом вернуть итог на русском. Если вы фиксируете только финальный ответ, вы не увидите, где именно модель свернула не туда.

Удобно описывать сценарий как короткую карточку с четырьмя полями:

  • язык пользовательского запроса
  • язык источников для поиска
  • язык интерфейса инструмента или его аргументов
  • язык итогового ответа

Этого уже хватает, чтобы различать похожие случаи. Запрос "Покажи активные invoices за март" и запрос "Покажи активные счета за март" выглядят почти одинаково, но тест ведет себя по-разному, если база знаний хранит статьи только на английском, а CRM ждет аргумент status=open.

После этого сценарий лучше разбить на шаги. Обычно достаточно трех: поиск, генерация и вызов инструмента. Иногда стоит выделить еще отдельный шаг с переписыванием запроса для retriever, потому что именно там часто ломается RAG на разных языках. Модель отвечает по-русски, но ищет только по русским словам и не находит английский документ, хотя нужная информация есть.

Для каждого шага храните свой ожидаемый результат. Не один общий эталон, а несколько простых проверок. После поиска система должна вернуть нужный документ хотя бы в top-N. При вызове инструмента модель должна передать правильное имя метода и аргументы на нужном языке. В финальном ответе она должна сохранить русский язык и не смешивать термины без причины.

Такой формат удобно гонять и вручную, и в автоматике. Он показывает ошибку по шагам, а не после жалобы от пользователя.

Как собрать набор тестов

Хороший набор для проверки смешанных русско-английских запросов почти всегда начинается не с придуманных примеров, а с логов. В них видно, как люди пишут на самом деле: русский вопрос, английский термин из интерфейса, название поля из API и кусок текста из письма. Такие случаи редко получается придумать правдоподобно.

Перед отбором уберите персональные данные. Маскируйте имена, телефоны, почту, номера договоров, адреса и любые идентификаторы, по которым можно узнать человека или компанию. Если вы работаете в контуре с требованиями 152-ФЗ, обезличивайте данные до того, как они попадут в тестовый набор или внешний репозиторий.

Не исправляйте фразы слишком старательно. Если пользователь написал "проверь invoice по договору за march", так и оставьте. Ошибки, смешение языков и странные формулировки ломают систему сильнее, чем чистый русский или чистый английский.

Что включить в выборку

Один и тот же смысл полезно дать в двух вариантах: с переводом термина и без перевода. Например, "обнови статус счета" и "обнови invoice status". Так быстро видно, понимает ли модель термин, когда он остался в языке источника, и не теряет ли смысл после перевода.

Документы тоже нужны разные. Возьмите короткое письмо от клиента, фрагмент договора и статью из базы знаний. На практике модель часто справляется с письмами, но путается в юридических формулировках или не находит ответ в сухом справочном тексте.

Отдельно соберите группу для сокращений, брендов и названий полей. Это частый источник ошибок в tool calling и RAG на разных языках. "KYC", "SLA", "customer_id", название тарифа, имя продукта, сокращение отдела - такие вещи лучше проверять отдельным срезом, а не вперемешку со всем остальным.

Для каждого кейса обычно достаточно сохранить четыре вещи:

  • текст запроса пользователя
  • язык документов и их тип
  • язык названий полей, параметров или инструментов
  • ожидаемое действие или короткий эталон ответа

Если ваш продовый поток выглядит как "запрос на русском, база знаний на английском, поля инструмента на английском", не делайте набор слишком академичным. Доли кейсов должны повторять реальность. Тогда первый прогон покажет не абстрактное качество, а конкретные поломки: где модель неверно перевела термин, где выбрала не тот документ и где спутала название поля с обычным словом.

Как прогнать тесты по шагам

Один прогон должен показывать, где ломается цепочка: на определении языка, на поиске, на вызове инструмента или уже в финальном ответе. Если смотреть только на последний текст, вы пропустите половину ошибок.

Если вы сравниваете несколько моделей через один совместимый с OpenAI шлюз, записывайте еще модель и провайдера. Иначе потом трудно понять, откуда пришел сбой.

Сначала язык и системный промпт

Начните с самого раннего сигнала: какой язык система увидела во входе. Для смешанных русско-английских запросов это частая точка сбоя. Запрос вроде "Покажи overdue invoices за март" легко уводит модель в английский ответ, хотя пользователь ждет русский.

Для каждого теста сохраните три поля: исходный запрос, определенный язык и выбранный системный промпт. Потом проверьте простую вещь: логика выбора совпала с ожиданием или нет. Если у вас есть отдельные промпты для ru, en и mixed, ошибка на этом шаге испортит весь прогон, даже когда поиск и tool calling работают нормально.

Потом поиск, инструмент и финальный ответ

Следующий шаг - посмотреть, что retriever положил в контекст. Не оценивайте поиск по принципу "что-то нашлось". Откройте 3-5 верхних фрагментов и проверьте две вещи: язык каждого фрагмента и то, отвечает ли он на вопрос. Частая проблема в RAG на разных языках простая: вопрос на русском, нужный документ на английском, а поиск поднимает только русские тексты с похожими словами.

Дальше остановите цепочку до выполнения инструмента и проверьте аргументы. Это особенно полезно для tool calling на двух языках. Пользователь пишет "отмени meeting на tomorrow 11 am", а инструмент ждет date, action=cancel и locale=ru. Если модель поняла смысл, но передала в аргументах "tomorrow" или русское "отмена" вместо нужного enum, ошибка уже есть. Запуск инструмента только скроет ее.

В конце сравните ответ с ожидаемым результатом по двум осям: язык и смысл. На каком языке модель ответила, не переключилась ли она без причины, не смешала ли термины в одной фразе. И сохранила ли она факт, дату, статус, сумму и ограничения из найденного контекста и из ответа инструмента.

Хороший отчет показывает весь путь запроса. Тогда команда видит, что чинить: выбор промпта, поиск, схему аргументов или финальную сборку ответа.

Какие метрики смотреть

Сравните маршруты моделей
Один набор кейсов через RU LLM быстро покажет сбои в поиске, аргументах и языке ответа.

Если в одном кейсе пользователь пишет по-русски, база знаний хранит статьи на английском, а инструмент ждет аргументы с английскими именами полей, общая оценка "ответ выглядит нормально" почти бесполезна. Нужны метрики по шагам. Иначе модель может ответить гладко, но взять не те документы или сломать вызов инструмента.

Для смешанных русско-английских запросов обычно хватает четырех цифр на одном и том же наборе кейсов:

  • доля верно выбранных документов при смешанном запросе
  • доля корректных аргументов инструмента без ручной правки
  • совпадение языка ответа с правилом сценария
  • цена и задержка на одном и том же наборе кейсов

В retrieval лучше считать не расплывчатую "релевантность", а точное попадание в эталон. Если запрос "верни invoice за март по договору" должен поднять английскую статью и один русский шаблон ответа, проверяйте, попали ли они хотя бы в top-3. Для RAG на разных языках это часто первый источник ошибок: модель понимает вопрос, но поиск тянет только русские документы и пропускает нужный английский термин.

В tool calling на двух языках смотрите на аргументы так же строго. Успешный кейс - это вызов без ручной правки, где модель передала правильные поля, формат даты, идентификатор и допустимые значения enum. Если оператор потом меняет "refund" на "chargeback" или правит account_id, кейс уже неуспешный, даже если ответ пользователю выглядел убедительно.

Как читать цифры

Метрику языка ответа лучше считать отдельно. В проде правило часто простое: отвечать пользователю по-русски, даже если документы и названия полей были на английском. Тогда проверка бинарная: ответ на нужном языке или нет. Отдельно можно помечать мягкие сбои, когда модель держит русский, но вставляет лишние куски вроде "Your request has been processed".

Цена и задержка имеют смысл только на том же наборе кейсов, где вы уже померили качество. Иначе сравнение обманывает. Одна модель может быть на 20% дешевле, но терять половину успешных tool calls на смешанном вводе. Смотрите не только среднюю задержку, но и p95. Именно длинные хвосты ломают чат поддержки и внутренние сценарии операторов.

Если у вас есть трассировка по каждому запросу, разбор становится быстрее: видно, где сломался поиск, где модель перепутала язык, а где неверно собрала аргументы. Если retrieval держится на уровне 85%, язык ответа дает 98%, а аргументы инструмента только 62%, проблема уже ясна. Модель менять рано. Сначала чините схему вызова и названия полей.

Пример из поддержки

В поддержке такие случаи встречаются постоянно. Клиент пишет по-русски: "У нас спор по оплате, как у вас идет chargeback и какие сроки ответа?" При этом нужный регламент лежит в базе знаний на английском, и в нем нет слова "оспаривание". Есть только раздел про chargeback response window и список причин, когда спор можно принять.

На хорошем прогоне модель не переводит весь документ целиком. Она находит нужный фрагмент на английском, вытаскивает правило, а потом отвечает клиенту по-русски простым текстом. Это быстрее и чище. Оператору не нужен машинный перевод на три страницы, ему нужен точный ответ на один вопрос.

В тесте стоит проверять не только финальную фразу для клиента. Нормальный сценарий выглядит так: поиск находит английский раздел, RAG подставляет именно его, модель отвечает по-русски, а после этого бот создает тикет в системе поддержки через API с англоязычными полями.

Например, в tool calling запрос может уйти с такими полями:

  • issue_type: chargeback
  • customer_language: ru
  • policy_language: en
  • summary: Customer asks about chargeback сроки и условия ответа

Здесь и появляется частая ошибка. Ответ клиенту может быть верным, но инструментальный вызов ломается. Модель пишет в issue_type слово возврат вместо допустимого chargeback, путает язык источника или кладет русский текст в поле, где downstream-сервис ждет английское значение enum. Для продакшена это уже провал, даже если сам ответ выглядит умно.

Поэтому тест должен проверять сразу несколько вещей: клиент получил точный ответ по сути вопроса, модель взяла правило из нужного английского раздела, тикет создался с валидными значениями полей API, а поля не потеряли смысл при переходе между русским текстом, английским документом и английским контрактом инструмента.

Где команды чаще ошибаются

Сравните сотни моделей
Подавайте смешанные запросы через один шлюз и сравнивайте поведение разных провайдеров.

Самая частая ошибка проста: команда пытается свести весь сценарий к одному баллу. Если пользователь пишет по-русски, поиск идет по английским документам, а ответ модель дает снова по-русски, один общий score почти ничего не объясняет. Непонятно, сломался поиск, потерялся смысл между шагами или уже сам финальный ответ.

Проверку лучше разделять по этапам. Иначе красивый текст легко маскирует плохую работу внутри пайплайна.

Обычно хватает четырех отдельных проверок: нашел ли поиск нужный фрагмент, выбрала ли модель правильный tool, передала ли она в tool верные аргументы и совпадает ли финальный ответ с фактами из источника. Для mixed-language сценариев это особенно важно, потому что сбой часто возникает не в генерации, а на стыке языков.

Вторая типичная проблема - смотреть только на гладкий финальный ответ. Он может звучать уверенно и естественно, но внутри модель уже сходила не в тот инструмент. Пользователь спрашивает по-русски про возврат заказа, tool описан на английском, а модель вызывает не refund_status, а order_tracking. Ответ при этом выглядит правдоподобно, но фактически он неверен.

В поддержке это особенно заметно. Бот может вежливо пересказать общий процесс возврата, и на беглый взгляд тест пройдет. Но если система не вызвала нужный инструмент или передала в него неверные аргументы, такой сценарий нужно считать провалом.

Быстрая проверка перед релизом

Прогоните смешанные кейсы
Проверьте русско-английские сценарии через один OpenAI-совместимый эндпоинт без правок в SDK.

Перед релизом не нужен огромный стенд. Нужен короткий прогон, который быстро покажет, ломаются ли смешанные русско-английские запросы в реальных цепочках.

Минимальный набор лучше собирать не по темам, а по направлению языка. Возьмите кейсы, где пользователь пишет по-русски, а документы лежат на английском. Добавьте обратный вариант, где вопрос на английском, а база знаний и подсказки инструмента на русском. Если у вас встречаются более сложные цепочки, проверьте и их: например, запрос на русском, документ на английском, а ответ от внешнего инструмента приходит на казахском или немецком.

У каждого кейса должен быть записан ожидаемый язык ответа. Не "примерно понятно", а явно: ответ только на русском, только на английском или двуязычный формат с заданным порядком. Иначе модель легко пройдет тест по смыслу, но провалится по UX. Пользователь спросил на русском, а получил хороший, но английский ответ. Для продакшена это уже сбой.

Перед выкладкой полезно проверить четыре вещи:

  • модель отвечает на нужном языке, а не на языке найденного документа
  • цитаты, названия полей и куски текста не меняют смысл при переключении языка
  • tool calling отправляет правильные аргументы, даже если описание функции и запрос пользователя на разных языках
  • fallback ведет себя предсказуемо, если один шаг цепочки не понял язык

Для tool calling держите рядом эталон не только по факту вызова, но и по форме. Название функции, имя каждого поля и тип значения должны совпадать с ожидаемым результатом. Это частая поломка: модель верно понимает задачу, но вместо customer_id отправляет локализованное поле или меняет формат даты.

После этого снимите отдельные цифры по эксплуатации. Цена, задержка и процент сбоев должны лежать в отчете отдельно, а не в одной "средней оценке". Смешанные сценарии часто проходят по качеству, но становятся слишком дорогими из-за лишнего перевода или повторного запроса. Бывает и наоборот: стоят дешево, но дают всплеск таймаутов на длинных англоязычных документах.

Короткий релизный порог можно задать так:

  • нет смены языка ответа без причины
  • нет ошибок в аргументах tool calling
  • задержка не выходит за рабочий лимит
  • цена на один сценарий не выросла после смены модели или маршрута
  • доля сбоев на смешанных кейсах не стала выше, чем на одноязычных

Если команда сравнивает модели через единый шлюз, например RU LLM, удобно прогонять один и тот же набор тестов через api.rullm.com без правок в SDK и коде. Это помогает быстро увидеть, как меняются маршрутизация, RAG и tool calling на смешанных запросах.

Что делать после первых прогонов

После первых запусков не пытайтесь сразу покрыть все случаи. Сначала зафиксируйте небольшой регрессионный набор: 20-40 сценариев, которые уже показали слабые места. Гоняйте его после каждой смены модели, промпта, retriever или схемы tool calling.

Такой набор лучше держать живым. Если бот один раз перепутал язык ответа, не нашел английский документ по русскому вопросу или отправил в инструмент аргументы не на том языке, добавьте этот кейс в постоянную проверку. Через пару недель у команды появится короткий, но очень полезный тестовый пакет, который быстро ловит повторные сбои.

Маршруты моделей тоже стоит разделять по типу задачи. Более дешевую модель можно оставить для определения языка, нормализации запроса, простой классификации и извлечения полей. Более сильную модель лучше вызывать там, где есть смешанный контекст: русский вопрос, английская документация, несколько инструментов и ответ для пользователя на русском.

На практике это экономит бюджет и снижает число странных ошибок. Саппорт-бот может сам понять, что вопрос написан по-русски, найти англоязычную статью в базе, а потом отдать итог на русском. Но план вызова инструментов и сбор ответа лучше поручить более сильной модели, иначе сбой часто прячется не в тексте, а в логике шага.

Что логировать после тестов

Логируйте язык каждого шага, а не только финального ответа. Обычно хватает пяти полей:

  • язык пользовательского запроса
  • язык найденных документов
  • язык системного или промежуточного промпта
  • язык аргументов в tool calling
  • язык финального ответа

Так проще увидеть, где именно все ломается. Если retrieval нашел английский текст, а модель внезапно ответила смесью языков, причина одна. Если инструмент получил русские аргументы вместо ожидаемых английских полей, причина уже другая.

Если вам нужен единый LLM API в российском контуре с логами и бэкапами внутри РФ, такой прогон можно вести через RU LLM. Но ориентир остается простым: если после смены модели ломается хотя бы один старый смешанный сценарий, релиз в прод еще рано отправлять.

Часто задаваемые вопросы

Почему смешанный запрос может ломать систему, даже если ответ выглядит нормальным?

Потому что сбой часто живет не в финальном тексте, а раньше: в поиске, переписывании запроса или аргументах инструмента. Модель может ответить по-русски гладко, но взять не тот документ или передать в API неверное значение вроде отменен вместо cancelled.

Что минимум нужно записать для одного mixed-language сценария?

Начните с четырех полей: язык запроса пользователя, язык документов, язык инструмента или его аргументов и язык итогового ответа. Этого хватает, чтобы увидеть, где именно система уходит не туда.

Откуда брать хорошие тестовые кейсы для таких запросов?

Берите примеры из логов, а не из головы. Сначала уберите персональные данные, потом оставьте живую форму запроса: ошибки, английские термины, названия полей и куски текста из писем.

Нужно ли сохранять опечатки и смесь языков в тестах?

Да, лучше оставлять. Фразы вроде проверь invoice за march ломают пайплайн чаще, чем чистый русский или чистый английский, поэтому именно они дают честную проверку.

Что первым делом смотреть в RAG на смешанных запросах?

Сначала проверьте, нашел ли retriever нужный документ хотя бы в верхних результатах. Потом откройте сами фрагменты и посмотрите две вещи: они правда отвечают на вопрос и система не потеряла английский термин, который был нужен для поиска.

Как проверять tool calling, если пользователь пишет на русском, а API ждет английские поля?

Остановите цепочку до реального вызова и проверьте имя функции, поля и значения. Если схема ждет RUB, cancel или customer_id, модель должна отправить ровно их, а не русский перевод и не свободный текст.

Какие метрики реально полезны для mixed-language проверки?

Держите четыре цифры на одном и том же наборе кейсов: попадание нужных документов, долю вызовов инструмента без ручной правки, совпадение языка ответа с правилом сценария и цену с задержкой. Общая оценка вроде ответ выглядит нормально тут мало что дает.

Сколько кейсов достаточно перед релизом?

Для короткого релизного прогона обычно хватает 20–40 сценариев, если они повторяют реальный поток запросов. Возьмите случаи, где русский вопрос идет в английские документы, и добавьте кейсы с инструментами, у которых поля и enum только на английском.

Что логировать после тестов, кроме финального ответа?

Логируйте язык на каждом шаге: у запроса, найденных документов, системного промпта, аргументов инструмента и финального ответа. Тогда вы быстро поймете, сломался поиск, модель смешала языки или инструмент получил не тот формат.

Когда стоит менять модель, а когда лучше править пайплайн?

Сначала чините тот шаг, где метрика просела. Если поиск держится нормально, а аргументы инструмента часто неверны, смена модели мало поможет. Модели удобно сравнивать через единый OpenAI-совместимый шлюз вроде RU LLM: так вы гоняете один набор кейсов без правок в коде и видите разницу по шагам.