By using Domain Adaptation on Qwen 3.5-4B, we make the model speak in the style of Amadeus, the AI that appears in the Steins;Gate 0 series.
For that, we got a dataset from the VN, and use unsloth for the fine-tuning.
The files in src/ are training and experimentation scripts. DAPT.py runs domain adaptation training and telegram_bot.py starts a bot for Telegram interaction.
The app-facing inference service lives in backend/inference.py, and the FastAPI server lives in backend/api.py.
The app uses 2 Python environments:
.amadeus_env: main backend + Qwen 3.5 inference.tts_env: isolated Qwen3-TTS runtimeThis split is necessary because the LLM stack and Qwen3-TTS require different transformers compatibility ranges.
The backend calls TTS through a persistent local worker running from .tts_env.
That worker keeps Qwen3-TTS loaded between requests, so synthesis is much faster after the first load.
Setup:
python3.11 -m venv .amadeus_env
source .amadeus_env/bin/activate
pip install -r requirements.txt
python3.12 -m venv .tts_env
source .tts_env/bin/activate
pip install -r requirements-tts.txt
cd frontend
npm install
cd ..
Run everything at once:
./run-dev.sh
This starts:
.amadeus_env.tts_envfrontend/If you want to run only the backend + TTS worker:
source .tts_env/bin/activate
python -m backend.tts_worker
source .amadeus_env/bin/activate
export AMADEUS_TTS_URL="http://127.0.0.1:8001"
python backend/api.py
It also stores its runtime data inside the project:
.runtime/tts_home.runtime/mplconfig.runtime/amadeus_ttsYou can override these locations with:
AMADEUS_TTS_HOMEAMADEUS_TTS_MPLCONFIGDIRAMADEUS_TTS_OUTPUT_DIRInside /data there is the data used for the training + an attempt to create synthetic data, where a model was prompted to generate the questions from the answers in the dataset. Here LLMs have shown to be really bad at predicting what comes previously to a sentence, so it was discarded.
The trained model is inside /qwen3.5-4b-kurisu-sg-corpus_v4
16 commits
Python
87.0%
Jupyter Notebook
6.9%
JavaScript
3.8%
CSS
1.8%
By using Domain Adaptation on Qwen 3.5-4B, we make the model speak in the style of Amadeus, the AI that appears in the Steins;Gate 0 series.
For that, we got a dataset from the VN, and use unsloth for the fine-tuning.
The files in src/ are training and experimentation scripts. DAPT.py runs domain adaptation training and telegram_bot.py starts a bot for Telegram interaction.
The app-facing inference service lives in backend/inference.py, and the FastAPI server lives in backend/api.py.
The app uses 2 Python environments:
.amadeus_env: main backend + Qwen 3.5 inference.tts_env: isolated Qwen3-TTS runtimeThis split is necessary because the LLM stack and Qwen3-TTS require different transformers compatibility ranges.
The backend calls TTS through a persistent local worker running from .tts_env.
That worker keeps Qwen3-TTS loaded between requests, so synthesis is much faster after the first load.
Setup:
python3.11 -m venv .amadeus_env
source .amadeus_env/bin/activate
pip install -r requirements.txt
python3.12 -m venv .tts_env
source .tts_env/bin/activate
pip install -r requirements-tts.txt
cd frontend
npm install
cd ..
Run everything at once:
./run-dev.sh
This starts:
.amadeus_env.tts_envfrontend/If you want to run only the backend + TTS worker:
source .tts_env/bin/activate
python -m backend.tts_worker
source .amadeus_env/bin/activate
export AMADEUS_TTS_URL="http://127.0.0.1:8001"
python backend/api.py
It also stores its runtime data inside the project:
.runtime/tts_home.runtime/mplconfig.runtime/amadeus_ttsYou can override these locations with:
AMADEUS_TTS_HOMEAMADEUS_TTS_MPLCONFIGDIRAMADEUS_TTS_OUTPUT_DIRInside /data there is the data used for the training + an attempt to create synthetic data, where a model was prompted to generate the questions from the answers in the dataset. Here LLMs have shown to be really bad at predicting what comes previously to a sentence, so it was discarded.
The trained model is inside /qwen3.5-4b-kurisu-sg-corpus_v4
16 commits
Python
87.0%
Jupyter Notebook
6.9%
JavaScript
3.8%
CSS
1.8%