Зачем это вообще нужно? (Спойлер: контроль и приватность)
Представьте: у вас есть 10 часов записей подкастов, лекций или встреч. Вы хотите их проанализировать, задавать вопросы по содержанию, найти конкретный момент. Отправлять это в облако через API OpenAI? Платить за каждый запрос и надеяться, что ваши данные не утекут? Скучно, дорого и рискованно.
Другое дело — собрать всё на своём железе. Даже на скромной RTX 2060 с её 6 ГБ VRAM. Это не про «потому что можем», а про реальный рабочий инструмент без внешних зависимостей. Вы загружаете аудио, система его транскрибирует, разбивает на смысловые куски, кладёт в векторную базу — и вы получаете персонального исследователя контента, который работает офлайн.
Предупреждение: Если вы ждёте магии «установил и забыл», лучше закройте статью. Здесь придётся немного покопаться в консоли и понять, как всё устроено изнутри. Зато результат будет вашим полностью.
Что у нас в арсенале? (И почему именно этот стек)
Каждый компонент выбран не просто так, а под ограничения железа и задачу.
- Faster-whisper (а не обычный Whisper): Это форк, который использует CTranslate2 для вывода. Результат? В 2-4 раза быстрее при том же качестве и меньшее потребление памяти. На RTX 2060 это разница между «работает» и «тормозит до бесконечности».
- Ollama: Самый простой способ запускать локальные LLM. Тянет модели, управляет контекстом, даёт удобное API. Для нашего пайплайна нужна небольшая, но умная модель.
- ChromaDB: Векторная база, которая живёт прямо на диске. Не требует отдельного сервера, проста в использовании. Идеально для локальных экспериментов.
- Streamlit: Чтобы не общаться с системой только через терминал. За час соберём простой веб-интерфейс для загрузки аудио и вопросов.
Подготовка поля боя: что должно быть установлено
Прежде чем начать, убедитесь, что у вас есть:
- Видеокарта NVIDIA с поддержкой CUDA (нам хватит RTX 2060).
- Python 3.10 или новее.
- Достаточно места на SSD (модели и база данных съедят 10-15 ГБ).
- Установленные CUDA Toolkit и cuDNN (если хотите GPU-ускорение для whisper, а вы хотите).
1Шаг 1: Транскрибация — превращаем звук в текст
Сначала нужно вытащить текст из аудио. Для этого берём faster-whisper. Установите его через pip.
Важно: Если у вас уже есть аудиофайлы — отлично. Если нет — можно использовать yt-dlp и ffmpeg, чтобы скачать и конвертировать видео с YouTube в аудио. Это отдельная тема, но команда выглядит примерно так: скачать аудио в формате opus, потом конвертировать в wav.
Запускаем транскрибацию с моделью «small» (баланс между скоростью и точностью). Обязательно указываем device=cuda, чтобы задействовать видеокарту. Без этого процессор будет считать минутами, а то и часами.
На выходе получаем текст с временными метками. Но это ещё не готовые чанки для RAG. Один длинный текст — плохой вход для векторного поиска.
2Шаг 2: Чанкинг — ломаем текст на осмысленные куски
Самая частая ошибка новичков — резать текст просто по символам (например, по 500 символов). Получается ерунда: предложение обрывается на полуслове, контекст теряется.
Правильный подход — рекурсивное разделение по абзацам, потом по предложениям, с перекрытием. Библиотека LangChain предлагает для этого готовые сплиттеры, но можно написать и свой простой вариант. Суть: каждый чанк должен быть семантически цельным. Перекрытие в 10-20% нужно, чтобы контекст не терялся на границах.
3Шаг 3: Векторизация и ChromaDB — упаковываем смысл в числа
Теперь каждый текстовый чанк нужно превратить в вектор — числовое представление его смысла. Для этого нужна модель эмбеддингов.
На RTX 2060 большие модели типа text-embedding-ada-002 (если бы она была локальной) не потянуть. Берём что-то полегче, например, all-MiniLM-L6-v2 от Sentence Transformers. Она небольшая, но даёт приличное качество.
Устанавливаем библиотеку sentence-transformers, загружаем модель. Каждый чанк прогоняем через неё — получаем вектор (список из 384 чисел). Этот вектор вместе с исходным текстом и метаданными (например, временная метка из аудио) сохраняем в ChromaDB.
ChromaDB создаёт коллекцию, индексирует векторы для быстрого поиска. Всё хранится в папке на диске. Никаких внешних сервисов.
4Шаг 4: Ollama и LLM — мозг системы
Теперь нужна языковая модель, которая будет получать найденные релевантные чанки и генерировать ответ на ваш вопрос. Ключевой момент — модель должна умещаться в 6 ГБ VRAM вместе со всем остальным.
Отлично подходят модели семейства Mistral (7B параметров) в квантованном формате, например, Mistral:7b-instruct-q4_K_M. Её через Ollama запустить проще простого: одна команда на скачивание и запуск.
Ollama запустит сервер с API. Наш пайплайн будет: 1) получать вопрос пользователя, 2) превращать его в вектор той же моделью эмбеддингов, 3) искать в ChromaDB самые похожие чанки, 4) передавать эти чанки как контекст вместе с вопросом в LLM через Ollama API, 5) возвращать сгенерированный ответ.
Не пытайтесь запустить модель на 13B параметров без квантования на RTX 2060. У вас кончится память, и всё упадёт. Начните с 7B q4, это проверенный вариант. Для более мощного железа есть другие варианты, как в обзоре лучших локальных LLM.
5Шаг 5: Streamlit UI — лицо проекта
Вести диалог через curl или Python-скрипт неудобно. Поднимаем минимальный веб-интерфейс на Streamlit.
Создаём два основных экрана. Первый — для загрузки нового аудиофайла. Там запускается весь пайплайн индексации (шаги 1-3). Второй — чат. Поле для вопроса, кнопка «Отправить». Под капотом — запрос к векторной базе и Ollama.
Streamlit хорош тем, что для такого интерфейса нужно всего 50 строк кода. Он сам запустит локальный сервер и откроет вкладку в браузере.
Сборка всего пайплайна в один скрипт
Теперь нужно связать все компоненты вместе. Пишем основной Python-скрипт, который:
- Принимает путь к аудиофайлу.
- Запускает faster-whisper с GPU.
- Разбивает результат на чанки.
- Создаёт или обновляет коллекцию в ChromaDB, добавляя новые эмбеддинги.
- Предоставляет функцию для поиска: вопрос -> эмбеддинг вопроса -> поиск в ChromaDB -> формирование промпта для LLM -> запрос к Ollama -> ответ.
Этот скрипт будет импортироваться в Streamlit-приложение. Главное — следить за потреблением памяти. Не держите все модели загруженными одновременно, если в этом нет необходимости. Загружайте модель эмбеддингов и Whisper только на этапе индексации.
Типичные грабли, на которые вы наступите
| Проблема | Причина | Решение |
|---|---|---|
| Out of Memory (CUDA) | Whisper, модель эмбеддингов и Ollama пытаются уместиться в 6 ГБ одновременно. | Используйте Whisper модель 'small' или даже 'tiny'. Квантуйте модель для Ollama (q4_K_M). Не индексируйте и не чатите одновременно. |
| ChromaDB не находит похожие чанки | Вопрос сформулирован иначе, чем текст в базе. Или чанки слишком большие/бессмысленные. | Экспериментируйте с размером чанка и перекрытием. Попробуйте перефразировать вопрос. Проверьте, что модель эмбеддингов загружена корректно. |
| Ollama генерирует ерунду | В промпт передаётся слишком много или мало контекста. Модель «придумывает». | Чётко указывайте в промпте: «Ответь на вопрос, используя ТОЛЬКО следующий контекст: ...». Ограничьте число возвращаемых чанков (3-5 штук). |
| Транскрибация очень медленная | Faster-whisper использует CPU вместо GPU. | Убедитесь, что CUDA установлена, а в код передаётся параметр device="cuda". |
Что дальше? Куда развивать систему
Рабочий пайплайн — это только начало. Дальше можно:
- Добавить агентские возможности: Научить систему не просто отвечать, но и выполнять действия на основе аудио-инструкций. Это уже уровень локального AI-агента, но для RTX 2060 нужны очень лёгкие модели.
- Индексировать сразу папки с аудио: Сделать фоновый процесс, который следит за папкой и автоматически добавляет новые файлы в базу.
- Улучшить поиск: Экспериментировать с другими моделями эмбеддингов или гибридным поиском (ключевые слова + векторы).
- Добавить TTS: Чтобы система не только читала, но и отвечала голосом. Но это уже дополнительная нагрузка на GPU. Если решитесь, посмотрите, как это делается в голосовом ассистенте на одной видеокарте.
Самое главное — вы теперь контролируете каждый байт данных и каждую операцию. Никаких скрытых платежей, никаких внезапных изменений в API. Система работает ровно так, как вы её настроили. Да, на слабом железе приходится идти на компромиссы, но сама возможность собрать такое локально — уже победа.
Теперь у вас есть схема. Осталось сесть и собрать. Первый запуск будет с ошибками, второй — медленным, а на третий вы уже будете задавать вопросы своим аудиозаписям, не подключаясь к интернету. Это того стоит.