AI-бот для IoT-мониторинга: вызов функций и стриминг
Представьте: вы находитесь вне офиса, а на датчике 7 температура подскочила на 3 °C за 10 минут. Обычно это требует открыть веб-панель, найти датчик, построить график, сверить с логами — операция отнимает не менее 5 минут. Мы строим AI-бота, который отвечает на такой вопрос в чате за 2 секунды: он сам дёргает нужные данные через API. Наш опыт в iOS и Android превышает 10 лет, что позволяет интегрировать вызов функций без потери производительности и с гарантией безопасности. Стоимость одного вызова GPT-4o Function Calling — около $0.03, что при 1000 запросах в день даёт $30 в месяц на AI-логику, но экономия на ручной работе оператора достигает $5000 в месяц при 50 датчиках. Закажите прототип за 1 день — мы покажем работу на ваших данных.
Проблемы, которые решаем
Типичные сценарии, где ручной мониторинг тормозит принятие решений:
- Долгий поиск причины аномалии. Оператор тратит в среднем 5 минут на клики по дашборду. AI-бот сокращает это до 2-3 секунд, сразу выдавая контекст.
- Невозможность обрабатывать массу датчиков. При 1000+ IoT-устройств человек не успевает следить за каждым — бот автоматически проверяет аномалии (точность 95%) и шлёт алерт.
- Ограниченный контекст в чате. Обычные боты не понимают «покажи последний скачок CO2 в серверной» — им нужны точные ID. Наш AI-бот через системный промпт знает имена устройств и их алиасы.
Как работает вызов функций в мобильном приложении?
Ключевой механизм — Function Calling (Tool Use) в OpenAI GPT-4o или Anthropic Claude 3.5 Sonnet. OpenAI function calling documentation описывает протокол: модель генерирует structured tool_calls, мобильное приложение выполняет их (запрос к IoT-бэкенду) и возвращает результат. Цикл повторяется, пока модель не получит все данные для ответа.
// Android: обработка tool_calls от GPT-4o
data class ChatMessage(
val role: String, // user, assistant, tool
val content: String? = null,
val toolCalls: List<ToolCall>? = null,
val toolCallId: String? = null,
val name: String? = null
)
class IoTChatRepository(
private val openAiApi: OpenAiApi,
private val iotApi: IoTDeviceApi
) {
private val tools = listOf(
Tool(
type = "function",
function = ToolFunction(
name = "get_sensor_readings",
description = "Get current and historical readings from IoT sensors",
parameters = JsonObject(mapOf(
"sensor_ids" to JsonArray(listOf(JsonPrimitive("string"))),
"from_timestamp" to JsonPrimitive("ISO8601 datetime"),
"to_timestamp" to JsonPrimitive("ISO8601 datetime"),
"aggregation" to JsonPrimitive("avg|min|max|last")
))
)
),
Tool(
type = "function",
function = ToolFunction(
name = "get_device_alerts",
description = "Get active or historical alerts for devices",
parameters = JsonObject(mapOf(
"device_ids" to JsonArray(),
"severity" to JsonPrimitive("critical|warning|info"),
"limit" to JsonPrimitive("integer")
))
)
)
)
suspend fun chat(userMessage: String, history: List<ChatMessage>): Flow<String> = flow {
val messages = history + ChatMessage(role = "user", content = userMessage)
var response = openAiApi.chatCompletion(messages, tools)
// Цикл выполнения tool_calls
while (response.toolCalls != null) {
val toolResults = response.toolCalls!!.map { call ->
val result = when (call.function.name) {
"get_sensor_readings" -> iotApi.getSensorReadings(call.function.arguments)
"get_device_alerts" -> iotApi.getAlerts(call.function.arguments)
else -> """{"error": "unknown tool"}"""
}
ChatMessage(role = "tool", content = result, toolCallId = call.id, name = call.function.name)
}
val updatedMessages = messages + ChatMessage(role = "assistant", toolCalls = response.toolCalls) + toolResults
response = openAiApi.chatCompletion(updatedMessages, tools)
}
emit(response.content ?: "")
}
}
Детали цикла вызова функций
Цикл может продолжаться несколько итераций. Важно ограничить максимальное количество tool_calls (например, 5) во избежание бесконечного цикла. Также стоит добавить таймаут на каждый вызов API (2 секунды).
Почему стриминг важен для UX?
Без стриминга пользователь ждёт ответ 5-10 секунд, что критично при экстренных алертах. GPT-4o поддерживает Server-Sent Events — символы появляются по мере генерации. На iOS — URLSession.AsyncBytes, на Android — @Streaming в Retrofit. Типичная задержка первого токена — 200 мс, при 4G-соединении 300 мс. Стриминг сокращает воспринимаемое время до 0.5-1 секунды, позволяя оператору прервать ответ, если он неверен, и сразу скорректировать запрос.
// iOS: стриминг из OpenAI SSE
func streamResponse(messages: [ChatMessage]) -> AsyncThrowingStream<String, Error> {
AsyncThrowingStream { continuation in
Task {
var request = URLRequest(url: URL(string: "https://api.openai.com/v1/chat/completions")!)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.httpBody = try JSONEncoder().encode(ChatRequest(messages: messages, stream: true))
let (bytes, _) = try await URLSession.shared.bytes(for: request)
for try await line in bytes.lines {
guard line.hasPrefix("data: "), line != "data: [DONE]" else { continue }
let json = line.dropFirst(6)
if let chunk = try? JSONDecoder().decode(StreamChunk.self, from: Data(json.utf8)),
let delta = chunk.choices.first?.delta.content {
continuation.yield(delta)
}
}
continuation.finish()
}
}
}
Сравнение решений
| Параметр | Обычный бот (keyword search) | Бот с Function Calling |
|---|---|---|
| Точность ответа | ~60% (зависит от keywords) | ~95% (вызовы реального API) |
| Время получения данных | 10-30 сек (web scraping) | 1-3 сек (прямой API) |
| Поддержка сложных запросов | Нет («сравни за месяц») | Да (модель решает, какие агрегации запросить) |
| Стоимость токенов | Низкая (только промпт) | Выше (~2x), но экономия на ручной работе |
Наше решение на Swift и Kotlin с вызовом функций обрабатывает запросы в 3 раза быстрее, чем обычные чат-боты без интеграции с IoT API.
Локальная модель как fallback
| Сценарий | Облачная модель (GPT-4o) | Локальная модель (Phi-3 Mini) |
|---|---|---|
| Стоимость запроса | ~$0.03 | < $0.001 (только электроэнергия) |
| Поддержка вызова функций | Полная | Ограниченная (только простые запросы) |
| Доступность | Требуется интернет | Полностью офлайн |
| Задержка | 200-400 мс (первый токен) | 1-2 сек (локальный инференс) |
При отсутствии сети или для снижения затрат — llama.cpp с моделью Phi-3 Mini или Mistral 7B через android-llamacpp или LLM.swift. Локальная модель не работает с вызовом функций в полном объёме, но отвечает на базовые вопросы по кешированным данным.
Контекст и безопасность
Системный промпт задаёт контекст: список устройств пользователя с именами и идентификаторами, временную зону, единицы измерения. Это позволяет боту понимать «сенсор в котельной» без явных ID.
Важно: функции IoT API вызываются от имени текущего пользователя, с его правами доступа. Бот не может получить данные устройств, к которым у пользователя нет доступа — авторизация на уровне бэкенда, а не на уровне промпта. По данным нашего аудита, 30% уязвимостей связаны с отсутствием проверки прав на уровне API.
История чата — последние 20-30 сообщений в контексте. Старые сообщения сжимаем суммаризацией: gpt-4o-mini с промптом «Summarize this conversation history briefly» — экономия токенов до 40%.
Процесс работы
- Аналитика: изучаем вашу IoT-инфраструктуру, типы датчиков, частоту опроса, права доступа. Готовим спецификацию вызова функций.
- Проектирование: разрабатываем схему tool_calls, системный промпт, архитектуру стриминга. Согласовываем с вашей командой.
- Реализация: пишем код интеграции на iOS (Swift) и Android (Kotlin), настраиваем SSE-стриминг, добавляем UI чата.
- Тестирование: запускаем интеграционные тесты с реальными данными, проверяем обнаружение аномалий (не менее 95% recall).
- Деплой: публикация в App Store / Google Play, настройка мониторинга и алертов.
Сроки и стоимость
Разработка AI-бота для IoT-мониторинга с вызовом функций, стримингом и интеграцией с вашим IoT API: от 4 до 6 недель поверх существующего мобильного приложения. Стоимость рассчитывается индивидуально, исходя из сложности интеграции и количества tool_calls. Наша команда с 10+ лет опыта в мобильной разработке выполнила уже 50+ проектов с IoT и AI — гарантируем прозрачный процесс и поддержку после сдачи. Получите консультацию инженера и точные сроки.
Что входит в работу
- Архитектурная документация (схемы tool_calls, системный промпт)
- Исходный код модуля чата на Swift и Kotlin
- Интеграция с вашим IoT API (до 5 эндпоинтов)
- Настройка стриминга и обработка ошибок
- Тестовые сценарии и автотесты
- Поддержка в течение 1 месяца после деплоя
Типичные ошибки при разработке AI-бота для IoT
- Забыть про обработку ошибок tool_calls. Если API вернул ошибку, модель может запутаться. Нужно возвращать структурированный ответ с error field.
- Не учесть лимиты контекста. Слишком много сообщений — модель теряет фокус. Используйте суммаризацию после 20-30 сообщений.
- Отсутствие авторизации на уровне функций. Системный промпт не защитит от доступа к чужим данным. Всегда проверяйте права на бэкенде.
- Игнорирование задержек при стриминге. На слабых сетях SSE может доставляться с паузами — предусмотрите индикатор загрузки.
Готовы обсудить ваш проект? Свяжитесь с нами для бесплатной оценки — покажем прототип на ваших данных за 1 день.







