Как сделать GeoAI-агента, который ищет пожары и отправляет к этим местам пожарные расчеты и дроны

—

от автора

По материалам Космохакатона-2026.

Привет, Хабр! На связи команда «Стрела». Недавно мы вернулись с Космохакатона-2026. Задача перед командой стояла следующая. Нужно было на основе исходных данных дистанционного зондирования Земли сделать программный продукт которым реально захотят и смогут пользоваться пожарные, спасатели и экологи для мониторинга возникновения чрезвычайных ситуаций, их предотвращения и анализа последствий.

Закапываться в бесконечные таблицы и диаграммы в моменты, когда каждая секунда на счету – так себе идея. В итоге мозгового штурма родилась идея Fire Monitor. Это умная система мониторинга лесных пожаров, которой управляет полноценный GeoAI-агент. Она сама собирает термоточки со спутников VIIRS и MODIS, оценивает масштабы выгорания территории по снимкам Santinel-2, строит маршруты от ближайших пожарных частей к очагу по дорожной сети для пожарных машин и даже рассчитывает траектории (галсы) для облета территории беспилотниками.

В этой статье расскажем, как устроен проект под капотом и как мы учили LLM работать с картами, контекстом и цепочками ГИС-инструментов.

Наш интерфейс: слева привычная интерактивная карта со слоями, справа — чат с AI-ассистентом, который понимает человеческий язык и управляет системой.

Наш интерфейс: слева привычная интерактивная карта со слоями, справа — чат с AI-ассистентом, который понимает человеческий язык и управляет системой.

Проектируя приложение мы пришли к выводу, что обычный дашборд – это тупик. Первая банальная идея сделать классическую админку, подтянуть термоточки из NASA FIRMS API, раскидать их по карте, прикрутить пару десятков фильтров по датам и координатам мы отбросили и полностью переосмыслили пользовательский интерфейс.

Мы быстро поняли, что когда у диспетчера на экране загорается сотни красных точек по всей территории страны, то такой дашборд скорее пугает, чем помогает. Спасателю не нужны абстрактные точки. Ему нужно готовое решение. Он просто хочет написать в чат или сказать голосом человеческим языком:

«Найди активные пожары в Иркутской области за последние сутки и отправь туда ближайшие пожарные расчеты».

Поэтому мы смело отбросили классическую идею с кучей кнопок и спроектировали GeoAI-агента. Он сам понимает намерения пользователя, крутит ReAct-цикл (рассуждение + действие) на базе модели Qwen3.7-Plus и выполняет нужные инструменты. Изначально мы дали ему 9 инструментов управляемых через три интерфейса: Model Context Protocol (для взаимодействия с внешними агентами), function calling (для взаимодействия с нашим агентом через чат, выбираемая LLM-модель должна поддерживать), не забыли и классический REST API (для взаимодействия с региональными ГИС). А чтобы модель в своих рассуждениях не зацикливалась, ограничили ее рассуждения жестким количеством итераций на запрос.

Идея огонь! Осталось реализация. А те кто практикует создание приложений немного сложнее «Hello world!» знает, что на этом этапе снимаются розовые очки и начинаются проблемы, которые мы все так любим героически преодолевать. Одним из таких вызовов, вставший перед нами, следующий. Как научить ИИ помнить результаты работы ГИС-инструментов и при этом не разориться на токенах, так как, главный кошмар при скрещивании языковых моделей и геоинформационных систем (ГИС) – это вес данных.

Представьте: агент вызывает функцию поиска пожаров и получает в ответ GeoJSON-массив на пару десятков тысяч полигонов. Это огромный кусок текста весом в несколько мегабайт. Если засунуть его целиком обратно в LLM, контекстное окно моментально переполнится, а кошелек наоборот. Но и просто отфильтровать эти данные нельзя. Если пользователь на следующем шаге попросит «Построй буфер вокруг ЭТИХ пожаров», нейросеть растеряется, ведь она не поймет каких-таких ЭТИХ.

Мы решили эту проблему через умное кеширование и разделение потоков данных:

  1. Сжатые сводки. В саму LLM мы отправляем только короткую текстовую выжимку (summary). А вот «тяжелая» геометрия в формате GeoJSON летит параллельно, минуя модель сразу на фронтенд для отрисовки браузером.

  2. Автоинъекция из кэша. Все результаты работы инструментов пишутся в глобальный кэш с TTL 5 минут. Когда агент вызывает следующий из цепочки метод система сама подставляет в его параметры данные из кэша.

Чтобы проверить не теряет ли агент нить разговора, мы устроили ему жесткий тест на многошаговую логику:

  1. «Покажи город Калининград и подпиши его».

  2. «Добавь город Черняховск тоже с названием».

  3. «Построй маршрут между ЭТИМИ городами и подпиши его протяженность».

Обычные чат-боты на третьем шаге уже забывают, о чем шла речь, и начинают переспрашивать координаты. Наш агент спокойно вытащил точки из памяти, передал их в OSRM и построил маршрут используя граф дорожной сети.

Агент держит контекст в уме: сам понял, что за города, и соединил их маршрутом.

Агент держит контекст в уме: сам понял, что за города, и соединил их маршрутом.

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

Сценарий 1. Пространственная фильтрация ложно-обнаруженных пожаров и построение маршрут для пожарной техники.

Спутники часто ошибаются. Факел нефтеперерабатывающего завода или градирня ТЭЦ на снимках VIIRS/MODIS выглядят точно также, как лесной пожар. Чтобы не гонять машины впустую, наша система делает пространственное объединение с промышленными зонами из Overture Maps и автоматически отсеивает ложные тревоги.

После этого агент через Overpass API ищет координаты ближайших МЧС-станций, скармливает их дорожному графу OSRM и выдает готовые маршруты до реальных очагов пожаров.

Маршруты для техники: ИИ сам нашел пожарные части поблизости и рассчитал пути подъезда

Маршруты для техники: ИИ сам нашел пожарные части поблизости и рассчитал пути подъезда

Сценарий 2. Планирование полета БПЛА (Этот модуль значительно доработан на втором хакатоне «Лидеры цифровой трансформации 2026», ожидайте материал).

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

Пользователь пишет в чат:

«Построй над этим кластером галсы для облета и съемки района беспилотником. Дрон должен вылететь из ближайшей пожарной части».

Агент анализирует форму полигонов, высчитывает оптимальные галсы для камеры беспилотника с учетом продольного и поперечного перекрытия кадров, прокладывает линию подлета от стартовой площадки и выдает готовый GeoJSON полетного задания. Оператору на месте остается только загрузить этот файл в станцию управления БПЛА и запустить его.

Проектирование полетной миссии прямо в диалоговом окне. И сама траектория облета. Все углы и расстояния просчитаны автоматически.

Проектирование полетной миссии прямо в диалоговом окне. И сама траектория облета. Все углы и расстояния просчитаны автоматически.

Сценарий 3. Картирование гарей для оценки ущерба.

Когда пожар потушен, нужно понять, насколько все плохо. Наш агент умеет обращаться к Planetary Computer STAC, выкачивать растры Santinel-2 «до» и «после» бедствия и запускать модуль оценки выгорания (Burn Severity):

  • Сначала через SCL (Scene Classification Layer) отсекаются снимки с облаками, чтобы они не портили результат оценки.

  • Затем рассчитываются вегетационные индексы NBR и разностный dNBR.

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

Карта гарей

Карта гарей

Еще оставалось некоторое время до дедлайна и мы, разгорячившись, решили пойти еще дальше и разрешить агенту писать Python код для целей ГИС-анализа.

С этой строки ! ВНИМАНИЕ ! это опасно, но мы решили и эту проблему, создав защищенную песочницу.

Заранее предусмотреть все хотелки аналитиков ГИС и зашить их в жесткие рамки функции такое себе. Рано или поздно придет пользователь, который скажет:

«Построй мне буферную зону 25 метров вокруг каждого пожара, у которого мощность излучения больше 10 МВт, и посчитай их общую площадь в гектарах».

Мы решили эту проблему радикально – дали агенту инструмент execute_python. Модель сама пишет скрипт на Python, используя встроенный ГИС-стек (GDAL/OGR, rasterio, pyogrio, xarray, scipy, matplotlib и др.), а бекенд его выполняет.

Модель сама набросала код на Python, применила Shapely и нарисовала 20-километровые буферы.

Модель сама набросала код на Python, применила Shapely и нарисовала 20-километровые буферы.

Но запустить чужой, незнакомый код, написанный нейросетью на своем сервере – это прямой путь к уничтожению человечества «Скайнет». Любая галюцинация или умышленный prompt injection вроде import os; os.system(‘rm –rf /’) и ваш проект удален. Поэтому мы построили четыре уровня защиты песочницы:

  1. Docker без сети. Песочница крутится в изолированном контейнере с флагом network_mode: none. Даже если нейрокод попытается украсть файл .env со всеми секретами, он физически не сможет отправить его наружу.

  2. AST-фильтрация. Перед запуском мы разбираем код на абстрактное синтаксическое дерево через встроенный модуль ast. Если внутри есть попытки импортировать os, subprocess или вызвать eval/exec – скрипт мгновенно банится.

  3. Защита dunder-методов. Мы перекрыли лазейки для обхода песочниц через интроспекцию (всякие ().class.mro). Доступ ко всем магическим атрибутам закрыт. Оставили только result для GeoJSON и charts для графиков.

  4. Ограничения на уровне ядра Linux (rlimits): С помощью модуля resource мы выставили жесткие системные лимиты. На выполнение кода дается максимум 30 секунд и не более 1,5 ГБ ОЗУ, а генерация core dumps отключена. Если модель напишет бесконечный цикл, операционка закиллит процесс через SIGKILL.

Наш проект хранится в репозитории fire-monitor и разворачивается одной командой через оркестратор docker compose.

Техстек проекта выглядит так:

  • Бекенд. Написан на Django REST Framework. Данные хранятся в PostgreSQL 16 в связке с PostGIS 3.4. Пространственные индексы здесь жизненно необходимы – именно они позволяют мгновенно фильтровать тысячи полигонов по границам экрана (bbox).

  • Фронтенд. Сделан на React и MapLibre GL JS. Картографический движок отлично переваривает огромные массивы геоданных и умеет на лету включать/выключать слои по команде из чата.

  • FastMCP Server. Всю логику взаимодействия мы вынесли в отдельный сервер, поддерживающий Model Context Protocol (MCP) от Anthropic. Это значит, что к аналитическим инструментам Fire Monitor можно подключаться не только через наш веб-чат, но и напрямую из сред разработки (вроде Cursor или Cline), чтобы автоматизировать рутину ГИС-аналитика обычными скриптами.

Что же дальше? Космохакатон 2026 стал для нас площадкой для давно задуманных идей. Мы смогли доказать на практике, что связка искусственного интеллекта и геоинформационных систем – это не просто хайп и дань моде, а новая парадигма взаимодействия пользователя с приложением с помощью естественной человеческой речи и рассуждений. Реализованные инструменты мониторинга чрезвычайных ситуаций применялись и ранее, но требовали более подготовленных специалистов для их освоения. Сейчас же порог входа в подобные системы значительно снижается высвобождая ресурсы специалистов для выполнения их непосредственных задач.

В планах развития Fire Monitor несколько пунктов:

  • Добавить предикативные математические модели, чтобы система могла прогнозировать распространение огня на пару дней вперед с учетом рельефа и ветра.

  • Наладить прямую интеграцию с софтом для планирования применения БПЛА, чем мы сейчас занимаемся в процессе другого хакатона Лидеры цифровой трансформации 2026.

  • Возможно оффлайн-режим на более легковесных моделях.

  • Управление приложением не только через чат, но и с помощью голоса (но это просто – времени не хватило).

Приглашаем к сотрудничеству с командой «Стрела». До новых встреч!

ссылка на оригинал статьи https://habr.com/ru/articles/1091794/