Головна / Статті / Loop engineering: як спроєктувати цикл агента, що знає, коли зупинитися

Loop engineering: як спроєктувати цикл агента, що знає, коли зупинитися

Як працює цикл ШІ-агента: від циклів «спостерігай — дій» і стану до умов зупинки, лімітів ретраїв, контролю витрат і метрик, плюс порівняння некерованого й керованого дизайну.

1513 слів

Довкола будь-якої ШІ-моделі є набір допоміжних частин, і одна з найважливіших серед них — цикл агента. Тут ми придивимося саме до нього і до того, як його спроєктувати, щоб агент поводився передбачувано, не розоряв і розумів, коли час закінчувати.

Від одного виклику до циклу

Звичайний чат-бот здебільшого йде одним прямим шляхом:

User → LLM → Response

В агента завдання складніше. Щоб завершити одну задачу, може знадобитися кілька кроків, і після кожного модель дивиться, що вийшло:

User
 ↓
Understand the task
 ↓
Decide what to do
 ↓
Use a tool
 ↓
Observe the result
 ↓
Decide what to do next
 ↓
Use another tool
 ↓
Evaluate the result
 ↓
Finish

Саме цим повторенням і займається loop engineering.

Цикл агента — це коло, в якому ШІ-агент раз у раз робить таке:

  1. Отримує інформацію.
  2. Обирає, що робити.
  3. Виконує дію.
  4. Дивиться на результат.
  5. Вирішує, чи потрібна ще одна дія.
  6. Зрештою зупиняється.

У спрощеному вигляді цикл виглядає так:

┌───────────┐
        │  Observe  │
        └─────┬─────┘
              ↓
        ┌───────────┐
        │   Decide  │
        └─────┬─────┘
              ↓
        ┌───────────┐
        │    Act    │
        └─────┬─────┘
              ↓
        ┌───────────┐
        │  Observe  │
        │   Result  │
        └─────┬─────┘
              ↓
         Finished?
          /     \
        No       Yes
        ↓         ↓
     Decide     Stop

Головне тут те, що один виклик моделі не мусить одразу видати фінальну відповідь. Агент може діяти, вчитися на тому, що повернулося, і продовжувати.

Невеликий приклад: погода в Бристолі

Припустімо, користувач питає: «Яка погода в Бристолі і чи брати парасольку?» Агент може впоратися за кілька ходів. Він отримує питання й розуміє, що потрібні поточні дані. Потім викликає погодний API, і той повертає ось що:

Temperature: 16°C
Condition: Heavy rain

Тепер агент має все потрібне й відповідає, що в Бристолі дощ, тож парасольку краще взяти. Навіть такий крихітний запит потребував більше ніж однієї операції.

Бувають і прості задачі. Питанню на кшталт «Скільки буде 15 × 20?» вистачає однієї операції. Запит важчий: «Знайди три британські університети з магістратурою з Data Science і порівняй вартість навчання та вимоги до вступу». Тут може знадобитися приблизно така послідовність:

Search University A
      ↓
Read information
      ↓
Search University B
      ↓
Read information
      ↓
Search University C
      ↓
Read information
      ↓
Compare results
      ↓
Generate answer

Жодна окрема відповідь мовної моделі надійно все це не покриє. Цикл дає агентові змогу розбити велику задачу на маленькі дії.

Агент як скінченний автомат

Ситуацію агента можна описати як стан. Нехай s_t — стан у момент t. На кожному такті агент отримує спостереження o_t, обирає дію a_t, і світ переходить у наступний стан:

У цьому виразі s_t — поточний стан, o_t — поточне спостереження, a_t — дія, f — функція переходу станів, а s_{t+1} — наступний стан. Вибір дії теж можна записати компактно:

Тут грецька літера пі позначає політику ухвалення рішень. В агенті на базі LLM модель є частиною цієї політики. Знімок стану може виглядати так:

State:
"We need the current weather."


Observation:
"Weather tool is available."
Action:
"Call weather(location='Bristol')"

А після відповіді інструмента:

New observation:
"16°C, heavy rain"


Next action:
"Generate final response"

Дивитися на агента так, як на систему, що змінює стан, корисніше, ніж вважати його чат-ботом із зайвими кроками.

Коли зупинитися

Мабуть, найважче питання в проєктуванні циклу — як агент розуміє, що закінчив. Уявіть агента, який застряг ось так:

Call search
 ↓
Get result
 ↓
Call search again
 ↓
Get result
 ↓
Call search again
 ↓
...

Без правила виходу це може тривати вічно. Тому продакшн-агентові потрібні умови завершення. Поширених кілька.

Перша — щасливий шлях, коли задачу виконано:

Task completed → STOP

Друга — бюджет кроків, наприклад максимум п'ять:

Maximum steps = 5

Якщо агент дійшов до п'яти кроків і не закінчив, він зупиняється:

STOP

Третя — повторювані збої інструмента, після яких прогін треба завершити або передати комусь іншому:

Tool failed repeatedly → STOP / ESCALATE

Четверта — ризикована дія, коли людина має схвалити її, перш ніж щось станеться:

High-risk action → STOP → Ask human

Вартість, затримка й надійність

Вважайте кожен крок чимось, що коштує грошей. Припустімо, ціна одного кроку така:

Тоді звичайний прогін із 10 кроків коштує приблизно стільки:

Баг, через який кроків стає 1000, різко змінює підсумок:

Для одного запиту це вже може бути неприємно.

Помножте на тисячі користувачів, і проблема очевидна. Тому loop engineering стосується вартості, затримки й надійності не менше, ніж функціональності.

Обробка збоїв

Реальні системи ламаються. Уявіть, що погодний виклик повернув ось це:

Error: API unavailable

Погано спроєктований агент просто падає. Кращий цикл реагує на помилку:

Tool call
   ↓
Error
   ↓
Retry?
 ┌─┴─┐
Yes  No
 ↓    ↓
Retry Escalate

Ретраям теж потрібні ліміти. Наприклад, після двох збоїв система може зупинитися, а не надсилати той самий приречений запит знову й знову.

Де трапляються цикли

Цикли агентів є в багатьох галузях. Ось п'ять типових.

Дослідження:

Search → Read → Compare → Search again → Summarise

Програмування:

Read code → Modify code → Run tests → Observe errors → Fix → Test again

Аналіз даних:

Inspect data → Run analysis → Observe result → Create visualisation → Explain

Підтримка клієнтів:

Understand issue → Search knowledge base → Check customer data → Respond

Керування комп'ютером:

Observe screen → Decide action → Click/type → Observe new screen → Continue

Спільна нитка проста: дій, дивись на результат, потім вирішуй, що далі.

Некеровані й керовані цикли

Порівняймо два варіанти. Перший дає моделі інструмент і відпускає її:

LLM
 ↓
Tool
 ↓
LLM
 ↓
Tool
 ↓
LLM
 ↓
Tool
 ↓
...

Тут ніщо нічого не контролює. Другий варіант додає контрольні точки довкола кожного кроку:

Task
 ↓
Observe
 ↓
Decide
 ↓
Validate action
 ↓
Execute
 ↓
Observe result
 ↓
Evaluate
 ↓
 ┌───────────────┐
 │ Goal complete?│
 └───────┬───────┘
      Yes│    No
         ↓      ↓
       Stop   Continue

Другий варіант запроваджує контроль, і в цьому суть loop engineering.

Як вимірювати цикл

Про успіх не можна судити лише з того, чи з'явилася зрештою відповідь. Ось кілька корисних метрик:

Ще варто відстежувати:

  • скільки триває задача (затримка)
  • скільки витрачено токенів
  • у що обходиться кожна завершена задача
  • як часто виклики повторюються
  • частку завершених задач
  • як часто доводиться втручатися людині

Разом ці показники кажуть, чи агент справді стає кращим.

Компроміс щодо кількості кроків

Додаткові кроки дають агентові змогу братися за складніші задачі. Але вони ж приносять зростання витрат, довше очікування, більше шансів помилитися, більше збоїв інструментів і менш передбачувану поведінку. Тож мета не в тому, щоб агент крутився якомога довше. Мета — виконати задачу за найменшу кількість кроків, за якої все ще працює надійно.

Що потрібно надійному циклу

Loop engineering — це проєктування й контроль повторюваного циклу виконання ШІ-агента. Базовий шаблон такий:

Він повторюється, доки задачу не виконано або система не вирішить зупинитися. Надійному агентові потрібні:

  • чітко визначені дії
  • ітерації, які хтось контролює
  • явні умови зупинки
  • обробка помилок
  • ліміти на ретраї
  • керований стан
  • обмеження на витрати
  • постійне оцінювання

Автономність не означає нескінченного виконання. Добрий агент знає не лише, що робити далі, а й коли зупинитися.

Сильна модель і продуманий цикл усе одно можуть помилитися, якщо агентові подають не ту інформацію. Звідси наступне питання: що агент має отримувати на кожному кроці? Відповідь лежить у царині context engineering, яка дбає про те, щоб агенти отримували потрібну інформацію в потрібний момент.