Как моделировать экономику агентов с ограниченными бюджетами на API вызовы?

Краткий тезис

В RAG|agentic RAG агенты часто вызывают API|внешние API (LLM, поиск, базы данных), каждый из которых потребляет ресурсы (токены, деньги, время). Для эффективного использования вводят бюджет – лимит на количество вызовов или токенов за период. Моделирование экономики агентов сводится к задаче оптимального распределения ограниченного бюджета между API-вызовами, максимизируя суммарную полезность (качество ответов). Используются методы задачи о рюкзаке (knapsack) для статического планирования и обучение с подкреплением (bandit-алгоритмы) для динамической адаптации. В многопользовательской среде добавляются аукционы для конкуренции за общий бюджет.


1. Термин: Экономика агентов (Agent Economics)

Экономика агентов – это подход, при котором каждый агент (LLM-агент, выполняющий задачи) рассматривается как рациональный субъект, стремящийся максимизировать свою полезность (utility) при ограниченных ресурсах. В контексте API-вызовов ресурсами являются:

  • Токены (входные/выходные токены LLM)
  • Деньги (стоимость каждого вызова)
  • Время (latency, количество вызовов в секунду)
  • Квоты (максимум вызовов в день/час)

Бюджет – это количественное ограничение на потребление ресурсов за определённый период (например, 100 000 токенов в день). Агент должен решить, какие API вызывать, в каком порядке и с какой частотой, чтобы не превысить бюджет и при этом получить наилучший результат.

Полезность (utility) – метрика, отражающая, насколько call|вызов API приближает агента к цели. Например, для RAG-агента полезность вызова поискового API может измеряться релевантностью найденных документов, а вызова LLM – качеством сгенерированного ответа.


2. Базовая модель: Задача о рюкзаке (Knapsack)

Простейшая статическая модель – задача о рюкзаке. У агента есть набор потенциальных API-вызовов, каждый с известной стоимостью (cost) и ожидаемой полезностью (utility). Бюджет B – максимальная суммарная стоимость. Нужно выбрать подмножество вызовов, максимизирующее суммарную полезность, не превышая B.

Формально:

  • Пусть есть N возможных вызовов, каждый i имеет стоимость c_i и полезность u_i.
  • Цель: выбрать бинарные переменные x_i ∈ {0,1} так, чтобы ∑ x_i * c_i ≤ B, максимизируя ∑ x_i * u_i.

Пример:

APIСтоимость (токены)Полезность (0-1)
Поиск документов5000.8
LLM генерация20000.9
Проверка фактов3000.5
Извлечение сущностей4000.6

Бюджет B = 2500 токенов. Оптимальный выбор: Поиск + LLM генерация (500+2000=2500, полезность 0.8+0.9=1.7). Альтернатива: Поиск + Проверка + Извлечение (500+300+400=1200, полезность 1.9) – но это дешевле, но полезность выше? На самом деле нужно считать суммарную полезность, но здесь она выше (1.9 > 1.7). Однако если полезности не аддитивны (например, LLM генерация даёт ответ, а проверка фактов его улучшает), то модель усложняется.

Ограничения:

  • Полезность часто неизвестна заранее (зависит от контекста).
  • Вызовы могут быть взаимозависимы (результат одного влияет на полезность другого).
  • Бюджет может быть динамическим (пополняется со временем).

Поэтому на практике используют онлайн-обучение.


3. Online Learning: Bandit-алгоритмы

Агент не знает точную стоимость и полезность каждого API заранее. Он учится в процессе, делая вызовы и наблюдая результаты. Это задача многорукого бандита (multi-armed bandit).

Основные подходы:

  • ε-greedy: с вероятностью ε выбирать случайный API (exploration), иначе – API с максимальной оценённой полезностью (exploitation). Оценки полезности обновляются после каждого вызова (например, среднее арифметическое полученных полезностей).
  • Upper Confidence Bound (UCB): выбирает API с максимальным значением оценка + константа * sqrt(log(t) / n_i), где t – общее число вызовов, n_i – число вызовов i-го API. Это балансирует exploration и exploitation.
  • Thompson Sampling: использует байесовское обновление априорного распределения полезности и выбирает API пропорционально вероятности быть оптимальным.

Пример реализации ε-greedy:

import random

class BudgetedBandit:
    def __init__(self, apis, budget, epsilon=0.1):
        self.apis = apis          # список API с их стоимостями
        self.budget = budget
        self.epsilon = epsilon
        self.counts = {api: 0 for api in apis}
        self.utilities = {api: 0.0 for api in apis}
        self.total_cost = 0

    def choose_api(self):
        if random.random() < self.epsilon:
            return random.choice(self.apis)
        else:
            # выбираем API с максимальной средней полезностью, который влезает в бюджет
            feasible = [api for api in self.apis if self.total_cost + api.cost <= self.budget]
            if not feasible:
                return None
            return max(feasible, key=lambda api: self.utilities[api] / (self.counts[api] + 1e-6))

    def update(self, api, observed_utility):
        self.counts[api] += 1
        n = self.counts[api]
        self.utilities[api] = (self.utilities[api] * (n-1) + observed_utility) / n
        self.total_cost += api.cost

Проблема: стоимость тоже может быть неопределённой (например, LLM может вернуть разное количество токенов). Тогда нужно оценивать и стоимость, и полезность – двумерный бандит.


4. Конкуренция: Аукционы за общий бюджет

В многопользовательской системе несколько агентов делят общий бюджет (например, пул токенов организации). Возникает конкуренция: каждый агент хочет максимизировать свою полезность, но бюджет ограничен. Решение – аукцион (auction).

Типы аукционов:

  • Аукцион первой цены (first-price): каждый агент подаёт заявку (bid) – сколько токенов он готов заплатить за вызов. Побеждает тот, кто предложил больше, и платит свою ставку.
  • Аукцион второй цены (Vickrey): победитель платит вторую по величине ставку. Стимулирует правдивые заявки.
  • Аукцион с распределением пропорционально ставкам: каждый агент получает долю бюджета, пропорциональную его ставке.

Пример аукциона Vickrey:

Пусть два агента хотят вызвать один и тот же API стоимостью 100 токенов. Агент A оценивает полезность в 200 токенов, агент B – в 150. Они подают ставки: A – 200, B – 150. Побеждает A, платит 150 (вторая ставка). Бюджет списывается на 150, остаток 50 (если общий бюджет 200). Агент B не получает вызов.

Преимущества: аукционы обеспечивают эффективное распределение – вызов получает агент, который ценит его больше. Недостаток: накладные расходы на проведение аукциона.


5. Динамические бюджеты и кредитные системы

Бюджет может пополняться со временем (например, ежедневно). Агенты могут копить неиспользованные токены (rollover) или занимать у будущего бюджета (кредит). Это добавляет временное измерение.

Модель с кредитом:

  • Агент может превысить бюджет сегодня, но должен вернуть долг завтра.
  • Вводится процентная ставка (штраф за превышение).
  • Оптимальная стратегия – динамическое программирование или марковские процессы принятия решений (MDP).

Пример: агент имеет дневной бюджет 1000 токенов. Сегодня ему нужно 1500 для важного запроса. Он берёт кредит 500, завтра его бюджет будет 1000 – 500 * 1.2 (20% штраф) = 400. Если завтрашние задачи менее важны, это может быть выгодно.


6. Метрики эффективности экономики агентов

Для оценки модели вводят метрики:

МетрикаОписание
Utility per tokenСредняя полезность на потраченный токен
Budget utilizationДоля использованного бюджета (не должен быть слишком низким или слишком высоким)
FairnessРавномерность распределения бюджета между агентами (индекс Джини)
RegretРазница между полезностью оптимальной стратегии (если бы все стоимости/полезности были известны) и реальной
Convergence timeСколько шагов нужно агенту, чтобы научиться оптимальному распределению

Пример расчёта utility per token:

  • За день агент потратил 8000 токенов, суммарная полезность (например, средняя оценка пользователей) = 6.4 → 0.0008 полезности на токен.

7. Практические соображения

  • Стоимость вызова LLM нелинейна: входные токены дешевле выходных, есть фиксированная плата за запрос.
  • Полезность субъективна: для RAG полезность может быть 1, если ответ точен, 0 – если галлюцинация. Но её сложно измерить в реальном времени.
  • Бюджет может быть разделён на типы вызовов (например, 70% на LLM, 30% на поиск) – это упрощает модель, но снижает гибкость.
  • Мониторинг: нужно логировать каждый вызов (стоимость, полезность) для обучения и отладки.

8. Расширения: многоагентная координация

Когда агентов много, они могут координироваться через центральный планировщик (orchestrator), который распределяет бюджет. Альтернатива – децентрализованные аукционы (каждый агент сам решает, сколько предложить). Второй подход масштабируется лучше, но может привести к неэффективности (трагедия общин).

Пример децентрализованного подхода:

  • Каждый агент имеет свой бюджет и может вызывать API независимо.
  • Если API общий (например, один поисковый сервис с rate limit), агенты конкурируют через очередь или аукцион.
  • Для предотвращения перегрузки вводят ценообразование (dynamic pricing): стоимость вызова растёт при высокой нагрузке.

Пет-проект для закрепления

Задача: Реализовать симуляцию агента с дневным бюджетом 10 000 токенов, который должен отвечать на 50 запросов пользователей. У агента есть 3 API: поиск (стоимость 200 токенов, полезность – релевантность найденных документов от 0 до 1), LLM (стоимость 1500 токенов, полезность – качество ответа от 0 до 1), проверка фактов (стоимость 500 токенов, полезность – снижение галлюцинаций на 0.2). Полезности генерируются случайно, но с известным распределением (например, поиск в среднем 0.7, LLM 0.85, проверка 0.5). Агент использует ε-greedy для выбора API на каждый запрос, но может вызывать несколько API на один запрос (суммарная стоимость не должна превышать остаток бюджета). Цель – максимизировать суммарную полезность за день.

Инструменты: Python, библиотеки random, numpy, matplotlib для визуализации.

Шаги:

  1. Создать класс API с атрибутами name, cost, true_utility (средняя), noise.
  2. Реализовать класс Agent с бюджетом, списком API, ε.
  3. В методе handle_request агент выбирает набор API (через жадный алгоритм по утилите на токен с exploration) и вызывает их, получая наблюдаемую полезность.
  4. Обновлять оценки полезности (среднее).
  5. Запустить симуляцию на 50 запросов, записывать накопленную полезность и остаток бюджета.
  6. Сравнить с baseline (всегда вызывать все API, если хватает бюджета) и с оптимальным статическим планом (решить knapsack для каждого запроса, зная истинные полезности).

Ожидаемый результат: График накопленной полезности по запросам для разных стратегий. ε-greedy должен приближаться к оптимальной, но с некоторым regret. Baseline (всегда все) быстро исчерпает бюджет и не сможет отвечать на последние запросы.


Связь с другими вопросами

ВопросТема
720Архитектура agentic RAG
721Планирование и разбиение задач
722Инструменты и их описание
724Память агентов
725Наблюдаемость и мониторинг
726Безопасность и контроль доступа

Эти вопросы вместе формируют полную картину построения production-grade agentic RAG: от архитектуры (720) до экономики ресурсов (723) и безопасности (726).


Навигация