ideipro logotyp

Как я собрал AI-ассистента для отца с больным сердцем: Tool-Calling RAG Pipeline на GPT-4o-mini без LangChain

🚀 Идея, Которая Важнее Кода

Мой отец — человек, переживший несколько сложнейших операций на сердце. Жизнь с хроническим заболеванием — это бесконечный поток анализов, заключений и схем приёма лекарств. Находясь далеко (я живу во Вьетнаме), я постоянно волновался: не забудет ли он про дозу, правильно ли понял назначение, задал ли все нужные вопросы врачу?

Мне нужен был не просто бот-напоминалка, а второй пилот — умный, конфиденциальный и мультимодальный AI-Кардиолог. Ассистент, который знает его анамнез наизусть, понимает голосовые команды и может «прочитать» фотографию свежего анализа.

Я решил собрать полноценный автономный агент с возможностью вызова внешних инструментов (Tool-Calling) и локальной базой знаний (RAG), но без использования громоздких фреймворков вроде LangChain или LlamaIndex.

🧠 Архитектура: Планировщик и Жесткий Контроль

Моя цель: максимальная надёжность, локальность данных и предсказуемость.

Ядро системы — это Полноценный Tool-Calling Pipeline на GPT-4o-mini, который работает в два этапа: Планирование и Генерация.

Компонент

Технология

Роль в системе

Планировщик

GPT-4o-mini (OpenRouter)

Принимает решение: local_rag, internet_search или none.

База знаний (RAG)

ChromaDB + SentenceTransformer (локально)

Хранит историю болезни, анализы, заметки.

Веб-поиск

DuckDuckGo Search (DDGS)

Предоставляет актуальные медицинские данные из сети.

Мультимодальность

Tesseract OCR + AssemblyAI STT

Понимание фотоанализов и голосовых сообщений.

Метаданные

SQLite

Надёжное хранение истории чата и метаинформации о документах.

1. Ядро: Двухэтапный Tool-Calling

Вместо того чтобы надеяться на то, что модель сама «вспомнит» или «погуглит», я заставляю её выбрать инструмент, прежде чем давать ответ.

Шаг A. Планирование (Forced JSON)

Мы передаём модели текущий вопрос и историю диалога. Самое важное: мы заставляем её вернуть ответ в строгом формате JSON:

JSON

{     «tool»: «local_rag,internet_search»,     «query»: «последний уровень холестерина и побочные эффекты статинов» }

Преимущества JSON: Это делает пайплайн невероятно надёжным. При ошибке парсинга я выполняю Graceful Fallback — автоматически переключаюсь на local_rag как на самый безопасный вариант.

Шаг Б. Сбор Контекста

После получения плана мы выполняем поиск:

  • Локальный RAG: Используем поисковый запрос (query из JSON) для извлечения релевантных личных данных из ChromaDB.

  • Веб-поиск: Используем DuckDuckGo Search с региональными настройками (region=’ru-ru’) для получения актуальной информации.

Все найденные данные объединяются в один системный промпт для финальной модели. При этом я использую жёсткую маркировку (например, === ИНФОРМАЦИЯ ИЗ ВЕБ-ПОИСКА ===), чтобы модель чётко разделяла личные факты и общие знания.

💻 Погружение в Код: Ключевые Функции

Вот как выглядит ядро пайплайна на Python.

A. Функция Планирования (chat_with_assistant)

Эта функция объединяет планирование и генерацию. Обратите внимание, как мы фиксируем текущую дату в промпте — это критически важно для медицинского ассистента при расчёте сроков действия рецептов или возраста пациента.

Python

# ГЛАВНАЯ ФУНКЦИЯ: Tool Calling (Планирование) с фиксацией даты def chat_with_assistant(user_id: int, message_text: str) -> str: # 💡 ИСПРАВЛЕНИЕ: Получаем текущую дату и время current_datetime_str = datetime.now().strftime(«%d.%m.%Y %H:%M:%S») PLANNING_PROMPT = f»»» Проанализируй следующий вопрос… Текущая дата: {current_datetime_str}. Тебе нужно решить, какой инструмент необходим… # … (Остальная часть промпта) … Вопрос пациента: «{message_text}» «»» # — ВЫЗОВ 1: ПЛАНИРОВАНИЕ (Формат JSON) — data_plan = { «model»: «gpt-4o-mini», # … «response_format»: {«type»: «json_object»} # Принудительный JSON } # … (Обработка ответа, извлечение tools и query) … # — ВЫПОЛНЕНИЕ ПЛАНА (Сбор контекста) — # … (Вызовы retrieve_relevant и search_internet) … # — ВЫЗОВ 2: ГЕНЕРАЦИЯ ОТВЕТА — if context_parts: # Жёсткая инструкция для финального ответа STRICT_INSTRUCTION = «nnВНИМАНИЕ! … Твой ответ ОБЯЗАН быть основан на информации из раздела ‘ИНФОРМАЦИЯ ИЗ ВЕБ-ПОИСКА’. …» context_joined = «nn=== РЕЛЕВАНТНЫЙ КОНТЕКСТ (ОБЯЗАТЕЛЬНО ИСПОЛЬЗУЙ) ===n» + «nn—nn».join(context_parts) full_system_prompt = SYSTEM_PROMPT + STRICT_INSTRUCTION + context_joined # … (Добавление истории и отправка финального запроса) …

Б. Конфиденциальность: RAG без облаков

Вся медицинская история хранится локально с помощью ChromaDB и SentenceTransformer.

Python

# ————————— # ChromaDB Embedder Initialization # ————————— try: # … (импорт и инициализация) … LOCAL_EMBEDDING_MODEL_NAME = «all-MiniLM-L6-v2» CHROMA_EMBEDDER = embedding_functions.SentenceTransformerEmbeddingFunction( model_name=LOCAL_EMBEDDING_MODEL_NAME, device=’cpu’ # Ключевой момент: все локально! ) # … (создание коллекции) … except Exception as e: logger.error(«Ошибка при инициализации SentenceTransformer: %s», e)

В. Полная Мультимодальность (Голос и Фото)

Это делает ассистента удобным для человека, не слишком активно пользующегося новыми технологиями.

1. OCR для Анализов (Tesseract)

Фотографии документов переводятся в текст, затем отправляются в LLM на расшифровку и сохраняются в RAG.

Python

@bot.message_handler(content_types=[‘photo’]) def handle_photo(message): # … (скачивание файла) … raw_text = extract_text_from_image_bytes(downloaded) # Анализ и саммаризация текста нейросетью summary = analyze_medical_text(raw_text) # Сохраняем в RAG add_to_chroma(doc_id, summary, metadata) # … (ответ пользователю) …

2. Голосовое управление (AssemblyAI)

Я добавил логику автоматического распознавания намерения для голосовых сообщений, начинающихся со слова «запомни».

Python

@bot.message_handler(content_types=[‘voice’]) def handle_voice(message): # … (транскрипция с AssemblyAI) … # 💡 ЛОГИКА АВТОМАТИЧЕСКОГО ЗАПОМИНАНИЯ ДЛЯ ГОЛОСА if transcribed_text.lower().startswith(«запомни»): memory_text = transcribed_text[len(«запомни»):].strip() if memory_text: # Сохраняем данные в RAG и прерываем обычный диалог add_to_chroma(doc_id, memory_text, metadata) # … return # Если это не команда «запомни», передаем в основную логику чата resp = chat_with_assistant(message.chat.id, transcribed_text) bot.reply_to(message, resp)

💡 Итог: Что получилось

Я создал автономного медицинского ассистента, который:

  1. Всегда помнит его личную историю, анализы и заметки.

  2. Умеет искать актуальную информацию в сети.

  3. Понимает любой ввод: текст, фото или голос.

  4. Сам выбирает, что делать с помощью двухэтапного Tool-Calling.

Это не просто код, это часть заботы. Проект показал, как можно использовать современные возможности LLM, RAG и мультимодальности для решения реальных и очень личных проблем, сохраняя при этом контроль, конфиденциальность и надёжность.

Надеюсь, мой опыт вдохновит и вас на создание социально-значимых проектов, где код служит самой важной цели.

Источник: habr.com

✅ Найденные теги: Как, новости

ОСТАВЬТЕ СВОЙ КОММЕНТАРИЙ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Фото сгенерированных лиц: исследование показывает, что люди не могут отличить настоящие лица от сгенерированных
Нейросети построили капитализм за трое суток: 100 агентов Claude заперли…
Скетч: цифровой осьминог и виртуальный мир внутри компьютера с человечком.
Сцена с жестами пальцами, где один жест символизирует "VPN", а другой "KHP".
‼️Paramount купила Warner Bros. Discovery — сумма сделки составила безумные…
Скриншот репозитория GitHub "Claude Scientific Skills" AI для научных исследований.
Структура эффективного запроса Claude с элементами задачи, контекста и референса.
Эскиз и готовая веб-страница платформы для AI-дизайна в современном темном режиме.
ideipro logotyp
Image Not Found
Звёздное небо с галактиками и туманностями, космос, Вселенная, астрофотография.

Система оповещения обсерватории Рубина отправила 800 000 сигналов в первую ночь наблюдений.

Астрономы будут получать оповещения о небесных явлениях в течение нескольких минут после их обнаружения. Теренс О'Брайен, редактор раздела «Выходные». Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной…

Мар 2, 2026
Женщина с длинными тёмными волосами в синем свете, нейтральный фон.

Расследование в отношении 61-фунтовой машины, которая «пожирает» пластик и выплевывает кирпичи.

Обзор компактного пресса для мягкого пластика Clear Drop — и что будет дальше. Шон Холлистер, старший редактор Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 2, 2026
Черный углеродное волокно с текстурой плетения, отражающий свет.

Материал будущего: как работает «бессмертный» композит

Учёные из Университета штата Северная Каролина представили композит нового поколения, способный самостоятельно восстанавливаться после серьёзных повреждений.  Речь идёт о модифицированном армированном волокном полимере (FRP), который не просто сохраняет прочность при малом весе, но и способен «залечивать» внутренние…

Мар 2, 2026
Круглый экран с изображением замка и горы, рядом электронная плата.

Круглый дисплей Waveshare для креативных проектов

Круглый 7-дюймовый сенсорный дисплей от Waveshare создан для разработчиков и дизайнеров, которым нужен нестандартный экран.  Это IPS-панель с разрешением 1 080×1 080 пикселей, поддержкой 10-точечного ёмкостного сенсора, оптической склейкой и защитным закалённым стеклом, выполненная в круглом форм-факторе.…

Мар 2, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых