3_Customization
Как кастомизировать персонажа.
Персональность
Промпты персонажа лежат в resources/Characters/<ваш_персонаж>/personalities.yml.
Общие промпты, не привязанные к персонажу (способности, агенты, формат вызова
инструментов), — в resources/Prompts/.
Основное описание роли и характера указано в streamer_abstract:
вы можете изменить это описание под вашего персонажа. Это промпт для LLM.
и сами мини-промпты команд и агентов захардкожены (указаны в коде напрямую) в src/agent/core_agent.py и в src\agent\multi\reaction_agent.py
Голос персонажа
Синтез с клонированием голоса работает так: на каждую эмоцию есть короткий образец голоса и его точная расшифровка. Движок слышит образец, читает расшифровку и произносит новый текст этим же голосом с этой же интонацией.
Файлы лежат в resources/Characters/<ваш_персонаж>/Voice/, а связь
«эмоция → файл → расшифровка» описана в refs_manifest.yml:
neutral:
wav: neutral # файл neutral.wav в этой же папке, без расширения
text: Чем могу быть полезен? # ровно то, что в нём произнесено
В поставке лежат образцы, синтезированные обычным TTS, — чтобы проект завёлся из коробки. Свой персонаж начинается с их замены.
Как поставить свой голос
- Запишите или синтезируйте образцы. Хорошо работают фрагменты 3–10 секунд, один говорящий, без музыки и шума. Слишком короткий образец (меньше двух секунд) даёт нестабильный результат, слишком длинный — ничего не добавляет.
- Сохраните как WAV, моно, 44.1 кГц, 16 бит. Проверить и привести файл:
bash
ffprobe -v error -show_entries stream=channels,sample_rate,bits_per_raw_sample -of default=nw=1 mysound.wav
ffmpeg -i mysound.wav -ac 1 -ar 44100 -c:a pcm_s16le resources/Characters/MyChar/Voice/neutral.wav
- Пропишите в
refs_manifest.ymlэмоцию, имя файла без.wavи точную расшифровку. Расхождение расшифровки со звуком — главная причина, почему клонирование звучит криво. - Эмоций может быть сколько угодно. Обязательна одна —
neutral: если агент выдаст эмоцию, которой нет в манифесте, возьмётся она.
Если используете простой синтез вместо клонирования, образцы не нужны —
там голос выбирается параметром speaker_id (1–6) в simple_tts_server.py.
Звуки интерфейса
Это короткие сигналы, которыми персонаж озвучивает происходящее: включение, ошибка, бан слова, запись в базу, критический отказ. Агент умеет проигрывать их сам — список доступных имён он получает как раз из манифеста.
Лежат в resources/Audio/fx/, связь «имя события → файл» в fx_manifest.yml.
Всё, что идёт в поставке, сделано самим проектом: сигналы из alarms/
синтезированы скриптом tools/make_fx_sounds.py, реплики диктора из records/
получены синтезом речи. Чужих сэмплов в репозитории нет и быть не должно —
звук из игр, фильмов и роликов сюда класть нельзя, даже «на время».
Как устроен манифест
Простой случай — имя события и путь к файлу:
error: records/error.wav
bell: alarms/bell.wav
Составной — список из нескольких сигналов подряд:
starting:
- poweron # имя другого сигнала из этого же манифеста
- none # короткая тишина-пауза
- powerstarting
Внутри последовательности доступны два особых элемента:
wiped_state:
- sequence: fatal_errored # вложенная последовательность
delay: 4 # пауза перед ней, секунды
wait: True # дождаться её конца, а не запускать параллельно
- bell
Как заменить сигналы своими
Проще всего — поправить генератор и пересобрать:
python tools/make_fx_sounds.py --list # что вообще создаётся
python tools/make_fx_sounds.py # пересоздать все сигналы
Внутри build() каждый сигнал собирается из примитивов: tone (тон, при
указании freq_end — свип), noise (шум), envelope (сглаживание краёв,
без него на стыке щелчок), decay (затухание), mix (наложение), seq
(подряд), silence (пауза). Скрипту не нужны зависимости, только стандартная
библиотека.
Если хотите положить готовые файлы вместо синтеза:
- Приведите к WAV, моно, 44.1 кГц, 16 бит той же командой
ffmpeg, что и для голоса. - Положите в
resources/Audio/fx/alarms/илиrecords/. - Пропишите путь в
fx_manifest.ymlнапротив нужного имени события. - Держите сигналы короткими. Всё, что длиннее двух секунд, персонаж будет перебивать собственной речью.
Ключ none должен остаться на месте — он используется как пауза внутри
последовательностей.
Если файл в манифесте указан, а на диске его нет, воспроизведение просто пропускается: проект не падает, но и звука не будет.
Отдельная инструкция
Пошаговая замена звуков со всеми форматами и разбором частых проблем — Свои звуки и голос.