Мой блог
Локальный ИИ-ассистент для созвонов, часть 4: что происходит после кнопки «Стоп» и как работает ревизия
В прошлых материалах моего проекта по созданию умного локального ассистента для онлайн-встреч я подробно разбирал процессы записи созвонов, формирования графа знаний и проблемы с точным определением того, кто именно говорит в конкретную секунду. Сегодня речь пойдёт о тридцатиминутном окне после того, как в интерфейсе нажата кнопка «Стоп». На первый взгляд, в эти минуты на экране ничего не происходит, но на самом деле диск нагружен по максимуму. Именно в этом блоке я недавно обнаружил системную проблему, существовавшую ещё с лета: облачная модель ревизии регулярно находила ошибки работы локальной ИИ-модели, детально описывала их в отчётах, но система просто игнорировала эти исправления.
Одна встреча, четыре файла и 25 минут работы фоновых процессов
Чтобы наглядно показать суть проблемы, приведу конкретный пример из своей практики. В пятницу у нас проходил двухчасовой рабочий созвон. Запись была официально остановлена в 17:33. В логах системы зафиксирована следующая хронология фоновых процессов:
- 17:33 — Снятие фиксации аудио, закрытие живого черновика стенограммы.
- 17:36 — Формирование финального текста стенограммы: полная канальная диаризация, повторный проход распознавания речи и сопоставление имён спикеров.
- 17:38 — Создание заметки встречи в графе знаний, обновление узлов участников и систем, генерация протокола (минуток), выявление задач и передача семи ключевых фактов в векторную память.
- 17:58 — Завершение работы облачной ревизии (заняло 20 минут): перенесено 57 правок графа, в протокол добавлено 7 пропущенных поручений.
Локальная модель при первичном разборе записала в протокол три ключевых решения и несколько задач. Однако облачная ревизия, изучив всю стенограмму целиком, отвергла два решения из трёх. Одно из них на поверку оказалось шуткой коллеге про «один токен на всех в следующем году», а второе относилось к соседней команде. Третье решение было правильным по сути, но содержало неверного исполнителя.
Кроме того, ревизия сняла три ложных поручения: одно было назначено человеку, не присутствовавшему на созвоне, второе имело выдуманный срок, а в третьем числовой показатель бюджета был прочитан с точностью до наоборот. Также была обнаружена ошибка распознавания ведущего: из-за обращения по имени дорожке присвоили чужой идентификатор.
Все эти корректировки были подробно описаны в файле ревизии с цитатами и таймкодами. Но возникла парадоксальная ситуация: система умела лишь дописывать новые данные! В результате новые поручения добавились, а ложные остались на месте и благополучно ушли во вкладку «Задачи». Ошибочная шутка про бюджет сохранила статус решения, а выдуманные факты попали в векторную память, из-за чего поиск по базе ответов выдавал шуточный токен как утверждённый регламент компании.
Логика конвейера после остановки записи
Весь пост-процессинг встречи в моём ассистенте разделён на пять последовательных этапов:
- Пересборка аудио и текста. Во время созвона черновик собирается из 3-секундных отрезков. После остановки запись заново диаризуется по каналам, эхо режется путём сравнения микрофона с системным звуком, а имена спикеров вычисляются по обращениям в речи. Исходные файлы убираются в архив.
- Формирование графа. Локальная нейросеть (35B MoE под управлением Ollama) разбирает стенограмму в структурированный JSON: участники, сервисы, принятые решения, поручения. Из этого формируется Markdown-заметка встречи, узлы сущностей и первичный разбор.
- Облачная ревизия. Если включён внешний облачный слой, система через CLI передаёт полный контекст и стенограмму крупной LLM. Она проводит глубокий аудит: ищет пропуски, галлюцинации и ошибки локальной модели, после чего вносит правки в клон графа.
- Доставка результатов. Отчёт ревизии публикуется рядом со стенограммой, а обновлённый протокол с задачами синхронизируется с реестром дел.
- Ночные регламенты. Сборка единого досье, актуализация связей и подготовка утреннего брифинга.
Зачем нужен второй проход нейросети
У многих возникнет логичный вопрос: почему сразу не заставить локальную модель работать без ошибок? Причина кроется в потоковой природе первичного разбора. Локальная нейросеть формирует протокол каждые две-три минуты, видя только короткий фрагмент диалога. Шутка про урезание бюджета кажется ей принятым решением, так как реакции аудитории или последующего пояснения в её контекстном окне ещё нет.
Облачная модель читает полный текст созвона от начала до конца за один проход. Она видит общую картину, замечает неверную смену спикеров и легко отсекает наводки из соседних веток графа. Использовать мощную облачную модель единоразово после завершения встречи оказывается ощутимо дешевле и эффективнее, чем пытаться вытянуть высокое качество от локальной нейросети в реальном времени.
Однако для полноценной работы второго прохода модель должна уметь не только добавлять найденные детали, но и жестко отменять (снимать) ошибочно созданные записи в графе, файлах задач и векторной базе данных.
Механика отмены и корректировки данных
Чтобы код программы мог однозначно трактовать вердикты ревизии, я ввёл строго структурированные Markdown-разделы в конце файла отчёта:
## Восстановленные поручения— список упущенных задач;## Снятые поручения— список ложных задач с указанием причины;## Исправления имён— сопоставление меток дорожек и реальных имён.
Особую сложность представлял алгоритм сопоставления текста ревизии с ранее созданными строками в протоколе. Первоначальный вариант нечёткого поиска приводил к тому, что одно снятое поручение аннулировало все похожие формулировки. Чтобы исключить случайное удаление реальных задач, я выработал следующие жесткие правила:
- Один пункт отмены снимает ровно одну строку протокола.
- При наличии нескольких похожих вариантов приоритет отдаётся точному совпадению. Если точного совпадения нет — операция отменяется, а событие логируется.
- Для частичного совпадения требуется минимум два общих ключевых слова.
- Задачи, уже отмеченные пользователем как выполненные, отмене не подлежат.
- Снятая строка не удаляется из файла навсегда, а переносится в блок «Снято ревизией» в зачёркнутом виде с указанием причины.
С решениями ситуация оказалась проще: при обнаружении ошибки облачная модель меняет статус маркера в заметке с 📌 на ⛔ и дописывает причину отмены. Все последующие сервисы индексации и поиска автоматически игнорируют строки со значком отмены.
Синхронизация векторной памяти
База данных долгосрочной памяти ассистента оперирует привязкой к ID встречи, а не к отдельным фактам. Следовательно, нельзя просто «стирать» одно решение — требуется полностью обновлять слепок встречи.
Я реализовал механизм сравнения списка активных решений до и после работы ревизии. Если список изменился, память встречи полностью сбрасывается и перезаписывается на основе актуализированной заметки без отменённых пунктов. Анализируя структуру сервиса, я также принял решение в перспективе выключить второй сервис векторной памяти, полностью переведя функционал на гибридный поиск внутри графа знаний на базе Markdown-файлов.
Корректировка имён спикеров
Ошибка диаризации, когда аудиотреку присваивается не то имя, раньше оставалась в стенограмме навсегда. Теперь на основе блока ## Исправления имён скрипт автоматической перештамповки заменяет заголовки реплик и список участников во всех материалах созвона.
При этом я установил четыре защитных ограничения:
- Текст самих поручений не переименовывается автозаменой, так как имя в тексте может относиться к реальному человеку из речи, а не к названию дорожки.
- Замена названий дорожек выполняется одновременно в один проход, чтобы избежать закольцовывания (когда А меняется на Б, а затем Б обратно на А).
- Объединение двух разных дорожек под одним именем без подтверждения запрещено.
- Аппаратная метка микрофона владельца системы не подлежит автоматической перезаписи.
Обработка сбоев и честные статусы
За время тестирования из 19 запусков ревизии 4 завершились без результата из-за таймаутов или сетевых сбоев. Раньше при таком сбое статус встречи всё равно помещался как «Готово», и пользователь не знал о необработанных ошибках.
Сейчас ревизия имеет четыре фиксированных состояния: Доставлено, Некорректный ответ, Сбой запуска и Таймаут. Автоматический повтор выполняется только при падении процесса — ровно один раз через 10 минут. Если произошёл таймаут, система не тратит ресурсы повторно, так как повторный запрос на том же контексте приведёт к аналогичной задержке.
Автоматический аудит кода AI-агентами
Для проверки надежности написанного кода я применил методику мультиагентного аудита по зонам. Репозиторий был разбит на 5 изолированных сегментов: пересборка имён, граф знаний, облачная ревизия, интеграция задач и синхронизация памяти.
Каждая зона параллельно анализировалась двумя независимыми моделями (DeepSeek и GLM) с ограничением по времени в 12 минут и чётким лимитом на количество шагов. В результате 10 параллельных процессов за $0,79 выявили 17 подтверждённых дефектов в логике обработки файлов и блокировок, которые я успешно исправил.
Итоги и планы по развитию проекта
За прошедший этап работы над локальным ассистентом удалось добиться существенных результатов:
- Ревизия научилась корректно отменять ложные задачи и решения, обновляя векторную память.
- Внедрена безопасная перештамповка имён спикеров без риска потери данных.
- Настроена прозрачная система статусов и устойчивость к сбоям API.
- Запущен регулярный автоаудит кода с помощью нейросетевых агентов.
В ближайших планах — закрытие всех найденных замечаний через пулл-рекуесты, постепенный отказ от избыточного второго сервиса векторной памяти в пользу единого графа на Markdown-файлах, а также окончательная интеграция голосового слепка (Voice Print) для точного распознавания моего голоса независимо от используемого канала аудио.
Источник: habr.com
