Наш агент перетворення тексту в запит скоротив час від 45 секунд на передових моделях до 2 секунд на GLM 5.3 Flash, зберігши ту саму точність при вартості в 20 разів меншій.
Більшість нашої нещодавньої роботи зі штучним інтелектом у Conversion була зосереджена на загальній маркетинговій аналітиці.
Команди з автоматизації маркетингу виконують широкий спектр завдань у різних системах: дослідження облікових записів, створення аудиторій, планування кампаній, написання контенту та робота з даними про ефективність. Ми створювали агентів, здатних аналізувати ці робочі процеси та використовувати ті самі інструменти, якими користується досвідчений маркетолог.
Ці системи виграють від використання потужних моделей загального призначення. Робота є відкритою, і часто правильне судження важливіше за швидке виконання завдання.
Але у нас також був накопичений список менших, більш спеціалізованих функцій ШІ. Однією з них були фільтри природною мовою: дозволити користувачеві описати аудиторію звичайною англійською мовою та перетворити цей опис на фільтр, який можна переглянути та відредагувати в існуючому конструкторі операторів Conversion. (У Conversion фільтр називається оператором.)
Спочатку це здавалося простим завданням структурованої генерації. Дати моделі доступні поля, описати формат виведення та попросити її створити JSON. Виявилося, що це значно складніше.

Складений оператор, згенерований менш ніж за 5 секунд за допомогою GLM 5.3 Flash.
Візьмемо наступний приклад:
Знайти контакти, які хоча б раз за останні 30 днів надіслали демо-форму та працюють у компанії-розробнику програмного забезпечення з відкритою можливістю на суму понад 50 000 доларів США.
Це вимагає від системи:
- Знайти конкретну форму, яку має на увазі користувач під "демо-формою"
- Визначити, яке поле представляє галузь компанії
- Дізнатися, як у цьому робочому просторі представлено "програмне забезпечення", що означає перегляд фактичних значень, збережених у цьому полі, а не припущення
- Перейти від контакту до його компанії, а потім до можливостей цієї компанії
- Переконатися, що "відкрита" та "понад 50 000 доларів США" стосуються однієї й тієї ж можливості
- Застосувати відносне вікно події
Також потрібно було зробити все це достатньо швидко, щоб це відчувалося як інтерфейс фільтра, а не як дослідницький агент.
Те, що виглядало як невелике завдання з інженерії запитів, перетворилося на обмежену проблему перетворення тексту в запит. Її вирішення вимагало агента, що використовує інструменти, проміжного представлення (IR), детермінованого компілятора та семантичного бенчмарку.
Ми прогнали вісім моделей через отриманий бенчмарк, Statement Bench, включаючи Claude Opus 5, Kimi K3, GLM 5.3 Flash та випущений сьогодні вранці Gemini 3.8 Flash. Результати наведені нижче.
Надання агенту інструментів
Більшість інформації, необхідної для відповіді на запит вище, є специфічною для середовища клієнта. Один робочий простір може містити сотні мільйонів історичних значень полів, а також його активи та об'єкти. З очевидних причин ми не могли помістити все це в один запит.
Нашим першим корисним архітектурним рішенням було припинити розглядати проблему як звичайну структуровану генерацію. Натомість модель отримує невеликий набір інструментів. Вона може шукати поля, перевіряти історичні значення та знаходити бізнес-специфічні активи, такі як форми, кампанії, електронні листи та аудиторії. Вона використовує ці інструменти лише тоді, коли цього вимагає запит.
Значна частина цієї інфраструктури пошуку походить від нашої нещодавньої роботи над Global Search, яка забезпечує текстовий та семантичний пошук по всіх записах у Conversion. Незабаром ми плануємо поділитися більш детальною інформацією про це!
Базовий потік виглядає так:
1Запит природною мовою2 |3 v4 Агент, що використовує інструменти <-----------------+5 / | \ |6поля активи зв'язки | відхилення з поясненнями7 \ | / |8 v |9 Обмежене IR |10 | |11 v |12 Валідатор і компілятор ---------------------------------+13 |14 v15 Продукційний оператор
Це дозволяє зберегти початковий контекст невеликим. Це також робить помилки набагато легшими для розуміння. Якщо оператор неправильний, ми можемо визначити, чи агент знайшов неправильний актив, вибрав неправильне поле, неправильно зрозумів зв'язок, неправильно представив правильну ідею або виявив помилку в компіляторі. Це розмежування пізніше стало важливим для нашого циклу оцінювання.
Створення меншої мови
Використання інструментів вирішило проблему контексту. Воно не вирішило проблему затримки.
Один з уроків з раннього зворотного зв'язку: користувачі терплять набагато меншу затримку в спеціалізованому інтерфейсі, ніж у чаті.
Це вказує на ширший парадокс. Ми встановлюємо очікування щодо затримки на основі того, наскільки складним здається завдання нам, а не наскільки воно складне для системи. Написання контенту здається складним, тому що ми бачимо роботу. Опис фільтра здається простим, тому що наш розум мовчки розпізнає контекст, сутності, зв'язки та наміри. Для моделі реконструкція цих прихованих припущень і є завданням. Чим менше роботи сприймає користувач, тим менше часу він дає системі на її виконання.
На основі раннього зворотного зв'язку ми поставили дві цілі: точність понад 95 відсотків і час відповіді близько 5 секунд для типових запитів.
Conversion має виразну внутрішню мову запитів. У наших ранніх тестах, використовуючи безпосередньо продукційний формат, лише найбільші моделі, такі як Claude Opus, могли надійно його генерувати. Навіть прості оператори займали близько 45 секунд.
Візуальний конструктор операторів відображає лише підмножину повної мови. Ми створили менше, зручне для агента проміжне представлення для цієї підмножини. Менші моделі могли створювати його, використовуючи менше токенів, тоді як детермінований компілятор обробляв повний продукційний формат.
Розглянемо оператор:
Назва посади містить "Директор".
Оригінальний продукційний оператор виглядає так:
1{2 "type": "LOGICAL",3 "version": 1,4 "logical": {5 "operator": "OR",6 "operands": [7 {8 "type": "LOGICAL",9 "version": 1,10 "logical": {11 "operator": "AND",12 "operands": [13 {14 "type": "VARIABLE",15 "version": 1,16 "variable": {17 "variableSchemaId": "550e8400-e29b-41d4-a716-446655440000",18 "where": {19 "type": "LOGICAL",20 "version": 1,21 "logical": {22 "operator": "AND",23 "operands": [24 {25 "type": "LOGICAL",26 "version": 1,27 "logical": {28 "operator": "CONTAINS",29 "operands": [30 {31 "type": "ATTRIBUTE",32 "version": 1,33 "attribute": {34 "name": "value"35 }36 },37 {38 "type": "CONSTANT",39 "version": 1,40 "constant": {41 "value": "Director"42 }43 }44 ]45 }46 }47 ]48 }49 }50 }51 }52 ]53 }54 }55 ]56 }57}
Представлення того самого фільтра для моделі виглядає так:
1{2 "field": "550e8400-e29b-41d4-a716-446655440000",3 "op": "contains",4 "value": "Director"5}
IR вже пройшло через кілька поколінь, і останнє було сформовано спостереженням за тим, як малі моделі зазнають невдач на попередніх. Одним із значних покращень стало впровадження кращої семантики того самого запису (те, що перевірка схеми не може виявити):
1{2 "related": "OPPORTUNITY",3 "all": [4 { "field": "<uuid стадії>", "op": "equals", "value": "Closed Won" },5 { "field": "<uuid суми>", "op": "gt", "value": 100000 }6 ]7}
Цей поділ між моделлю та кодом дав нам кілька корисних властивостей:
- Непідтримувані оператори важко виразити
- Семантика зв'язків того самого запису є видимою
- Посилання на поля та зв'язки можна перевірити
- Компілятор можна тестувати незалежно від моделі
- Згенеровані оператори залишаються редагованими в існуючому інтерфейсі користувача
Зрештою, IR зменшує роботу моделі: агент визначає намір користувача та створює обмежений план; код обробляє продукційний формат.
Створення семантичного бенчмарку
Вивід може бути повністю валідним і все одно неправильним. Візьмемо цей запит:
Контакти в компаніях з виграною можливістю на суму понад 100 000 доларів США.
Контакт належить до компанії, а компанія може мати багато можливостей. Відповідність цьому фільтру означає проходження по зв'язках (контакт до компанії, компанія до можливостей) та перевірку двох умов по дорозі: угода виграна, а сума угоди перевищує 100 000 доларів США.
Складність полягає в тому, що ці умови повинні виконуватися для однієї й тієї ж можливості. Якщо їх перевіряти незалежно, компанія з виграною угодою на 20 000 доларів США та відкритою угодою на 150 000 доларів США задовольняє обидві: одна умова відповідає кожній. Перевірка схеми ніколи цього не виявить.
Як тільки кілька таких прикладів пройшли, редагування запиту ризикувало викликати регресію. Нам потрібен був спосіб перевіряти значення, а не лише валідність, і перевіряти його щоразу, коли щось змінювалося.
Ми побудували Statement Bench навколо поведінки продукту, отриманої з анонімізованих шаблонів аудиторій, які наші клієнти раніше створювали. Набір зараз містить 100 випадків у п'ятнадцяти категоріях, таких як прості умови полів, події, відносні та календарні часові вікна, зв'язки та складені запити.
Кожен випадок запускається в реалістичному пісочниці робочого простору. Агент отримує ті самі дані та інструменти, що й у продакшені.
Оцінювач перевіряє кілька рівнів:
- Чи повернув агент оператор?
- Чи задовольняє IR свою схему?
- Чи існують посилання на поля та зв'язки?
- Чи може оператор скомпілюватися та пройти продукційну валідацію?
- Чи представляє він запитане значення?
- Скільки кроків моделі, викликів інструментів, токенів та відхилених подань він вимагав?
П'ятий є найцікавішим, оскільки валідність не гарантує семантичної еквівалентності.
Семантичні перевірки читають скомпільований оператор, стверджуючи такі речі, як "одна умова можливості, що містить як стадію, так і суму", "подія електронної пошти, тип якої є кліком, а не відкриттям", або "умова вебінару, а не умова спеціальної кампанії".
Запуск циклу оптимізації на основі оцінювання
Бенчмарк змінив те, як ми могли продовжувати працювати над функцією. Замість того, щоб просити кодувального агента "покращити запит" або "впровадити нове IR", ми могли дати йому виконуване визначення покращення.
Цикл виглядав так:
- Запустити бенчмарк
- Згрупувати невдачі за їх основною причиною
- Перевірити траєкторію інструментів агента та подане IR
- Змінити запит, інструменти, валідатори або компілятор
- Запустити повний бенчмарк знову
- Зберегти зміну лише якщо вона покращує систему без внесення регресій
Кодувальні агенти могли використовувати бенчмарк для порівняння моделей, експериментів з IR, покращення описів інструментів та автономного вдосконалення запиту. Запуск повного набору після кожної зміни також запобігав перенавчанню на окремих невдачах, і ми залишили ще 50 випадків для підтвердження цього.
Кілька змін дали найкращі результати:
- Перенести шляхи, типи та структуру в компілятор. Наше перше IR змушувало модель виписувати всі зв'язки явно: контакт до компанії, компанія до можливості. Метадані поля вже мають на увазі цей шлях, тому компілятор тепер виводить його. Ми зробили те саме для дат, приведення типів, розміщення заперечень та вкладеності груп. Перенесення правил у компілятор спростило IR та зменшило кількість помилок схеми.
- Відхиляти з поясненнями та виправленнями. Кожне відхилення схеми та компілятора говорить, що написати замість цього (коли це можливо): "gt не можна заперечувати для цього поля; використовуйте lte", "скопіюйте id з campaign_list". Малі моделі сходяться за одну-дві спроби, а продукційна модель відхиляється на кілька запитів на сотню.
- Структурувати запит для малих моделей. Реорганізація запиту не змінила точність, але вдвічі зменшила кількість повторних спроб, що безпосередньо покращило затримку. Це було натхненно Найкращими практиками створення запитів від Anthropic.
- Використовувати приклади замість прози. Два додаткові приклади в нашому довіднику форматів вирішили клас пропусків, яких не виправили абзаци пояснень, скоротивши відхилені подання приблизно вдвічі.
- Надавати повний контекст або жодного. Моделі тягнуться до того, що є в контексті, перш ніж викликати інструмент. Коли контекст містив неповний або непозначений набір полів, модель використовувала найближче, а не шукала, створюючи семантично неправильні оператори. Зменшивши частковий контекст на користь викликів інструментів, ми збільшили швидкість створення та скоротили вхідні токени на п'яту частину.
Остаточна продукційна конфігурація, GLM 5.3 Flash, завершила всі 100 випадків бенчмарку з медіанною затримкою 2,3 секунди та 95-м перцентилем 7,1 секунди. Крім того, 97 зі 100 були семантично правильними. Порівняно з оригінальним підходом продукційного формату, прості фільтри перейшли з приблизно 45 секунд до трохи більше однієї секунди при вартості в 20 разів меншій.
Порівняння моделей на Statement Bench
Бенчмарк також дав нам спосіб порівнювати моделі на реальному завданні.
2 вересня 2026 року ми запустили ті самі 100 випадків на восьми моделях. Кожна модель отримала однаковий запит, інструменти, IR, компілятор та 30-секундний тайм-аут запиту.
Маршрутизація провайдера, кешування запитів та тимчасове навантаження на висновки впливають на затримку.
Модель
Валідні збірки
Семантично правильні
P50 затримка
P95 затримка
Читання кешу
Виклики інструментів
Відхилені подання
Орієнтовна вартість на 1 000 запитів
Claude Opus 5
100/100 (100%)
100/100 (100%)
3.16s
8.53s
91.1%
162
0
$27.51
GLM 5.2
100/100 (100%)
100/100 (100%)
4.38s
13.02s
93.5%
201
5
$14.94
Kimi K3
100/100 (100%)
100/100 (100%)
5.17s
11.84s
34.3%
157
0
$48.51
GLM 5.3 Flash
100/100 (100%)
97/100 (97%)
2.34s
7.07s
92.8%
163
2
$1.33
DeepSeek V4 Pro
96/100 (96%)
96/96 (100%)
5.53s
24.31s
47.8%
172
1
$12.00
Gemini 3.7 Flash
77/100 (77%)
77/77 (100%)
15.14s
30.01s
26.5%
228
1
$18.24
Gemini 3.8 Flash
76/100 (76%)
76/76 (100%)
14.29s
30.01s
35.4%
266
1
$27.44
DeepSeek V4 Flash
56/100 (56%)
55/56 (98%)
6.79s
30.00s
41.5%
100
1
$0.56
Орієнтовні витрати розраховані на 1 000 спроб запитів з використанням спостережуваних вхідних, кешованих вхідних та вихідних токенів за опублікованими непромоційними тарифами кожного провайдера станом на 2 вересня 2026 року. Кешований вхідний трафік тарифікується за опублікованою ставкою читання кешу, якщо провайдер публікує таку, а в іншому випадку за повною вхідною ставкою.

Рисунок 1. Правильність проти вартості. GLM 5.3 Flash досягає 97 відсотків приблизно за одну двадцяту вартості Claude Opus 5.

Рисунок 2. Розподіл затримки, медіана та 95-й перцентиль, впорядковані за P95.
Кілька висновків виділилися.
Ні розмір моделі, ні ціна не передбачали затримку. Найшвидша модель була найменшою та найдешевшою. Друга за швидкістю була найбільшою та найдорожчою.
Невдача перемістилася з неправильних відповідей на повільні відповіді. Шість із восьми моделей були семантично правильними для кожного оператора, який вони завершили; відмінності між ними майже повністю полягають у тому, скільки запитів завершилося в межах тайм-ауту. На ранніх ітераціях IR та запитів більшість менших моделей провалювали бенчмарк на етапі збірки з семантичною точністю <50%.
Токени міркувань переважають виклики інструментів. Gemini 3.8 Flash витратив 180 000 зі своїх 192 000 вихідних токенів на міркування та зробив 266 викликів інструментів; Claude Opus 5 витратив 813 токенів на міркування, зробив 162 і завершив кожен випадок. Наші зусилля Global Search скоротили кожен пошук інструменту до діапазону мілісекунд, тому решта витрат — це хід моделі між ними.
Висновок
Моделі добре розв'язують неоднозначність, код добре забезпечує точність, і більшість наших ранніх невдач були спричинені тим, що ми просили модель робити і те, й інше. Створення цього агента було роботою з визначення того, яка з двох частин має володіти кожною частиною. Ми очікуємо, що те саме справедливо для text-to-SQL та більшості інших інтерфейсів природною мовою.
Якщо вас цікавлять будь-які з цих проблем, зв'яжіться з нами! Ми наймаємо.





