Mode Orchestrateur
Mode Orchestrateur
Le mode orchestrateur est une fonctionnalité optionnelle qui permet au chatbot de détecter l'intention de l'utilisateur et de déléguer certaines requêtes à un agent externe (ex: système de réservation, API métier tierce) tout en conservant le RAG pour les questions standard.
Activation
ENABLE_ORCHESTRATOR=true
EXTERNAL_AGENT_URL=http://external-agent-service:8080Sans ENABLE_ORCHESTRATOR=true, le chatbot fonctionne en mode RAG pur, sans classification d'intention.
Concept : sessions NORMAL vs ALTER
NORMAL → le chatbot répond via le RAG standard
ALTER → le chatbot transfère la question à l'agent externe (SSE)La session est unidirectionnelle: une fois en mode ALTER, toutes les questions suivantes sont envoyées à l'agent externe pour ce thread. Le mode est persisté dans les métadonnées du thread Chainlit.
Flux de traitement
process_question(question, session_mode, ...)
│
├─ si session_mode == "ALTER"
│ → forward_to_external_agent(question, user_id, history) # immédiat
│
└─ sinon (NORMAL ou None)
→ prepare_rag_context(...) # récupère contexte RAG
→ classify_intent_and_answer(client, question, context, few_shots, history)
│
├─ LLM retourne "ALTER ..."
│ → yield "__MODE__:ALTER"
│ → forward_to_external_agent(...) # SSE
│
└─ LLM retourne réponse normale
→ yield "__MODE__:NORMAL"
→ stream réponse (tokens)classify_intent_and_answer
apps/chatbot/src/chatbot/core/intent_classifier.py
async def classify_intent_and_answer(
client: Mistral,
question: str,
context: str,
few_shots_examples: str,
conversation_history: Optional[List[Dict[str, str]]] = None
) -> Tuple[IntentType, Optional[AsyncGenerator[str, None]]]:Args:
client— client Mistral initialiséquestion— question de l'utilisateurcontext— chunks RAG récupérés (texte concaténé)few_shots_examples— exemples Q&A formatésconversation_history— historique de conversation (messages précédents)
Returns: (intent, answer_generator)
intent—IntentType.NORMALouIntentType.ALTERanswer_generator—AsyncGeneratorsiNORMAL,NonesiALTER
Comportement: effectue un seul appel LLM avec le prompt système d'intent detection (get_intent_detection_prompt()). Si la réponse commence par "ALTER", l'intention est ALTER et answer_generator est None. Sinon, l'intention est NORMAL et answer_generator streame la réponse déjà générée.
IntentType enum
class IntentType(str, Enum):
NORMAL = "NORMAL" # Répondre via RAG
ALTER = "ALTER" # Déléguer à l'agent externeforward_to_external_agent
apps/chatbot/src/chatbot/core/external_agent.py
async def forward_to_external_agent(
question: str,
user_id: str = "chainlit_user",
conversation_history: Optional[List[Dict[str, str]]] = None
) -> AsyncGenerator[str, None]:Args:
question— question à transmettreuser_id— identifiant utilisateur (transmis à l'agent externe)conversation_history— historique de conversation
Yields: tokens streamés depuis l'agent externe.
Protocole:
- Envoie
POST {EXTERNAL_AGENT_URL}/assistantavec:{ "message": "question", "user_id": "user_id", "conversation_history": [...] } - Lit la réponse en SSE (Server-Sent Events):
- Événement
message→ yield le contenu - Événement
tool_call→ yield"__STEP__:tool:{message}" - Événement
done→ fin du stream
- Événement
- Fallback: si SSE non supporté, tente une réponse JSON
{"response": "..."}. - En cas d'erreur réseau: yield un message d'erreur localisé.
Prompt de classification d'intention
Configurable via INTENT_DETECTION_PROMPT. Prompt par défaut (résumé):
You are an intent classifier. Given the user's question, context, and conversation history, determine:
- NORMAL: the question can be answered using the provided context (RAG)
- ALTER: the question requires an external action (booking, reservation, etc.)
If NORMAL: respond naturally using the context.
If ALTER: respond with exactly "ALTER" followed by a brief explanation.get_enhanced_system_prompt
apps/chatbot/src/config/orchestrator_config.py
def get_enhanced_system_prompt(base_prompt: str) -> str:Quand ENABLE_ORCHESTRATOR=true, ajoute au prompt système de base des instructions expliquant au modèle qu'il peut escalader vers un agent externe. Injecté dans le message système Chainlit au démarrage de chaque session.
Cas d'usage type
- Un utilisateur pose une question sur la politique de congés → intent
NORMAL→ réponse RAG. - L'utilisateur demande de "réserver un voyage à Paris" → intent
ALTER→ session bascule en mode ALTER. - Toutes les questions suivantes dans ce thread sont directement envoyées à l'agent de réservation via SSE.
Extension
- Nouvel agent externe: implémentez
POST /assistantavec SSE sur votre service, configurezEXTERNAL_AGENT_URL. - Prompt personnalisé: overridez
INTENT_DETECTION_PROMPTpour adapter les critères NORMAL/ALTER à votre domaine. - Multi-agents: modifiez
classify_intent_and_answerpour retourner des types d'intention supplémentaires et router vers différents agents.
Kalli