# Skull Pi - AI Service (svc-ai)

Service AI robuste pour le projet Skull Pi. Consomme du texte ASR, applique des prompts système éditables, appelle des modèles LLM locaux/remote (gpt-5-mini/nano), et publie les réponses pour TTS.

## Architecture

Le service est conçu avec une architecture modulaire et résiliente :

- **Client LLM** avec retries exponentiels et circuit breaker
- **Gestion du contexte** conversationnel court terme
- **Filtrage et post-processing** des réponses
- **Monitoring de santé** avec métriques de performance
- **Communication MQTT** robuste avec debounce ASR
- **Configuration à chaud** via topics retained

## Installation

### Prérequis

- Python 3.9+
- MQTT broker (Mosquitto recommandé)
- Environnement virtuel Python

### Dépendances

```bash
pip install paho-mqtt asyncio
# Pour la production, ajouter le client LLM approprié (ex: openai)
```

### Déploiement

1. Copier les fichiers dans `/opt/Skull/apps/ai/`
2. Créer le fichier de configuration environnement
3. Installer le service systemd
4. Démarrer le service

```bash
# Copier les fichiers
sudo cp -r ai/ /opt/Skull/apps/

# Créer les dossiers nécessaires
sudo mkdir -p /opt/Skull/{config,logs,bin}

# Créer le prompt par défaut
echo "Tu es un crâne joyeux, poli, humour léger. Évite politique, santé, argent." | sudo tee /opt/Skull/config/prompt.txt

# Créer le wrapper de démarrage
sudo tee /opt/Skull/bin/skull-ai.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
cd /opt/Skull/apps
source /opt/Skull/venv/bin/activate
exec python -m ai.main
EOF

sudo chmod +x /opt/Skull/bin/skull-ai.sh
```

## Configuration

### Variables d'environnement (.env)

```env
MQTT_HOST=127.0.0.1
MQTT_PORT=1883
AI_MODEL=gpt-5-mini
AI_TIMEOUT_S=12
AI_MAX_TOKENS=256
AI_TEMPERATURE=0.7
AI_TOP_P=0.9
AI_LANG=fr
```

### Topics MQTT

#### Entrées (Souscriptions)

- `asr/text` - Texte de reconnaissance vocale
- `ai/request` - Requêtes directes
- `ai/cancel` - Annulation de requête en cours
- `skull/config/ia` - Configuration IA (retained)
- `skull/config/prompt_system` - Prompt système (retained)

#### Sorties (Publications)

- `ai/response` - Réponse IA pour TTS
- `ai/usage` - Métriques d'utilisation
- `ai/capabilities` - Capacités du service (retained)
- `ai/health` - Statut de santé

## Schémas des Messages

### Configuration IA (`skull/config/ia`)

```json
{
  "model": "gpt-5-mini",
  "lang": "fr",
  "eos_ms": 800,
  "max_tokens": 256,
  "temperature": 0.7,
  "top_p": 0.9
}
```

### Prompt Système (`skull/config/prompt_system`)

```json
{
  "text": "Tu es un crâne joyeux, poli, humour léger. Évite politique, santé, argent."
}
```

### Requête ASR (`asr/text`)

```json
{
  "ts_ms": 1640995200000,
  "text": "raconte une blague"
}
```

### Réponse IA (`ai/response`)

```json
{
  "ts_ms": 1640995200420,
  "text": "Salut ! Je suis Skull, ton crâne loquace. Que puis-je faire pour toi ?"
}
```

### Métriques d'usage (`ai/usage`)

```json
{
  "ts_ms": 1640995200420,
  "latency_ms": 420,
  "input_tokens": 120,
  "output_tokens": 40,
  "model": "gpt-5-mini",
  "cached": false
}
```

### Statut de santé (`ai/health`)

```json
{
  "ok": true,
  "uptime_seconds": 3600,
  "requests_total": 150,
  "requests_success": 147,
  "requests_failed": 3,
  "success_rate": 0.98,
  "latency_p50": 650,
  "latency_p95": 1200,
  "last_request_age": 5,
  "cpu_usage": 5.2,
  "memory_usage": 45.6
}
```

### Capacités (`ai/capabilities`)

```json
{
  "models": ["gpt-5-mini", "gpt-5-nano"],
  "lang": "fr",
  "max_tokens": 512
}
```

## Fonctionnalités

### Client LLM Robuste

- **Retries exponentiels** : 3 tentatives avec backoff et jitter
- **Circuit breaker** : Bascule automatique vers modèle fallback après 5 échecs
- **Timeouts configurables** : 6s pour nano, 12s pour mini
- **Gestion des erreurs** : Rate limiting, timeouts, erreurs réseau

### Gestion du Contexte

- **Mémoire courte** : 1-2 derniers tours de conversation
- **Adaptation au modèle** : Plus de contexte pour gpt-5-mini
- **Purge automatique** : Nettoyage après 10min d'inactivité
- **Limite de tokens** : Troncature intelligente si nécessaire

### Post-processing et Filtres

- **Limitation de longueur** : Max 2-3 phrases par réponse
- **Nettoyage du texte** : Suppression HTML, normalisation ponctuation
- **Politique soft** : Redirection polie pour sujets sensibles
- **Validation** : Vérification qualité et cohérence des réponses

### Monitoring et Santé

- **Métriques temps réel** : Latence P50/P95, taux de succès
- **Alertes de performance** : Détection dégradation service
- **Logs structurés** : JSON avec contexte pour debugging
- **Monitoring ressources** : CPU, mémoire, uptime

## Service systemd

### Installation du service

```bash
sudo tee /etc/systemd/system/skull-ai.service << 'EOF'
[Unit]
Description=Skull AI Service
After=network.target mosquitto.service
Requires=mosquitto.service
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
Type=simple
User=skull
Group=skull
WorkingDirectory=/opt/Skull/apps
Environment=PYTHONPATH=/opt/Skull/apps
EnvironmentFile=-/opt/Skull/config/ai.env
ExecStart=/opt/Skull/bin/skull-ai.sh
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
StandardOutput=journal
StandardError=journal

# Security
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/Skull/logs
ReadOnlyPaths=/opt/Skull/config

[Install]
WantedBy=multi-user.target
EOF

# Activer et démarrer
sudo systemctl daemon-reload
sudo systemctl enable skull-ai.service
sudo systemctl start skull-ai.service
```

### Gestion du service

```bash
# Statut
sudo systemctl status skull-ai

# Logs
sudo journalctl -u skull-ai -f

# Redémarrage
sudo systemctl restart skull-ai

# Arrêt/démarrage
sudo systemctl stop skull-ai
sudo systemctl start skull-ai
```

## Tests

### Tests unitaires

```bash
cd /opt/Skull/apps
python -m pytest ai/tests/test_ai_service.py -v
```

### Tests de charge

```bash
python ai/tests/test_load.py
```

Les tests de charge valident :

- **Burst test** : 5 requêtes simultanées, P95 < 2000ms
- **Sustained test** : 1 req/s pendant 10s, latence moyenne < 1500ms
- **Taux de succès** : > 80% dans tous les cas

### Test manuel rapide

```bash
# Terminal 1 : Écouter les réponses
mosquitto_sub -t 'ai/#' -v

# Terminal 2 : Envoyer requête
mosquitto_pub -t ai/request -m '{"text":"Dis une courte devinette."}'

# Vérifier la réception de ai/response et ai/usage
```

## Critères de Performance

### Objectifs de latence

- **gpt-5-nano** : ≤ 900ms médian (asr→ai/response)
- **gpt-5-mini** : ≤ 1500ms médian (asr→ai/response)
- **Capabilities** : Publié ≤ 2s après démarrage

### Résilience

- **Retries** : 3 tentatives avec backoff exponentiel
- **Fallback** : Bascule automatique nano si 5 échecs/60s
- **Debounce ASR** : 300ms pour éviter doublons
- **Queue management** : Max 3 requêtes en vol, drops contrôlés

### Respect des Règles

- **Langue** : Réponses exclusivement en français
- **Longueur** : 2-3 phrases maximum par défaut
- **Sujets sensibles** : Évitement poli (politique, santé, argent, données personnelles)
- **Débit supporté** : 1 req/s pendant 10s sans saturation

## Configuration Avancée

### Personnalisation du prompt système

```bash
# Via fichier (priorité basse)
echo "Nouveau prompt système" > /opt/Skull/config/prompt.txt

# Via MQTT (priorité haute, retained)
mosquitto_pub -t skull/config/prompt_system -r -m '{"text":"Tu es un assistant très drôle et créatif."}'
```

### Ajustement des modèles

```bash
# Basculer vers nano pour plus de rapidité
mosquitto_pub -t skull/config/ia -r -m '{
  "model": "gpt-5-nano",
  "max_tokens": 128,
  "temperature": 0.8,
  "timeout_s": 6
}'
```

### Surveillance en temps réel

```bash
# Monitoring continu de la santé
mosquitto_sub -t ai/health -v

# Suivi des métriques d'usage
mosquitto_sub -t ai/usage -v

# Debug avec logs détaillés
sudo journalctl -u skull-ai -f --no-pager
```

## Dépannage

### Problèmes courants

1. **Service ne démarre pas**

   ```bash
   # Vérifier les logs
   sudo journalctl -u skull-ai --no-pager

   # Vérifier MQTT
   systemctl status mosquitto

   # Tester la connectivité
   mosquitto_pub -t test -m "hello"
   ```

2. **Latence élevée**

   - Vérifier la charge système (`htop`)
   - Confirmer le modèle utilisé (nano plus rapide)
   - Ajuster timeout et max_tokens

3. **Taux d'échec élevé**

   - Vérifier l'API LLM et les credentials
   - Examiner les logs pour erreurs spécifiques
   - Tester le circuit breaker

4. **Réponses de mauvaise qualité**
   - Ajuster le prompt système
   - Modifier température/top_p
   - Vérifier les filtres de post-processing

### Logs importants

```bash
# Erreurs de génération LLM
grep "LLM generation failed" /opt/Skull/logs/ai.log

# Problèmes de circuit breaker
grep "Circuit breaker" /opt/Skull/logs/ai.log

# Statistiques de performance
grep "latency_p50" /opt/Skull/logs/ai.log
```

## Développement

### Structure du code

```
ai/
├── __init__.py          # Package initialization
├── main.py             # Service principal et orchestration
├── config.py           # Gestion configuration
├── llm.py             # Client LLM avec retries
├── context.py         # Gestion mémoire conversationnelle
├── prompt.py          # Assemblage prompts
├── filters.py         # Post-processing réponses
├── mqtt.py           # Client MQTT
├── health.py         # Monitoring santé
└── tests/
    ├── __init__.py
    ├── test_ai_service.py  # Tests unitaires
    └── test_load.py       # Tests de charge
```

### Ajout d'un nouveau modèle

1. Modifier `llm.py` pour supporter le nouveau modèle
2. Mettre à jour `config.py` avec les nouveaux paramètres
3. Ajuster `ai/capabilities` dans `config.py`
4. Tester avec les suites existantes

### Contribution

1. Fork et clone le repository
2. Créer une branche feature
3. Implémenter avec tests
4. Vérifier `ruff` et `mypy`
5. Soumettre PR avec description détaillée

## Licence

Projet Skull Pi - Licence interne

---

_Documentation générée pour le service svc-ai v1.0.0_
