Коротка відповідь. Jev – це нова модель від TypeSafe AI, яка не генерує текст взагалі. Ти даєш їй стан (текст або JSON) і типізовані запитання, а вона повертає рішення: вибір зі списку, оцінку за шкалою або ймовірність «так/ні» – з каліброваною впевненістю і за 70–500 мс. Фактично це «if/else на стероїдах» для випадків, коли умова написана природною мовою. Це не заміна LLM і тим паче не заміна бізнес-логіки – це окремий, вужчий інструмент. Розбираємось, коли він доречний, а коли це просто дорогий класифікатор.
Новий if/else
Кожен із нас колись писав щось таке:
if (message.toLowerCase().includes('термінов')) {
return 'high_priority';
}І воно навіть працювало. Рівно до моменту, коли клієнт написав «та не горить, але бажано швидше», і твій includes() відправив його в чергу з пожежами. Або навпаки: «У МЕНЕ ВСЕ ЗЛАМАЛОСЬ І НІЧОГО НЕ ПРАЦЮЄ!!!» без жодного ключового слова спокійно осів у стандартній черзі на три дні.
П'ятнадцятого вересня 2026 року компанія TypeSafe AI вийшла зі стелсу з моделлю Jev і сміливою заявкою: спеціальна модель, яка нічого не пише, а лише приймає рішення. Запуск зібрав тред на ~1800 поінтів на Hacker News, інтеграції з'явились у Vercel AI SDK і LangChain, а компанію заснував Diogo Almeida – колишній дослідник OpenAI і один зі співавторів RLHF.
Іронія ситуації прекрасна: десятиліттями ми писали умови руками. Потім навчили величезні моделі писати умови за нас. А тепер з'явилась окрема модель, робота якої – вирішувати, в яку гілку if/else заходити. Коло замкнулося. Питання лише одне: навіщо це, якщо if/else безкоштовний?
Що таке Jev насправді
TypeSafe називає Jev «першою System One моделлю» – відсилка до Канемана з його швидкою інтуїтивною «системою 1» і повільною аналітичною «системою 2». Якщо звичайні LLM – це «система 2», яка розмірковує токен за токеном, то Jev – «система 1»: миттєва відповідь без внутрішнього монологу.
Технічно за цим стоять три речі, які компанія описує в анонсі:
- Неавторегресивна генерація. Звичайна LLM передбачає наступний токен, потім наступний, і так сотні разів. Jev видає всі відповіді за один прохід, паралельно. Звідси і швидкість: TypeSafe заявляє 70–500 мс end-to-end.
- Жодного тексту. Модель фізично не вміє генерувати рядки. На виході – лише типізовані структури з наперед заданої схеми.
- RLCD (Reinforcement Learning for Calibrated Decisions) – метод тренування, оптимізований не під «сподобатись людині», а під чесні, калібровані ймовірності. Тобто коли модель каже «впевненість 0.9», це має статистично означати ~90% влучань.
Три типи рішень
За офіційною документацією, запити до Jev складаються зі стану і набору запитань трьох типів. Усі запитання оцінюються паралельно й ізольовано за один виклик:
- Choice – «обери варіант зі списку». Повертає
choice, розподілprobabilitiesіconfidence. Класика: «який відділ має обробити цей тикет?». Обмеження: до 255 варіантів. - Score – «оціни стан за рубрикою». Повертає
score, розподіл іconfidence. Наприклад: «наскільки токсичний цей коментар за шкалою 1–5?». - Noul – «чи істинне це твердження?». Повертає одне число від 0 до 1 – ймовірність «так». Окремого поля confidence немає: у бінарного розподілу саме це число і є повним описом упевненості.
Зверни увагу, чого тут немає: генерації відповіді клієнту, реферування, «поясни свій хід думок». Jev не розмовляє. Якщо тобі потрібен текст – це до звичайних LLM, і про це чесно пише сам вендор: модель «повністю відмовляється від генерації рядків».
Jev + TypeScript: запускаємо свій перший AI-powered if/else за 10 хвилин
Теорія теорією, але руки сверблять. Нижче – повний шлях від порожньої папки до працюючого прикладу. Обидва сніпети скомпільовані проти реального SDK версії 0.6.0 у strict-режимі TypeScript; живий виклик API я не виконував (для нього потрібен власний ключ), тож приклади виводу нижче позначені як ілюстративні.
Крок 1 – ключ і залізне правило
Реєструйся на console.typesafe.ai і створи API key. Далі правило, яке не обговорюється: ключ живе лише в змінних оточення на сервері. Не в коді, не в git, не в React-компоненті. Створи файл .env і одразу додай його в .gitignore:
echo 'TYPESAFE_API_KEY=твій-ключ-сюди' > .env
echo '.env' >> .gitignoreКрок 2 – порожній проєкт за хвилину
Потрібен Node.js 20+. Далі:
mkdir jev-typescript-demo
cd jev-typescript-demo
npm init -y
npm pkg set type=module
npm install @typesafe-ai/sdk
npm install -D typescript tsx @types/nodeРядок npm pkg set type=module – не косметика: без нього TypeScript зустріне тебе помилкою TS1309 про top-level await. Я на це наступив, поки готував приклад, тож ти вже не мусиш.
Мінімальний tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"noEmit": true,
"types": ["node"]
}
}Крок 3 – перший AI if/else
Створи first.ts. Задача максимально життєва: визначити, чи повідомлення термінове.
import { noul, TypeSafeClient } from '@typesafe-ai/sdk';
const client = new TypeSafeClient(); // ключ бере з process.env.TYPESAFE_API_KEY
const message = process.argv[2] ?? 'Та не горить, але бажано швидше.';
const { answers, usage } = await client.systemOne({
state: message,
questions: {
isUrgent: noul('Чи потребує це повідомлення термінової реакції?', {
true: 'Щось зламалось, хтось втрачає гроші або доступ прямо зараз',
false: 'Питання може почекати стандартної черги',
}),
},
});
const probability = answers.isUrgent.noul; // number від 0 до 1
if (probability > 0.7) {
console.log(`🔥 Терміново (${(probability * 100).toFixed(0)}%) – будимо чергового`);
} else if (probability > 0.4) {
console.log(`🤔 Незрозуміло (${(probability * 100).toFixed(0)}%) – хай гляне людина`);
} else {
console.log(`😴 Не горить (${(probability * 100).toFixed(0)}%) – у звичайну чергу`);
}
console.log(`Витрачено токенів: ${usage.input_tokens} (вихідні – безкоштовні)`);Запуск:
npx tsx first.ts "У нас упав прод і клієнти дзвонять!"Що повертає модель: об'єкт answers, де кожен ключ відповідає твоєму запитанню. Для Noul це одне число noul від 0 до 1 – одночасно і відповідь, і впевненість (у бінарного розподілу інших ступенів свободи просто немає). Плюс usage із витраченими токенами. Вивід виглядатиме приблизно так (ілюстративно – без ключа реальний запуск повертає 401, що я особисто перевірив):
🔥 Терміново (91%) – будимо чергового
Витрачено токенів: 43 (вихідні – безкоштовні)Вітаю: твій if/else тепер має власний API key. Залишилося додати йому Kubernetes.
Крок 4 – додаємо відділ: Choice і Noul разом
Одне запитання – це розминка. Сила systemOne у тому, що всі запитання оцінюються паралельно за один виклик. Створи triage.ts:
import { choice, noul, TypeSafeClient } from '@typesafe-ai/sdk';
const client = new TypeSafeClient();
async function triage(message: string) {
const { answers } = await client.systemOne({
state: message,
questions: {
department: choice('Який відділ має обробити це звернення?', {
billing: 'Оплати, підписки, рахунки, повернення коштів',
technical: 'Помилки, збої, щось не працює',
account: 'Доступ, email, паролі, налаштування профілю',
other: null,
}),
isUrgent: noul('Чи потребує звернення термінової реакції?'),
},
});
// TypeScript сам знає, що department.choice – це
// 'billing' | 'technical' | 'account' | 'other'. Спробуй одрукуватись
// у switch нижче – компілятор упіймає.
const department = answers.department;
const urgent = answers.isUrgent.noul > 0.7;
const needsHuman = department.confidence < 0.6;
if (needsHuman) {
return { queue: 'human-review', urgent } as const;
}
switch (department.choice) {
case 'billing':
return { queue: 'billing', urgent } as const;
case 'technical':
return { queue: urgent ? 'oncall' : 'technical', urgent } as const;
case 'account':
return { queue: 'account', urgent } as const;
case 'other':
return { queue: 'triage-inbox', urgent } as const;
}
}
console.log(await triage('Не можу зайти в акаунт, а через годину демо клієнту!'));npx tsx triage.tsНайприємніша частина тут – типи. SDK використовує const generics: ключі, які ти передав у choice(), стають літеральним union-типом відповіді. answers.department.choice – це не string, а рівно 'billing' | 'technical' | 'account' | 'other', тому switch вище – вичерпний, і одруківка в назві гілки не переживе компіляцію. У Choice, на відміну від Noul, є окреме поле confidence і повний розподіл probabilities по всіх варіантах – саме на confidence ми вішаємо рішення «віддати людині».
Це іграшкова версія того, що в наступному розділі виросте в production-приклад із fallback-ами й обробкою помилок – не повторюватимусь, там усе є.
Крок 5 – типові граблі
- Забутий ключ. Без
TYPESAFE_API_KEYперший же виклик впаде зAuthenticationError(401). SDK кидає типізовані помилки –APIError,RateLimitError,APITimeoutError– лови їх, а не загадковийunknown. - Ключ у браузері. Спроба створити
TypeSafeClientу React-компоненті на клієнті – і SDK відмовиться працювати: у конфігу є прапорецьdangerouslyAllowBrowser, який за замовчуваннямfalse, і назва в нього така не випадково. Правильна схема для Next.js: фронт шле текст на свій Route Handler (app/api/triage/route.ts) або викликає Server Action, а ключ живе тільки на сервері. Для чистого React – той самий принцип із будь-яким бекендом. - Відсутність обробки помилок. Дефолтний таймаут – 10 секунд, ретраїв – 2. Зовнішній сервіс у критичному шляху без try/catch і плану Б – це інцидент, який просто ще не стався.
- Пороги «зі стелі». 0.5 усюди – майже завжди неправильно. Поріг залежить від ціни помилки в конкретній гілці: про це детально в розділі про production нижче.
- Сліпа довіра. Типізована відповідь – не означає правильна. Але про це вже вся друга половина статті.
Крок 6 – міні-челендж
Домашка на 15 хвилин, щоб помацати модель руками:
- Додай у
triage.tsкатегоріюspamз описом на кшталт «реклама, фішинг, нерелевантні розсилки». - Прожени три повідомлення і подивись не лише на
choice, а й на весь розподілprobabilities:- «Вітаємо! Ви виграли мільйон, перейдіть за посиланням» – очікувано spam?
- «Після оновлення застосунок вилітає на старті» – technical, але наскільки термінове?
- «ТЕРМІНОВО!!! забув пароль» – капс кричить, а чи кричить ймовірність?
- Посунь поріг
isUrgentз 0.7 до 0.4, потім до 0.85 – і подивись, як ті самі повідомлення мігрують між гілками.
Реальні відповіді моделі наводити не буду – у мене немає твого ключа, а вигадувати цифри в статті про калібровані ймовірності було б особливо іронічно. Проганяй – і побачиш свої.
Спробуй сам: твій if/else тепер із AI
Читати про різницю між правилами і моделлю – одне, а потикати її пальцем – інше. Нижче – інтерактивне демо: чотири готові повідомлення клієнтів і два підходи поруч. Лівий стовпчик – справжній детермінований класифікатор на ключових словах, який виконується прямо в твоєму браузері. Правий – наперед підготовлені результати в стилі Jev для тих самих повідомлень (реальний API зі статті не викликається – і чому саме, демо чесно пояснює).
Особливо звертай увагу на четвертий сценарій: там ключові слова сідають у калюжу найцікавішим способом.