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:
- Swagger — https://git.totmin.ru/weather/swagger
- Документация — https://git.totmin.ru/weather/help/
- API —
https://git.totmin.ru/weather/ams/...
Префикс /weather срезается прокси, а uvicorn запущен с UVICORN_ROOT_PATH=/weather,
поэтому ссылки в Swagger формируются корректно.
Параметры
| Параметр | Тип | Описание |
|---|---|---|
city |
string | Название города (кириллица или латиница). |
Поведение при ошибках
| Ситуация | Ответ |
|---|---|
| Город не найден | «Не удалось получить погоду: город «…» не найден.» |
| Пустой город | «Не удалось получить погоду: не указан город.» |
| Внешний сервис недоступен | «Не удалось получить погоду: внешний сервис погоды недоступен.» |
| LLM недоступна | Детерминированная сводка из полученных данных |
Тесты
python -m venv .venv && . .venv/bin/activate
pip install pytest requests
pytest
Тесты не обращаются к сети: HTTP-слой подменяется (monkeypatch).
Лицензия
Не задана (все права сохранены).