Наглядный пример, зачем нужны агенты

Расскажу историю длиной в полгода, на которой я ясно ощутил все плюсы и ограничения современных инструментов работы с LLM.

Простая идея с глубокими последствиями

В августе 2025 года мой отец предложил создать поисковик-анализатор новостей: задаёшь список источников и запрос — система присылает сводку с ответами и ссылками. Казалось, это классическая задача для RAG: собрал, показал, получил аплодисменты. Я за 1–2 месяца в свободное время собрал рабочий прототип. Он умел искать по смыслу, генерировать ответы на основе найденных постов и даже помогал открывать статьи. В мыслях — салюты, шампанское, AI-единороги.

Но реальность

При тестировании выявились две серьёзные проблемы. Во-первых, сложные запросы вроде «причины шатдауна правительства США» давали мимо: либо находили только упоминания Трампа, либо вообще ничего. Во-вторых, система плохо понимала сущности: ЦБ РФ мог трактоваться как два отдельных слова или вообще как неизвестная абстракция. Обе проблемы указали на один фундаментальный изъян — чрезмерная зависимость от семантической близости. Это ведёт к размытию смысла на длинных запросах, непредсказуемому поведению имён собственных и поиску по частоте, а не по смыслу.

Особенно остро встал вопрос связей. Например, связь «Израиль — нефть — рубль» очевидна для любого, кто живёт в 2026 году, но её не найти через семантический поиск, как бы вы ни переформулировали запрос. Я начал искать альтернативы.

Ищем связи

Семантический поиск хорош, но он не видит связей между событиями и объектами. Обычный RAG — плоская система: он находит схожие тексты, но не понимает, как они связаны. Есть Graph RAG и Event-based RAG. Первый строит связи на основе совместного упоминания в документах. Это работает для статичных источников, вроде Кодекса, но не для динамичных новостей, где связи меняются, а сущности устаревают или приобретают новые значения.

Graph RAG слишком неповоротлив: он строит жёсткие связи, а в мире новостей сложно определить, что будет узлом — новость, событие или объект. А если появится сверхузел вроде «экономика», граф станет неуправляемым. Поэтому я выбрал Event-based RAG — подход, заточенный под динамические события и их связи. Подробнее — в статье arxiv.org/abs/2507.13396. Я рассмотрел готовые фреймворки, но в итоге решил написать свою реализацию — база уже была, а graphiti не подходил под мои задачи.

Дао мягких и жёстких связей

Я понял: ключевое — понять, что и как связывать. Цель — построить граф, который:

  • легко обновлять (минимум усилий на изменение весов или рёбер);
  • расширяет знания, а не дублирует частотную связанность;
  • учитывает временной контекст;
  • избегает сверхузлов.

Такой граф можно поддерживать в актуальном состоянии и использовать для расширенного контекста. Но как его построить?

Новость — это состояние объектов в момент времени. Проще: новость = событие = отношения объектов. Так родилась формула, которая до сих пор лежит в основе проекта: ARTICLE - EVENT - ENTITY.

Теперь нужно было разместить это в графе. Если хранить всё вместе, получится перепутанный клубок. Например, текст про катки и OpenAI окажутся в одной плоскости, а Трамп — центральным узлом с тысячами связей. Это неработаемо.

Решение — разделить данные на изолированные плоскости: статьи, события, объекты. Связи между плоскостями — жёсткие (неизменные): статья содержит событие, событие включает объекты. Внутри плоскостей — мягкие связи, которые рассчитываются динамически.

Например, статья:

Иран открывает Ормузский пролив для судоходства, сообщил глава МИД страны Аббас Арагчи. «В соответствии с прекращением огня в Ливане, проход для всех коммерческих судов через Ормузский пролив объявляется полностью открытым на оставшийся период прекращения огня», — написал министр в X. (источник).

В системе: статья попадает в плоскость постов, два события — в плоскость событий (с жёсткой связью к статье), объекты (Иран, Ормузский пролив, Аббас Арагчи, Ливан) — в плоскость объектов (с жёсткой связью к событиям). При поиске по «Ливан» алгоритм может найти «Ормузский пролив» через общее событие — именно это и нужно от «умного» поиска.

Как работала система и чего ей не хватало

К тому моменту система напоминала франкенштейна с двумя пайплайнами:

Сохранение: по расписанию собираются посты из открытых Telegram-каналов. Они нормализуются, фильтруются и обрабатываются: из них LLM выделяет события и объекты, строятся эмбеддинги. Тексты идут в векторную БД, связи — в SQL.
Поиск: запрос перефразируется, выделяется временной интервал. Формируется несколько подзапросов, идёт семантический поиск, фильтрация, добавление слабо связанных событий, затем LLM суммирует найденные статьи и отвечает на вопрос.

Были и оптимизации: извлечение тегов, якорей, разные стратегии под типы запросов. В целом — почти готовое решение. Но изначальные цели — качество и удобство — не были достигнуты полностью.

Заказчик (опять же, папа) выдвигал требования, о которых я не подумал:

  • если в посте есть «читайте дальше на сайте», система должна парсить внешнюю ссылку;
  • нужно задавать тему и получать оповещения по расписанию;
  • события надо проверять в зарубежных источниках и сравнивать интерпретации.

Я понял: впихивать всё в один проект — путь к неподдерживаемому швейцарскому ножу. Либо всё в одном промпте, либо в куче мелких инструментов — и везде потеря контроля.

Агенты (самая важная часть)

Я несколько недель использовал агента на OpenClaw: он вёл учёт трат, искал товары, напоминал о событиях. Был впечатлён простотой и «дружелюбностью» интерфейса. Решил внедрить агента в свой проект. Решение пришло быстро:

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

Я разбил проект на минимальные функции и открыл к ним доступ через авторизацию. Результат:

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

Смена парадигмы — с push на pull. Это принципиально: ответственность разделена, пользователь получает свободу. С точки зрения бизнеса: зачем продавать доступ к API, следить за тарифами, бороться с ботами? Лучше продавать доступ к платформе — хранилищу и MCP-серверу для агентов. Агенты пользователь настраивает сам: из шаблонов или покупает отдельно. Для меня это — новый взгляд на мир.

Ограничения и открытые вопросы

Статья упрощает некоторые проблемы. Например, безопасность источников: если разрешить внешним пользователям добавлять данные, злоумышленник может заспамить систему. Для «семейного» проекта это не критично, но в продакшене нужна защита.

Вторая проблема — память. Она не решена. Входная точка поиска — всё ещё семантический поиск. Я исследую ассоциативную память, но пока без значимых результатов.

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

Читать оригинал