194 lines
7.5 KiB
Markdown
194 lines
7.5 KiB
Markdown
# Architecture Pipeline Kazeia
|
|
|
|
*Version 2.0 — 28 mars 2026*
|
|
|
|
## Principe
|
|
|
|
Le pipeline Kazeia est **modulaire** : STT et TTS sont indépendants et échangent uniquement du texte avec une chaîne de processeurs pluggables.
|
|
|
|
```
|
|
┌─────────┐ ┌──────────────────────────┐ ┌─────────┐
|
|
│ STT │────→│ PROCESSOR CHAIN │────→│ TTS │
|
|
│(Whisper)│ │ │ │(Android/│
|
|
│ │ │ ┌──────────────────┐ │ │Chatterbox│
|
|
│ Audio │ │ │ Voice Commands │ │ │ │
|
|
│ → Text │ │ └────────┬─────────┘ │ │ Text │
|
|
│ │ │ ┌────────▼─────────┐ │ │ → Audio│
|
|
│ │ │ │ LLM (Qwen3 NPU) │ │ │ │
|
|
│ │ │ └────────┬─────────┘ │ │ │
|
|
│ │ │ ┌────────▼─────────┐ │ │ │
|
|
│ │ │ │ (Future: RAG) │ │ │ │
|
|
│ │ │ └────────┬─────────┘ │ │ │
|
|
│ │ │ ┌────────▼─────────┐ │ │ │
|
|
│ │ │ │ (Future: Emotion)│ │ │ │
|
|
│ │ │ └──────────────────┘ │ │ │
|
|
└─────────┘ └──────────────────────────┘ └─────────┘
|
|
```
|
|
|
|
## Interfaces
|
|
|
|
### SttEngine (Speech-to-Text)
|
|
```kotlin
|
|
interface SttEngine {
|
|
suspend fun load(modelPath: String?)
|
|
fun isLoaded(): Boolean
|
|
suspend fun transcribe(audioData: ShortArray, language: String): TranscriptionResult
|
|
fun release()
|
|
}
|
|
```
|
|
|
|
Implémentations :
|
|
| Classe | Backend | Latence | NPU |
|
|
|--------|---------|---------|-----|
|
|
| `WhisperSttEngine` | whisper.cpp CPU | ~1500ms | Non |
|
|
| `WhisperNpuSttEngine` | ExecuTorch QNN | ~50ms* | Oui |
|
|
| `AndroidSttEngine` | Google SpeechRecognizer | ~500ms | Non (cloud) |
|
|
|
|
### TtsEngine (Text-to-Speech)
|
|
```kotlin
|
|
interface TtsEngine {
|
|
suspend fun load(modelPath: String?, voiceId: String?)
|
|
fun isLoaded(): Boolean
|
|
suspend fun synthesizeAndPlay(text: String, language: String, onStart: (() -> Unit)?, onComplete: (() -> Unit)?)
|
|
fun stop()
|
|
fun release()
|
|
}
|
|
```
|
|
|
|
Implémentations :
|
|
| Classe | Backend | Latence | Clonage voix |
|
|
|--------|---------|---------|-------------|
|
|
| `AndroidTtsEngine` | Google TTS | ~200ms | Non |
|
|
| `ChatterboxTtsEngine` | ONNX CPU/NPU | ~3-10s | Oui |
|
|
|
|
### MessageProcessor (Middleware)
|
|
```kotlin
|
|
interface MessageProcessor {
|
|
val name: String
|
|
suspend fun initialize()
|
|
fun isReady(): Boolean
|
|
suspend fun process(input: String, context: ConversationContext): ProcessorResult
|
|
fun release()
|
|
}
|
|
```
|
|
|
|
Implémentations :
|
|
| Classe | Rôle | Priorité |
|
|
|--------|------|----------|
|
|
| `VoiceCommandProcessor2` | Intercepte les commandes vocales | 1 (premier) |
|
|
| `LlmProcessor` | Génère des réponses via LLM | 2 |
|
|
| `EchoProcessor` | Répète l'input (fallback/test) | 3 |
|
|
| *(Future)* `EmotionProcessor` | Détecte l'émotion de la voix | 1.5 |
|
|
| *(Future)* `RagProcessor` | Enrichit avec des documents | 1.5 |
|
|
| *(Future)* `DiarizationProcessor` | Identifie le locuteur | 1 |
|
|
|
|
### Chaîne de traitement
|
|
|
|
Les processeurs sont exécutés **dans l'ordre**. Le premier qui retourne `shouldContinueChain = false` termine la chaîne.
|
|
|
|
```
|
|
Input: "Bonjour, comment vas-tu ?"
|
|
→ VoiceCommandProcessor2: pas de commande → continue
|
|
→ LlmProcessor: "Je vais bien, comment puis-je t'aider ?" → done
|
|
Output: "Je vais bien, comment puis-je t'aider ?"
|
|
|
|
Input: "stop"
|
|
→ VoiceCommandProcessor2: commande STOP_LISTENING → done (shouldSpeak=false)
|
|
Output: (arrête l'écoute)
|
|
```
|
|
|
|
## Ajouter un nouveau processeur
|
|
|
|
```kotlin
|
|
class MonNouveauProcessor : MessageProcessor {
|
|
override val name = "MonProcesseur"
|
|
|
|
override suspend fun process(input: String, context: ConversationContext): ProcessorResult {
|
|
// Traiter l'input
|
|
val enrichedInput = "[$emotion] $input"
|
|
|
|
return ProcessorResult(
|
|
responseText = "",
|
|
shouldContinueChain = true, // passe au processeur suivant
|
|
metadata = mapOf("emotion" to "triste")
|
|
)
|
|
}
|
|
}
|
|
|
|
// Ajout au pipeline
|
|
pipeline.addProcessor(MonNouveauProcessor())
|
|
```
|
|
|
|
## ConversationContext
|
|
|
|
Le contexte est partagé entre tous les processeurs :
|
|
|
|
```kotlin
|
|
data class ConversationContext(
|
|
val history: List<ChatMessage>, // historique conversation
|
|
val metadata: MutableMap<String, Any>, // données partagées
|
|
val language: String, // "fr"
|
|
val speakerId: String?, // identification locuteur
|
|
val emotion: String?, // émotion détectée
|
|
val sessionId: String // identifiant session
|
|
)
|
|
```
|
|
|
|
Les processeurs peuvent lire et écrire dans `metadata` pour communiquer entre eux.
|
|
|
|
## Performances actuelles
|
|
|
|
| Composant | Backend | Latence |
|
|
|-----------|---------|---------|
|
|
| STT Whisper | CPU (whisper.cpp) | 1500ms |
|
|
| STT Whisper | NPU (ExecuTorch) | ~50ms* |
|
|
| LLM Qwen3-0.6B | NPU (ExecuTorch) | 93 tok/s, TTFT 31ms |
|
|
| LLM Qwen3-1.7B | NPU (ExecuTorch) | 46 tok/s, TTFT 27ms |
|
|
| TTS Android | Google | 200ms |
|
|
| Pipeline total (CPU STT) | STT→LLM→TTS | ~3-7s |
|
|
| Pipeline total (NPU STT)* | STT→LLM→TTS | ~1-3s |
|
|
|
|
*STT NPU en cours d'intégration
|
|
|
|
## Fichiers
|
|
|
|
```
|
|
kazeia-android/app/src/main/java/com/kazeia/
|
|
├── core/
|
|
│ ├── LlmEngine.kt # Interface LLM
|
|
│ ├── SttEngine.kt # Interface STT
|
|
│ ├── TtsEngine.kt # Interface TTS
|
|
│ ├── VadEngine.kt # Interface VAD
|
|
│ ├── ConversationState.kt # États pipeline
|
|
│ └── Pipeline.kt # Interfaces MessageProcessor, PipelineOrchestrator
|
|
├── llm/
|
|
│ ├── ExecuTorchLlmEngine.kt # LLM sur NPU via ExecuTorch
|
|
│ └── GenieLlmEngine.kt # LLM via Genie SDK (abandonné)
|
|
├── stt/
|
|
│ ├── WhisperSttEngine.kt # STT CPU via whisper.cpp
|
|
│ ├── WhisperNpuSttEngine.kt # STT NPU via ExecuTorch
|
|
│ └── AndroidSttEngine.kt # STT cloud via Google
|
|
├── tts/
|
|
│ ├── AndroidTtsEngine.kt # TTS Google natif
|
|
│ └── ChatterboxTtsEngine.kt # TTS avec clonage voix
|
|
├── conversation/
|
|
│ ├── LlmProcessor.kt # Processor LLM
|
|
│ ├── EchoProcessor.kt # Processor écho
|
|
│ ├── VoiceCommandProcessor.kt # Commandes vocales (config JSON)
|
|
│ ├── VoiceCommandProcessor2.kt # Adapter MessageProcessor
|
|
│ ├── PromptBuilder.kt # Construction prompts
|
|
│ └── StoppingCriteria.kt # Critères d'arrêt
|
|
├── service/
|
|
│ ├── KazeiaService.kt # Service Android foreground
|
|
│ └── KazeiaPipeline.kt # Orchestrateur pipeline modulaire
|
|
└── ui/
|
|
├── ChatActivity.kt # Interface utilisateur
|
|
├── ChatAdapter.kt # Adapter RecyclerView
|
|
├── MiniGraphView.kt # Graphe temps réel
|
|
└── ResourceMonitor.kt # Monitoring CPU/GPU/RAM
|
|
```
|
|
|
|
---
|
|
|
|
*Projet Kazeia — Damien Micottis & Richard Loyer*
|