AMS Weather Agent

Агент для AMS (Agent Management System): по названию города возвращает короткую сводку о текущей погоде. Понимает русские (кириллица) и латинские названия.

Пользователь: Казань
Агент:        В Казани переменная облачность, температура 22,2 °C. Ветер 4,1 м/с,
              осадков нет. Возьмите лёгкую ветровку.

Возможности

  • Кириллица и латиница: Казань, Нижний Новгород, Санкт-Петербург, Kazan.
  • Данные о погоде: температура, влажность, ветер (скорость и направление), осадки.
  • Ответ формулирует языковая модель, но только из переданных фактов — числа не выдумываются.
  • Graceful degradation: если LLM недоступна, агент отдаёт детерминированную сводку.
  • Понятные сообщения об ошибках вместо исключений (диалог в AMS не падает).
  • Кэширование геокодинга и переиспользование HTTP-соединений.
  • API-ключи не нужны: оба внешних сервиса бесплатные.

Источники данных

Этап Сервис Ключ
Город → координаты Nominatim (OpenStreetMap) не нужен
Координаты → погода MET Norway Locationforecast не нужен

Структура

agents/custom/weather/
├── config.json        # метаданные агента для UI (name, description)
├── schema.py          # Pydantic-модель Params (валидация входа в AMS)
├── handler.py         # адаптер AMS: экспортирует генератор step(...)
├── system_prompt.txt  # правила формулировки ответа для LLM
└── weather.py         # сервисный слой: HTTP, модели, маппинг погодных кодов
tests/
└── test_weather.py    # unit-тесты (без сети)

Разделение ответственности: weather.py ничего не знает про AMS и тестируется отдельно; handler.py — тонкий слой интеграции.

Требования

  • AMS 7.005+ (Python 3.12, requests и pydantic-ai уже в окружении сервиса).
  • Доступ к nominatim.openstreetmap.org и api.met.no с хоста AMS.

Установка в AMS

Скопировать каталог агента и выдать права пользователю сервиса:

sudo cp -r agents/custom/weather /opt/ams/agents/custom/weather
sudo chown -R lexicom:lexicom /opt/ams/agents/custom/weather

Loader AMS подхватит изменения примерно через 10 секунд. Проверка:

curl -s http://127.0.0.1:6165/ams/agent/list | jq '.agents.custom'

Альтернатива — импорт через API AMS (zip-архив агента).

Использование (API AMS)

POST /ams/start/{type}/{agent_id} с телом в формате JSON. Синхронный стрим удобнее для клиентов, которые хотят получить ответ в одном запросе (async_mode: "no"):

curl -sN http://127.0.0.1:6165/ams/start/custom/weather \
  -H 'Content-Type: application/json' \
  -H 'Accept: text/event-stream' \
  -d '{"async_mode":"no","params":{"city":"Казань"}}'

Ответ — поток JSON-строк (NDJSON):

{"type": "chunk", "data": "В Казани ", "chat_id": "..."}
{"type": "chunk", "data": "переменная облачность...", "chat_id": "..."}
{"type": "end", "data": "message", "chat_id": "..."}

Асинхронный режим (async_mode: "yes") возвращает chat_id; далее читать GET /ams/stream/{chat_id}, продолжать диалог POST /ams/ask/{chat_id} и завершать POST /ams/stop/{chat_id}.

Публичный доступ (пример развёртывания)

AMS отдаётся наружу через reverse-proxy Apache на git.totmin.ru:

Префикс /weather срезается прокси, а uvicorn запущен с UVICORN_ROOT_PATH=/weather, поэтому ссылки в Swagger формируются корректно.

Параметры

Параметр Тип Описание
city string Название города (кириллица или латиница).

Поведение при ошибках

Ситуация Ответ
Город не найден «Не удалось получить погоду: город «…» не найден.»
Пустой город «Не удалось получить погоду: не указан город.»
Внешний сервис недоступен «Не удалось получить погоду: внешний сервис погоды недоступен.»
LLM недоступна Детерминированная сводка из полученных данных

Тесты

python -m venv .venv && . .venv/bin/activate
pip install pytest requests
pytest

Тесты не обращаются к сети: HTTP-слой подменяется (monkeypatch).

Лицензия

Не задана (все права сохранены).

S
Description
No description provided
Readme
54 KiB
Languages
Python 100%