<!-- Canonical URL: https://ask.atlascloud.ai/ru/test-streaming-tool-call-compatibility-before-changing-llm-apis -->

# Как проверить совместимость streaming и tool call до смены LLM API?

> Тестируйте миграцию LLM API записываемыми контрактными fixture, а не одной chat-демонстрацией. Проверьте текстовый поток, принудительный инструмент, фрагменты аргументов, несколько вызовов, возврат результата, отмену, ошибки и usage.

Десятиминутный chat-тест может пропустить опасные ошибки: двойной вызов после retry, исполнение JSON до финального потокового события, возврат результата с неверной ролью или продолжающуюся запись после отмены. Полезный migration gate проводит фиксированные запросы через настоящий parser и исполнитель, затем проверяет структурные инварианты.

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

## Определите контракт, от которого зависит клиент

До проверки провайдера запишите конкретное поведение клиента. Не ограничивайтесь расплывчатым ярлыком «OpenAI compatible».

| Область контракта | Обязательный инвариант | Сохраняемое доказательство |
|---|---|---|
| Аутентификация | Endpoint принимает ключ | Статус и request ID |
| Текстовый поток | Дельты собираются в одно сообщение | Упорядоченные сырые события |
| Поток инструмента | Вызов завершается до исполнения | Buffer и финальное событие |
| Корреляция | Результат привязан к нужному вызову | Сопоставление call ID |
| Retry | Вызов выполняется не более раза | Журнал idempotency |
| Usage | Счётчики есть или помечены unavailable | Метаданные финального ответа |

Поддержка протокола зависит от модели. Atlas Cloud предлагает несколько форматов запросов, поэтому до выбора тестового маршрута проверьте актуальное руководство по [`supported_apis`](https://www.atlascloud.ai/docs/llm-protocols?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=test-streaming-tool-call-compatibility-before-changing-llm-apis).

## Создайте четыре детерминированных инструмента

Используйте fixture, раскрывающие разные ошибки:

* `echo_json` возвращает проверенные аргументы без изменений.
* `read_fixture` читает известный файл из sandbox.
* `delayed_value` завершается после управляемой задержки.
* `always_error` возвращает стабильную структурированную ошибку.

Каждый инструмент должен иметь строгую схему с `additionalProperties: false` и уникальный fixture ID, чтобы двойное исполнение было заметно. Не зависьте от погоды, поиска или меняющегося repository.

## Запустите поэтапную матрицу совместимости

Сначала проверяйте режим без streaming, затем streaming; сначала один вызов, затем несколько.

| Этап | Поведение prompt | Условие успеха |
|---|---|---|
| A | Вернуть обычный текст | Получены финальный текст и stop status |
| B | Принудить `echo_json` | Получены имя и валидные аргументы |
| C | Вызвать `echo_json` потоком | Фрагменты собраны один раз |
| D | Вызвать два инструмента чтения | Оба результата правильно соотнесены |
| E | Получить одну ошибку | Модель исправляет её или чисто выходит |
| F | Отменить поток | Позднего исполнения не происходит |

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

## Записывайте сырые события ниже SDK

Высокоуровневые объекты SDK удобны в production, но скрывают различия миграции. Добавьте debug-transport, записывающий монотонный номер, response ID, output index, call ID, тип события и длину очищенного payload.

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

```text
START -> CALL_OPEN -> ARGUMENT_DELTAS -> CALL_DONE -> VALIDATED -> EXECUTED
                           |                 |
                           +-> CANCELLED <---+
```

Отклоняйте обратные переходы и двойное исполнение. Если соединение потеряно после `EXECUTED`, но до получения результата моделью, используйте idempotency key, а не повторяйте запись вслепую.

## Проверяйте полный круг результата

Валидный tool call — только половина контракта. Верните результат с ожидаемым протоколом типом сообщения или item, затем потребуйте финальный ответ, использующий известное поле результата.

Проверьте большие и пустые результаты, Unicode и структурированные ошибки. Ограничьте размер до возврата в context. Скрытое предположение адаптера может проявиться только при первом крупном результате.

## Сравнивайте инварианты, а не формулировки

Не проваливайте тест из-за разной фразы в финальном ответе. Проверьте, что:

* Выбрано ожидаемое имя инструмента.
* Аргументы прошли JSON Schema.
* Каждый call ID уникален и правильно соотнесён.
* Каждый инструмент выполнен ноль или один раз по плану.
* Цикл завершился в заданном бюджете.
* Финальный ответ использовал результат fixture.

Специфические snapshot храните только для отладки, а критерии успеха оставляйте нейтральными к провайдеру.

## Добавьте ошибки и отмену

Разрывайте поток после первого фрагмента аргумента, после завершения вызова и после исполнения инструмента. Инъецируйте 429, timeout, повреждённый JSON и неизвестное имя инструмента. Проверьте безопасный retry, восстановление или полезную остановку.

Самая опасная ошибка — неоднозначный retry, повторяющий изменение состояния. Для записи требуйте явной идемпотентности.

## Сделайте набор gate для релиза

Держите быстрый smoke-набор для изменений конфигурации и полную матрицу для обновления SDK или gateway. Сохраняйте модель, протокол, base URL, hash схемы, streaming flag, версию клиента и timestamp.

Atlas Cloud поддерживает потоковые и непотоковые LLM-запросы и позволяет изучать кандидатов в одном [каталоге моделей](https://www.atlascloud.ai/llm-models?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=test-streaming-tool-call-compatibility-before-changing-llm-apis). Общий доступ не означает одинаковых возможностей, поэтому запускайте gate для каждой модели.

## Итог

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

## FAQ

### Что должен покрывать первый тест совместимости?

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

### Зачем записывать сырые потоковые события?

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

### Можно ли сравнивать провайдеров по точному совпадению текста?

Обычно нет. Сравнивайте структурные инварианты: валидность вызова, обязательные поля, число исполнений, финальный статус и результат задачи.

### Как тестировать некорректные аргументы инструмента?

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

### Нужны ли в наборе тестов инструменты записи?

Сначала используйте детерминированные инструменты чтения. Добавляйте sandbox-запись после успешной сборки вызова, валидации, дедупликации и восстановления.

### Как часто запускать тесты совместимости?

Запускайте короткий smoke-набор перед каждой сменой модели или протокола и полный набор при изменении SDK, схемы, gateway или stream parser.
