В этом материале
Сравнение движков полезно, когда допустимые различия перечислены заранее, а несовпадение текста не маскирует нарушение контракта.
Сформулировать общий контракт
Два движка могут объявлять совместимый endpoint и всё равно различаться по параметрам, значениям по умолчанию и дополнительным полям. Дифференциальный тест подаёт один fixture двум адаптерам и сравнивает только заранее выбранные свойства. Это не соревнование скорости и не доказательство одинакового качества модели. Перед запуском записывают пересечение поддерживаемых функций, версии интерфейсов и допустимые различия. Если одна сторона не умеет нужный режим, результатом становится неподдерживаемая возможность, а не случайное сравнение другого запроса. Особенно опасно незаметно удалить параметр только у одной стороны и затем объявить ответы эквивалентными по контракту.
Зафиксировать envelope и ограничения
Базовые утверждения охватывают HTTP status, тип содержимого, обязательные JSON поля, идентификаторы и завершение последовательности. OpenAPI 3.1.1 помогает хранить версию схемы независимо от конкретного клиента. Документация online serving vLLM отдельно перечисляет поддерживаемые интерфейсы и ограничения; знакомое имя endpoint не означает поддержку каждого поля без исключений. Для второго движка требуется такой же версионированный паспорт. В тестовом отчёте сохраняют исходные ответы и результат нормализации. Без исходных данных нельзя понять, возникло ли расхождение на сервере или его создал слишком агрессивный адаптер тестовой системы.
Нормализовать только объяснимые различия
Случайный идентификатор и время создания обычно не подходят для буквального равенства, однако их наличие, тип и согласованность между кадрами остаются проверяемыми. Реестр исключений описывает поле, основание, область применения и срок пересмотра. Неизвестное отличие не должно автоматически исчезать при нормализации. Например, отсутствие usage в одном ответе нельзя превратить в нули только ради совпадения. Для finish_reason сначала сравнивают согласованную семантику, затем отдельно сохраняют исходное значение. Исключение относится к конкретной версии и сценарию, а не навсегда отключает проверку целого класса данных во всех будущих выпусках.
Разобрать расхождение генерации
Если envelope совпал, а текст отличается, следующим шагом проверяют модель, tokenizer, chat template, sampling и окружение исполнения. Раздел воспроизводимости vLLM описывает ограничения повторяемости по версиям и оборудованию. Даже одинаковый seed не является универсальным обещанием побитового равенства между произвольными движками. Для tool calling проверяют структуру вызова и возможность разобрать аргументы, а не одинаковую пунктуацию пояснения. Для ограниченного вывода проверяют допустимый terminal state. Смысловое качество текста оценивают отдельным корпусом, чтобы протокольная проверка не смешивалась с субъективным выбором более удачной формулировки или случайной вариацией модели.
Сохранить пригодный для решения артефакт
Итоговая матрица связывает fixture, версии обеих сторон, проверяемое свойство, результат и известное исключение. Небольшой ограниченный набор запускают до миграции; спорные случаи повторяют с сохранённым окружением и установленным пределом попыток. Дополняют контекст сравнение SGLang и vLLM и vLLM и Ollama. Матрица позволяет принять конкретное решение о переносе клиентского сценария. Она не гарантирует совместимость с любой библиотекой, одинаковую токенизацию или производительность под нагрузкой. Такие утверждения требуют самостоятельных опытов, а список исключений должен оставаться видимым после успешной миграционной проверки.