diff --git a/README.md b/README.md index 282cf1b..13ba406 100644 --- a/README.md +++ b/README.md @@ -1,101 +1,345 @@ # 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 -- Python 3.10+ -- Une clé API Mistral : [console.mistral.ai](https://console.mistral.ai) -- Lecteur audio installé : - - **macOS** : `afplay` (inclus) - - **Linux** : `mpg123` → `sudo apt install mpg123` +- **Python 3.10+** +- **Node.js 18+** (pour les serveurs MCP embarqués TypeScript) +- **Une clé API Mistral** : [console.mistral.ai](https://console.mistral.ai) +- Lecteur audio système : + - **Linux** : `aplay` (inclus dans `alsa-utils` → `sudo apt install alsa-utils`) + - **macOS** : `afplay` (inclus avec le système) + - **Windows** : PowerShell (inclus) + +--- ## Installation ```bash -# Cloner et entrer dans le projet +# 1. Cloner le projet +git clone cd arioch-assistant -# Créer un environnement virtuel +# 2. Créer et activer l'environnement virtuel Python python -m venv .venv -source .venv/bin/activate # Linux/macOS -# .venv\Scripts\activate # Windows +source .venv/bin/activate # Linux/macOS +# .venv\Scripts\activate # Windows -# Installer les dépendances +# 3. Installer les dépendances Python pip install -r requirements.txt -# Configurer l'environnement +# 4. Configurer l'environnement 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 ```bash +# Activer l'environnement et lancer +source .venv/bin/activate python main.py ``` -### Commandes disponibles +### Commandes disponibles dans le REPL | Commande | Description | |----------|-------------| +| `help` | Afficher l'aide | | `exit` / `quit` | Quitter l'assistant | | `reset` | Effacer l'historique de conversation | -| `voice ` | Changer la voix Voxtral (voice_id) | -| `voice clear` | Revenir à la voix par défaut | -| `help` | Afficher l'aide | +| `profiles` | Lister les profils disponibles | +| `profile ` | Charger un profil (ex : `profile traveller_scout`) | +| `voice ` | 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 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= ``` -## Architecture - -``` -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 : +### Lister les voix disponibles ```bash -cd mcp_servers/traveller_map -npm install # première fois seulement -npm run build +python scripts/list_voices.py ``` -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"] -``` diff --git a/profiles/traveller_scout.yaml b/profiles/traveller_scout.yaml index 62d946f..7c0c901 100644 --- a/profiles/traveller_scout.yaml +++ b/profiles/traveller_scout.yaml @@ -1,9 +1,9 @@ name: Scout Ship AI — 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: | - 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. @@ -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 - 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 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 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 @@ -34,5 +34,4 @@ documents: mcp_servers: - name: traveller-map command: node - args: [ "mcp_servers/traveller_map/dist/index.js" ] - + args: ["mcp_servers/traveller_map/dist/index.js"]