Медицинский AI-агент: Пошаговый гайд с smolagents и AWS на 2026 год | AiManual
AiManual Logo Ai / Manual.
01 Мар 2026 Гайд

Как построить агентный AI для медицины с Hugging Face smolagents и AWS: код, архитектура и deployment

Создаем production-ready медицинского AI-агента с помощью Hugging Face smolagents и AWS (Bedrock, SageMaker). Полный код, архитектура и инструкция по deployment

Почему медицинские агенты все еще не работают у вас в больнице

Вы видели демо. Агент читает историю болезни, ставит предположительный диагноз, советует терапию. Звучит как будущее. А потом вы пытаетесь запустить это в реальной клинике, и все ломается. Модель галлюцинирует, доступ к медицинским данным заблокирован файрволом, а юристы хватаются за голову.

Проблема не в моделях. Claude 3.5 Sonnet или Llama 3.2 90B достаточно умны. Проблема в архитектуре. В том, как заставить модель безопасно взаимодействовать с инструментами, EHR-системами (Electronic Health Records) и при этом не сойти с ума от контекста в 200 тысяч токенов.

Самый частый провал - это попытка запихнуть все в один промпт к ChatGPT API. Не делайте так. Медицина требует модульности, аудита и четкого разделения ответственности между компонентами.

Спасательный круг: smolagents от Hugging Face и сервисы AWS

В 2026 году экосистема для сборки агентов созрела. Hugging Face smolagents (актуальная версия 2.1+) - это не просто еще один фреймворк. Это минималистичный, но мощный каркас, который заставляет вас думать об архитектуре, а не о синтаксисе. Он родился из осознания, что большие фреймворки часто мешают в production.

А AWS? Это ваша инфраструктурная платформа. Не просто для запуска моделей, а для создания цепочки: безопасный доступ к данным → выполнение агента → логирование и мониторинг. Связка smolagents и AWS решает ключевые вопросы:

  • Безопасность и комплаенс: Данные пациентов не улетают в сторонние API.
  • Масштаб: От десятка запросов в день до тысяч параллельных консультаций.
  • Интеграция: Агент становится частью IT-ландшафта больницы, а не игрушкой в Jupyter Notebook.

Если вы хотите глубже понять философию проектирования современных агентов, загляните в наш гайд о проектировании AI-агентов.

Архитектура: что происходит под капотом

Забудьте про монолитного агента. Наш медицинский помощник - это система.

Слой Технологии (актуально на 01.03.2026) Зачем
Оркестратор / Мозг Hugging Face smolagents, модель (Llama 3.2 90B или Claude 3.5 через Bedrock) Принимает решение, какой инструмент использовать и в каком порядке. Не лечит, а планирует.
Инструменты (Skills) Python-функции, обернутые в smolagents.Tool, доступ к AWS HealthLake, медицинским калькуляторам Конкретные действия: рассчитать дозу, поиск в медицинской литературе, запрос к EHR.
Безопасный контекст AWS PrivateLink, VPC, зашифрованные S3-бакеты для данных Изоляция данных пациента. Ключевой момент для HIPAA/GDPR.
Сервисный слой FastAPI (контейнеризованный), запущенный на AWS Fargate или SageMaker Endpoints Предоставляет REST API для интеграции с фронтендом или EHR-системой.

Архитектура напоминает принципы, описанные в статье про production-ready агентов, но заточена именно под медицинские нужды.

1 Готовим инструменты: что умеет наш врач-агент

Агент без инструментов - просто чат-бот. Вот набор, который имеет смысл:

from smolagents import Tool
from typing import Dict
import json

# 1. Инструмент для поиска в медицинской базе знаний (условно)
class MedicalLiteratureSearchTool(Tool):
    name = "medical_literature_search"
    description = "Searches the latest medical guidelines and research for a given query."
    inputs = {"query": "The medical question or topic to search for"}

    def forward(self, query: str) -> str:
        # Здесь интеграция с PubMed API или собственной векторной БЗ
        # Например, через Amazon Bedrock Knowledge Bases
        return f"Found relevant info on {query}: ..."

# 2. Калькулятор дозировки (крайне упрощенно!)
class DoseCalculatorTool(Tool):
    name = "calculate_dose"
    description = "Calculates medication dose based on weight, condition, and guidelines."
    inputs = {
        "drug_name": "Name of the medication",
        "patient_weight_kg": "Patient's weight in kilograms",
        "condition": "Medical condition being treated"
    }
    def forward(self, drug_name: str, patient_weight_kg: float, condition: str) -> Dict:
        # В реальности - сложная логика с проверкой по базе данных
        # Это пример, не используйте в реальной медицине!
        standard_dose_per_kg = 5.0  # мг/кг
        calculated_dose = patient_weight_kg * standard_dose_per_kg
        return {
            "drug": drug_name,
            "calculated_dose_mg": round(calculated_dose, 2),
            "warning": "ALWAYS verify with a licensed pharmacist."
        }

# 3. Инструмент для запроса безопасных данных из EHR (имитация)
class QueryPatientEHRTool(Tool):
    name = "query_patient_ehr"
    description = "Retrieves de-identified patient data from the EHR system for the current session."
    inputs = {"patient_id": "De-identified patient identifier"}
    def forward(self, patient_id: str) -> str:
        # В production здесь будет вызов AWS HealthLake или API вашей EHR
        # через PrivateLink в безопасной VPC
        mock_data = {
            "age": 45,
            "latest_observations": {"blood_pressure": "120/80"},
            "active_medications": ["Lisinopril"]
        }
        return json.dumps(mock_data, indent=2)

Внимание! Калькулятор дозировки выше - это демо-заглушка. Настоящий медицинский инструмент должен быть валидирован, сертифицирован и включать десятки проверок. Не используйте такой код в реальных системах без участия врачей и фармакологов.

Идея в том, что каждый инструмент делает одну конкретную, проверяемую вещь. Это делает агента интерпретируемым. Вы всегда можете посмотреть в логи, какой инструмент был вызван и с какими аргументами. В медицине это не просто удобно, это обязательно.

2 Собираем агента воедино с smolagents

Теперь склеиваем инструменты с моделью. Ключевая фишка smolagents - минимализм. Вы явно указываете, что чем управляет.

from smolagents import CodeAgent, ToolCallingAgent
from dotenv import load_dotenv
import os

load_dotenv()

# Создаем экземпляры инструментов
med_search_tool = MedicalLiteratureSearchTool()
dose_calc_tool = DoseCalculatorTool()
ehr_query_tool = QueryPatientEHRTool()

tools = [med_search_tool, dose_calc_tool, ehr_query_tool]

# Выбор модели: локальная или через Bedrock
# Вариант 1: Локальная модель (например, для прототипирования в VPC)
# from transformers import AutoModelForCausalLM, AutoTokenizer
# model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-90B")

# Вариант 2: Модель через Amazon Bedrock (актуально на 2026)
# Это предпочтительный путь для production: управляемый сервис, compliance, масштабирование.
import boto3
from smolagents.models import BedrockModel

# Инициализация клиента Bedrock (предполагается, что права есть)
bedrock_client = boto3.client(
    service_name='bedrock-runtime',
    region_name='us-east-1'
)

# Используем Claude 3.5 Sonnet - одна из самых способных моделей на 2026 для рассуждений
model = BedrockModel(
    model_id="anthropic.claude-3-5-sonnet-20241022",
    client=bedrock_client,
    max_tokens=4000
)

# Создаем агента
agent = ToolCallingAgent(
    model=model,
    tools=tools,
    max_steps=6,  # Ограничиваем, чтобы агент не зациклился
    verbosity_level=2  # Подробные логи для отладки
)

# Тестовый запуск
question = "Пациент ID-12345, вес 70 кг. Какая рекомендуемая стартовая доза препарата X для лечения гипертонии согласно последним гайдлайнам?"
try:
    answer = agent.run(question)
    print("Ответ агента:", answer)
except Exception as e:
    print(f"Агент споткнулся: {e}")

Что здесь происходит? Агент получает вопрос, планирует цепочку: 1) Запросить данные пациента из EHR. 2) Поискать актуальные гайдлайны по гипертонии и препарату X. 3) Рассчитать дозу, используя вес из EHR и информацию из гайдлайнов. Smolagents управляет этим циклом (think → act → observe).

💡
Если ваша задача сложная и требует иерархии, присмотритесь к подходу с сабагентами. Вместо одного большого агента вы создаете нескольких узкоспециализированных. Об этом у нас есть отдельный разбор в статье про суб-агентов.

3 Упаковка и деплой на AWS: где живет production-агент

Запуск скрипта на ноутбуке - это не продакшен. Медицинская система требует отказоустойчивости, мониторинга и безопасности. Вот план развертывания.

Шаг 3.1: Контейнеризация

Упаковываем агента, инструменты и легковесный HTTP-сервер (например, FastAPI) в Docker-контейнер.

# Dockerfile
FROM python:3.11-slim

WORKDIR /app

# Устанавливаем системные зависимости, если нужны
RUN apt-get update && apt-get install -y --no-install-recommends gcc g++ && rm -rf /var/lib/apt/lists/*

# Копируем requirements
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Копируем исходный код
COPY app ./app

# Открываем порт
EXPOSE 8000

# Запускаем сервер
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
# app/main.py - основа FastAPI приложения
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from app.agent import get_medical_agent  # Ваша функция для создания агента
import logging

app = FastAPI(title="Medical AI Agent API")
logger = logging.getLogger(__name__)

# Глобально инициализируем агента (или лениво в запросе)
agent = None

class AgentQuery(BaseModel):
    question: str
    session_id: str  # Для трекинга диалога
    patient_id: str | None = None  # Деидентифицированный ID

@app.on_event("startup")
async def startup_event():
    global agent
    logger.info("Initializing Medical Agent...")
    agent = get_medical_agent()
    logger.info("Agent ready.")

@app.post("/query")
async def query_agent(query: AgentQuery):
    if not agent:
        raise HTTPException(status_code=503, detail="Agent not initialized")
    
    # Здесь можно добавить валидацию, проверку прав доступа к patient_id и т.д.
    logger.info(f"Processing query for session {query.session_id}")
    
    try:
        result = agent.run(query.question)
        # Обязательно логируем вопрос и ответ (в безопасном, деидентифицированном виде)
        logger.info(f"Session {query.session_id}: Q: {query.question[:100]}... | A generated.")
        return {"session_id": query.session_id, "answer": result, "status": "success"}
    except Exception as e:
        logger.error(f"Agent error in session {query.session_id}: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Agent processing failed: {str(e)}")

Шаг 3.2: Развертывание на AWS

У вас есть несколько путей, но для медицинского load'а сценарий обычно такой:

  1. Реестр образов: Заливаем Docker-образ в Amazon ECR (Elastic Container Registry).
  2. Оркестрация: Запускаем сервис на AWS Fargate. Почему Fargate, а не SageMaker Endpoints? Потому что наш агент - это кастомное Python-приложение со сложными зависимостями, а не просто модель для инференса. Fargate дает полный контроль над окружением.
  3. Сеть: Размещаем сервис в приватных подсетях VPC. Настраиваем AWS PrivateLink для безопасного доступа к внутренним API (например, к вашей EHR-системе или AWS HealthLake). Входящий трафик из интернета идет через Application Load Balancer (ALB) с TLS-терминацией.
  4. Секреты и конфигурация: Ключи API для Bedrock, параметры подключения к базам данных храним в AWS Secrets Manager и передаем в контейнер через переменные окружения.
  5. Мониторинг: Логи агента (через CloudWatch Logs) и метрики (задержка, количество шагов, ошибки инструментов) настраиваем для тревог. Это критично для отладки и compliance.

Развернуть все это руками - боль. Используйте Infrastructure as Code. Вот кусочек Terraform для Fargate (концептуально):

# main.tf (фрагмент)
resource "aws_ecs_task_definition" "medical_agent" {
  family                   = "medical-agent"
  cpu                      = "4096"  # 4 vCPU
  memory                   = "16384" # 16 GB - для больших моделей в памяти
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  execution_role_arn       = aws_iam_role.ecs_execution_role.arn
  task_role_arn           = aws_iam_role.agent_task_role.arn  # Роль с доступом к Bedrock, Secrets Manager и т.д.

  container_definitions = jsonencode([{
    name  = "agent-container"
    image = "${aws_ecr_repository.medical_agent.repository_url}:latest"
    portMappings = [{ containerPort = 8000, hostPort = 8000 }]
    environment = [
      { name = "BEDROCK_REGION", value = "us-east-1" },
      # Остальное из Secrets Manager
    ]
    secrets = [
      {
        name      = "BEDROCK_ACCESS_KEY"
        valueFrom = data.aws_secretsmanager_secret_version.bedrock_creds.arn
      }
    ]
    logConfiguration = {
      logDriver = "awslogs",
      options = {
        "awslogs-group"         = "/ecs/medical-agent",
        "awslogs-region"        = var.region,
        "awslogs-stream-prefix" = "ecs"
      }
    }
  }])
}

Почему не SageMaker? SageMaker Endpoints отлично подходят для обслуживания одной модели. Но наш агент - это приложение с состоянием, множеством вызовов инструментов и сложной логикой. Его проще упаковать в контейнер и запустить как сервис. Хотя, для прототипа вы можете использовать SageMaker JumpStart с готовыми контейнерами для моделей, а логику агента реализовать в лямбде. Но это быстро становится громоздко.

Где все еще больно: ошибки, которые сломают ваш агент

Теория гладкая. Практика - это сплошные грабли.

  • Модель отказывается пользоваться инструментами. Особенно в медицинских сценариях, где ответ «я не могу» предпочтительнее галлюцинации. Решение: Тщательно промпт-инжиниринг в smolagents, описание инструментов с явным указанием их важности. И выбор модели, которая хорошо слушает инструкции (Claude 3.5 в этом чемпион).
  • Зацикливание. Агент вызывает один и тот же инструмент с одинаковыми аргументами по кругу. Решение: Строгое ограничение max_steps, добавление инструмента-«предохранителя», который завершает сессию при повторении.
  • Утечка PII (Personal Identifiable Information). Самое страшное. Модель может случайно вывести имя пациента в ответе. Решение: Все инструменты, работающие с EHR, должны возвращать только деидентифицированные данные. На выходе агента ставьте дополнительный фильтр-сканер на PII (например, с помощью Amazon Comprehend Medical).
  • Непредсказуемая стоимость. Bedrock Claude 3.5 за 1000 токенов входных/выходных данных стоит денег, а агент может делать много шагов. Решение: Жесткие лимиты на длину запроса и количество шагов, мониторинг стоимости на дашборде AWS Cost Explorer.

Оценивать готовность такой системы к продакшену вам поможет фреймворк, о котором мы писали в статье про оценку AI-агентов Amazon.

Что дальше? Агент как часть команды

Успешно развернутый агент - это не конец, а начало. Следующий уровень - интеграция в рабочие процессы врачей. Не как замена, а как ассистент.

Представьте интерфейс, где врач видит ход рассуждений агента: «Я запросил историю прививок → проверил гайдлайны CDC → рассчитал, что вакцина X рекомендуется». Это builds trust. Логи каждого сеанса можно использовать для улучшения инструментов и обучения новых моделей (с соблюдением всех этических норм и анонимизации).

Совет напоследок: начните с узкой, конкретной медицинской задачи. Не «диагностика», а «помощь в подборе начальной дозы антикоагулянта на основе веса, возраста и функции почек». Соберите для нее набор проверенных инструментов. Отработайте цикл на прототипе с юристами и врачами. И только потом масштабируйте архитектуру на AWS. Так у вас будет меньше шансов построить еще одну крутую, но бесполезную игрушку.

Подписаться на канал