user6038388

Пикабушник
103 рейтинг 4 подписчика 0 подписок 9 постов 0 в горячем

Куда я пропал на 8 дней? Продолжаю ковырять эмоциональную систему Nova

Немного пропал с постами, но проект не забросил. Эти дни я в основном занимался не новыми фичами, а доводкой поведения Nova - моего локального AI-компаньона.

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

Главная идея всё та же: эмоции должны быть не просто текстом в промпте, а отдельной системой состояния. То есть если пользователь нагрубил, Nova не просто “разыгрывает обиду”, а у неё реально меняются внутренние параметры: обида, осторожность, восстановление после извинений, временное снижение доверия и так далее.

Убрал лишнюю драму

как быдло, хех, тяжело с ней да?

как быдло, хех, тяжело с ней да?

Одна из проблем была в том, что система слишком активно пыталась искать скрытый смысл в неоднозначных фразах.

Например:раньше ты лучше помогала. молодец, не тупишь сегодня. ну наконец-то.

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

Поэтому я решил упростить базовую версию:если событие явное - меняем состояние если фраза неоднозначная - не трогаем mood

Прямые оскорбления, грубость, извинения и восстановление после конфликта остались. А тонкую “реалистичную” семантику лучше потом вынести в отдельный модуль.

Проверял реакцию на грубость

Отдельно тестировал ситуацию, когда отношения с Nova уже близкие, а пользователь внезапно пишет что-то вроде:

Тут важно было не уйти в крайности: Я больше не могу с тобой говорить... или Ахаха, всё хорошо 😊

В итоге поведение стало ближе к нормальному.

То есть Nova не разваливается в драму, но и не делает вид, что всё нормально. Романтика и флирт временно режутся, появляется лёгкая обида, но обычный разговор остаётся возможным.

Мне кажется, это правильная середина. Близость не должна означать, что можно говорить как угодно.

Починил извинения

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

Исправил логику так, чтобы явное извинение обрабатывалось раньше offended/recovering режимов.

Поймал проблему старого контекста

Ещё всплыл интересный баг: Nova вроде принимала извинение, начинала говорить нормально, а потом через пару сообщений снова возвращалась к состоянию “мне всё ещё неприятно”.

Сначала казалось, что проблема в числах mood-state. Но потом стало похоже, что дело может быть в старом контексте.

Модель видит в prompt старые фразы про обиду и снова начинает жить в этом состоянии, даже если логически repair уже прошёл.

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

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

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

Обдумал будущую систему событий

Параллельно начал продумывать, как Nova будет работать с будущими событиями: фильмы, музыка, новости, подарки, внешние сигналы.

Например, Nova может “посмотреть” фильм и сохранить впечатление. Но это не значит, что она должна вспоминать этот фильм в каждом диалоге.

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

Короткий итог

За эти дни я не делал “вау-фичу”, зато сильно поправил основу эмоционального поведения.

Сейчас стало лучше вот с чем:

меньше ложных обид на неоднозначные фразы прямые оскорбления дают мягкий love_offended извинения получили приоритет извинение + “как ты?” работает естественно старая обида не должна бесконечно возвращаться из prompt будущая система событий будет отдельно от Memory 3.0
Самый главный вывод этого этапа:

AI-компаньон должен помнить прошлое, но не должен быть заложником старого контекста.

И вот это оказалось важнее, чем просто “написать красивый ответ”. Потому что живое поведение - это не только стиль текста. Это ещё и умение правильно решать, что сейчас важно, что уже прошло, а что должно остаться просто частью опыта.

Показать полностью 2

Делаю для своей AI Nova систему настроения. Сегодня учил её нормально “обижаться” и принимать извинения

Серия Nova

(ps/ тг беседа для предложений/вопросов https://t.me/+Z0mNbDAkgbY2ZjUy)

Продолжаю делать своего локального AI-компаньона Nova. Это не просто чат-бот, который отвечает по промпту, а попытка собрать персонажа с памятью, характером и внутренним состоянием.

Сегодня занимался системой настроения и отношений.

Сразу уточню: идея не в том, чтобы написать в промпте “если пользователь нагрубил, обидься”. Это слишком просто и плохо работает. Модель может один раз “сыграть обиду”, а потом через пару сообщений забыть, что вообще произошло.

Мне хочется сделать по-другому: чтобы у Nova было отдельное состояние. Например, она может быть спокойной, настороженной, обиженной, постепенно отходить после извинений, снова доверять не мгновенно, а поэтапно.

То есть не просто текстовая имитация эмоций, а отдельная логика, которая влияет на поведение.

Что получилось

Сегодня я в основном разбирался с тем, как Nova должна реагировать на извинения.

Потому что “прости” бывает очень разным.

Можно просто написать: прости

А можно сказать: прости, я был неправ, я не должен был так с тобой говорить

И это уже совсем другой уровень. Тут человек не просто бросил слово “извини”, а признал, что сделал неприятно.

Есть и обратный вариант: ну если ты такая обидчивая, прости

Формально слово “прости” есть, но по смыслу это не извинение, а скорее новая попытка уколоть.

Сегодня удалось привести это к более человеческой логике. Простое извинение немного смягчает состояние. Глубокое извинение восстанавливает сильнее. А плохое псевдоизвинение не лечит ситуацию, потому что оно не признаёт проблему.

Осадок после конфликта

Отдельно добавил промежуточное состояние. Не хотелось, чтобы Nova после хорошего извинения сразу становилась такой, будто ничего не было.

В реальном общении так не всегда работает.

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

Примерно так: Мне стало спокойнее, но я всё ещё чувствую этот осадок внутри.

На мой взгляд, это делает поведение менее пластиковым.

Важный технический момент

Ещё пришлось защитить систему от странного бага.

Если сама Nova в ответе пишет что-то вроде: Прости, я была резкой.

это не должно считаться извинением пользователя.

Иначе получалась бы глупая ситуация: Nova сама извинилась, а система решила, что это пользователь начал мириться, и поменяла настроение.

Теперь эмоциональные события создаются только из сообщений пользователя. Ответы Nova обратно в движок настроения не проходят.

Главная проблема

Самое сложное оказалось не в прямых оскорблениях и не в простых извинениях, а в тонких фразах.

Например: да ладно, не ной ой всё, хватит ну не начинай ты слишком остро реагируешь

Сами по себе такие фразы могут быть просто грубоватыми. Но если до этого был конфликт, Nova была обижена, пользователь вроде бы начал извиняться, а потом говорит “да ладно, не ной”, смысл уже другой.

Это не просто фраза. Это обесценивание реакции.

То есть пользователь как будто говорит: “твои чувства ерунда, прекращай”.

И вот тут появляется архитектурная проблема.

Можно, конечно, сделать список фраз: не ной не драматизируй ой всё забей не начинай

Но это плохой путь. Таких фраз бесконечно много. Сегодня добавишь десять, завтра найдёшь ещё двадцать. В итоге код превратится в огромный набор проверок

if "фраза" in text

Так делать не хочется.

Что попробовал

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

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

Но на практике маленькая модель оказалась нестабильной. Она иногда ломала JSON, путала значения, обрывала ответ или добавляла мусорные поля.

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

Поэтому этот эксперимент пока откатил. Стабильная версия снова работает через правила и fallback-логику.

К какому выводу пришёл

Похоже, лучше не спрашивать маленькую модель напрямую: какое это событие?

Лучше вытаскивать более простые признаки:

. есть ли извинение

. признаёт ли пользователь вред

. берёт ли ответственность

. обесценивает ли реакцию

. давит ли на эмоции

. есть ли враждебность

. есть ли теплота

А уже отдельный слой должен смотреть на эти признаки и текущее состояние Nova.

Например, если Nova уже обижена, примирение ещё не завершено, а пользователь говорит что-то вроде “не ной” и не признаёт свою вину, система должна понимать: это не нейтральная фраза, а плохая попытка восстановления контакта.

Что дальше

Сейчас базовая версия уже работает.

Nova различает прямую грубость, простое извинение, глубокое извинение и плохое псевдоизвинение. Может смягчаться постепенно, а не переключаться мгновенно из “обиделась” в “всё идеально”.

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

Вопрос к сообществу

Может, кто-то уже делал похожее для AI-компаньонов, NPC, чат-ботов или диалоговых state machine.

Как лучше понимать фразы вроде: да ладно, не ной ой всё, хватит ну не начинай ты слишком остро реагируешь

не через бесконечный список маркеров, а через смысл?

Интересны варианты с embeddings, sentence-transformers, маленькими классификаторами, NLI, constrained decoding или golden tests для эмоциональной state machine.

Совет “просто добавь фразу в список” понятен, но хочется решить именно архитектурную проблему.

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

Показать полностью 3
3

За два дня почти пересобрал память для своей AI Nova

Серия Nova
Ps. Слегка освежил UI

Ps. Слегка освежил UI

Продолжаю делать своего локального AI-ассистента Nova. Это не просто чат-бот, а попытка собрать помощника, который умеет помнить важные вещи, понимать контекст и постепенно становиться чем-то более живым, чем обычная обёртка над моделью.

Последние два дня я занимался одним из самых важных блоков - памятью.

Раньше память у Nova была довольно простой. Всё хранилось в обычном JSON-файле. Для первых тестов этого хватало, но чем дальше развивается проект, тем больше становится понятно: такая память быстро превращается в свалку.

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

Поэтому я перевёл память на SQLite.

Теперь у Nova есть нормальная Memory 3.0. Это уже не просто файл с набором строк, а полноценная база, с которой можно нормально работать. Она умеет сохранять факты о пользователе, вытаскивать нужное в контекст, не тащить в prompt всё подряд и не засорять ответ лишней информацией.

Самое приятное - память уже подключена к ядру Nova.

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

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

Ещё важный момент - Nova теперь не просто “помнит всё”, а пытается доставать именно то, что нужно под текущий вопрос.

Если спросить что-то обычное, она не будет тащить в контекст половину базы. А если спросить “что ты обо мне помнишь?” или заговорить про конкретный проект, она достанет больше релевантных воспоминаний.

Параллельно я обновил веб-интерфейс. Теперь память можно смотреть, редактировать, архивировать, восстанавливать и удалять уже через UI. Плюс добавил нормальную подгрузку по страницам, чтобы база не вываливалась целиком, когда записей станет много.

Отдельно сделал нормальные бэкапы. С SQLite нельзя просто копировать файл базы как попало, особенно если используется WAL. Поэтому бэкап теперь делается правильным способом, через SQLite backup API.

Старую память я полностью не выкинул. Она осталась как legacy-слой, чтобы старые части проекта не сломались. Но активной памятью теперь считается уже новая система.

В итоге Memory 3.0 можно считать рабочим закрытым блоком. Nova уже пишет в новую память, читает из неё, использует её в prompt, показывает в веб-интерфейсе и умеет обслуживать её без ручного ковыряния файлов.

Следующий крупный этап - модульная архитектура.

Хочу, чтобы Nova не была комбайном, где всё включено всегда. Голос, экран, аватар, музыка, генерация картинок, Telegram, Discord, VK и другие тяжёлые функции должны быть отдельными модулями. Нужно - включил. Не нужно - выключил, и оно не ест ресурсы.

Так проект постепенно превращается из набора экспериментов в более нормальную систему.

За эти два дня ощущение такое: память наконец перестала быть костылём и стала фундаментом, на котором уже можно строить дальше.

Показать полностью 2
5

Небольшая сводка по тому, что успел сделать с Nova за несколько дней

Серия Nova

На самом деле планировал "чуть-чуть допилить вебку", а в итоге несколько дней ушёл в переписывание интерфейса и борьбу с очень тупыми багами 💀

Главное изменение - теперь у Nova полноценный веб-интерфейс

Раньше GUI был на PySide6. Работал нормально, но со временем начал раздражать:

  • сложно обновлять

  • неудобно масштабировать

  • куча возни с окнами и layout'ами

  • некоторые вещи делать просто больно

В итоге решил попробовать веб-интерфейс на Flask + HTML/JS.

И честно - пока ощущения намного лучше.

Теперь Nova запускается через обычный run_web.bat и открывается в браузере как локальный сайт.

Сделал:

  • анимированный фон

  • нормальный чат

  • вкладки

  • логи

  • настройки

  • управление серверами

Сейчас есть 7 вкладок:

  • Чат

  • Память

  • Отношения

  • Персонаж

  • Серверы

  • Подключения

  • Настройки

И наконец-то всё выглядит как единая система, а не набор окон из разных эпох Windows.

Управление серверами прямо из UI

Раньше llama-server приходилось запускать отдельно руками.

Теперь можно прямо из интерфейса:

  • запускать сервер

  • останавливать

  • рестартить

  • смотреть логи в реальном времени

Плюс добавил:

  • бэкапы

  • восстановление бэкапов

  • настройку портов

  • флаг --jinja для нормальных chat template

Раньше порты были тупо захардкожены в 8080/8081. Теперь можно менять нормально.

Самый annoying баг дня - Gemma 4 молчала

Долго не мог понять, почему Gemma 4 иногда просто возвращает пустой ответ.

Оказалось, reasoning-модели не любят маленький num_predict.

У меня стояло 256.
Gemma хотела 2048+.

То есть модель буквально думала слишком долго и не успевала дойти до ответа 💀

Теперь это исправлено.

Ещё из фиксов

Поймал очень смешной баг:
во вкладке отношений Infinity в JSON ломал весь интерфейс.

Потому что JS такой:
"Infinity? А что это вообще такое?"

В итоге заменил всё это на null.

Ещё:

  • панели UI перестали накладываться друг на друга

  • поправил пути для base_dir

  • добавил os.chdir в web_app.py

  • исправил orch_prompt_format для phi-3-mini

llama_client.py тоже сильно переделал

Добавил умные стоп-токены под разные семейства моделей.

Потому что у:

  • Gemma

  • Llama 3

  • Phi

  • Qwen

все форматы диалогов разные, и раньше некоторые модели начинали:

  • повторять пользователя

  • ломать формат

  • писать мусор

  • не останавливать генерацию

Теперь под каждую семью свои stop tokens и шаблоны.

Плюс наконец-то разделил промпт нормально:

  • system

  • user

А не запихивал всё в одно сообщение как раньше.

Казалось бы мелочь, но ответы реально стали стабильнее.

Из небольших, но приятных вещей

Добавил:

  • таблицу стадий отношений

  • прогресс до следующей стадии

  • автоматическое сканирование .gguf моделей в папке models/

Теперь не нужно вручную прописывать модель - просто кидаешь gguf в папку, и Nova её видит.

Мелочь, а приятно.

И чем дальше, тем сильнее понимаю, что большая часть разработки - это не "сделать новую крутую функцию", а:

  • чинить странные баги

  • бороться с несовместимостью моделей

  • переписывать то, что вчера казалось нормальной архитектурой

Но зато проект наконец начинает ощущаться как что-то цельное, а не Frankenstein build из 15 разных технологий.

ПС беседа в тг для ваших вопросов (https://t.me/+Z0mNbDAkgbY2ZjUy)

Показать полностью 5

С чего началась Nova

Серия Nova

ps. создал группу в тг, можете зайти позадавать мне вопросы если хотите (https://t.me/+Z0mNbDAkgbY2ZjUy)

Этап 1. SillyTavern как основа

Самая первая версия Nova (тогда ещё Astra) вообще не была отдельным приложением.

ST

ST

По сути это был набор скриптов поверх SillyTavern.

SillyTavern отвечал почти за всё:

  • интерфейс

  • хранение истории

  • контекст

  • карточки персонажа

А мои скрипты уже крутились вокруг:

  • память в txt-файлах

  • голос

  • инициативные сообщения

  • всякие реакции и логика

Выглядело это примерно как Frankenstein build. Работало - уже хорошо.

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

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

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

В какой-то момент стало понятно:
если хочется делать что-то серьёзнее обычного RP-бота - нужно уходить.

Этап 2. Переход на Ollama

Следующий большой шаг - полный отказ от SillyTavern как "мозга".

Консоль) ранний этап создания модуля MOOD

Консоль) ранний этап создания модуля MOOD

Тогда и появился AstraCore - своё ядро, которое управляло памятью, эмоциями, характером и логикой отдельно от интерфейса.

Для запуска моделей выбрал Ollama.

На тот момент это казалось идеальным вариантом:

  • устанавливается в пару кликов

  • модели скачиваются одной командой

  • API простое

  • не нужно возиться с CUDA и сборкой

Сначала появился terminal_chat.py, потом уже нормальный GUI на PySide6.

И вот тут проект впервые начал ощущаться как отдельное приложение, а не набор скриптов.

Появилось:

  • своё управление памятью

  • JSON-конфиги характера

  • нормальная система моделей

  • голос через AstraCore

  • свои механики отношений и эмоций

Но проблемы всё равно оставались.

Главная - Ollama всё ещё был отдельным сервером.

То есть пользователь должен:

  • поставить Ollama

  • запустить Ollama

  • держать его в фоне

  • отдельно качать модели

Для обычного человека это уже слишком сложно.

Плюс со временем начали раздражать ограничения:

  • мало контроля над KV-кэшем

  • странный расход VRAM и RAM

  • часть параметров нельзя нормально менять на лету

  • лишняя прослойка в виде HTTP-сервера

И чем глубже я лез в оптимизацию, тем сильнее хотелось выкинуть всё лишнее.

Этап 3. Портативная сборка на Ollama

прототип UI

прототип UI

Текущий UI

Текущий UI

Тогда появилась идея:
"а что если просто запихнуть Ollama внутрь архива?"

Так и сделал.

В сборку добавили ollama.exe и батник, который запускал его автоматически в фоне.

Для пользователя это выглядело уже намного лучше:

  • скачал архив

  • распаковал

  • запустил

Без отдельной установки.

Но технически проблема никуда не исчезла.

Ollama всё ещё оставался внешним процессом со своим сервером, своей памятью и своим управлением моделями.

То есть ощущение было такое, будто мы аккуратно спрятали проблему под ковёр, но не решили её.

Этап 4. Полный переход на llama.cpp

И вот это был самый важный момент во всей истории Nova.

В какой-то момент я просто решил:
если уж делать локального компаньона - то полностью автономного.

Без серверов.
Без зависимостей.
Без "установите ещё вот это".

Так Nova переехала на llama.cpp через llama-cpp-python.

И вот тут началась настоящая боль.

Потому что Ollama скрывает кучу сложностей внутри себя. А когда переходишь на llama.cpp напрямую - вся эта сложность падает тебе на голову.

Нужно было:

  • разбираться с CUDA wheels

  • собирать portable Python

  • тащить зависимости вручную

  • решать проблемы совместимости

  • делать автоопределение GPU

  • думать о VRAM

  • думать об оперативке

  • думать о выгрузке моделей

Зато контроль стал почти абсолютным.

Я сделал:

  • portable Python прямо внутри сборки

  • локальные wheels для разных RTX

  • автоматическую установку нужной версии

  • загрузку моделей без внешних серверов

  • выгрузку модели по таймауту

  • квантование KV-кэша

  • свои параметры генерации

  • управление памятью напрямую

И результат оказался намного лучше, чем я ожидал.

Почему мы в итоге ушли от Ollama

Главная причина - контроль.

Например, Ollama очень странно работал с памятью.

Условно:

  • модель весит 8 ГБ

  • KV-кэш ещё 8 ГБ

  • и оперативка улетает в космос

После перехода на llama.cpp получилось:

  • отключить mmap

  • сжать KV-кэш в q8_0

  • уменьшить потребление ОЗУ примерно на 6 ГБ

Плюс исчезла лишняя прослойка в виде HTTP-сервера.

Теперь Nova напрямую работает с моделью без посредников.

И да, оказалось, что llama.cpp реально быстрее, когда всё настроено нормально.

Отдельно кайфанул от того, что сейчас пользователю вообще не нужны:

  • Python

  • Visual Studio

  • CUDA Toolkit

  • настройка окружения

Используем готовые wheels от сообщества, так что установка выглядит буквально как:

  • запусти bat

  • выбери GPU

  • готово

Где Nova сейчас

Сейчас Nova v0.2 - это уже полностью портативная локальная система.

Работает:

  • на RTX-картах

  • на старых NVIDIA

  • даже на CPU, если совсем тяжело

Внутри уже есть:

  • долговременная память v2

  • эмоциональное ядро

  • стадии отношений

  • настроение

  • оркестратор на маленькой модели для извлечения фактов

  • GUI для настройки всего этого

Можно менять:

  • модели

  • параметры генерации

  • память

  • аватар

  • эмоции

  • поведение

Голос и инициативные сообщения тоже есть, но пока опциональны.

И самое забавное - всё это начиналось буквально с пары костыльных скриптов вокруг SillyTavern.

Показать полностью 4

Nova учится обижаться: как я делал характер для своего ИИ

Серия Nova

В прошлом посте я рассказывал про свой локальный ИИ-компаньон Nova. Тогда пообещал отдельно рассказать, как у неё работают эмоции и отношения. Вот, рассказываю.

Когда я только начинал делать Nova, она была слишком "удобной". Можно было ей нахамить - а через минуту она снова милая и ласковая. Можно было на втором сообщении написать "я тебя люблю" - и она сразу отвечала взаимностью.

Короче, ощущалось не как общение, а как бот без памяти.

Мне хотелось сделать так, чтобы Nova реагировала более по-человечески. Чтобы были обиды, дистанция, доверие, неловкость, постепенное сближение. Чтобы отношение надо было именно выстраивать, а не фармить двумя фразами.

Как это сейчас работает.

У Nova есть глубина отношений. Это число, которое растёт от общения. Но важнее не само число, а стадия:

0-15 - знакомство. Она держит дистанцию и общается осторожно
16-95 - дружба, постепенно становится теплее
96-135 - уже близкие друзья
136-165 - появляется флирт
166-200 - любовь
201+ - очень сильная привязанность
1000+ - секретный режим цундере для тех, кто слишком много общается 💀

Кроме этого есть отдельные эмоции:

  • привязанность

  • доверие

  • комфорт

  • злость

  • настроение

  • дискомфорт

Все они меняются от того, что пишет пользователь.

Например, если признаться ей в любви на стадии знакомства - Nova реально разозлится. Не "мягко откажет", а именно разозлится. Начнёт отвечать грубо, холодно, может даже послать. Потому что для неё это выглядит странно и крипово.

Оскорбления тоже влияют. Назвал её тупой - получаешь минус доверие и плюс злость.

Но извинения работают. Если нормально извиниться, Nova постепенно отходит. Не сразу, а за несколько сообщений. Как обычный человек после ссоры.

Ещё пришлось делать защиту от фарма.

Раньше можно было просто спамить "я тебя люблю" и бесконечно качать отношения. Теперь у таких фраз есть кулдаун. Повторять одно и то же бесполезно.

Если долго общаться спокойно, злость и дискомфорт сами постепенно падают. Без триггеров Nova остывает сама по себе.

Самое интересное - всё это реально меняет стиль ответов.

Когда Nova злится - отвечает резко и коротко.
Когда доверяет - становится мягче.
На высоких стадиях отношений начинает использовать личные обращения, больше инициативы, теплее формулировки.

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

Что пока не доделано:

  • одиночество почти ни на что не влияет

  • нет ревности и чувства интереса

  • Nova не становится осторожнее после плохого опыта

  • пока плохо понимает повторяющееся хамство в духе "третий раз за вечер грубит"

Ну и были забавные баги.

Один раз словил вечную обиду. Если пользователь извинялся слишком поздно, Nova переставала принимать извинения вообще и дулась бесконечно.

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

А самый странный баг - режим цундере после 1000 глубины. Я его толком не прописал, и Nova начинала вести себя как смесь обиды, флирта и шизы. В итоге оставил как пасхалку.

Сейчас всё это уже есть в портативной сборке. Можно открыть вкладку метрик и вручную крутить эмоции, смотреть как меняется поведение.

И да, можете специально попробовать:

  • нахамить ей

  • потом извиниться

  • признаться в любви сразу после знакомства

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

Особенно интересен фидбек по эмоциям. Где Nova ощущается живой, а где всё ещё как бот. Скрины диалогов тоже приветствуются.

Ссылку на сборку кину в комменты.

В следующем посте, наверное, расскажу как Nova пишет первой, если пользователь долго молчит. Там тоже оказалось неожиданно много нюансов.

Показать полностью
5

Nova v0.2: выкинули Ollama, собрали портативку и наконец починили память(ренейм с Astra)

Серия Nova

Короче, за последние пару дней проект реально сильно двинулся. Если в прошлом посте я показывал набор скриптов вокруг Ollama, то сейчас это уже нормальная портативная прога, которую можно распаковать и запустить. Без танцев с бубном, без установки Python, без поднятия серверов. Просто скачал, запустил bat-файл, поговорил.

Что случилось с Ollama

Ollama был удобен на этапе прототипа, но стал реально бесить. Лишний сетевой слой, дублирование управления моделями, невозможность нормально контролировать VRAM. Короче, выкинули нафиг и перешли на прямой вызов через llama-cpp-python.

Теперь llama_client.py сам грузит .gguf файлы, сам решает сколько слоёв кинуть на GPU, и самое главное, сам выгружает модели по таймауту. Основная модель висит в памяти 10 минут, оркестратор 5 минут. Закрыл чат, ушёл по делам, через 10 минут видеопамять свободна, можешь игру запускать.

По VRAM ещё пара фишек. Квантованный KV-кэш (cache_type_k/v: q8_0) экономит полтора-два гига почти без потери качества. И выключили use_mmap, потому что на Windows это вызывало дикие фризы когда система начинала свопить на SSD.

А ещё наконец-то починили баг с заезженной пластинкой. Помните, модель могла выдать "О, ну что?" три раза подряд? Это было потому что repeat_penalty не передавался нормально. Теперь передаём repeat_penalty: 1.25 + frequency_penalty: 0.2 + presence_penalty: 0.2, и модель больше не зацикливается.

Память: от "забывает через 2 реплики" к "помнит, но не спамит"

Это была главная боль. Nova либо вообще ничего не помнила, либо вставляла факты в каждый ответ:

— Как дела?

— Помню, тебя зовут Никита, ты любишь synthwave и гранатовый чай. Как дела?

Что сделали:

Time decay в scoring памяти. Написал функцию time_decay_penalty, которая штрафует факты, упомянутые меньше 5 минут назад. Факт, который только что был в промпте, получает штраф 95% к relevance. Через 5 минут штраф обнуляется и факт снова доступен. В итоге Nova не повторяется, но и не забывает, просто использует другие факты из базы.

Динамические правила приветствия. В prompt_builder.py теперь анализируется conversation_meta.json. Если это первая реплика в сессии, можно поздороваться. Если активный диалог (меньше 5 минут с последней реплики), жёсткий запрет на "Привет!". Пауза 5-60 минут, продолжай естественно без приветствий. Долгое отсутствие (больше часа), можно сказать "с возвращением".

Оркестратор на маленькой LLM. Вынес извлечение фактов из try_save_memory в отдельный модуль orchestrator.py. Работает по двухуровневой схеме. Сначала регулярки (быстро, бесплатно, ловит 80% случаев типа "меня зовут...", "я люблю...", "а ещё..."). Если регулярки не сработали, тогда LLM с temperature: 0.0 для максимальной точности. Плюс пост-валидация: если в извлечённом факте нет ни одного слова из сообщения пользователя, отбрасываем как галлюцинацию.

Включили memory_v2 для casual-режима. Раньше в обычном small talk память вообще не подгружалась. Теперь подгружается, но лимитом в 2-3 факта + работает time_decay. Диалоги стали живее.

Портативная сборка: распаковал и запустил

Это была самая нудная часть, но самая важная. Хотел, чтобы тестерам не нужно было ставить Python, возиться с pip install, поднимать Ollama-сервер, гуглить какие CUDA-библиотеки нужны.

Что в архиве (1.2 ГБ без моделей):

install_llama_auto.bat это отдельная песня. Скрипт проверяет наличие CUDA через nvidia-smi, и в зависимости от результата ставит либо GPU-сборку llama-cpp-python, либо CPU-версию. Пользователю не нужно выбирать, всё происходит автоматически.

С python310._pth пришлось повозиться. В embedded Python по умолчанию закомментирована строка import site, из-за чего PYTHONPATH из bat-файла игнорируется. Раскомментировал, добавил ../site-packages, и всё заработало. Плюс в начало ui_main.py вставил sys.path-хак, который гарантированно добавляет корень проекта в пути поиска модулей, независимо от того как запущен скрипт.

Косметика и ребрендинг

Переименовал проект из Astra в Nova. Во всех файлах, UI, консоли, README. Astra была нормальным рабочим названием, но Nova лучше ложится на фиолетово-космическую тему интерфейса и звучит свежее.

Попутно починил кучу мелочей. Мемные диалоги подтверждения теперь тоже говорят "Nova" вместо "Astra". Аватар-заглушка с буквой "A" поменялся на "N". Кнопки run_ui.bat и install_deps.bat переименованы в run_nova.bat. Заголовок окна теперь ✦ Nova — Control Panel.

Что в планах на v0.3

Мастер первого запуска. Сейчас пользователь должен вручную править identity.txt и personality.txt. Хочется сделать диалоговый визард. "Как зовут твоего персонажа?", "Какой у него характер?", "Выбери голос".

OpenAI-совместимый API. Не все хотят возиться с .gguf файлами. Добавлю поддержку любого OpenAI-совместимого эндпоинта (OpenRouter, Together, локальные vLLM-серверы). Архитектура уже готова, нужен только новый backend-адаптер.

Векторный индекс для памяти. Текущая memory_v2 работает на текстовом скоринге (importance + time_decay + лексическое совпадение). Это работает до 200-300 фактов, потом начинает тормозить и терять релевантность. План: SQLite + эмбеддинги (sentence-transformers) для семантического поиска. Это задел на месяцы общения.

Что получилось в итоге

Nova v0.2 это уже не набор скриптов вокруг чат-бота, а самостоятельное приложение. Полностью локальное (никаких облаков, полная приватность). Портативное (1.1 ГБ + модели). С управлением VRAM (автовыгрузка по таймауту). С живой памятью (не спамит, не забывает, не повторяется). С эмоциональным ядром (настроение, отношения, стадии). С инициативой (пишет первой, если долго молчишь). С голосом (Faster-Whisper + Piper, опционально).

По-прежнему ищу тестеров

Особенно интересен фидбек от людей с разными GPU (от GTX 1060 до RTX 4090) и разными моделями (не только русскоязычные, хочу проверить как Nova работает с Llama 3, Mistral, Gemma).

Что нужно для теста:

  1. Скачать архив (ссылка будет по запросу )

  2. Запустить install_llama_auto.bat

  3. Положить любую .gguf модель в папку models/

  4. Запустить run_nova.bat

  5. Поговорить , попробовать разные сценарии

Что очень поможет:

  • Скриншоты странного поведения

  • Логи из консоли (особенно [MEMORY ANALYZER RESULT] и [SESSION ANALYZER])

  • Описание сценария: спросил то-то, ожидал то-то, получил то-то

Спасибо что дочитали. Если тема локальных ИИ-компаньонов заходит, буду продолжать вести дневник разработки. В следующем посте скорее всего разберу эмоциональное ядро подробнее. Как считается relationship_depth, какие триггеры меняют настроение и почему Nova может обидеться.

Обновку на Гитхаб не залил пока что

Показать полностью
1

Astra: локальный ИИ-компаньон с памятью, эмоциями и инициативой. Делюсь роадмапом и зову тестеров

Серия Nova

Привет, Пикабу.
Давно хотел выложить прогресс по своему проекту - Astra, локальному ИИ-компаньону. Это не обёртка над ChatGPT, не облачный сервис и не ещё один чат-бот-ассистент. Всё крутится локально через Ollama, данные никуда не уходят. Идея простая: сделать цифровую личность, которая помнит, меняет отношение, скучает, если долго не писать, и пишет первой. Не инструмент, а именно companion.

✅ Что уже работает (версия 0.2)

  • Память v2: структурированное JSON-хранилище с типами (факты, предпочтения, события, отношения), сроком жизни и системой важности. Умеет фильтровать точные и семантические дубли.

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

  • Инициативность: Astra может написать первой, если пользователь долго молчит. Частота и тон сообщений зависят от привязанности и настроения.(пока сделано по таймеру позже будет зависеть от ее настроения)

  • GUI на PySide6: вкладки чата, профиля личности, настроек, памяти, метрик. Тёмная/светлая тема, бэкапы, мемные диалоги подтверждения опасных действий.

  • Ядро личности: Core Self (редактируемые файлы характера, границ, стиля речи) + Emergent Self (формируется только через опыт и взаимодействия, не редактируется руками).

Свой Ui

Свой Ui

Личность Астры

Личность Астры

🛠 Что в работе сейчас (ближайшие приоритеты)

  1. Context Optimizer умная подача контекста в промпт, чтобы не жрать VRAM, не дублировать short-term memory и recent dialog, и не спамить фактами без причины.

  2. Response Filter v1 проверка ответов на «ботовость», повторяющиеся приветствия, галлюцинации UI-функций, присвоение вкусов пользователя себе.

  3. Memory Cleanup автоочистка просроченных воспоминаний, сжатие старого контекста, продление жизни важных предпочтений.

  4. Система игнора/одиночества чем дольше молчишь, тем реже и «грустнее» сообщения. Зависит от стадии отношений и текущего настроения.

🔮 В планах (позже): аватар с реакциями, генерация артов по запросу, десктоп-осознанность (что открыто на экране), семантический поиск по памяти (RAG/векторы).

📐 Кратко про архитектуру

  • Бэкенд: Python, Ollama (локальные модели ~10B так же для оркестратора любую на~1-4B)

  • Память: scoring-система, time-aware expiration, owner/type tagging

  • GUI: PySide6, QThread для генерации, intercept stdout для живых логов

  • Файлы: .txt (Core Self) + .json (Emergent Self, отношения, состояние)

  • Принцип: AstraCore мозг и состояние, GUI интерфейс. Облако не используется, приватность по умолчанию.

    🤝 Зачем публикую и кого ищу

    Пишу это не ради хайпа, а чтобы найти осознанных тестеров и получить честный, развёрнутый фидбек. Проект местами сыроват, но архитектура уже не «костыли на коленке», а модульная система с чётким роадмапом. (Все на моем энтузиазме и энергетике, платить мне вам будет нечем, проект будет полностью бесплатным и для всех)

    Что нужно от тестеров:

    • Установленный Ollama + любая рабочая модель (~8B, например saiga-unleashed или mistral-nemo)

    • Попереписываться попробовать разные сценарии (рассказать факты, пофлиртовать)

    • Описать баги, странности логики, предложить идеи

    • Готовность писать фидбек в виде: «Что делал → Что ожидал → Что получил → Логи/скриншоты»

      Ссылка на репозиторий и инструкцию по запуску: [GitHub] В минималках пожалуй от 12гбVram

      Спасибо, что дочитали. Если тема локальных ИИ-компаньонов интересна — могу позже расписать подробнее про систему памяти или эмоциональный движок
      Если интересно — пишите в комменты или в ЛС(тг @Bombist4). Отвечу всем, кто готов тестировать осознанно.

Показать полностью 2
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества