Библиотека внутри ассистента
AICharya открывает корпус Listen to Sadhu любому ИИ-ассистенту — как устроена библиотека, какими двумя способами к ней обращаться и как поиск в две дорожки соединяет смысл с точными словами, чтобы и пересказ, и редкий санскритский термин попадали в нужный фрагмент.
Попросите языковую модель объяснить стих «Бхагавад-гиты» — и она охотно объяснит, гладко и уверенно, даже если этот стих ей ни разу не встречался. В этом и вся беда, когда речь о писании и памяти модели: уверенный пересказ и точная цитата выглядят одинаково, пока не откроешь источник и не проверишь.
AICharya — наш ответ на это. Это небольшой публичный сервер, который отдаёт ИИ-ассистенту настоящий корпус за Listen to Sadhu: стихи, пураны, расшифровки лекций — с адресами и ссылками. Ассистент читает подлинный текст, а не сочиняет его заново. В названии — тихая игра слов: ачарья — это учитель, который передаёт текст без искажений. Ровно это мы и поручили серверу.
Эта статья — о том, как он устроен: что лежит в библиотеке, какими двумя способами до неё добраться и — самое главное — как поиск на самом деле находит нужный фрагмент.
Что это: один разъём в корпус
AICharya говорит на MCP — Model Context Protocol,
стандарте, по которому ассистент обращается к внешним инструментам и данным. На
практике это один адрес. Добавьте https://mcp.listentosadhu.app/mcp как
пользовательский коннектор в Claude, ChatGPT, Grok, Mistral Le Chat, Perplexity или
любой другой MCP-клиент — и вся библиотека станет тем, что ассистент умеет искать и
цитировать прямо в обычном разговоре.
Две вещи здесь несущие, и обе выбраны намеренно:
- Без ключа и без аккаунта. Сервер открытый. Корпус создан, чтобы его читали, поэтому регистрироваться и что-то ставить не нужно.
- Только чтение, до самого низа. Каждый инструмент помечен как read-only; сервер открывает данные только на чтение и вообще не умеет писать. AICharya покажет библиотеку, но не изменит её.
Ассистент видит компактный набор инструментов — примерно полтора десятка. Каждый
возвращает один и тот же аккуратный конверт: либо { ok: true, result }, либо
{ ok: false, error } с коротким и честным набором кодов ошибок (invalid_argument,
not_found, dependency_failed). Ничего не приходится разбирать наугад.
Что лежит в библиотеке
Всё сводится к трём формам — потому что ссылка должна указывать на нужный тип вещи:
- Стихи. У стиха есть оригинал на деванагари или бенгали, транслитерация IAST и перевод. Адрес — структурный: книга, глава, стих. Поэтому «BG 2.13» называет реальное место, а не удачную фразу.
- Документы. Проза традиции: пураны и комментарии, прозаические главы, письма. Пурана к стиху — это просто документ-комментарий, привязанный к адресу стиха; получить его — один запрос.
- Записи. Лекции и беседы в расшифровке. У каждой записи есть метаданные — кто говорит, где, когда, на каком языке, — ссылки на стихи, которые в ней звучат, и расшифровка: её можно читать вокруг любого момента, вплоть до миллисекунды.
Под капотом всё это лежит в двух разных хранилищах — каждое под свою задачу. Стихи и документы держит компактный файл-библиотека; каталог — все книги, авторы и места плюс указатель лекций — лежит в отдельном. Расшифровки лекций, которые нужно искать по смыслу, лежат в Postgres с pgvector — рядом с эмбеддингами. Снаружи этого деления не видно: спрашиваете — отвечает нужное хранилище.
Два пути внутрь: по имени или по вопросу
До нужного фрагмента ведут ровно два пути. Ответам можно доверять именно потому, что пути не смешиваются.
По имени. Знаете адрес — просто назовите его. AICharya понимает канонические
ссылки в том виде, в каком их пишет читатель: «BG 2.13», «ŚB 5.5.3»,
«CC Madhya 8.128» — причём и на латинице, и на кириллице, так что «ШБ 5.5.3» и
«SB 5.5.3» ведут к одному стиху. Коды книг распознаются и нестрого: «gita»,
«бхагаватам», «CC Madhya» — каждый находит свою книгу. Голый номер главы
означает всю главу: tokens: "7" — это вся седьмая глава, tokens: "7.1" —
только один стих. Этот путь не гадает: ссылка либо ведёт в реальное место, либо нет.
По вопросу. Когда непонятно, где искать — «где Прабхупада говорит, что душа вечна?» — в дело вступает поиск. Вот тут и начинается интересное.
Как работает поиск
Наивный подход — превратить и запрос, и корпус в векторы и взять ближайших соседей по косинусной близости. Так находится смысл: фразу «душа никогда не умирает» поиск свяжет с отрывком о вечности души, даже если ни одного общего слова нет. Но к точным строкам такой поиск слеп — а писание полно точных строк, и они важны. Санскритский термин вроде sanātana, имя, каноническая формула: смысловой вектор преспокойно округлит их до чего-то просто похожего.
Поэтому AICharya ведёт сразу две дорожки и сводит их вместе.
flowchart TD Q["Запрос на естественном языке"] --> E["Превращаем запрос в вектор"] E --> V["Смысловая дорожка · pgvector HNSW · косинусные соседи"] Q --> L["Дорожка точных строк · Postgres full-text плюс триграммы"] V --> F["Reciprocal Rank Fusion · k равно 60"] L --> F F --> R["Ранжированные фрагменты · у каждого id для полной записи"]
Смысловая дорожка превращает запрос в вектор на 1536 измерений и просит у
pgvector ближайшие фрагменты по косинусному расстоянию, проходя по индексу HNSW. Она
настроена искать чуть упорнее, чем по умолчанию: шире ef_search и мягче итеративный
обход — чтобы даже запрос с фильтрами возвращал полный список, а не почти пустой.
Дорожка точных строк — это полнотекстовый поиск Postgres, и он намеренно работает
в двух конфигурациях. Первая — russian, со стеммингом Snowball: русские запросы
совпадают в любой словоформе. Вторая — simple, вообще без стемминга, — и она
незаметно, но критически важна: транслитерация IAST остаётся как есть, поэтому
sanātana-dharma не превращается в кашу до того, как успеет совпасть. Рядом идёт
триграммный индекс — ловит канонические адреса и почти-совпадения написаний.
Дальше два ранжированных списка сводит Reciprocal Rank Fusion. RRF — приятно скучный алгоритм: каждая дорожка добавляет фрагменту очки, обратные рангу в этой дорожке, , где ; очки складываются, список сортируется, а ничьи для повторяемости разводятся по чистому косинусу. Хорош этот приём тем, чего ему не нужно: дорожки дают очки в совершенно разных шкалах — косинусную близость и текстовый ранг, — и напрямую эти очки RRF никогда не сравнивает. Он сравнивает только ранги. Фрагмент, который понравился обеим дорожкам, поднимается наверх; фрагмент, который нашла лишь одна, тоже получает слово. Смысл и точное совпадение — и ни одно не глушит другое.
На выходе — ранжированный список, где нужный фрагмент находят и пересказ обычными
словами, и редкий санскритский термин. У каждого попадания есть min_score:
поднимите его — и слабые совпадения отсеются. Поиск, который честно признаёт, что
нашёл мало, стоит больше, чем тот, что раздувает выдачу.
От попадания — к источнику
Результат поиска — не конец, а указатель. В каждом попадании лежит ровно тот id, по которому ассистент достаёт полную запись. Правила везде одинаковы:
verse_idидёт вverse_get— за оригиналом, транслитерацией и переводом;document_id— вdocument_get, за полным комментарием или письмом;track_idвместе сstart_msиend_msидёт вtranscript_window— тот читает расшифровку вокруг этого момента, то есть соседние фразы, а не голый обрывок;media_id— вmedia_get.
Последние два ведут к чему-то приятнее текста. Если ответ — это лекция, ассистент показывает прямо в диалоге аудиоплеер, настроенный на нужный отрывок: источник звучит вслух, а сам отрывок нарезается по запросу. Если ответ — снятый момент, воспоминание ученика или запись беседы, — видеоплеер проигрывает его тут же, в разговоре. Ссылка здесь не сноска, за которой надо куда-то идти, — это сама запись, в одно касание.
Почему только чтение — это принцип
Легко было бы разрешить AICharya больше — помечать, ставить закладки, писать обратно. Мы сознательно этого не сделали. Открытый корпус писания хочется отдать так, чтобы его читали многие ассистенты и никто не правил. Только чтение — не ограничение, за которое неловко; это гарантия, ради которой одну и ту же библиотеку можно спокойно отдать сразу всем.
Вот, собственно, и вся картина. Listen to Sadhu уже отвечает на такие вопросы прямо в приложении — в чате с опорой на источники. AICharya берёт слой под ним — корпус с адресами, поиском и ссылками — и открывает его так, что и ваш ассистент может его читать. Работа ачарьи, сведённая к разъёму: дать модели настоящий текст — и пусть цитирует источник, а не своё воспоминание о нём.
Часть проекта
AICharya