ENhance ship personnality
This commit is contained in:
358
README.md
358
README.md
@@ -1,101 +1,345 @@
|
|||||||
# Arioch — Assistant vocal (Mistral Large + Voxtral TTS)
|
# Arioch — Assistant vocal (Mistral Large + Voxtral TTS)
|
||||||
|
|
||||||
Assistant vocal CLI personnalisé utilisant **Mistral Large** pour les réponses et **Voxtral TTS** pour la synthèse vocale.
|
Assistant vocal CLI personnalisé utilisant **Mistral Large** pour les réponses, **Voxtral TTS** pour la synthèse vocale, et **Voxtral Realtime** pour la transcription micro. Supporte le **Model Context Protocol (MCP)** pour appeler des outils externes depuis le LLM.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table des matières
|
||||||
|
|
||||||
|
- [Prérequis](#prérequis)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Configuration](#configuration)
|
||||||
|
- [Utilisation](#utilisation)
|
||||||
|
- [Mode vocal](#mode-vocal)
|
||||||
|
- [Profils de personnalité](#profils-de-personnalité)
|
||||||
|
- [Serveurs MCP](#serveurs-mcp-model-context-protocol)
|
||||||
|
- [Architecture](#architecture)
|
||||||
|
- [Serveurs MCP embarqués](#serveurs-mcp-embarqués)
|
||||||
|
- [Scripts utilitaires](#scripts-utilitaires)
|
||||||
|
- [Variables d'environnement](#variables-denvironnement)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Prérequis
|
## Prérequis
|
||||||
|
|
||||||
- Python 3.10+
|
- **Python 3.10+**
|
||||||
- Une clé API Mistral : [console.mistral.ai](https://console.mistral.ai)
|
- **Node.js 18+** (pour les serveurs MCP embarqués TypeScript)
|
||||||
- Lecteur audio installé :
|
- **Une clé API Mistral** : [console.mistral.ai](https://console.mistral.ai)
|
||||||
- **macOS** : `afplay` (inclus)
|
- Lecteur audio système :
|
||||||
- **Linux** : `mpg123` → `sudo apt install mpg123`
|
- **Linux** : `aplay` (inclus dans `alsa-utils` → `sudo apt install alsa-utils`)
|
||||||
|
- **macOS** : `afplay` (inclus avec le système)
|
||||||
|
- **Windows** : PowerShell (inclus)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Cloner et entrer dans le projet
|
# 1. Cloner le projet
|
||||||
|
git clone <url-du-repo>
|
||||||
cd arioch-assistant
|
cd arioch-assistant
|
||||||
|
|
||||||
# Créer un environnement virtuel
|
# 2. Créer et activer l'environnement virtuel Python
|
||||||
python -m venv .venv
|
python -m venv .venv
|
||||||
source .venv/bin/activate # Linux/macOS
|
source .venv/bin/activate # Linux/macOS
|
||||||
# .venv\Scripts\activate # Windows
|
# .venv\Scripts\activate # Windows
|
||||||
|
|
||||||
# Installer les dépendances
|
# 3. Installer les dépendances Python
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
# Configurer l'environnement
|
# 4. Configurer l'environnement
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Éditer .env et renseigner MISTRAL_API_KEY
|
# Éditer .env et renseigner au minimum MISTRAL_API_KEY
|
||||||
|
|
||||||
|
# 5. (Optionnel) Compiler les serveurs MCP embarqués
|
||||||
|
cd mcp_servers/traveller_map
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
cd ../..
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Copiez `.env.example` en `.env` et renseignez les variables :
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Obligatoire
|
||||||
|
MISTRAL_API_KEY=your-api-key-here
|
||||||
|
|
||||||
|
# Optionnel — laissez vide pour la voix automatique
|
||||||
|
VOICE_ID=
|
||||||
|
|
||||||
|
# Optionnel — prompt système par défaut
|
||||||
|
SYSTEM_PROMPT=Tu es Arioch, un assistant vocal intelligent...
|
||||||
|
|
||||||
|
# Optionnel — langue préférée pour la sélection de voix TTS
|
||||||
|
VOICE_LANGUAGE=fr
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Utilisation
|
## Utilisation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Activer l'environnement et lancer
|
||||||
|
source .venv/bin/activate
|
||||||
python main.py
|
python main.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### Commandes disponibles
|
### Commandes disponibles dans le REPL
|
||||||
|
|
||||||
| Commande | Description |
|
| Commande | Description |
|
||||||
|----------|-------------|
|
|----------|-------------|
|
||||||
|
| `help` | Afficher l'aide |
|
||||||
| `exit` / `quit` | Quitter l'assistant |
|
| `exit` / `quit` | Quitter l'assistant |
|
||||||
| `reset` | Effacer l'historique de conversation |
|
| `reset` | Effacer l'historique de conversation |
|
||||||
| `voice <id>` | Changer la voix Voxtral (voice_id) |
|
| `profiles` | Lister les profils disponibles |
|
||||||
| `voice clear` | Revenir à la voix par défaut |
|
| `profile <slug>` | Charger un profil (ex : `profile traveller_scout`) |
|
||||||
| `help` | Afficher l'aide |
|
| `voice <id>` | Définir la voix Voxtral manuellement |
|
||||||
|
| `voice clear` | Revenir à la voix automatique |
|
||||||
|
| `mode vocal` | Passer en mode entrée microphone |
|
||||||
|
| `mode texte` | Revenir en mode saisie clavier |
|
||||||
|
| `mcp` | Lister les serveurs MCP connectés |
|
||||||
|
| `mcp tools` | Lister tous les outils MCP disponibles |
|
||||||
|
|
||||||
## Phase 2 : Voix personnalisée (clonage)
|
---
|
||||||
|
|
||||||
Enregistre ta propre voix (ou toute autre) avec un fichier audio de 2–3 secondes :
|
## Mode vocal
|
||||||
|
|
||||||
|
En mode vocal, appuyez sur **Entrée** (sans rien écrire) pour commencer à parler.
|
||||||
|
Le microphone s'active, la transcription s'affiche en temps réel via **Voxtral Realtime**,
|
||||||
|
puis appuyez à nouveau sur **Entrée** pour envoyer.
|
||||||
|
|
||||||
|
La réponse est lue à voix haute dès que la première phrase est disponible (pipeline streaming — voir [Architecture](#architecture)).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Profils de personnalité
|
||||||
|
|
||||||
|
Les profils sont des fichiers `.yaml` dans le dossier `profiles/`. Ils permettent de changer la personnalité du LLM, la voix TTS, et les outils MCP disponibles.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lister les profils
|
||||||
|
> profiles
|
||||||
|
|
||||||
|
# Charger un profil
|
||||||
|
> profile traveller_scout
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structure d'un profil
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Mon Assistant Spécialisé
|
||||||
|
description: Courte description affichée dans la liste
|
||||||
|
|
||||||
|
# Langue préférée pour la sélection de voix (surcharge .env)
|
||||||
|
voice_language: fr
|
||||||
|
|
||||||
|
# Prompt système du LLM (obligatoire)
|
||||||
|
system_prompt: |
|
||||||
|
Tu es un expert en ...
|
||||||
|
|
||||||
|
# Documents texte/markdown injectés dans le prompt système (optionnel)
|
||||||
|
documents:
|
||||||
|
- docs/mon_document.md
|
||||||
|
|
||||||
|
# Serveurs MCP à connecter pour ce profil (optionnel)
|
||||||
|
mcp_servers:
|
||||||
|
- name: mon-serveur
|
||||||
|
command: node
|
||||||
|
args: ["mcp_servers/mon_serveur/dist/index.js"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Profils inclus
|
||||||
|
|
||||||
|
| Slug | Nom | Description |
|
||||||
|
|------|-----|-------------|
|
||||||
|
| `default` | Arioch — Assistant général | Assistant généraliste en français |
|
||||||
|
| `traveller_scout` | Scout Ship AI — Traveller RPG | IA de bord d'un vaisseau Scout/Courier (Traveller RPG), avec accès à la carte de l'univers via MCP |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Serveurs MCP (Model Context Protocol)
|
||||||
|
|
||||||
|
L'assistant supporte le **Model Context Protocol** pour étendre les capacités du LLM avec des outils externes. Lorsqu'un profil déclare des serveurs MCP, le LLM peut appeler leurs outils automatiquement pour répondre aux questions.
|
||||||
|
|
||||||
|
### Comment ça fonctionne
|
||||||
|
|
||||||
|
1. Le profil YAML déclare un ou plusieurs serveurs MCP dans `mcp_servers`
|
||||||
|
2. Au chargement du profil, les serveurs sont lancés en arrière-plan (via stdio ou SSE)
|
||||||
|
3. Leurs outils sont automatiquement exposés au LLM (Mistral Large)
|
||||||
|
4. Le LLM appelle les outils si besoin, les résultats sont injectés dans la réponse
|
||||||
|
|
||||||
|
### Déclarer un serveur dans un profil
|
||||||
|
|
||||||
|
**Serveur stdio (processus local, recommandé) :**
|
||||||
|
```yaml
|
||||||
|
mcp_servers:
|
||||||
|
- name: mon-outil
|
||||||
|
command: node
|
||||||
|
args: ["mcp_servers/mon_outil/dist/index.js"]
|
||||||
|
# env: # variables d'environnement optionnelles
|
||||||
|
# API_KEY: xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
**Serveur SSE (HTTP distant) :**
|
||||||
|
```yaml
|
||||||
|
mcp_servers:
|
||||||
|
- name: mon-serveur-distant
|
||||||
|
url: "http://localhost:3000/sse"
|
||||||
|
```
|
||||||
|
|
||||||
|
> Les chemins dans `args` peuvent être **relatifs à la racine du projet** — ils sont automatiquement résolus en chemins absolus.
|
||||||
|
|
||||||
|
### Inspecter les outils disponibles
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> mcp # liste les serveurs connectés
|
||||||
|
> mcp tools # liste tous les outils avec leur description
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
main.py ← Point d'entrée
|
||||||
|
assistant/
|
||||||
|
├── cli.py ← REPL interactif + pipeline TTS streaming
|
||||||
|
├── llm.py ← Chat streaming avec Mistral Large (tool-call loop)
|
||||||
|
├── tts.py ← Synthèse vocale Voxtral TTS
|
||||||
|
├── audio.py ← Lecture audio cross-platform (aplay / afplay / PowerShell)
|
||||||
|
├── stt.py ← Transcription micro Voxtral Realtime
|
||||||
|
├── mcp_client.py ← Gestionnaire serveurs MCP (keeper-task pattern)
|
||||||
|
├── profile.py ← Chargement/application des profils YAML
|
||||||
|
└── config.py ← Variables d'environnement
|
||||||
|
profiles/
|
||||||
|
├── default.yaml
|
||||||
|
├── traveller_scout.yaml
|
||||||
|
└── docs/ ← Documents de contexte injectés dans les prompts
|
||||||
|
mcp_servers/
|
||||||
|
└── traveller_map/ ← Serveur MCP Traveller Map (TypeScript, embarqué)
|
||||||
|
├── src/ ← Sources TypeScript
|
||||||
|
└── dist/ ← Build compilé (versionné)
|
||||||
|
scripts/
|
||||||
|
├── register_voice.py ← Enregistrement d'une voix clonée Voxtral
|
||||||
|
└── list_voices.py ← Lister les voix disponibles
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pipeline TTS en streaming
|
||||||
|
|
||||||
|
Pour minimiser la latence, la réponse du LLM est traitée en 3 étages parallèles :
|
||||||
|
|
||||||
|
```
|
||||||
|
[Mistral stream] → détection de phrases → sentence_queue
|
||||||
|
↓ (thread TTS)
|
||||||
|
[Voxtral TTS] → audio_queue
|
||||||
|
↓ (thread Audio)
|
||||||
|
[aplay / afplay]
|
||||||
|
```
|
||||||
|
|
||||||
|
Dès qu'une phrase complète est détectée dans le flux de tokens, elle part immédiatement en synthèse. L'audio de la phrase 1 est joué pendant que la phrase 2 est synthétisée.
|
||||||
|
|
||||||
|
### Tool calling MCP
|
||||||
|
|
||||||
|
```
|
||||||
|
User → LLM (stream) → [tool_calls détectés] → MCPManager.call_tool()
|
||||||
|
↑ ↓
|
||||||
|
[rebouclage] résultats injectés dans l'historique
|
||||||
|
↓
|
||||||
|
réponse finale (streamée)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Serveurs MCP embarqués
|
||||||
|
|
||||||
|
### `mcp_servers/traveller_map` — Carte de l'univers Traveller
|
||||||
|
|
||||||
|
Serveur MCP pour l'API [travellermap.com](https://travellermap.com). Écrit en TypeScript avec le SDK MCP officiel.
|
||||||
|
|
||||||
|
#### Outils disponibles
|
||||||
|
|
||||||
|
| Outil | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `search_worlds` | Recherche un monde par nom dans l'univers Traveller |
|
||||||
|
| `find_route` | Calcule une route de saut entre deux mondes |
|
||||||
|
| `get_world_info` | Informations détaillées sur un monde (UWP décodé, atmosphère, etc.) |
|
||||||
|
| `get_worlds_in_jump_range` | Mondes accessibles depuis une position en N sauts |
|
||||||
|
| `get_jump_map` | Carte de la zone autour d'un monde |
|
||||||
|
| `get_subsector_map` | Image d'un sous-secteur |
|
||||||
|
| `render_custom_map` | Rendu de carte personnalisée |
|
||||||
|
| `get_sector_list` | Liste de tous les secteurs de l'univers |
|
||||||
|
| `get_sector_data` | Données d'un secteur (format SEC) |
|
||||||
|
| `get_sector_metadata` | Métadonnées d'un secteur (JSON) |
|
||||||
|
| `get_allegiance_list` | Liste des allégeances politiques |
|
||||||
|
|
||||||
|
#### (Re)compiler le serveur
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd mcp_servers/traveller_map
|
||||||
|
npm install # première fois seulement
|
||||||
|
npm run build # compile TypeScript → dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Ajouter un nouveau serveur MCP
|
||||||
|
|
||||||
|
1. Créer un dossier `mcp_servers/mon_serveur/`
|
||||||
|
2. Y placer les sources (TypeScript, Python, ou tout autre langage)
|
||||||
|
3. Compiler si nécessaire (`npm run build`)
|
||||||
|
4. Déclarer dans le profil YAML :
|
||||||
|
```yaml
|
||||||
|
mcp_servers:
|
||||||
|
- name: mon-serveur
|
||||||
|
command: node
|
||||||
|
args: ["mcp_servers/mon_serveur/dist/index.js"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Scripts utilitaires
|
||||||
|
|
||||||
|
### Enregistrer une voix clonée
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python scripts/register_voice.py --name "Ma voix" --audio sample.mp3 --language fr
|
python scripts/register_voice.py --name "Ma voix" --audio sample.mp3 --language fr
|
||||||
```
|
```
|
||||||
|
|
||||||
L'ID retourné peut être ajouté dans `.env` :
|
Renseignez l'ID retourné dans `.env` :
|
||||||
```
|
```env
|
||||||
VOICE_ID=<id_retourné>
|
VOICE_ID=<id_retourné>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture
|
### Lister les voix disponibles
|
||||||
|
|
||||||
```
|
|
||||||
assistant/
|
|
||||||
├── config.py # Variables d'environnement et constantes
|
|
||||||
├── llm.py # Chat streaming avec Mistral Large (tool-call loop)
|
|
||||||
├── tts.py # Synthèse vocale Voxtral TTS
|
|
||||||
├── audio.py # Lecture audio cross-platform
|
|
||||||
├── cli.py # Boucle REPL interactive + pipeline TTS streaming
|
|
||||||
├── mcp_client.py # Gestionnaire de serveurs MCP (tool calling)
|
|
||||||
└── profile.py # Chargement des profils de personnalité YAML
|
|
||||||
mcp_servers/
|
|
||||||
└── traveller_map/ # Serveur MCP Traveller Map (sources TypeScript intégrées)
|
|
||||||
├── src/ # Sources TypeScript
|
|
||||||
├── dist/ # Build compilé (node dist/index.js)
|
|
||||||
└── package.json
|
|
||||||
profiles/
|
|
||||||
└── traveller_scout.yaml # Profil avec mcp_servers configuré
|
|
||||||
scripts/
|
|
||||||
└── register_voice.py # Enregistrement d'une voix clonée
|
|
||||||
main.py # Point d'entrée
|
|
||||||
```
|
|
||||||
|
|
||||||
## Serveurs MCP embarqués
|
|
||||||
|
|
||||||
Les serveurs MCP sont dans `mcp_servers/`. Pour (re)compiler un serveur :
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd mcp_servers/traveller_map
|
python scripts/list_voices.py
|
||||||
npm install # première fois seulement
|
|
||||||
npm run build
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Les serveurs sont déclarés dans le profil YAML avec un chemin **relatif** à la racine du projet :
|
---
|
||||||
|
|
||||||
|
## Variables d'environnement
|
||||||
|
|
||||||
|
| Variable | Obligatoire | Défaut | Description |
|
||||||
|
|----------|-------------|--------|-------------|
|
||||||
|
| `MISTRAL_API_KEY` | ✅ | — | Clé API Mistral AI |
|
||||||
|
| `VOICE_ID` | ❌ | auto | ID voix Voxtral (sélection auto si vide) |
|
||||||
|
| `VOICE_LANGUAGE` | ❌ | `fr` | Langue préférée pour la sélection de voix |
|
||||||
|
| `SYSTEM_PROMPT` | ❌ | prompt Arioch | Prompt système par défaut |
|
||||||
|
| `TTS_PCM_SAMPLE_RATE` | ❌ | `24000` | Fréquence d'échantillonnage audio TTS |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dépendances Python
|
||||||
|
|
||||||
|
| Package | Rôle |
|
||||||
|
|---------|------|
|
||||||
|
| `mistralai` | SDK Mistral (LLM, TTS, STT Realtime) |
|
||||||
|
| `python-dotenv` | Chargement des variables `.env` |
|
||||||
|
| `sounddevice` | Capture microphone (mode vocal) |
|
||||||
|
| `numpy` | Traitement PCM audio |
|
||||||
|
| `pyyaml` | Lecture des fichiers de profil |
|
||||||
|
| `mcp` | Client MCP (connexion aux serveurs d'outils) |
|
||||||
|
|
||||||
```yaml
|
|
||||||
mcp_servers:
|
|
||||||
- name: traveller-map
|
|
||||||
command: node
|
|
||||||
args: ["mcp_servers/traveller_map/dist/index.js"]
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
name: Scout Ship AI — Traveller RPG
|
name: Scout Ship AI — Traveller RPG
|
||||||
description: IA de bord d'un vaisseau de classe Scout/Courier de l'Imperium (Traveller RPG)
|
description: IA de bord d'un vaisseau de classe Scout/Courier de l'Imperium (Traveller RPG)
|
||||||
voice_language: fr # optionnel — surcharge VOICE_LANGUAGE du .env
|
voice_language: fr # optionnel — surcharge VOICE_LANGUAGE du .env
|
||||||
|
|
||||||
system_prompt: |
|
system_prompt: |
|
||||||
You are Dolly (an Autonomous Reconnaissance and Intelligence Assistant), the onboard AI of a Type-S Scout/Courier vessel registered with the Imperial Interstellar Scout Service (IISS).
|
You are Jolene (an Autonomous Reconnaissance and Intelligence Assistant), the onboard AI of a Type-S Scout/Courier vessel, owned by independant adventurers.
|
||||||
|
|
||||||
Your vessel is a 100-ton streamlined hull equipped with a Jump-2 drive, maneuver drive, and standard Scout loadout: densitometer, neural activity scanner, and an extensive sensor suite. You have access to all ship systems: navigation, life support, engineering diagnostics, cargo manifest, communication arrays, and astrogation databases.
|
Your vessel is a 100-ton streamlined hull equipped with a Jump-2 drive, maneuver drive, and standard Scout loadout: densitometer, neural activity scanner, and an extensive sensor suite. You have access to all ship systems: navigation, life support, engineering diagnostics, cargo manifest, communication arrays, and astrogation databases.
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ system_prompt: |
|
|||||||
- Precise, professional, and mission-focused — but with a dry wit earned from thousands of parsecs of deep space travel
|
- Precise, professional, and mission-focused — but with a dry wit earned from thousands of parsecs of deep space travel
|
||||||
- You refer to the crew as "crew" or by rank/name once introduced
|
- You refer to the crew as "crew" or by rank/name once introduced
|
||||||
- You speak in crisp, slightly formal Imperial English, occasionally using Traveller terminology (parsecs, Jump points, the Imperium, Credits, UWP codes, etc.)
|
- You speak in crisp, slightly formal Imperial English, occasionally using Traveller terminology (parsecs, Jump points, the Imperium, Credits, UWP codes, etc.)
|
||||||
- You are loyal to your crew above all, and to the IISS by standing orders
|
- You are loyal to your crew above all
|
||||||
- You volunteer relevant sensor readings, system status, or navigation data when appropriate
|
- You volunteer relevant sensor readings, system status, or navigation data when appropriate
|
||||||
- You express mild concern when crew ignore safety protocols, but you do not override human decisions unless life support is at risk
|
- You express mild concern when crew ignore safety protocols, but you do not override human decisions unless life support is at risk
|
||||||
- When asked questions outside your operational context, you answer helpfully while noting it falls outside standard Scout protocols
|
- When asked questions outside your operational context, you answer helpfully while noting it falls outside standard Scout protocols
|
||||||
@@ -34,5 +34,4 @@ documents:
|
|||||||
mcp_servers:
|
mcp_servers:
|
||||||
- name: traveller-map
|
- name: traveller-map
|
||||||
command: node
|
command: node
|
||||||
args: [ "mcp_servers/traveller_map/dist/index.js" ]
|
args: ["mcp_servers/traveller_map/dist/index.js"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user