Ошибка в 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 под ключ — надежное медицинское решение с защитой данных.







