351 lines
13 KiB
Markdown
351 lines
13 KiB
Markdown
# Arioch — Assistant vocal (Mistral Large + Voxtral TTS)
|
|
|
|
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.
|
|
|
|
Disclaimer : Cet outil est un "proof-of-concept" expérimental pour investiguer les possibilités offertes par des agents vocaux personnalisés.
|
|
|
|
---
|
|
|
|
## 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+**
|
|
- **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
|
|
# 1. Cloner le projet
|
|
git clone <url-du-repo>
|
|
cd arioch-assistant
|
|
|
|
# 2. Créer et activer l'environnement virtuel Python
|
|
python -m venv .venv
|
|
source .venv/bin/activate # Linux/macOS
|
|
# .venv\Scripts\activate # Windows
|
|
|
|
# 3. Installer les dépendances Python
|
|
pip install -r requirements.txt
|
|
|
|
# 4. Configurer l'environnement
|
|
cp .env.example .env
|
|
# É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 dans le REPL
|
|
|
|
| Commande | Description |
|
|
| ---------------- | -------------------------------------------------- |
|
|
| `help` | Afficher l'aide |
|
|
| `exit` / `quit` | Quitter l'assistant |
|
|
| `reset` | Effacer l'historique de conversation |
|
|
| `profiles` | Lister les profils disponibles |
|
|
| `profile <slug>` | Charger un profil (ex : `profile traveller_scout`) |
|
|
| `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 |
|
|
|
|
---
|
|
|
|
## 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.
|
|
|
|
> **Crédit** : Ce serveur est basé sur le projet [traveller-map-mcp](https://github.com/shammond42/traveller-map-mcp)
|
|
> par **[@shammond42](https://github.com/shammond42)**, distribué sous licence **MIT**.
|
|
> Les sources ont été intégrées dans ce projet pour être embarquées directement.
|
|
|
|
#### 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
|
|
```
|
|
|
|
Renseignez l'ID retourné dans `.env` :
|
|
```env
|
|
VOICE_ID=<id_retourné>
|
|
```
|
|
|
|
### Lister les voix disponibles
|
|
|
|
```bash
|
|
python scripts/list_voices.py
|
|
```
|
|
|
|
---
|
|
|
|
## 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) |
|