Введение: зачем запускать LLM-агента в реальном шутере?
LLM-агенты управляют браузерами, пишут код и ведут переписки. Проект Local LLM agent для Perfect Dark ставит задачу сложнее: научить языковую модель играть в динамичный шутер от первого лица. Принципиальное отличие от большинства экспериментов - агент взаимодействует с реальным бинарником игры, а не с эмулятором или реимплементацией. Стек: Mac с Apple Silicon и фреймворк MLX для локального инференса.
Центральная проблема очевидна: LLM генерирует ответ за секунды, а шутер требует реакции за миллисекунды. Разработчики решили это через двухуровневую архитектуру управления. Быстрый слой обрабатывает прицеливание и движение каждые ~50 мс. Медленный слой, управляемый LLM, принимает стратегические решения: куда идти, кого атаковать, какую позицию занять. Система логирования оценивает агентность по изменению позиции и направления, а не по факту нажатия кнопок.
Материал разбирает техническую архитектуру проекта, интеграцию с игрой через кастомный мост, обоснование выбора Mac + MLX и метрики оценки агентности. Если вы проектируете AI-агентов для реального времени или интересуетесь практическим применением LLM вне чатов - этот разбор даст конкретные архитектурные паттерны.
Тема перекликается с более широким контекстом: мы уже разбирали архитектуру AI-агентов послойно - от токенов до ReAct-цикла, а также практику самостоятельной разработки агентов с метриками latency и reliability. Проект для Perfect Dark добавляет в эту картину жёсткие ограничения реального времени.
Архитектура агента: быстрый и медленный слои управления
Ключевое архитектурное решение - разделение контура управления на два слоя с разной частотой обновления. Это стандартный паттерн для систем, где медленный планировщик не может реагировать на события в реальном времени. В робототехнике его применяют десятилетиями; здесь он адаптирован под LLM.
Быстрый слой работает на частоте ~20 Гц (цикл 50 мс). Он отвечает за прицеливание, движение и стрельбу - действия, где задержка критична. Медленный слой получает состояние игры, формирует промпт для LLM, ожидает ответ и обновляет стратегическую цель. Частота обновления стратегии измеряется секундами, а не миллисекундами.
Схема взаимодействия: медленный слой задаёт цель (например, «переместиться к точке X и атаковать противника Y»), быстрый слой реализует её через набор эвристик и алгоритмов управления движением. Когда LLM генерирует новую стратегию, быстрый слой переключается на новые целевые параметры. Так модель не блокирует критический контур управления.
Быстрый слой: прицеливание и движение с минимальной задержкой
Быстрый слой реализован без использования LLM. Это набор алгоритмических решений: движение к целевой точке по навигационной сетке, доворот камеры к цели, удержание прицела с поправкой на движение противника. Данные передаются в игру через кастомный мост с минимальной буферизацией.
Цикл 50 мс выбран как компромисс между плавностью управления и нагрузкой на систему. Для шутера это достаточная частота: игроки-люди редко реагируют быстрее 150-200 мс. Алгоритмический слой компенсирует инерцию LLM, обеспечивая базовую боеспособность агента между стратегическими обновлениями.
Псевдокод быстрого цикла выглядит примерно так:
while game_running:
target = get_current_strategic_target() # от медленного слоя
move_towards(target.position)
aim_at(target.enemy)
if has_clear_shot():
fire()
sleep(50) # мс
Фактическая реализация учитывает геометрию уровня, препятствия и поведение противников. Детали кода не раскрыты, но общий подход воспроизводим в любом проекте, где нужно совместить медленный планировщик с быстрым исполнением.
Медленный слой: стратегические решения от LLM
Медленный слой формирует промпт из состояния игры: позиция агента, видимые противники, уровень здоровья и боеприпасов, текущая цель. Модель получает описание ситуации на естественном языке и возвращает структурированное решение: тип действия (атаковать, отступать, искать укрытие), целевые координаты, приоритетные противники.
Частота обновления стратегии варьируется от 2 до 5 секунд в зависимости от скорости инференса конкретной модели. Этого достаточно для тактических решений в масштабе боя: сменить позицию после убийства противника, отреагировать на появление новой угрозы, выбрать маршрут к следующей контрольной точке.
Промпт включает историю предыдущих решений и их результатов - это базовый механизм памяти агента. Если модель приказала атаковать противника, а через 3 секунды агент потерял половину здоровья, следующий промпт будет содержать этот контекст для корректировки поведения.
Влияние на геймплей: агент демонстрирует поведение, отличимое от скриптованных ботов. Он меняет тактику, иногда ошибается в оценке угроз и принимает субоптимальные решения - ровно как и человек, играющий без полной информации о карте.
Интеграция с игрой: кастомный мост для Perfect Dark
Perfect Dark - игра 2000 года, не имеющая API для внешнего управления. Разработчики написали кастомный мост, который читает состояние игры из памяти процесса и отправляет команды управления, эмулируя ввод с клавиатуры и мыши.
Чтение состояния включает: позицию и ориентацию камеры, координаты противников в поле зрения, показатели здоровья и боеприпасов, состояние уровня. Эти данные извлекаются напрямую из структур памяти игрового процесса. Метод специфичен для каждой игры и требует реверс-инжиниринга, но даёт полный доступ к информации без задержек скриншотного подхода.
Отправка команд реализована через виртуальные устройства ввода на уровне ОС. Мост транслирует решения быстрого слоя в нажатия клавиш WASD, движения мыши и клики. Задержка ввода минимальна - на уровне драйверов операционной системы.
Сравнение с альтернативами: эмуляция добавляет прослойку, которая вносит задержки и искажения. Реимплементация игры (как в проектах вроде Gym Retro) даёт полный контроль, но требует воссоздания игровой логики - трудоёмкий процесс, не масштабируемый на другие игры. Подход с прямым доступом к памяти и виртуальным вводом работает с оригинальным бинарником, сохраняя аутентичное поведение игры.
Стек Mac + MLX: почему локальный инференс на Mac?
Выбор Mac на Apple Silicon с фреймворком MLX продиктован практическими соображениями. MLX - это библиотека Apple для машинного обучения, оптимизированная под чипы M-серии. Она использует unified memory: CPU и GPU работают с одними и теми же данными без копирования между буферами. Для инференса LLM это сокращает задержки и упрощает код.
Производительность: на MacBook Pro с M3 Max инференс 7B-модели с 4-битной квантизацией занимает 1-3 секунды на стратегическое решение. Этого достаточно для цикла обновления в 2-5 секунд. Модели меньшего размера (1-3B параметров) могут работать быстрее, но качество стратегических решений падает.
Альтернативы: облачные API (OpenAI, Anthropic) добавляют сетевую задержку 200-500 мс и вносят зависимость от внешнего сервиса. Другие локальные решения (llama.cpp, Ollama) работают на Mac, но MLX даёт более плотную интеграцию с железом и лучшую производительность на Apple Silicon. Требования к железу: любой Mac с чипом M1 и выше, минимум 16 ГБ unified memory для комфортной работы 7B-моделей.
Система логирования и оценка агентности
Проект вводит понятие «агентности» - меры осмысленности действий. Вместо логирования нажатых кнопок система оценивает изменения в игровом мире, вызванные агентом. Два ключевых параметра: изменение позиции (переместился ли агент в ответ на стратегическое решение) и изменение направления (повернулся ли к цели).
Программная проверка агентности работает так: после получения стратегического решения от LLM система ждёт интервал времени (например, 3 секунды) и сравнивает фактическое состояние с предсказанным. Если агент должен был переместиться к точке X, а остался на месте - решение не выполнено, и это фиксируется в логе как ошибка агентности. Если агент движется к цели, но не доходит из-за препятствия - это частичное выполнение.
Пример записи в логе:
[t=12.3s] LLM decision: move_to(450, -230), attack(enemy_3)
[t=12.4s] Fast layer: path calculated, 14 waypoints
[t=14.1s] Position delta: +32.1 units toward target
[t=15.3s] Agent check: target reached, enemy_3 eliminated
[t=15.3s] Agency score: 0.94 (full execution)
Такой подход даёт количественную метрику для сравнения разных моделей и конфигураций промптов. Модель, чьи решения чаще приводят к фактическим изменениям в игре, получает более высокий средний балл агентности. Это объективнее, чем субъективная оценка «играет хорошо».
Ограничения и перспективы подхода
Проект демонстрирует работоспособность концепции, но имеет чёткие границы применимости. Задержка LLM остаётся фундаментальным ограничением: в ситуациях, требующих реакции быстрее 1-2 секунд, агент полагается только на быстрый слой. Противники-люди, использующие неожиданные тактики, могут эксплуатировать эту инерцию.
Качество стратегических решений зависит от размера модели. 7B-модели иногда принимают тактически слабые решения: атакуют в меньшинстве, игнорируют укрытия, не координируют использование оружия с дистанцией. Файн-тюнинг на игровых данных мог бы улучшить ситуацию, но требует набора примеров успешных стратегий.
Зависимость от конкретной игры высока: мост для Perfect Dark завязан на структуры памяти этого бинарника. Адаптация к другой игре потребует нового раунда реверс-инжиниринга. Это ограничивает тиражируемость подхода, но не его ценность как демонстрации архитектурного паттерна.
Перспективные направления: использование более быстрых моделей (1-3B с файн-тюнингом), применение спекулятивного декодирования для ускорения инференса, обучение быстрого слоя через imitation learning на действиях LLM. Интересен сценарий с несколькими агентами, координируемыми одной LLM - это ближе к реальным задачам мультиагентных систем, которые мы разбирали в контексте открытых агентных систем вроде NemoClaw и LangChain Deep Agents.
Заключение: что этот проект значит для будущего AI-агентов в играх
Проект Local LLM agent для Perfect Dark - это инженерно честная попытка ответить на вопрос: можно ли использовать LLM для управления в реальном времени. Ответ: да, если разделить ответственность между быстрым алгоритмическим слоем и медленным стратегическим.
Архитектурный паттерн «быстрый исполнитель + медленный планировщик» применим далеко за пределами игр. Любая система, где LLM должна управлять процессом с жёсткими временными ограничениями - дроны, промышленные роботы, торговые алгоритмы - может использовать этот подход. Меняется быстрый слой, принцип остаётся.
Система оценки агентности через измерение фактических изменений в среде - вторая ценная идея проекта. Она заменяет субъективную оценку «модель работает хорошо» на измеримую метрику. Для разработчиков агентов это шаг к инженерной дисциплине: мы тестируем не промпт, а поведение системы в целом.
Если вы проектируете AI-агента для задач реального времени, начните с двух вопросов: какой минимальный цикл управления допустим, и как измерить успешность действий. Ответы приведут вас к архитектуре, похожей на этот проект - независимо от того, игра это или производственный процесс.