惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
Arctic Wolf
WordPress大学
WordPress大学
月光博客
月光博客
J
Java Code Geeks
罗磊的独立博客
V
Visual Studio Blog
阮一峰的网络日志
阮一峰的网络日志
Y
Y Combinator Blog
GbyAI
GbyAI
The Cloudflare Blog
B
Blog
S
SegmentFault 最新的问题
T
Tenable Blog
P
Privacy International News Feed
爱范儿
爱范儿
V
Vulnerabilities – Threatpost
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Scott Helme
Scott Helme
量子位
博客园 - 三生石上(FineUI控件)
The Hacker News
The Hacker News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Security Latest
Security Latest
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
P
Proofpoint News Feed
P
Privacy & Cybersecurity Law Blog
G
GRAHAM CLULEY
C
CXSECURITY Database RSS Feed - CXSecurity.com
U
Unit 42
D
DataBreaches.Net
T
Threatpost
C
Cisco Blogs
Project Zero
Project Zero
K
Kaspersky official blog
MongoDB | Blog
MongoDB | Blog
C
Check Point Blog
A
About on SuperTechFans
The Register - Security
The Register - Security
C
Cyber Attacks, Cyber Crime and Cyber Security
S
Schneier on Security
L
Lohrmann on Cybersecurity
T
Threat Research - Cisco Blogs
I
InfoQ
Simon Willison's Weblog
Simon Willison's Weblog
F
Fortinet All Blogs
Recorded Future
Recorded Future
AWS News Blog
AWS News Blog
The GitHub Blog
The GitHub Blog
C
CERT Recently Published Vulnerability Notes

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Если клиент не идёт в больничку — телефонный бот для телемедицины
Илья Сивков · 2026-06-18 · via Все публикации подряд на Хабре

Если клиент не идёт в больничку — телефонный бот для телемедицины

Средний

5 мин

69

Никто не любит ходить по врачам: больницы, очереди, ещё и заразу можно подхватить. Поэтому сейчас развивается телемедицина. Один из вариантов - лаборант с камерой, кардиографом и т.п. катается по людям, а в офисе сидит врач и ведёт “приём” по видеосвязи. Но даже это не вдохновляет людей - пока гром не грянет, как говорится.

А грянувший гром стоит очень дорого как самим людям, так и их страховым компаниям. Поэтому они долбят своих клиентов (особенно тех, у кого есть хронические болезни), чтобы те регулярно показывались врачу. Долбят, разумеется, по телефону. Вот этот-то процесс мне поручили попробовать автоматизировать.

Архитектура

По сути, наш бот - это LLM, который разговаривает и слушает через Twilio.

Архитектура телефонного бота

Архитектура телефонного бота

Когда-то в 2019 я уже работал с Twilio. Тогда нужно было подключить к нему гугловский DialogFlow. Веселье было на полную: SIP-клиент на Python, работа с аудиопотоком через расширение на сях (без плюсов, struct/malloc/free), ручной вызов API для STT/TTS и прочие радости.

Сейчас всё упростилось до нельзя - <ConversationRelay> рулит: Twilio само переводит речь в текст и обратно, мы получаем и отправляем текст через WebSocket. Мало того, можно отправлять ответ частями (см. ниже про стриминг), а также “договаривать” (вроде “Минутку, проверяю”, потом вызываем API и сообщаем результат).

Для работы с этим хозяйством есть классическая связка “API Gateway плюс Lambda”. Лямбд здесь, на самом деле, две. Первая принимает обычные REST-запросы и отвечает за hook-и вроде начала звонка или брошенной трубки. Вторая - это сама “говорилка”. Именно здесь живёт “птичка” LangGraph, которая работает с LLM, checkpoint-ами и tools.

Есть ещё и третья лябмда. Она асинхронно дёргает наши внутренние API для проверки и бронирования времени. Про асинхронность подробнее будет ниже.

Все необходимые данные хранятся в DynamoDB. Данных этих два вида - запросы на асинхронный вызов и checkpoint-ы от LangGraph. Написать свой Saver под “динамку” - это был тот ещё квест.

К LLM мы обращаемся через Bedrock. В качестве модели мы взяли Amazon Nova. Есть модели куда мощнее, но нам хватает и этой.

Это хозяйство описано через стэк CloueFormation на AWS CDK. Немного веселья с Github Actions и всё красиво деплоится на push в master. CI/CD, однако!

Диалог

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

  • Проверяем, что на проводе тот, кто нам нужен,

  • Предлагаем записаться,

  • Если нужно, немного уговариваем,

  • Уточняем возраст, состояние здоровья и таблетки,

  • Обсуждаем удобную дату и время встречи,

  • Назначаем встречу.

Разумеется, всё что угодно может пойти не так:

  • Ответил другой человек - тогда просим пригласить нужного нам или сказать, когда перезвонить,

  • Человек не хочет записываться - уговариваем, приводим простую статистику,

  • Просит время, чтобы (например) посмотреть, как именно называются таблетки - даём время.

Обсуждение удобного времени - отдельная история. Здесь мы обрабатываем такие случаи:

  • Человек не знает, что предложить - предлагаем сами ближайшее свободное время, два-три слота

  • Если предложенное время не подходит, ищем свободное позже.

  • Люди редко мыслят датами. Обычно это “завтра вечером”, “на той недели кроме вторника” и т.п. - переводим в диапазоны даты-времени,

  • Если человек уже согласился на какое-то время, но потом вспомнил, что тогда не может - предлагаем дальше.

Промпты

Весь диалог у нас разделён на части: приветствие, уговоры (если надо), сбор сведений и обсуждение времени. Для каждой части есть свой промпт. В состоянии графа есть поле с id текущего промпта. Именно этот промпт мы отправляем в LLM, чтобы получить очередной ответ.

Сами промпты состоят из нескольких частей:

  • Контекст - что делает агент в этой части диалога,

  • Шаги - что сказать или спросить,

  • Переходы - к какой части диалога перейти потом,

  • Правила - указания по построению фраз, запреты на упоминание AI и т.п.,

  • Примеры - два-три варианта именно этой части беседы с разными исходами.

Для переходов мы инструктируем модель отвечать текстом вроде goto:booker. Эта команда затем считывается в коде.

Вызовы API и асинхронные задачи

Структура обработчика сообщений

Структура обработчика сообщений

В нашем боте есть два вызова внешних API: проверка доступного времени и назначение встречи. Второй работает мгновенно, а вот первый может думать несколько секунд. Раньше запрос был только из веб-морды, там было вполне допустимо покрутить спиннер. В телефоне такие лаги - ещё не катастрофа, но уже намёк. И мало того, что человек долго ждёт - он ещё и не может ничего спросить, даже “Ну, что там?”.

Чтобы решить эту проблему, мы сделали асинхронный вызов API через механизм задач (jobs). Работает он так:

  • Когда бот хочет проверить расписание, он говорит в трубку “Сейчас посмотрю” и тут же вызывает tool, который создаёт в DynamoDB задачу с нужными параметрами,

  • DynamoDB через Stream вызывает лямбду, которая дёргает внутренний API, ждёт ответ и сохраняет результат,

  • Если в это время человек спросит, что да как, бот вызовет tool проверки состояния задач и ответит, что ещё проверяет,

  • Когда ответ API пришёл, лямбда с ботом получает событие из DynamoDB Stream и сообщает результат. Здесь как раз полезны веб-сокеты: бот может начать говорить, не дожидаясь очередной реплики пользователя.

  • Пока API думает, бот говорит в трубку “Я тут, проверяю” примерно раз в десять секунд. Сделано это через отправку вопроса “нучёкак” по таймеру.

Стрим токенов

Модели сейчас быстрые, но не мгновенные. Чтобы пользователь не ждал, пока модель родит ответ целиком, мы используем поток токенов. Идея тут простая: как только модель выдала хоть что-то, мы отправляем это в сокет Twilio с пометкой “будет ещё”. Когда модель закончила свою тираду, сообщаем об этом в сокет.

Вроде всё здорово, и даже из коробки, но есть два момента:

  • у нас есть команды смены промптов, которые не надо зачитывать,

  • LLM в режиме стриминга не убирает размышления,а обрамляет их в тег <thinking>.

Поэтому мы добавили фильтр, который не пропускает в сокет мысли модели и наши команды. Интересно, что LLM выдаёт текст с почти непредсказуемым разбиением. Например, ‘try!<’, ‘think’, ‘ing’, ‘>Now’. Получилась неплохая задачка в духе LeetCode на buffer/flush и регулярки.

Генерация ответа

Процесс обработки реплики пользователя

Процесс обработки реплики пользователя

Работа с LLM и tools проводится через LangGraph. Сначала мы проверяем, есть ли у нас незавершённые асинхронные вызовы. Напомню, что в LangGraph чат хранит не только реплики, но и вызовы и результаты работы tools. Поэтому эти сведения можно узнать прямо из сообщений, которые у нас уже есть. Если незавершённые вызовы есть, проверяем их статус.

Далее выбираем нужный промпт, подставляем туда некоторые сведения вроде имени пользователя, и отправляем в LLM. Ответ модели в большинстве случаев отправляем в стрим Twilio. Исключение составляют команды перехода к другой части диалога. Например, после приветствия человек согласился обсудить приём. Тогда в качестве ответа модель вернёт команду перехода к сбору сведений. В этом случае мы берём соответствующий промпт и вызываем LLM ещё раз. Результат уже точно будет сообщением (в нашем примере - просьба назвать возраст), отправляем его в стрим Twilio.

К тому моменту, как дело дойдёт до выбора времени, диалог может быть достаточно длинным. Поэтому перед началом мы сжимаем все предыдущие сообщения в один абзац. Он сообщает модели нечто вроде “Ты говоришь с женщиной по имени Гюльчатай, ей 55 лет, у неё…” ну и т.д. Этот кусок мы вставляем в промпт в качестве вводных.

Заключение

Кроме описанного выше есть ещё веб-морда для звонков по WebRTC. Вместе с ней получился вполне приличный прототип. Направлений развития здесь пруд пруди:

  • Автоматическое определение языка - если человек вместо “здравствуйте” предложил что-то там опустить в чай, то предложить ему перейти на китайский,

  • Интеграция с внешними сервисами - например, некто ходит к врачам только в определённую фазу луны. Можно вызвать API лунного календаря и узнать ближайшие даты,

  • Разные цели диалога и набор шагов - естественный шаг к multi-tenancy

Но это уже в следующей жизни…