Путь от фанатского вопроса до полноценного AI-поиска в МДС Коллекции

 Публичный пост
5 декабря 2025  407


В фан-сообществах Модели для сборки регулярно всплывают похожие сообщения:

«Помогите вспомнить рассказ… Там был мальчик… робот… и какой-то поворот в конце…»

Десятки комментариев, версии, догадки - почти коллективная реконструкция сюжета. Я каждый раз ловил себя на мысли, что и сам бывал в этой ситуации. Ты помнишь эмоцию, отдельный эпизод, звук голоса диктора - а название потерялось. Сегодня у слушателей есть один рабочий инструмент: спросить других.

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

Но идея упёрлась в фундаментальную проблему.

У меня не было текстов.
У меня были только аудиозаписи. С фоновой музыкой и проблемами с громкостью.

Whisper, ffmpeg и 1600 рассказов, которые нужно превратить в текст

МДС Коллекция - это примерно 1600 рассказов, более месяца непрерывного прослушивания. Записаны они в разное время, разными людьми, на разном оборудовании. Whisper, как и большинство моделей ASR, любит чистые, стабильные WAV-файлы. У меня были MP3, некоторые - повреждённые.

Пайплайн казался очевидным:
ffmpeg → Whisper → текст
Но масштаб означал, что работать «в лоб» нельзя - это заняло бы недели.

Варианты ускорения были простыми:

  • Одолжить у друга GPU (RTX 3060 Ti) и распараллелить скрипт.
  • Арендовать GPU-сервер у Hetzner.
  • Запустить всё локально на Apple M4 через Metal.

Экономика и удобство победили - я отнёс задачу другу.

И это сработало: три дня, три потока whisper.cpp, модель ggml-large-v3 - и все 1600 аудиофайлов превратились в текст.
Я выборочно проверил качество - оно казалось приемлемым. Но только до тех пор, пока я не начал строить поиск.

Когда поисковая модель говорит: «Я не знаю этот рассказ», хотя он должен быть найден

На этапе создания векторного поиска я заметил странность: некоторые рассказы не находились даже по точному описанию, хотя содержали соответствующие фразы.

Открываю текст - вижу искажения, пропуски, неправильно распознанные слова. Whisper сделал своё дело, но далеко не идеально.
Переписывать всю коллекцию заново я не хотел. Нужно было:

  • найти «кривые» тексты,
  • обработать только их,
  • повысить качество транскрибации.

Первую задачу решил простой shell-скрипт: эвристики, подсчёт плотности текста, анализ резких провалов по длине фрагментов.
Так нашлось около 200 проблемных файлов.

Теперь требовалось улучшить качество модели.

Как звук влияет на смысл: ffmpeg, VAD и вторая волна транскрибаций

При углублённом изучении Whisper стало ясно, что качество можно существенно улучшить двумя вещами:

1. Предобработка аудио
ffmpeg отлично справляется с задачами:

  • усиление речи относительно фона,
  • подавление шумов,
  • нормализация громкости.

Whisper после такой очистки слышит уже не «аудиофайл с музыкой», а голос, который он и обучен распознавать.

2. Voice Activity Detection (VAD)
VAD размечает участки, где есть человеческая речь. Whisper может пропускать тишину, искажения и бессмысленные фрагменты. Это:

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

GGML, GGUF и почему не CoreML

Техническое отступление.
GGML - лёгкий формат, оптимизированный под CPU.
GGUF - его преемник: более структурированный, с квантованием, удобными метаданными и лучшей совместимостью. Сегодня практически все Whisper-модели распространяются в GGUF.

Почему не CoreML?
Потому что под CoreML доступна только версия Whisper v2.
Она хуже по качеству, чем v3-модели, особенно на шумных и старых записях.

Поэтому вторую волну транскрибаций я делал локально, на Apple M4 с Metal backend, используя ggml-модель.
Результат: качество выросло настолько, что поисковая система наконец начала работать так, как задумано.

От текста - к поиску: как построить семантическую систему для 30-летнего архива

Теперь у меня был корпус текстов, отражающий не только сюжеты, но и звучание эпохи.

Это важный момент:
МДС появилась более 30 лет назад, и ранние выпуски несут в себе культурный слой конца 90-х. Рекламные вставки клубов, объявления «для взрослых», шумы эфира - это тоже часть памяти слушателей.

Я хотел сперва их удалить, но после разговора с поклонниками передачи понял: люди ищут не только по сюжету, но и по этим случайным маркерам времени.
Очищать их - значит терять часть ключей для поиска.

Как устроен поиск: от человеческого описания до пяти самых подходящих рассказов

Структура моего поискового пайплайна выглядит так:

  • Пользователь вводит описание - иногда размытое, иногда в одно предложение.
  • Сервер преобразует описание в вектор - числовое представление смысла.
  • Этот вектор идёт в векторную базу данных, где ищутся 30 ближайших фрагментов текста.
  • Срабатывает реранкинг - уже не фрагментов, а историй целиком.
  • Пользователь получает топ-5 наиболее вероятных совпадений.

Снаружи всё выглядит просто, но внутри крутится несколько ключевых решений.

Почему именно Qdrant

Сегодня многие базы заявляют, что умеют векторный поиск: PostgreSQL, MongoDB, ClickHouse. Они действительно умеют, но как надстройку.

Мне нужен был инструмент, который:

  • создавался для векторного поиска,
  • быстрый,
  • лёгкий,
  • надёжен,
  • разворачивается в один docker run,
  • open source.

Таким инструментом оказался Qdrant.
Rust под капотом, минималистичная архитектура, удобный API - ровно то, что нужно мобильному сервису с быстрыми ответами.

Выбор эмбеддинговой модели: BGE-M3

Модель должна уметь понимать человеческий способ описания. Люди не пишут так: «пожалуйста, найди мне рассказ, содержащий признаки X, Y, Z». Они пишут:
«там был поезд… кажется, девушка… что-то таинственное…»

Модель BGE-M3 оказалась идеальным вариантом:

  • отлично работает на длинных текстах (целых рассказах),
  • понимает неформальные описания,
  • находит смысловые пересечения даже в туманных запросах,
  • не требует мощной видеокарты.

Она стала основой качества поиска.

Как работает реранкинг

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

Поэтому я ввёл формулу, которая:

  • усиливает вклад лучшего совпадения,
  • добавляет вес остальных релевантных фрагментов,
  • даёт итоговый story score для каждой истории.

Логика проста:
история, у которой несколько совпадающих фрагментов, скорее всего ближе к запросу, чем история с единственным случайным попаданием.

Первые результаты - и первое разочарование

Когда я собрал всё в FastAPI, завернул в Docker и развернул сервис, результаты были вдохновляющими.
Для подробных запросов поиск работал как надо: точный, быстрый, уверенный.

Но вскоре проявились два ограничения:
1. Большинство людей пишут очень коротко
Иногда всего одно слово.
Модель умеет работать с малым контекстом, но качество таких запросов естественно хуже.

2. Время запроса оказалось выше желаемого
На холодной системе: 600–1000 мс.
На p99 под нагрузкой - до 3 секунд.

Для мобильного приложения это многовато.
Система работала, но не была оптимизирована.

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

Кстати, попробовать его можно в АппСторе и ГуглПлее

13 комментариев 👇

Ааааа! Так это вашей аппкой я пользуюсь уже давно! Хе-хе. Ну попался. Щас я все расскажу.

Ладно, шучу. На самом деле, у вас одна из самых вменяемых приложух. По поиску хотел бы попросить одну вещь. Можно, пожалуйста, что то сделать с буквой ё? Потому что в поиске если не знаешь есть ли там е или ё то хрен найдешь.

Хотел было пойти и проверить новый ИИ поиск и тут:

висим
висим

Я сижу на вайфае в США.

Кстати, будут ли способы оплаты с карточек? Потому что рублей у меня нет, а с криптой возиться не хочу.

  Развернуть 1 комментарий

@newarked, отличное предложение! Я поправлю поиск на след неделе :)

Висит потому что я переехал базой к новому провайдеру, а у них сеть ни к чёрту, постоянно соединение ломается. Поищу как поправить. Написал им тикет уже.

С карточками зарубежными засада) Я пробовал пдобрать варианты, но что-то ни один не подошел. Есть предложения? Чтоб не особо официально.

  Развернуть 1 комментарий

@azaikin, Зависит от того, где ты и кто ты.

Я в США, у меня компания по продаже ПО. Я уже двум другим делаю по следующей схеме: Я делаю инвойс в страйпе, вы по нему получаете оплату, я снимаю 15% на налоги, а вы мне в конце месяца (или каждую неделю) выставляете инвойс на оплату разработки ПО. (Соотвественно цену на страйпе поднимаете на эти же 15%) Я оплачиваю этот инвойс через moneywise или что-то в этом роде. Но, понятное дело, когда я связался с некоторыми ребятами, и они хотят попросить помощи в проведении сотни транзакций в день - это круто.

Другое дело - совсем другое дело - это если тебе надо три с половиной транзакции в год. Это будет больше проблем и тебе и мне.

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

И тут - ты.

Кстати, всегда хотел спросить, вы, ребята, насколько связаны с самим МДС и Владом Коппом? Так, чисто из интереса. Потому что я вижу, что вы их рекламу продвигаете. Можете рассказать, как у вас взаимоотношения построенны?

  Развернуть 1 комментарий

@newarked, МДС Коллекция - официальное приложение Модели для сборки. То есть у нас официальное добро от ребят)

  Развернуть 1 комментарий

@azaikin, Прикольно. Спасибо за вашу работу. МДС слушал с 2000х годов. Всю жизнь. А щас ребёнок отлипнуть не может. Кобель Жук и Пёрышко (чёрт его, никак у вас не могу найти)

Поэтому придётся продлевать лицензию. Давайте, помогу чем смогу 8-)

  Развернуть 1 комментарий

Наивный вопрос - а почему по автору и названию не найти оригинальные тексты в условной Флибусте?

  Развернуть 1 комментарий

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

  Развернуть 1 комментарий

@azaikin, интересно! Возможно, это относится в основном к современным российским авторам? У меня тут bias, так как я с наследием МДС знаком выборочно, слушал там классиков типа Брэдбери и Шекли, и сложно поверить, чтобы их тексты нельзя было относительно просто извлечь.

  Развернуть 1 комментарий

@SergeiTikhomirov, скорее всего можно было бы вытащить проще, но тут был еще мой личный интерес к решению именно такой технической задачи, которая оказалась очень увлекательной))

  Развернуть 1 комментарий
🕵️ Юзер скрыл свои комментарии от публичного просмотра...
🕵️ Юзер скрыл свои комментарии от публичного просмотра...

😎

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

Что вообще здесь происходит?


Войти  или  Вступить в Клуб