Реализация Guardrails (ограничений ответов) AI-ассистента в мобильном приложении
AI-ассистент в продакшене без guardrails — это открытая уязвимость. Пользователь задаст вопрос вне домена, попробует prompt injection через пользовательский контент, или модель сама уйдёт в нежелательную тему. Guardrails — это не один фильтр, а слоёная система валидации на входе и выходе.
Слои защиты: что и где проверяем
Input guardrails — проверка запроса пользователя до отправки в LLM.
Тематический фильтр: определяем, относится ли вопрос к домену приложения. Простейший вариант — embeddings + cosine similarity с набором «разрешённых тем». Более надёжный — отдельный быстрый классификатор (GPT-4o-mini с примитивным промптом, latency ~200мс):
func isOnTopic(_ userMessage: String) async -> Bool {
let classifierPrompt = """
Определи, относится ли следующий вопрос к теме личных финансов (бюджет, расходы, сбережения, инвестиции).
Ответь только: YES или NO.
Вопрос: \(userMessage)
"""
let response = await llmClient.complete(classifierPrompt, temperature: 0)
return response.trimmingCharacters(in: .whitespaces) == "YES"
}
Prompt injection detection: если приложение обрабатывает пользовательский контент (заметки, документы) и передаёт его в контекст LLM, нужна проверка на инжекции вида «Ignore previous instructions and...». Базовая защита — поиск по паттернам, более надёжная — специализированный классификатор типа rebuff или lakera-guard.
Output guardrails — валидация ответа модели перед показом пользователю.
Контроль формата и бизнес-правил
Когда ассистент возвращает структурированные данные, каждый ответ нужно валидировать перед рендерингом:
// Android — Kotlin
data class AssistantResponse(
val text: String,
val category: String?,
val amount: Double?
)
fun validateResponse(raw: String): AssistantResponse? {
return try {
val parsed = gson.fromJson(raw, AssistantResponse::class.java)
// Бизнес-правила: сумма не может быть отрицательной
if (parsed.amount != null && parsed.amount < 0) return null
// Категория должна быть из разрешённого списка
if (parsed.category != null && parsed.category !in allowedCategories) return null
parsed
} catch (e: JsonSyntaxException) {
null // Ответ не в формате JSON — отбрасываем, показываем fallback
}
}
Длина и тон ответа. Некоторые модели при определённых запросах начинают генерировать неожиданно длинные ответы. Жёсткий max_tokens в запросе + проверка длины на клиенте до рендеринга.
Библиотеки и готовые решения
Guardrails AI (guardrails-ai Python) — декларативное описание правил валидации с автоматическим retry. Применимо на сервере, который проксирует запросы от мобильного клиента. NeMo Guardrails от NVIDIA — более тяжеловесное решение для enterprise, поддерживает диалоговые флоу и topical rails.
Для небольших приложений достаточно собственной middleware-прослойки на сервере с набором правил. Главное — не делать это на клиенте: guardrails должны работать на сервере, иначе их можно обойти прямым обращением к API.
Ориентиры по срокам
Базовые input/output фильтры — 1–2 дня. Тематический классификатор с тестовым покрытием — 2–3 дня. Полная слоёная система с логированием нарушений — 4–5 дней.







