API вернул успех, но параметр не сработал: проверяем клиент и шлюз
Сопоставьте исходящий запрос клиента, вход и выход шлюза и результат задачи. Отличите пропуск поля от удаления, преобразования протокола и ограничений поддержки; проверьте поля локальным примером с нулём и логическими значениями.
API возвращает HTTP 200, но ответ не соответствует заданному формату, либо после смены посредника настройка словно перестала работать. Не спешите судить о подмене модели по стилю ответа. Сначала выясните, отправил ли клиент поле, сохранилось ли оно после шлюза и поддерживает ли конечный endpoint именно этот параметр и способ его использования.
Статья посвящена передаче параметров по цепочке вызова и проверке результата, а не настройке семплирования. LiteLLM и OpenRouter приведены как примеры механизмов с официальной документацией; их поведение нельзя приписывать всем посредникам. Документация проверена 19 октября 2026 года. Пример ниже проверен локально на искусственных данных: платные API не вызывались, фактическое поведение поставщиков не тестировалось.
1. Разделите наблюдения на четыре уровня
Значение в интерфейсе, объект, переданный SDK, и фактическое тело HTTP-запроса могут различаться. Запишите версию клиента, путь интерфейса, точный ID модели, группу аккаунта, использование потокового режима и автоматического переключения. Затем последовательно ищите место изменения поля.
| Место наблюдения | Что подтверждает | Чего не доказывает |
|---|---|---|
| Интерфейс клиента или файл настроек | Желаемое пользователем значение | Наличие поля в конечном запросе |
| Исходящее тело запроса клиента | Поле действительно покинуло клиент | Передачу шлюзом без изменений |
| Вход своего шлюза и его выход к поставщику | Удаление, переименование, изменение типа или значения | Исполнение параметра поставщиком |
| Ответ и проверка прикладных правил | Соответствие результата ограничениям этой задачи | Строгое применение параметра на основании одного удачного ответа |
Просматривайте записи только в тестовой среде, к которой у вас есть разрешённый доступ. Передавайте поддержке ID запроса и необходимые обезличенные поля, без полных заголовков авторизации и личных промптов. Если выход стороннего шлюза недоступен, отметьте этот уровень как «неизвестно» и попросите поставщика подтвердить фактически переданные поля по ID запроса. Журнал клиента не заменяет недоступные сведения.
Различайте четыре случая: поле отсутствует; число превратилось в строку; выполнено документированное преобразование между протоколами; поле сохранилось, но функция не поддерживается. Преобразование не обязательно ошибочно, а передача без изменений не обязательно корректна.
2. До изменения чисел проверьте пропуск и удаление полей
Начните с минимального запроса, который выполняет базовую задачу. Добавляйте по одному проверяемому полю, сохраняя остальные условия. Просматривайте тело после окончательной сериализации, а не только переменную, напечатанную перед вызовом SDK.
Частые причины на стороне клиента: настройка переопределена значением по умолчанию, поле вложено не туда, SDK не принимает расширение либо сборщик запроса считает 0 и false незаполненными значениями. Значение null, отсутствие поля и допустимый ноль — разные вещи. Разрешён ли null, нужно проверять по документации конкретного интерфейса; заменять всё одним значением нельзя.
Шлюз тоже может удалять параметры намеренно. Официальная документация LiteLLM описывает следующее поведение: по умолчанию передача неподдерживаемого моделью параметра вызывает исключение; при drop_params=True неподдерживаемое поле удаляется вместо исключения. Отдельная настройка additional_drop_params позволяет указать поля для удаления.[1] Исчезновение ошибки не означает появления возможности: иногда исчезло само ограничение.
Описанный там же allowed_openai_params разрешает передачу выбранных полей без изменений. Это название настройки LiteLLM, которая не добавляет отсутствующую функцию конечному поставщику. Меняйте список разрешённых полей только после подтверждения их соответствия контракту целевого интерфейса. Не копируйте эти переключатели в другие продукты.
Если формат вывода, ограничения инструментов или другие условия обязательны для задачи, предпочтительнее явная ошибка с диагностикой. Удалять поле допустимо, когда бизнес-процесс явно разрешает упрощённый режим. Фиксируйте такой режим отдельно как ослабление требований, а не как полное выполнение первоначальной задачи.
3. Сравните поля двух этапов локально
Следующий пример Node.js не обращается к сети. Сохраните его как compare-fields.mjs и выполните node compare-fields.mjs. Оба JSON содержат искусственные данные: они имитируют изменение одного значения и удаление одного поля шлюзом. Скрипт не перехватывает ваши реальные запросы.
import { isDeepStrictEqual } from 'node:util';
const fields = ['temperature', 'stream', 'response_format'];
export function compareFields(beforeText, afterText) {
const parse = (text) => {
if (typeof text !== 'string' || text.length > 100000) {
throw new TypeError('Expected a JSON string of at most 100000 characters');
}
const value = JSON.parse(text);
if (value === null || Array.isArray(value) || typeof value !== 'object') {
throw new TypeError('Expected a JSON object');
}
return value;
};
const before = parse(beforeText);
const after = parse(afterText);
return fields.map((field) => {
const left = Object.hasOwn(before, field);
const right = Object.hasOwn(after, field);
const state = !left && !right ? 'absent'
: left && !right ? 'removed'
: !left && right ? 'added'
: isDeepStrictEqual(before[field], after[field]) ? 'same' : 'changed';
return { field, state };
});
}
const before = JSON.stringify({
temperature: 0, stream: false,
response_format: { type: 'json_object' }
});
const after = JSON.stringify({ temperature: 0.7, stream: false });
console.log(compareFields(before, after));
Ожидаемые состояния: changed для temperature, same для stream, removed для response_format. Пример выводит только имена полей из фиксированного списка и их состояния, без значений, ключей и содержимого запроса. В собственном диагностическом процессе тоже используйте нечувствительные образцы; не записывайте полные рабочие запросы в файлы или журналы.
Сравнение различает 0, false и null, замечает различие числа и строки и не зависит от порядка ключей вложенного объекта. Оно проверяет лишь три перечисленных поля верхнего уровня, не проверяет допустимость параметров и не оценивает правильность преобразования протокола. Для преобразованных полей сначала установите соответствие по целевому контракту; прямое сравнение тел двух разных протоколов не позволяет объявить различия ошибками.
Локальные проверки охватили добавление и удаление полей, изменение значений и типов, ноль и логические значения, null и отсутствие поля, порядок ключей вложенного объекта, а также невалидный JSON, вход не в виде объекта и слишком длинный ввод. Их успешность подтверждает поведение сравнения на этих примерах, но не корректную передачу реальным шлюзом.
4. Уточните глубину поддержки параметра
Составьте карточку возможностей: интерфейс и версия, точный ID модели, endpoint или группа поставщика, имя поля, диапазон значений, допустимые комбинации, ограничения потокового режима, ссылка на документацию и дата проверки. Фраза «поддерживает инструменты» или «поддерживает изображения» на странице модели не означает совместимость выбранного интерфейса, канала и всех сочетаний параметров.
Например, поддержка базового режима форматирования не равнозначна поддержке всех ключевых слов Schema. Возможность использовать поле отдельно не означает, что его можно сочетать с любым другим режимом. Даже принятый параметр не исключает непригодного результата из-за ограничений содержимого, обрыва вывода или иных причин: проверяйте конкретную ошибку и состояние завершения.
Текущая документация OpenRouter описывает provider.require_parameters со значением false по умолчанию. Значение true исключает поставщиков, не поддерживающих параметры запроса; при обычной маршрутизации неподдерживаемые поля всё ещё могут игнорироваться.[2] Для некоторых полей документация дополнительно описывает предпочтение поддержки: если подходящие endpoints есть, выбор ограничивается ими, но если их нет, обычное предпочтение всё равно может допустить игнорирование поля. Поэтому «обычно выбирается поддерживающий endpoint» не заменяет обязательного требования.
Такой фильтр маршрутов не гарантирует правильность каждого ответа и не является универсальной настройкой всех шлюзов. Если доступных путей после фильтрации нет, разберите ограничения возможностей и маршрутизации, а не снимайте обязательное требование незаметно ради исчезновения ошибки. Автоматическая смена endpoint или модели тоже мешает сравнению. Записывайте фактический путь и переключения каждой попытки; о границах переключения см. проверку резервных моделей API.
5. Ищите причину по сопоставимым наблюдениям
Ниже приведён план проверки, а не результаты испытаний поставщиков. Используйте фиксированный нечувствительный ввод, ограниченное число попыток и заранее подтверждённый бюджет. Не повторяйте очевидно некорректные параметры и не разрешайте диагностике выполнять реальные записи или платежи через инструменты.
| Наблюдение | Что проверить первым | Следующее действие |
|---|---|---|
| Настройка есть в интерфейсе, но отсутствует в исходящем теле | Переопределение настроек, сериализацию, способ передачи расширений SDK | Исправить сборку запроса и вновь проверить отправленное тело |
| Поле есть на входе шлюза, но отсутствует на выходе | Настройки удаления, разрешённые поля, преобразование протокола | Восстановить по контракту цели либо явно отклонить запрос |
| Поле сохранено, но получена ошибка поддержки | Endpoint, модель, тип, значение и сочетание параметров | Выбрать поддерживаемый путь, не повторять запрос бесконечно |
| HTTP 200, но результат не прошёл проверку | Тело, состояние завершения, область поддержки, реальный маршрут | Сохранить неудачный образец, отличить усечение от нарушения требований |
| Два ответа одинаковы или различаются | Случайность, сложность ввода, кэш, другие настройки | Не делать вывод о действии параметра только по двум ответам |
Для форматных ограничений проверяйте разбор результата, типы и обязательные поля по правилам задачи. Для потокового режима — фактический тип ответа и структуру событий. Ограничения инструментов проверяйте с имитациями, не выполняющими внешних действий. Параметры семплирования влияют на распределение генерации; изменение стиля двух ответов недостаточно для доказательства передачи и применения поля.
Сохраните три сопоставимые записи: ожидаемые ограничения, наблюдаемые поля запроса и фактический результат приёмки. Если есть только удачный ответ, но нет свидетельств передачи поля, пишите «пример прошёл проверку», а не «строгое применение параметра доказано». В обращении поставщику укажите время, ID запроса, интерфейс и версию, различия полей и ожидаемое поведение. Можно использовать шаблон минимального воспроизведения и обезличенного обращения.
Источники: [1] LiteLLM: Drop Unsupported Params; [2] OpenRouter: Provider Routing. Они подтверждают только описанные механизмы соответствующих продуктов и не определяют поведение других API-посредников.