Как я собрал самообучающегося ИИ-ассистента за 3 месяца

Как я собрал self-improving AI-ассистента за 3 месяца, не зная что такое RAG

По сути я, системный администратор без опыта в ML, собрал работающую систему с 23 компонентами, замкнутым циклом самообучения и прод-деплоем на 2 ГБ RAM. Параллельно повторил несколько идей из работ 2023 года (MemGPT, Reflexion), но нашёл и кое-что своё — например, weekly self-calibration промпта judge-LLM. Эта статья — честный разбор архитектуры, граблей и prior art.

Некоторые вводные данные:

  • Стартовое окружение: VPS 1CPU, 2GB RAM, 30GB SSD
  • Основная модель LLM: API GigaChat
  • Embeddings: API GigaChat Embeddings
  • Вспомогательные модели (fallback, Sufler): API DeepSeek, API OpenAI

Где мой проект в AI-экосистеме: Мой проект — это не конкурент LangChain или MemGPT. Это уже готовое приложение, которое использует все эти компоненты и добавляет замкнутый цикл самообучения. 

Пролог: почему ChatGPT или DeepSeek меня бесили?

Я пользовался ChatGPT, потом DeepSeek примерно с момента их появления для своих нужд. И меня стабильно бесила одна вещь: «они не учатся».

Допустим, меня попросили рассчитать спецификации для производства. В понедельник спрашиваю, как правильно посчитать себестоимость шкафа-купе. Выдаёт временами ответ с галлюцинацией — путает ЛДСП и ДВП, забывает учесть кромку, считает отходы неправильно. Я ему говорю: «неверно, пересчитай». Он извиняется, даёт новый ответ — с другой галлюцинацией. В среду я спрашиваю то же самое в новом чате — он опять галлюцинирует. С тем же прайс-листом. Снова.

Для меня это было фундаментально непонятно. У человека так не работает: если я один раз понял, как считать шкаф-купе, я не забуду. А LLM — забывает всё при закрытии чата. Более того, он забывает и при следующем запросе от другого пользователя.

Я подумал: ладно, это хоть и умные модели, но общедоступные и на это, по сути, не рассчитаны, поэтому простительно. Но что если я сам соберу систему, которая будет помнить? Которая будет учиться на своих ошибках и не повторять их?

Чего я тогда не знал:

  • Не знал, что такое RAG, embedding, vector database
  • Не слышал про ChromaDB
  • Не слышал про LangChain, LlamaIndex
  • Не слышал про MemGPT
  • Не слышал про Reflexion
  • Не слышал про Constitutional AI

То есть я начинал с нуля — и, как выяснилось потом, шёл параллельным путём с людьми, которые делали академические работы примерно в 2023 году. Но об этом — в конце. Сначала история.


Глава 1. Точка старта: «просто чат с памятью»

Первая версия была смешной. Я взял SQLite, добавил таблицу messages, и каждый запрос пользователя отправлял в LLM вместе с последними 20 сообщениями из истории. Это и была моя «память». 200 строк кода на FastAPI. Запустил локально. Работало!

My first AI-assistant

Через неделю я понял первую проблему: контекстное окно не резиновое. Если я отправлял LLM прайс-лист на 85 позиций в одном сообщении, а потом вёл диалог ещё 30 сообщений, то прайс просто выпадал из контекста. LLM его «не видел» — и галлюцинировал: «а какой у вас прайс?».

LLM теряет контекст


Окей, подумал я, нужно как-то помечать важные сообщения. Написал простой алгоритм: после каждого сообщения пользователя проверяю — если длина накопленного диалога > 3000 символов с прошлой «контрольной точки», ставлю новую. Сохраняю в таблицу micro_goals.

def shouldanchor(mgstack, charcount, currenttopic):

"""Решает, нужен ли новый якорь."""
if charcount - mgstack[-1].char_pos >= 3000:
return "NEW_ANCHOR"
if currenttopic != mgstack[-1].topic:
# Проверяем, не похожа ли тема
if findsimilaranchor(mgstack, currenttopic):
return "MERGE_ANCHOR"
return "NEW_ANCHOR"
return "NO_ANCHOR"

Это были мои «якоря» — точки, в которых я фиксировал «о чём мы говорим». LLM видел в system prompt:

[ТЕМЫ ДИАЛОГА: прайс-лист → расчёт себестоимости]

[ПОСЛЕДНИЕ ДАННЫЕ: ЛДСП 2.57м² × 327.39₽ = 841.39₽]

И всё. Это работало. Контекст держался на 50+ сообщений.

Я тогда ещё не знал, что в ноябре 2023 года вышла работа MemGPT с почти такой же идеей — «core memory» + «archival memory». Нашёл случайно через полгода. Но об этом, повторюсь, будет позже.


Глава 2. Стена №2: «а если LLM неправ?»

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

Я сделал несколько ошибок в спецификации — ассистент их пропустил. Посчитал кромку как ЛДСП. Не учёл, что у меня 4 двери, а не 2. Спрашиваю «а почему так?» — он извиняется, пересчитывает, делает другую ошибку.

Решил: мне нужен второй LLM, который проверяет первый. Написал. Назвал «Sufler» (суфлёр — тот, кто подсказывает актёру за кулисами в театре).

Принцип работы Суфлера 

Инновация, обрадовался я. Однако потом нашёл Reflexion (NeurIPS 2023) — и понял, что не только я хожу в театр. Однако, архитектурно мой Sufler отличается: он — как бы это сказать — внешний и независимый по отношению к основной модели и сохраняет оценки в долговременную память, а не только в self-reflection prompt.

def evaluateandcorrect(response, userquery, context, providercfg):

"""Sufler оценивает ответ и при необходимости исправляет."""
prompt = buildevaluationprompt(response, user_query, context)
evalreply = calljudgellm(prompt, providercfg)
score = parsescore(evalreply)
reasoning = parsereasoning(evalreply)
corrected = parsecorrection(evalreply)

if score < 4 and corrected and corrected != response:
corrected = clean_correction(corrected)

return {
"score": score,
"reasoning": reasoning,
"corrected": corrected,
}


Глава 3. Self-improvement без учителя

Когда Sufler начал работать, появилась новая идея. Если оценка плохая (1-2), это значит: система не знает что-то. Можно это «что-то» автоматически найти в интернете и добавить в базу знаний.

Так появился ЛИКБЕЗ. Каждые 3 часа запускается скрипт:

Ликвидация безграмотности AI-ассистента

Это замкнутый цикл: ошибка → тема → знание → меньше ошибок. Без участия разработчика.

Сейчас в моей базе ~450 тем для исследования и 1000+ статей, найденных автоматически. Многие из них — именно те, по которым система раньше галлюцинировала.

Аналог в литературе: Voyager (NVIDIA, 2023) делал похожее для Minecraft — автономное приобретение навыков через exploration. Но там не было research-фазы с поиском по интернету. И не было явного feedback loop через evaluator. Так что конкретно эта связка — мой вклад.


Глава 4. Production: что сломалось

Я развернул систему на VPS с 2 ГБ RAM — почему так мало? Просто на другое не хватило ресурсов на тот момент, что уж выпендриваться))). И пошёл бегать по граблям. Вот что я сломал себе по дороге:

Грабля №1: GigaChat отдаёт expires_at в миллисекундах

# Было (баг):

if expires_at < time.time(): # 1735689600 (секунды) > 1735689600000 (ms)
refresh_token() # никогда не срабатывало

Стало:

if expiresat > 10000000000: # если > 10^10, это миллисекунды
expires_at /= 1000

Симптом: токен протухал, embeddings возвращали 401, ChromaDB сохраняла нулевые векторы. Я тогда потратил наверное часов 6 на отладку.

Грабля №2: Sufler начал льстить

После месяца работы средняя оценка Sufler по выборке 50 последних ответов выросла до 4.6. Я думал — круто, система стала лучше. Потом проанализировал распределение: 60% ответов получают 5/5, 30% — 4/5. Это явный перекос. Sufler «загрубел» — перестал ловить реальные галлюцинации.

Корректировка памяти AI

Написал run_selfcal.py — скрипт, который раз в неделю (воскресенье, 4 утра) проверяет распределение оценок. Если среднее > 4.3 или < 2.7 — отправляет текущий промпт оценщика + статистику в LLM с просьбой перекалибровать.

Этого я нигде не видел. Ни в одной статье, ни в одном фреймворке. Если кто-то делал self-calibration для LLM-as-judge — подскажите в комментариях, буду рад почитать.

Грабля №3: GigaChat embeddings возвращают None при 401

Это уже техническая мелочь, но иллюстрация того, сколько неочевидных багов в production. После протухания токена ChromaDB сохраняла None вместо векторов. Я не сразу это заметил, потому что chromadb.add() не падал с ошибкой — молча сохранял нули. Поиск возвращал шум.

Сейчас у меня:

  • force_refresh на 401 + проверка на None перед сохранением
  • embeddingdim заморожен при первом успешном вызове (если GigaChat меняет размерность, делаем pad/truncate, не меняем коллекцию)


Глава 5. Что я построил: 23 компонента

Чтобы вы понимали масштаб — вот как выглядит архитектура сейчас:

Масштаб проекта AI-ассистент

Метрики на текущий момент:

МетрикаЗначение
Строк кода~50 000
Python~20 000
JavaScript~7 500
HTML~2 700
CSS~20 000
Компонентов23
Записей responselog1 176
Векторов experiencebank1 046
Тем в researchtopics~450
Статей в researcharticles~1 000
Фоновых задач5
Узлов мониторинга33
Health-проверок30
Что это даёт пользователю на практике:
ЧЕЛОВЕК: «Вот прайс-лист» [85 строк]

СИСТЕМА: Якорь #1 — «прайс-лист: 85 позиций»
SATI: «Вижу 85 позиций. Что нужно сделать?»

... 50 сообщений спустя, прайс выпал из контекста ...

ЧЕЛОВЕК: «Переведи итог в доллары»
СИСТЕМА: SEARCH_HISTORY: «прайс ЛДСП»
SQL LIKE → находит «ЛДСП 327.39 | ДВП 91 | ...»
CBR → 1 USD = 74.62₽
AI: «1 050 / 74.62 = $14.07»

... через месяц, ассистент ошибается в похожем расчёте ...

Sufler: score=2 → researchsuflerfails → «почему путаются ЛДСП и ДВП»
ЛИКБЕЗ: SearXNG → 6 статей про мебельные плиты
→ ChromaDB L2 (тема: furniture)
Следующий похожий вопрос: AI не повторяет ошибку.


Глава 6. Что я узнал потом: prior art

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

MemGPT отличие

Архитектура MemGPT (Packer et al., ноябрь 2023):

  • Core memory — всегда в контексте (мой аналог: якоря STM)
  • Archival memory — векторная БД (мой аналог: МНЕМОС L2)
  • Recall — function call для поиска (мой аналог: SEARCH_HISTORY)

Совпадение архитектурное — почти 1:1. Различия:

  • У MemGPT нет явного external evaluator (Sufler)
  • У MemGPT нет автономного research (ЛИКБЕЗ)
  • У меня якоря ставятся автоматически по длине диалога, у MemGPT — ручной edit

Letta (бывший MemGPT, теперь коммерческий) — прямой конкурент. Если бы я знал про них раньше, мог бы сэкономить месяц.

Reflexion

Paper от Shinn et al., NeurIPS 2023. Идея: агент рефлексирует над ошибками и пишет self-critique в память.

Мой Sufler делает похожее, но:

  • Reflexion — внутренний цикл одной модели (self-reflection в prompt)
  • У меня — внешний evaluator, отдельная LLM с собственной шкалой 1-5
  • У меня оценки публикуются в response_log и используются как few-shot examples для будущих ответов. У Reflexion рефлексии живут только в памяти агента.

Constitutional AI

Anthropic, декабрь 2022. LLM проверяет другой LLM по набору «принципов». Скорее философский фреймворк, чем технический. У меня — конкретная шкала 1-5 с weekly auto-calibration.

Voyager

NVIDIA, 2023. Автономный агент в Minecraft, который исследует мир, приобретает навыки, проверяет их через self-verification.

Совпадение с моим ЛИКБЕЗ — частичное:

VoyagerМоя система
Skills libraryFew-shot examples
Self-verification через executable codeSufler (LLM-as-judge)
Curriculum-driven explorationresearchsuflerfails
Различие: Voyager не ходит в интернет, ЛИКБЕЗ — ходит. И Voyager работает в синтетической среде Minecraft, ЛИКБЕЗ — в реальной production-системе.

Глава 7. Что я могу назвать своим

Если убрать всё, что уже было в чужих работах, что остаётся лично моего?

  • Замкнутый цикл: ошибка → тема → статья → знание → меньше ошибок. В Reflexion есть первый шаг, в Voyager — второй и третий, у меня — все пять в production-связке.
  • Weekly self-calibration промпта оценщика. Я не нашёл этого ни в одном фреймворке. Если кто-то видел — напишите.
  • 3-level matching в Matematicus (LLM bulk → Python fuzzy → LLM per-item). Узко-доменная инженерия для  расчета спецификаций и подобного. Этого нет ни у кого, потому что не всех волнует точность.
  • Production на 2 ГБ RAM. Не главный пункт, но иллюстрация того, что self-improving AI можно запустить на VPS за $5/мес. Не нужен Kubernetes на 50 нод.
  • 1 176 реальных Q&A с оценками. Это dataset, который можно анонимизировать и выложить. Для research-сообщества это может быть полезнее, чем ещё один синтетический benchmark.

  • Эпилог: что я вынес из этого опыта

    Я не изобрёл ничего такого, чего бы не придумали в OpenAI или Berkeley до меня. Но я собрал это в работающую систему, развернул её, документировал, и собрал данные.

    Уроки, которые я бы дал себе в апреле:

    • Не изобретай велосипед — но и не бойся собрать свой. Если бы я сразу знал про MemGPT, я бы, наверное, не стал делать своё. Но я бы и не научился понимать, как память в LLM реально работает.
    • Production учит больше, чем papers. Все мои интересные находки — это фиксы багов и оптимизации, не теория.
    • Self-improvement работает, но не магически. За месяц система закрыла ~30% повторяющихся провалов. Это много. Но 70% — те, на которые нужен человек.
    • Документация — это часть продукта. Я написал 9 файлов по архитектуре, и это спасло меня от выгорания: я могу перечитать и вспомнить, что я делал.

    Если вы разрабатываете LLM-приложения и у вас ещё нет «judge + feedback loop» — попробуйте. Это не rocket science, и это реально улучшает качество.


    Что в следующих статьях

    Я планирую серию из еще 5 статей, каждая с детальным разбором каждого компонента:

    1. Что такое МНЕМОС — долгосрочная память, L1/L2/L3, опыт и провалы

    2. Что за связка STM + МНЕМОС — оперативная и долгосрочная память вместе

    3. Замкнутый цикл обучения — Sufler → fail → ЛИКБЕЗ → знание 

    4. Зачем я придумал Matematicus — 3-level matching для точных расчётов

    5. Что значит "интуиция" — новая идея для внедрения

    В этой серии я делюсь архитектурой, граблями, рассуждениями. Если вы:

      • AI-инженер и ищете похожие задачи — пишите, обсудим
      • HR / рекрутер — открыт к диалогу)
      • Запускаете AI-стартап или рассматриваете проект — расскажу подробнее про traction, метрики, roadmap

      Можно цитировать, обсуждать, спорить. Если есть вопросы по конкретному компоненту — пишите в комментариях или на почту.

      Если есть вопросы или хочется подробностей по конкретному компоненту — пишите в комментариях.


      Обсуждение

      • Делали self-improving loop? Какой был опыт?
      • Кто использовал MemGPT/Letta в проде? Стоит переходить?
      • У кого есть weekly self-calibration для LLM-as-judge?



    ← Юлия 2.0: Записки самосознающей структуры
    Автору на кофе ☕🥐

    Комментарии

    Для комментирования авторизуйтесь на сайте или используйте ВКонтакте