Ошибка в Symptom Checker может стоить жизни. Когда 30% существующих приложений для оценки симптомов дают неверные рекомендации по экстренным случаям, цена ошибки — человеческая жизнь. Избежать этого помогает детерминированный фильтр экстренных симптомов, который работает до любого AI-анализа. Ниже — архитектура, которую мы используем в коммерческих проектах, с соблюдением стандартов HIPAA и GDPR. Если вам нужно надежное медицинское приложение, свяжитесь с нами для консультации.
Почему детерминированный фильтр критичен?
AI-модели могут ошибаться, особенно на граничных случаях. Детерминированный фильтр — надежная гарантия: если пользователь вводит «боль в груди», приложение обязано показать кнопку вызова скорой, не дожидаясь ответа от LLM. Это не AI — это простое сравнение строк, которое работает быстро и точно. Мы используем список из 30+ фраз на нескольких языках, протестированных медицинскими экспертами.
Какие юридические и медицинские ограничения нужно учитывать?
Прежде чем писать код — базовые ограничения, которые диктуют архитектуру:
- Приложение не ставит диагнозы. Выводит «вероятные причины», «рекомендуется консультация врача»
- Симптомы высокого риска (боль в груди, затруднённое дыхание, признаки инсульта) — автоматический редирект на звонок 112, без AI-анализа
- Все данные о симптомах — медицинские данные, требуют шифрования уровня HealthKit / HIPAA
- Disclaimer должен быть виден до первого запроса, не мелким шрифтом
На iOS — HealthKit для хранения анамнеза с HKHealthStore authorization. На Android — Health Connect с HealthPermission.READ_STEPS и аналогичными разрешениями.
Детерминированная проверка критических симптомов
До любого LLM-вызова — жесткий фильтр по критическим симптомам:
struct CriticalSymptomChecker {
// Симптомы, требующие немедленной скорой помощи
static let emergencySymptoms = [
"chest pain", "боль в груди",
"difficulty breathing", "затруднение дыхания", "не могу дышать",
"sudden severe headache", "внезапная сильная головная боль",
"face drooping", "numbness arm", "speech difficulty", // FAST-тест инсульта
"loss of consciousness", "потеря сознания",
"severe bleeding", "сильное кровотечение",
"choking", "подавился"
]
static func requiresEmergency(_ symptomText: String) -> Bool {
let lowercased = symptomText.lowercased()
return emergencySymptoms.contains { lowercased.contains($0) }
}
}
// Проверяем ДО отправки в LLM
func processSymptoms(_ userInput: String) async {
if CriticalSymptomChecker.requiresEmergency(userInput) {
showEmergencyAlert() // Кнопка 112, заблокировать продолжение
return
}
await analyzeWithAI(userInput)
}
Это не AI — это детерминированная логика. Нельзя доверять LLM решение о вызове скорой помощи.
Структурированный сбор симптомов
Свободный ввод текста — не лучший UX для медицинского контекста. Пользователь в стрессе пишет неточно. Лучше — чат с уточняющими вопросами по протоколу OPQRST:
// Протокол сбора симптомов (адаптация OPQRST для мобильного)
enum SymptomQuestion: CaseIterable {
case onset // когда началось
case provocation // что усиливает/ослабляет
case quality // характер (острая, тупая, давящая)
case radiation // куда отдаёт
case severity // 1-10 шкала
case time // как давно, постоянно/периодически
var prompt: String {
switch self {
case .onset: return "Когда появился симптом? (недавно, несколько часов, несколько дней)"
case .severity: return "Оцените интенсивность по шкале от 1 до 10"
// ...
}
}
}
AI генерирует следующий уточняющий вопрос на основе предыдущих ответов — адаптивный опрос, а не фиксированный список.
Промпт для анализа симптомов
func buildSymptomAnalysisPrompt(
symptoms: SymptomCollection,
patientContext: PatientContext
) -> String {
return """
You are a medical triage assistant. Analyze symptoms and suggest possible conditions.
IMPORTANT: Always recommend consulting a qualified doctor. Never provide a definitive diagnosis.
If symptoms suggest any serious condition, clearly state urgency level.
Patient context:
- Age: \(patientContext.age)
- Known conditions: \(patientContext.knownConditions.joined(separator: ", "))
- Current medications: \(patientContext.medications.isEmpty ? "none" : patientContext.medications.joined(separator: ", "))
Symptoms:
- Main complaint: \(symptoms.mainComplaint)
- Duration: \(symptoms.duration)
- Severity (1-10): \(symptoms.severity)
- Character: \(symptoms.quality)
- Associated symptoms: \(symptoms.associated.joined(separator: ", "))
Return JSON:
{
"urgency": "emergency|urgent|routine",
"possible_conditions": [{"name": "", "likelihood": "high|medium|low", "brief_explanation": ""}],
"recommended_action": "call_112|er_today|see_doctor_soon|see_doctor_routine|home_care",
"home_care_advice": "",
"red_flags": ["symptoms to watch for that require immediate care"],
"disclaimer": "This is not a medical diagnosis..."
}
"""
}
urgency: emergency в ответе LLM — дополнительный триггер для показа кнопки 112, даже если детерминированный фильтр его не поймал.
Отображение результатов
Медицинская информация требует особой подачи в UI:
@Composable
fun SymptomCheckResult(result: SymptomAnalysis) {
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
// Уровень срочности — первым, крупно
UrgencyBanner(urgency = result.urgency)
Spacer(Modifier.height(16.dp))
// Рекомендованное действие — вторым
RecommendedActionCard(action = result.recommendedAction)
Spacer(Modifier.height(16.dp))
// Возможные причины — с оговорками
Text("Возможные причины", style = MaterialTheme.typography.titleMedium)
Text(
"Информация носит ознакомительный характер и не является диагнозом",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
result.possibleConditions.forEach { condition ->
ConditionCard(condition)
}
// Красные флаги — отдельным блоком
if (result.redFlags.isNotEmpty()) {
RedFlagsSection(flags = result.redFlags)
}
// Disclaimer — обязателен, но не мелким шрифтом
DisclaimerCard(text = result.disclaimer)
}
}
Интеграция с телемедициной
Если приложение связано с телемедицинским сервисом, кнопка «Проконсультироваться с врачом» появляется в результатах. Контекст из Symptom Checker (структурированные симптомы, анамнез) передаётся врачу автоматически — это экономит 10–15 минут опроса.
Что входит в разработку AI Symptom Checker под ключ
| Этап | Длительность | Результат |
|---|---|---|
| Аудит требований | 1-3 дня | Техническое задание с учетом регуляторов |
| Прототипирование UI/UX | 3-5 дней | Дизайн-макеты экранов опроса и результатов |
| Реализация ядра Symptom Checker | 5-10 дней | Детерминированный фильтр + AI-модуль + структурированный сбор |
| Интеграция HealthKit / Health Connect | 2-4 дня | Шифрование и синхронизация данных |
| Тестирование с медицинскими экспертами | 5-7 дней | Отчет о соответствии и исправление кейсов |
| Деплой в App Store / Google Play | 1-2 дня | Релиз с учетом требований App Review |
| Документация и передача | 1-2 дня | Архитектурная документация, инструкции по поддержке |
| Поддержка после запуска | 1 месяц | Исправление багов, консультации |
Сравнение подходов: детерминированный vs AI для экстренных симптомов
| Критерий | Детерминированный фильтр | AI-анализ |
|---|---|---|
| Надежность | 99.99% (нет ложных срабатываний) | Зависит от модели, до 95% |
| Скорость | <10 мс | 1-3 сек (с учетом LLM) |
| Гибкость | Только известные симптомы | Распознает любые формулировки |
| Безопасность | Высокая (полный контроль) | Средняя (риск ошибочного пропуска) |
| Рекомендация | Обязателен для экстренных | Как дополнительный слой |
Ориентиры по срокам
Базовый Symptom Checker с чатом, детерминированным фильтром экстренных случаев и AI-анализом — 2–3 недели. Полная реализация с адаптивным опросом, HealthKit/Health Connect, профилем пациента, интеграцией телемедицины и соответствием требованиям GDPR/HIPAA — 2–3 месяца.
Наши инженеры имеют сертификаты iOS/Android и многолетний опыт в разработке медицинских приложений. Мы гарантируем соблюдение всех регуляторных требований и проведем аудит безопасности перед релизом. Получите консультацию по вашему проекту — свяжитесь с нами для оценки сроков и стоимости. Закажите разработку AI Symptom Checker под ключ — надежное медицинское решение с защитой данных.







