Simple Jev

· 4 мин чтения
text-classification llm-serving huggingface structured-output python
📂 Исходный код на GitHub

Turn any open model into a classifier/jev endpoint

Simple Jev

Simple Jev — проект от Featherless, который превращает любую совместимую open-модель с Hugging Face в classifier-эндпоинт без обучения отдельного classifier head. Вы отправляете общий контекст и набор вопросов, сервер читает next-token logits модели для каждого вопроса и сам собирает JSON-ответ с выборами, rubric-скорами или truth/support-суждениями. Модель ничего не генерирует построчно — ответ строится из скоров.

Демо, playground и документация доступны на simple-jev.featherless.ai. Текущая реализация работает локально на Hugging Face Transformers и PyTorch. Валидация запросов, версионированные prompt-инструкции и scoring ответов лежат в plain-Python каталоге common/, чтобы другие inference-реализации могли использовать те же правила.

Публичное демо API

Публичный demo API работает без логина, API key и аутентификации. Лимиты: контекст до 2k токенов, 2 запроса в секунду.

curl https://simple-jev-demo-api.featherless.ai/v1/models

Демо уже отдаёт Gemma как featherless-ai/gemma-4-26B-A4B-classifier:

curl https://simple-jev-demo-api.featherless.ai/v1/classifier \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON'
{
  "model": "featherless-ai/gemma-4-26B-A4B-classifier",
  "state": "Mia owns a red bicycle.",
  "questions": {
    "color": {
      "type": "choice",
      "instructions": "What color is Mia's bicycle?",
      "criteria": {"red": null, "blue": null}
    }
  }
}
JSON

Для production-развёртывания выше лимиты дают платные тарифы Featherless.

Запуск HF-сервера

Нужен Python 3.12+ (команды ниже используют 3.13):

git clone https://github.com/featherless-ai/simple-jev.git
cd simple-jev
python3.13 -m venv .venv
source .venv/bin/activate

python -m pip install -e './hf-server'

python hf-server/hf_server.py \
  --model Qwen/Qwen3.5-0.8B \
  --device cpu --dtype float32 \
  --max-model-len 4096 \
  --max-batch-size 4 --max-batch-tokens 4096

Вариант с Gemma 4 MoE на NVIDIA GPU с BF16:

python hf-server/hf_server.py \
  --model google/gemma-4-26B-A4B-it \
  --device cuda --dtype bfloat16 \
  --max-model-len 8192 \
  --max-batch-size 4 --max-batch-tokens 8192

Есть и backend Laya для Typed Decisions с нативным encoder:

python -m pip install -e './hf-server[laya]'
USE_TF=0 python hf-server/hf_server.py \
  --backend laya \
  --model convaiinnovations/laya \
  --subfolder typed-decisions \
  --device cpu \
  --rope-factor 2 --max-model-len 2048

Первый запуск скачивает модель, если её нет в кеше. В --model можно передать и локальную директорию. Для CUDA/ROCm сначала установите соответствующий build PyTorch. GPU-пример с Gemma 4 26B-A4B Instruct — пример запуска, а не verified benchmark: память нужна под веса, KV cache и inference-буферы; sparse активация экспертов не означает, что в памяти только активные эксперты. --device auto позволяет Transformers распределить веса по доступным устройствам.

Сервер слушает http://127.0.0.1:8000. После загрузки модели:

curl http://127.0.0.1:8000/health

Интерактивная документация API — на http://127.0.0.1:8000/docs. После установки команды simple-jev и python -m hf_server принимают те же аргументы, что и скрипт. Детали бэкенда Laya — в hf-server/README.md.

API

Отправляйте non-streaming POST /v1/classifier. Значение model должно точно совпадать с ID или путём, на котором запущен сервер. Ровно одно из двух полей:

  • state — строка, JSON-объект или JSON-массив с общим контекстом;
  • messages — текстовая chat-история, рендерится через собственный chat template модели.

/v1/systemone — алиас /v1/classifier, реализация одна. Контракт для клиентов — API reference. Пример запроса с тремя типами вопросов:

curl http://127.0.0.1:8000/v1/classifier \
  -H 'Content-Type: application/json' \
  --data-binary @- <<'JSON'
{
  "model": "Qwen/Qwen3.5-0.8B",
  "state": "Mia owns a red bicycle. Her dog is named Max.",
  "questions": {
    "color": {
      "type": "choice",
      "instructions": "What color is Mia's bicycle?",
      "criteria": {"red": null, "blue": null}
    },
    "support": {
      "type": "score",
      "instructions": "How well does the context support that Mia owns a bicycle?",
      "criteria": ["Unsupported", "Partially supported", "Fully supported"]
    },
    "dog": {
      "type": "noul",
      "instructions": "Is Mia's dog named Max?"
    }
  }
}
JSON

ID вопросов становятся ключами в answers. Типы вопросов:

Тип Входные criteria Результат
choice Объект с 2–50 candidate ID и опциональными описаниями Кандидат с наибольшей вероятностью, его confidence и распределение.
score Массив из 2–50 rubric-уровней, от низшего к высшему Нулевой индекс rubric, confidence, распределение и legend. Трёхуровневый rubric даёт значение от 0 до 2, включая дробные.
noul Опциональные описания true и/или false Truth/support-суждение от 0.01 до 0.99 из распределения модели по девяти rating-токенам.

Для chat-входа отправляйте messages вместо state — например, классификация обращения клиента с маршрутизацией в billing/technical и определением запроса на возврат. Неизвестные top-level поля запроса игнорируются (включая temperature, max_tokens, stream); неизвестные поля внутри questions и options отклоняются. Сэмплинга и стриминга нет. HF-сервер пока поддерживает только текст.

usage.input_tokens считает уникальные token-префиксы запроса, разделяя общий контекст между вопросами; usage.output_tokens всегда ноль — токены не генерируются. Для диагностики запускайте сервер с ENABLE_OPEN_JEV_ADVANCED_METRICS=1, а в запрос добавляйте "options": {"raw_logits": true}.

Зачем classifier и «System One»

Classifier отображает вход в заданный набор ответов: сообщение поддержки маршрутизируется в billing или technical, срочность оценивается по ordered rubric, запрос возврата — бинарное суждение. Результаты напрямую попадают в обычный application code.

TypeSafe называет «System One» модели для быстрых структурированных решений — по аналогии с быстрым интуитивным мышлением против медленного обдумывания (см. intro to System One and Jev). Simple Jev исследует такой интерфейс на существующих open-моделях, не воспроизводя архитектуру и обучение TypeSafe и не заявляя эквивалентных accuracy, calibration или скорости.

Как меняется использование модели:

  1. Общий prompt builder создаёт консистентные classifier-инструкции и по одной scoring-ветке на вопрос.
  2. HF-сервер рендерит инструкции и контекст в нативный chat-формат модели.
  3. Общий точный token-префикс вычисляется один раз, его KV cache переиспользуется для батчей question-суффиксов.
  4. Читаются next-token logits для допустимых answer-лейблов, общий scorer нормализует скоры и собирает JSON.

Так не нужно генерировать и парсить prose или JSON по токенам. Валидная структура ответа не гарантирует правильность решения — capability модели и формулировка вопроса тоже важны, качество ответов стоит оценивать отдельно.

Prefill-only scoring и общий префикс

Обычный text-generation состоит из prefill (обработка входа) и decode (генерация токенов). Prefill уже даёт logits следующего токена — Simple Jev использует их напрямую для скоринга заранее заданных лейблов, без авторегрессивного цикла.

Когда несколько вопросов относятся к одному контексту, большая часть промпта совпадает. После применения chat template и токенизации сервер находит точный общий token-префикс:

Shared instructions + context + shared question briefing
                           │
                     Prefill once
                     Save KV cache
                           │
         ┌─────────────────┼─────────────────┐
         ▼                 ▼                 ▼
  Color question    Support question    Dog question
         │                 │                 │
    Label logits      Label logits      Label logits
         └─────────────────┼─────────────────┘
                           ▼
                JSON built by the server

KV cache хранит attention-состояние общего префикса; каждый вопрос продолжает с копии кеша и своим суффиксом. Суффиксы батчируются, logits читаются по последнему реальному токену строки, выбранные лейбл-скоры уходят в общий scorer. Вопросы не используют ответы друг друга.

Пример: четыре промпта с общим префиксом в 1 000 токенов и суффиксом в 50:

Способ Обработано prompt-токенов, без padding
Каждый промпт отдельно 4 × (1,000 + 50) = 4,200
Переиспользование общего префикса 1,000 + 4 × 50 = 1,200

Это иллюстрация экономии на повторной обработке входа, а не измеренное latency-соотношение: каждый суффикс всё равно attends к закешированному префиксу, у копирования кешей и padding есть свои накладные расходы. --max-batch-size ограничивает вопросы в батче суффиксов, --max-batch-tokens — число padded suffix-токенов. Кеш переиспользуется внутри одного запроса, запросы обрабатываются последовательно. Подробности — в HF execution guide.

Структура проекта

Путь Назначение
common/ Plain-Python модули: ClassifierRequest, prompt planning, response scoring.
common/PROMPT_STRUCTURE_V1.md Языконезависимая v1-спецификация: входы, prompt-строки, chat-роли, answer-лейблы, правила scoring.
hf-server/hf_server.py Однофайловая Transformers-реализация: chat-рендеринг, загрузка модели, cached inference, HTTP API, CLI.
hf-server/API_REFERENCE.md Контракт request/response, валидация, диагностика, конфигурация.
RFDT/ Task-specific decision training: подготовка меток, distillation teacher-оценок, обучение на answer-token logits, экспорт student-модели.

prepare_prompt(request, version="v1") возвращает cacheable system-prompt prefix, prefix instruction, suffix instruction и упорядоченные вопросы. Версия фиксирует конфигурацию prompt/scoring для консистентности между реализациями, включая другие языки; по умолчанию v1, HTTP API сейчас использует только её.

Тесты

python -m pip install -e './hf-server[test]'
python -m pytest -c hf-server/pyproject.toml common/tests hf-server/tests -q

Тесты покрывают валидацию запросов, построение prompt, response scoring, tensor/token маппинг, HTTP-поведение и cached-versus-full inference на крошечных локально инициализированных моделях. Скачивание pretrained-весов не требуется, accuracy они не измеряют.

Модели должны иметь поддерживаемую реализацию Transformers, рабочий chat template, совместимые cache-операции, а answer-лейблы — продлевать rendered prompt ровно на один различимый токен. Сервер проверяет токенизацию лейблов; совместимость со всеми open-моделями не гарантируется.

RFDT: Really Fancy Decision Training

RFDT позволяет дообучить меньшую модель под конкретный use case: предоставьте контекст или chat-историю, вопросы и ответы — или дайте более крупной teacher-модели проставить недостающие ответы.

RFDT обучается напрямую на допустимых answer-token logits по той же prompt-структуры, что и inference Simple Jev. Скрипты поддерживают подготовку dataset, teacher labeling, multi-GPU training, LoRA-адаптеры, evaluation и экспорт в HF-сервер — см. RFDT guide and examples. Скрипты RFDT доступны в репозитории уже сейчас; поддержка hosted fine-tuned моделей и fine-tuning на платформе Featherless заявлена как предстоящий rollout.

Источник: https://github.com/featherless-ai/simple-jev