Гайд · TNWS AI
Как ограничить ответ vLLM вариантами choice при классификации заявок
Получаем одну из заранее разрешённых меток и отдельно проверяем, что классификация совпала с текстом обращения.
Задача и применимость
Вопрос читателя: «как задать choice структурированный ответ vLLM». Для Chat API vLLM и актуального поля structured_outputs.choice после удаления guided_choice в v0.12.0; сверено с официальной документацией 20 сентября 2026 года. Модель должна поддерживать серверную генерацию структурного вывода.
Для воспроизводимости запишите фактическую версию установленного vLLM, модельный checkpoint и параметры запуска. Путь /models/your-chat-checkpoint либо /models/your-embedding-checkpoint в команде ниже — заполнитель, а не реальный файл. Наличие GPU, объём памяти и условия лицензии весов проверяются до запуска. Демонстрация не утверждает, что ответ модели заранее известен по буквам.
Проверенные возможности
Официальная документация перечисляет choice как структурное ограничение: вывод должен быть одним из заданных вариантов. Старое поле guided_choice заменено на structured_outputs.choice. Ограничение допустимых слов не гарантирует, что выбрана семантически верная категория.
Пошаговая процедура
- Выберите взаимоисключающие классы для конкретного процесса.
- Подготовьте короткие размеченные обращения с известной меткой.
- Передайте список разрешённых меток в structured_outputs.choice.
- Проверьте, что ответ — ровно одна метка без объяснения.
- Сравните метку с разметкой и отдельно обработайте неоднозначные случаи.
Команда для тестового запуска на локальном адресе (подставьте законно полученный checkpoint):
vllm serve /models/your-chat-checkpoint --host 127.0.0.1 --port 8000
Готовый запрос и контроль ответа
В приведённом фрагменте используется стандартная библиотека Python и простой общий помощник для отправки JSON. Подставьте при необходимости Bearer-токен через защищённую переменную окружения и проверьте, что ваш сервер его ожидает.
import json, urllib.request
BASE = "http://127.0.0.1:8000"
def call(path, payload):
data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
request = urllib.request.Request(BASE + path, data=data,
headers={"Content-Type": "application/json"}, method="POST")
with urllib.request.urlopen(request, timeout=120) as reply:
return json.load(reply)
model = json.load(urllib.request.urlopen(BASE + "/v1/models"))["data"][0]["id"]
payload = {"model": model, "messages": [{"role": "user",
"content": "Выбери тип обращения: 'Не пришла посылка'. "
"Варианты: доставка, возврат, оплата."}],
"structured_outputs": {"choice": ["доставка", "возврат", "оплата"]},
"max_tokens": 16}
reply = call("/v1/chat/completions", payload)
label = reply["choices"][0]["message"]["content"].strip()
assert label in {"доставка", "возврат", "оплата"}
print(label)
Пример входа и ожидаемого результата
Вход: жалоба «Не пришла посылка»; возможные классы доставка, возврат, оплата. Ожидаемая правильная метка по ручной разметке — доставка. Технический assert проверяет только членство в списке; семантическую правильность сравните с эталоном отдельно.
Как интерпретировать результат
Структурное ограничение помогает тем, что downstream система не увидит неожиданное «проблема с заказом». Но если классы перекрываются, модель всё равно может выбрать неверный допустимый вариант. Например «верните деньги за не пришедшую посылку» содержит сразу возврат и доставку; до внедрения решите, какой отдел должен первым обработать обращение. Если нельзя честно выбрать один класс, добавьте отдельную категорию для ручного разбора вместо принудительной ошибки. Формат не является классификатором высокого качества сам по себе.
Развёртывание без потери контекста
В условиях vLLM v0.12.0+ старые инструкции с guided_choice неактуальны; обновляйте ключ в запросе и автоматические тесты одновременно. Не полагайтесь на английские варианты для русскоязычных сообщений без оценки. Сохраните исходный текст, модель, допустимые классы и эталонные метки в закрытом тестовом наборе. Измеряйте precision и recall каждого класса отдельно: частая категория доставка может скрыть плохую работу на редких вопросах об оплате.
Проверки качества и границы метода
Проводите стресс-тест на орфографических ошибках, пустой строке, двух запросах в одном сообщении и отрицании «это не вопрос оплаты». Рассмотрите ручную модерацию входов с угрозами и персональными данными. Короткий max_tokens нужен лишь для компактной метки; если он окажется недостаточен для токенизации конкретных слов, тест выявит ошибку. При смене набора классов старые показатели качества нельзя сравнивать без ремарки, потому что задача классификации изменилась.
Оцените матрицу ошибок: сколько заявок о возврате оказалось в доставке и наоборот. Это важнее общей доли правильных меток, если разные категории обрабатываются с разной срочностью. Запрещайте автоматическое действие вроде возврата средств только на основании категории; классификация должна маршрутизировать заявку, а не выполнять финансовую операцию. Если выбор неверен, начните с пересмотра определений классов и качества разметки, затем тестируйте модель и формат запроса.
Критерии готовности
- Получена одна из трёх допустимых строк.
- На контрольной жалобе ожидается доставка.
- Неоднозначный текст вынесен на отдельный процесс.
Типичные ошибки и чего не делать
- Не использовать guided_choice в новой версии.
- Не путать допустимый формат с правильной классификацией.
- Не запускать денежные действия по одной метке.
Частые вопросы
Может ли модель вывести четвёртую метку?
Ограничение choice предназначено для заданных вариантов.
Что делать с двумя темами в сообщении?
Определить правило маршрутизации либо ручной разбор.
Достаточно ли одного примера?
Нет, нужен размеченный набор.
Официальные источники
Частые вопросы
Может ли модель вывести четвёртую метку?
Ограничение choice предназначено для заданных вариантов.
Что делать с двумя темами в сообщении?
Определить правило маршрутизации либо ручной разбор.
Достаточно ли одного примера?
Нет, нужен размеченный набор.
Читайте также
Как извлечь JSON по схеме в vLLM через response_format
Схема для извлечения артикула и количества из текста: разбираем ответ и проверяем значения против исходника.
Как обработать named tool call в vLLM без произвольного выполнения кода
Требуем вызов одной безопасной функции, валидируем аргументы и не отдаём модели право запускать произвольные команды.
Как найти очередь запросов vLLM по метрикам /metrics
Разделяем очередь и генерацию через метрики ожидающих запросов и времени ожидания; строим контрольный замер.
Комментарии
Пока тихо. Скажите первое слово