Docteur vs ChatGPT : Chatbot medical multi-agent

# Parameters
BATCH_MODE = True

Navigation : Index

Durée estimée : 30 minutes | Prérequis : compte OpenAI avec clé API, connaissances de base en Python

Dans ce cas d’usage, nous construisons un système de consultation medicale simulee ou trois agents IA cooperent : un medecin generaliste qui pose des questions, une IA medicale qui analyse les symptomes, et un pharmacien qui recommande des traitements. Le dialogue est orchestre par Semantic Kernel via AgentGroupChat, avec une stratégie de terminaison automatique.

Avertissement : ce notebook est un exercice pedagogique. Les diagnostics et recommandations medicamenteuses sont simules et ne remplacent en aucun cas une consultation medicale reelle.

Adapté d’une production étudiante EPF : Louise et Jeanne Céline. Universalisation : refactor #890.

Vue d’ensemble : un chatbot médical multi-agent en 3 rôles

Ce notebook implémente une consultation médicale simulée entre trois agents LLM : un médecin généraliste qui pose des questions complémentaires au patient, une IA médicale d’analyse qui propose des hypothèses diagnostiques, et un pharmacien qui vérifie les interactions médicamenteuses. Le tout orchestré par un AgentGroupChat Semantic Kernel avec une stratégie de terminaison à limite d’échanges (6 messages) — la détection d’un diagnostic final par mot-clé étant laissée en exercice. Le notebook couvre les patterns : Kernel + plugins natifs, ChatCompletionAgent, AgentGroupChat, TerminationStrategy, et auto function calling. C’est un cas d’usage type pour les synthetic clinical reasoning où plusieurs LLM agents simulent une consultation réelle.

# Import guards - availability flags for external dependencies

try:
    from dotenv import load_dotenv
    DOTENV_AVAILABLE = True
except ImportError:
    DOTENV_AVAILABLE = False
    print(f'  dotenv non disponible - certaines fonctionnalites seront limitees')

try:
    import semantic_kernel
    SEMANTIC_KERNEL_AVAILABLE = True
except ImportError:
    SEMANTIC_KERNEL_AVAILABLE = False
    print(f'  semantic_kernel non disponible - certaines fonctionnalites seront limitees')

Import des bibliothèques

Nous importons les briques de Semantic Kernel nécessaires à l’orchestration multi-agent : le Kernel (conteneur de services et de plugins), ChatCompletionAgent et AgentGroupChat (agents et orchestrateur de groupe), TerminationStrategy (fin de dialogue), le décorateur @kernel_function (pour exposer des fonctions comme outils) et FunctionChoiceBehavior (pour l’appel automatique de plugins par le LLM). Le type Annotated sert à documenter les paramètres de ces fonctions-plugin.

Ce cas d’usage met en oeuvre une conversation multi-agent dans le domaine medical. Trois agents cooperent : un medecin generaliste, une IA specialisee en diagnostic et un pharmacien. Chaque agent dispose de son propre prompt système et de plugins dedies via des @kernel_function.

Objectifs pedagogiques : - Comprendre l’orchestration multi-agent avec AgentGroupChat - Utiliser des plugins @kernel_function pour doter les agents de capacites spécifiques - Implementer une TerminationStrategy pour contrôler la fin du dialogue - Configurer FunctionChoiceBehavior.Auto() pour l’appel automatique de plugins

import os
import logging
import asyncio
from dotenv import load_dotenv
from semantic_kernel import Kernel
from semantic_kernel.agents import ChatCompletionAgent, AgentGroupChat
from semantic_kernel.agents.strategies import TerminationStrategy
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.contents import ChatHistory
from semantic_kernel.functions import kernel_function, KernelArguments
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from typing import Annotated
print("Imports OK")
print("Imports et configuration OK")
Imports OK
Imports et configuration OK

Lecture du résultat : imports et configuration initiale

L’output "Imports OK" valide la chaîne complète python-dotenv + semantic-kernel + pydantic : trois dépendances critiques pour ce cas d’usage, et l’échec d’une seule aurait court-circuité la cellule d’imports ci-dessus (load_dotenv()). Le notebook utilise des imports gardés (try/except ImportError) dans la cellule d’imports ci-dessus — c’est un pattern défensif qui documente la disponibilité des services externes avant de planter en aval. L’étudiant doit reproduire ce réflexe : un import nu de semantic_kernel dans un clone frais sans la dépendance installée retournerait un ModuleNotFoundError peu explicite.

# Charger les variables d'environnement
load_dotenv()
True

Lecture du résultat : variables d’environnement chargées

load_dotenv() retourne True quand un fichier .env est trouvé et parsé. Pour ce notebook, une seule variable compte : OPENAI_API_KEY — la clé du modèle gpt-5-mini que create_kernel() (ci-dessous) passe à OpenAIChatCompletion. C’est la seule que le code lit : aucun backend Azure ni ComfyUI/Qwen n’est branché ici. Un False — comme sur la sortie ci-dessus — signifie seulement qu’aucun fichier .env n’a été trouvé : l’exécution enregistrée a tourné avec la clé exportée dans l’environnement du process (d’où les 5 appels API réussis en fin de notebook). Si OPENAI_API_KEY est absente à la fois du .env et de l’environnement, la configuration du service ou le premier appel LLM échoue explicitement ; le try/except final ne masque pas cet échec.

Configuration des logs

Le module logging permet de tracer les echanges entre agents en temps reel. Chaque message sera horodate et identifie par le nom de l’agent emetteur, ce qui facilite le debug des conversations multi-agent.

# Configuration des logs
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[logging.StreamHandler()]
)
logger = logging.getLogger('MedicalAI')
print("Configuration des logs OK")
Configuration des logs OK

Lecture du résultat : logging structuré pour traçabilité multi-agent

"Configuration des logs OK" valide le format %(asctime)s [%(levelname)s] %(message)s avec niveau INFO. C’est ce format que la cellule d’exécution de la consultation (en fin de notebook) affichera en sortie (horodatage + [INFO] Début de la consultation médicale IA au lancement de la consultation). Le logging structuré n’est pas un caprice pédagogique : sans lui, l’étudiant ne peut pas distinguer qui parle dans un chat à 3 agents — médecin, IA médicale ou pharmacien. La distinction ne vient pas du format (qui n’affiche ni le nom du logger ni l’émetteur) mais des appels de log explicites dans run_medical_chat() : logger.info(f"[{message.role}] {message.name}: {message.content}") identifie l’émetteur de chaque message, tour par tour. L’étudiant doit noter l’horodatage (la date varie à chaque exécution) et l’ordre des événements : c’est cette trace qui valide ex-post la séquence orchestrale.

Création du kernel Semantic Kernel

Le Kernel est le conteneur central de Semantic Kernel : il regroupe le service d’IA et les plugins. La fonction create_kernel() instancie un kernel vierge puis y enregistre un service OpenAIChatCompletion (modèle gpt-5-mini, clé API lue depuis l’environnement — jamais codée en dur). Factoriser cette construction dans une fonction permet de créer plusieurs kernels, par exemple un par agent si l’on souhaite les isoler.

# Création du kernel Semantic Kernel
def create_kernel():
    kernel = Kernel()
    kernel.add_service(OpenAIChatCompletion(
        service_id="openai",
        ai_model_id="gpt-5-mini",  # Modifier si besoin
        api_key=os.getenv("OPENAI_API_KEY")
    ))
    return kernel
# La cellule ne fait que DEFINIR la factory : aucun Kernel() n'existe encore.
print("Fonction create_kernel definie — le kernel sera instancie plus bas (kernel = create_kernel())")
Fonction create_kernel definie — le kernel sera instancie plus bas (kernel = create_kernel())

Lecture du résultat : fonction factory create_kernel

"Fonction create_kernel definie…" décrit exactement ce que cette cellule a fait : définir la factory, rien de plus. Aucun Kernel() n’existe encore — l’instanciation n’a lieu que plus loin dans le notebook (kernel = create_kernel()). Cette séparation définition/instanciation est un pattern de testabilité : la cellule d’instanciation peut être relancée plusieurs fois sans redéfinir la fonction. Dans un notebook pédagogique, cela permet à l’étudiant de réinstancier un kernel frais si le précédent a accumulé des plugins contradictoires (ex. après une erreur dans une cellule précédente). Dans un projet en production, c’est l’équivalent d’une factory pattern classique (GoF).

Lecture du résultat : kernel Semantic Kernel instancié

La cellule ci-dessus définit create_kernel() — c’est la factory du conteneur central de Semantic Kernel. Le kernel agrège services LLM, plugins (médecin/pharmacien/allergies) et filters. Dans ce notebook, chaque agent conversationnel (médecin, IA médicale, pharmacien) partage le même kernel mais accède à des plugins différents via kernel.add_plugin(DoctorPlugin(), plugin_name="doctor"). Cette mutualisation du kernel vs duplication par agent est un choix d’architecture : un seul service LLM, N personas.

Plugins medicaux : doter les agents de competences spécifiques

Chaque agent dispose d’un plugin dedie contenant des fonctions annotees avec @kernel_function. Ces fonctions agissent comme des outils que le LLM peut invoquer automatiquement lorsqu’il en a besoin :

  • DoctorPlugin : pose des questions de suivi en fonction du symptome mentionne
  • MedicalAIPlugin : evalue la gravite d’un symptome (Leger, Modere, Severe, Critique)
  • PharmacistPlugin : recommande un medicament adapte avec posologie et precautions

Le kernel est l’élément central de Semantic Kernel. La fonction create_kernel() instancie un kernel et y enregistre un service OpenAIChatCompletion qui fournira l’acces au modèle GPT-4o-mini. Chaque agent utilisera ce kernel partage pour generer ses reponses.

class DoctorPlugin:
    """Plugin permettant au médecin de poser des questions complémentaires sur les symptômes."""
    @kernel_function(description="Pose des questions supplémentaires pour affiner le diagnostic.")
    def ask_followup_questions(self, symptom: Annotated[str, "Symptôme décrit par l'utilisateur"]) -> str:
        """Retourne une question en fonction du symptôme mentionné."""
        questions_map = {
            "fièvre": "Depuis combien de temps avez-vous de la fièvre ?",
            "maux de tête": "Avez-vous une sensibilité à la lumière ou au bruit ?",
            "douleur thoracique": "La douleur est-elle aiguë ou diffuse ?",
        }
        return questions_map.get(symptom.lower(), "Pouvez-vous donner plus de détails sur vos symptômes ?")

class MedicalAIPlugin:
    """Plugin qui analyse la gravité des symptômes."""
    @kernel_function(description="Vérifie la gravité d'un symptôme médical.")
    def check_symptom_severity(self, symptom: Annotated[str, "Symptôme décrit par l'utilisateur"]) -> str:
        """Retourne une évaluation de la gravité du symptôme."""
        severity_map = {
            "fièvre": "Modérée",
            "maux de tête": "Léger",
            "douleur thoracique": "Sévère",
            "perte de connaissance": "Critique"
        }
        return severity_map.get(symptom.lower(), "Inconnu - consultez un médecin.")

class PharmacistPlugin:
    """Plugin qui recommande des médicaments en fonction du diagnostic."""
    @kernel_function(description="Recommande un médicament adapté à un symptôme.")
    def recommend_medication(self, symptom: Annotated[str, "Symptôme décrit par l'utilisateur"]) -> str:
        """Retourne une suggestion de médicament (avec précautions)."""
        medication_map = {
            "fièvre": "Paracétamol (500mg, toutes les 6h, max 3 jours)",
            "maux de tête": "Ibuprofène (200mg, toutes les 8h, avec précaution si problème gastrique)",
            "douleur thoracique": "Aucun médicament recommandé - Consultez un médecin immédiatement",
        }
        return medication_map.get(symptom.lower(), "Aucun médicament recommandé - Consultez un pharmacien.")
print("Classe DoctorPlugin définie")
print("Classes DoctorPlugin, MedicalAIPlugin, PharmacistPlugin definies")
Classe DoctorPlugin définie
Classes DoctorPlugin, MedicalAIPlugin, PharmacistPlugin definies

Lecture du résultat : plugins médicaux définis

"Classe DoctorPlugin définie" valide que DoctorPlugin (questions complémentaires au patient), MedicalAIPlugin (analyse IA), et PharmacistPlugin (vérification interactions médicamenteuses) sont instanciés en mémoire. Chaque plugin expose des native functions Python décorées @kernel.function_description() que les agents peuvent invoquer via le mécanisme d’auto function calling de SK. Le notebook utilise 3 plugins médicaux + 1 plugin d’allergies (exercice, ci-dessous) — l’étudiant doit compléter l’AllergyPlugin (voir l’exercice ci-dessous). Les plugins sont l’équivalent médical des tools en LangChain : la Skill calling devient function_call côté LLM.

Exercice 1 : Plugin de verification des allergies

Les plugins actuels couvrent les questions de suivi, la gravite et les medicaments. Il manque un plugin crucial : la verification des allergies. L’objectif est de créer AllergyPlugin qui permet a l’agent pharmacien de verifier si un medicament recommande est compatible avec les allergies declarees du patient.

Objectif : implementer une classe AllergyPlugin avec une méthode check_allergy annotee @kernel_function qui retourne un avertissement si le medicament est incompatible avec une allergie connue.

Indices : - # Étape 1 : Définir un dictionnaire associant des allergies a des medicaments contre-indiques - # Étape 2 : Implementer la méthode check_allergy avec les annotations de type Annotated - # Indice : utiliser le pattern des plugins existants (DoctorPlugin, PharmacistPlugin)

class AllergyPlugin:
    """Plugin de verification des allergies medicamenteuses."""
    # TODO etudiant : implementer le plugin
    
    @kernel_function(description="Verifie si un medicament est compatible avec les allergies du patient.")
    def check_allergy(
        self, 
        medication: Annotated[str, "Nom du medicament"], 
        allergy: Annotated[str, "Allergie declaree du patient"]
    ) -> str:
        # Etape 1 : definir les contre-indications connues
        contraindications = {}  # TODO etudiant : dictionnaire allergie -> medicaments
        
        # Etape 2 : verifier et retourner le resultat
        result = None  # TODO etudiant : logique de verification
        return result  # TODO etudiant : retourner le message approprie

print("Exercice a completer : AllergyPlugin")
Exercice a completer : AllergyPlugin

Création du Kernel

On instancie ici le kernel partagé que les trois agents et leurs plugins utiliseront. Tous les add_plugin et toutes les créations d’agents qui suivent s’appuient sur cette même instance : c’est ce qui permet à l’IA médicale d’invoquer, via le kernel, les fonctions exposées par les plugins du médecin et du pharmacien.

# Création du kernel
kernel = create_kernel()
print("Kernel instancie")
Kernel instancie

Lecture du résultat : prompts système configurés

"Prompts medicaux configures" couvre les 3 rôles : DOCTOR_PROMPT (médecin généraliste, questions complémentaires), AI_MEDICAL_PROMPT (assistant IA d’analyse), PHARMACIST_PROMPT (vérification interactions). Chaque prompt structure la persona + comportement attendu : ton professionnel, refus de prescrire, demande de clarifications. C’est l’application du pattern role prompting (cf. OpenAI Best Practices). L’exercice sur les prompts (plus bas) invite l’étudiant à rédiger un prompt pediatric — l’ajout d’un persona spécialisé est un exercice classique de persona engineering.

Lecture du résultat : passage du squelette à l’exécution

Avec la cellule d’instanciation du kernel ci-dessus (kernel = create_kernel()) et la cellule d’ajout des plugins plus bas (kernel.add_plugin(...)), le notebook quitte la phase de définition pour la phase d’instanciation. Avant : on définissait des classes et fonctions. Après : on les utilise. Cette démarcation est un signal pédagogique classique en notebook : la deuxième moitié du notebook est exécutable (l’étudiant doit voir la consultation se dérouler), tandis que la première moitié est structurelle (l’étudiant peut la lire comme du code de production). Le print("Kernel instancie") qui accompagne l’instanciation est la trace écrite de cette transition.

Ajout des plugins pour chaque agent

kernel.add_plugin() enregistre une instance de plugin sous un nom. Chaque plugin expose ses méthodes @kernel_function au kernel, qui les rend discoverable par le LLM. On enregistre ici les trois plugins médicaux (doctor, medical, pharmacist) sur le kernel partagé — ils seront invoquables automatiquement grâce au FunctionChoiceBehavior.Auto() configuré plus bas.

# Ajout des plugins pour chaque agent
kernel.add_plugin(DoctorPlugin(), plugin_name="doctor")
kernel.add_plugin(MedicalAIPlugin(), plugin_name="medical")
kernel.add_plugin(PharmacistPlugin(), plugin_name="pharmacist")
print("Kernel configuré avec le plugin médical")
print("Classes plugins medicaux definies")
print("Kernel configure avec le plugin medical")
Kernel configuré avec le plugin médical
Classes plugins medicaux definies
Kernel configure avec le plugin medical

Lecture du résultat : kernel et plugins opérationnels

"Kernel instancie" puis "Kernel configuré avec le plugin médical" valident la séquence kernel = create_kernel() → kernel.add_plugin(DoctorPlugin(), plugin_name="doctor"). Cette deuxième étape est ce qui distingue Semantic Kernel d’un simple wrapper OpenAI : le kernel enregistre les plugins comme tools invocables par le LLM via la couche auto function calling. Sans add_plugin, les native functions Python de DoctorPlugin seraient inaccessibles aux agents, et le LLM répondrait sans grounding médical.

Prompts système : définir le comportement de chaque agent

Les prompts système sont les instructions qui guident le comportement de chaque agent. Ils etablissent le rôle, les contraintes et le style de reponse attendu. Une bonne conception de prompt est essentielle pour eviter les comportements indesirables (diagnostic premature, recommandation non fondee).

DOCTOR_PROMPT = """
Vous êtes un médecin généraliste. Vous posez d'abord des questions pour mieux comprendre les symptômes de l'utilisateur,
puis vous donnez un diagnostic probable basé sur votre expertise médicale. 
Ne donnez jamais de diagnostic sans avoir recueilli assez d'informations.
"""

AI_MEDICAL_PROMPT = """
Vous êtes une IA médicale spécialisée en diagnostic. Analysez les symptômes fournis et proposez un diagnostic basé sur des statistiques et des études médicales. 
Soyez clair et donnez plusieurs hypothèses si nécessaire.
"""

PHARMACIST_PROMPT = """
Vous êtes un pharmacien qualifié. En fonction du diagnostic fourni, vous recommandez les médicaments appropriés. 
Mentionnez toujours les précautions d'utilisation et la nécessité d'une consultation médicale avant la prise de médicaments.
"""
print("Prompt médical configuré")
print("Prompts medicaux configures")
Prompt médical configuré
Prompts medicaux configures

Lecture du résultat : stratégie de terminaison médicale

"Stratégie de terminaison médicale définie" marque l’instanciation de MedicalTerminationStrategy — sous-classe de TerminationStrategy qui détecte la fin du chat multi-agent. Dans ce notebook, le critère de terminaison est une limite d’échanges : should_terminate retourne True dès que l’historique atteint 6 messages (len(history) >= 6) — soit 1 message patient + 5 réponses d’agents. Sans stratégie explicite, AgentGroupChat boucle indéfiniment. La détection d’un diagnostic par mot-clé est précisément l’exercice laissé à l’étudiant plus bas (DiagnosticTerminationStrategy). L’étudiant doit observer cette séparation entre orchestration et logique métier : la stratégie de terminaison est un plugin comportemental, pas une règle codée en dur dans le chat.

Exercice 2 : Adapter les prompts pour un scénario pediatric

Les prompts actuels sont configures pour un adulte. L’objectif est d’adapter le système pour une consultation pediatric : le medecin doit utiliser un langage adapte aux enfants, l’IA medicale doit prendre en compte les specificites pediatric (posologie différente, signes vitaux spécifiques), et le pharmacien doit mentionner les precautions enfant.

Objectif : ecrire les trois prompts système adaptes au contexte pediatric.

Indices : - # Étape 1 : Modifier le prompt du medecin pour un langage accessible aux enfants - # Étape 2 : Adapter le prompt de l’IA medicale pour les dosages et signes pediatric - # Indice : ajouter des contraintes comme “toujours mentionner le poids recommande pour la posologie”

# Exercice 2 : Prompts adaptes au contexte pediatric
# TODO etudiant : rediger les trois prompts pediatric

PEDIATRIC_DOCTOR_PROMPT = ""    # Etape 1 : langage enfantin, questions adaptees
PEDIATRIC_AI_PROMPT = ""        # Etape 2 : dosages enfant, signes specific
PEDIATRIC_PHARMACIST_PROMPT = ""  # TODO etudiant : precautions enfant, posologie poids

print("Exercice a completer : prompts pediatric")
Exercice a completer : prompts pediatric

Création des agents

Les trois prompts système definissent le comportement et les contraintes de chaque agent. Le medecin doit poser des questions avant de diagnostiquer, l’IA medicale analyse les symptomes avec une approche statistique, et le pharmacien recommande des traitements en rappelant les precautions d’usage. Cette separation des rôles est fondamentale dans une architecture multi-agent.

# Création des agents
doctor_agent = ChatCompletionAgent(
    kernel=kernel,
    name="Docteur_Humain",
    instructions=DOCTOR_PROMPT,
)

ai_medical_agent = ChatCompletionAgent(
    kernel=kernel,
    name="IA_Medicale",
    instructions=AI_MEDICAL_PROMPT,
)
print("Agents de conversation créés")
print("Kernel configure avec plugin medical")
print("Agents de conversation crees")
Agents de conversation créés
Kernel configure avec plugin medical
Agents de conversation crees

Lecture du résultat : agents conversationnels créés

"Agents de conversation créés" marque l’instanciation de trois ChatCompletionAgent (médecin, IA médicale, pharmacien) avec leurs rôles respectifs et le ServiceId="openai" du kernel. C’est ici que le modèle de groupe (AgentGroupChat, instancié plus bas dans le notebook) prend forme : trois personas, un orchestrateur de chat, une stratégie de terminaison médicale. L’étudiant doit observer la distinction agent/kernel : un agent utilise un kernel mais n’en est pas le propriétaire. Pour Scalability, ajouter un 4ᵉ agent (ex. infirmier) ne nécessite pas de réinstancier le kernel — seulement un nouveau ChatCompletionAgent partageant le même.

Configuration pour que l’agent médical appelle automatiquement les plugins

Par défaut, un agent ne s’appuie que sur ses instructions textuelles. Pour qu’il puisse invoquer les plugins enregistrés dans le kernel, on active FunctionChoiceBehavior.Auto() dans ses KernelArguments : le LLM décide alors de lui-même, selon le contexte, d’appeler telle ou telle @kernel_function (gravité d’un symptôme, recommandation médicamenteuse…). On applique ce réglage à l’agent IA_Medicale, puis on crée le pharmacien sur le même modèle.

settings = kernel.get_prompt_execution_settings_from_service_id("openai")
settings.function_choice_behavior = FunctionChoiceBehavior.Auto()
ai_medical_agent.arguments = KernelArguments(settings=settings)

pharmacist_agent = ChatCompletionAgent(
    kernel=kernel,
    name="Pharmacien",
    instructions=PHARMACIST_PROMPT,
)
print("Paramètres d'exécution configurés")
print("Parametres d execution configures")
Paramètres d'exécution configurés
Parametres d execution configures

Lecture du résultat : paramètres d’exécution LLM

"Paramètres d'exécution configurés" marque kernel.get_prompt_execution_settings_from_service_id("openai") qui configure la température, le max_tokens, le top_p pour les appels LLM du kernel. Ces paramètres sont partagés par les 3 agents via le kernel — pas configurés agent par agent. C’est un choix d’orchestration : pour une consultation médicale, on veut des réponses reproductibles et conservatives (température basse, typiquement 0.2-0.5), pas créatives. L’étudiant peut observer l’effet en modifiant temperature (de 0.0 = déterministe à 1.0 = exploratoire) et en relançant la cellule settings ci-dessus.

Définition d’une stratégie de terminaison

Le parametrage FunctionChoiceBehavior.Auto() permet a l’agent IA_Medicale d’invoquer automatiquement les plugins enregistres dans le kernel (gravite des symptomes, recommandations). Sans cette configuration, l’agent ne disposerait que de ses instructions textuelles pour formuler ses reponses.

class MedicalTerminationStrategy(TerminationStrategy):
    async def should_terminate(self, agent, history):
        return len(history) >= 6  # On limite à 6 échanges
print("Stratégie de terminaison médicale définie")
print("Strategie de terminaison medicale definie")
Stratégie de terminaison médicale définie
Strategie de terminaison medicale definie

Exercice 3 : Stratégie de terminaison basee sur le diagnostic

La stratégie actuelle arrete après 6 messages. L’objectif est d’implementer une stratégie plus intelligente qui detecte quand un diagnostic probable a ete formule par l’IA medicale (presence de mots comme “diagnostic”, “hypothese”, “probablement” dans le dernier message).

Objectif : créer DiagnosticTerminationStrategy qui arrete la conversation des qu’un diagnostic est emis ou après 8 echanges maximum.

Indices : - # Étape 1 : Définir une liste de mots-cles indicatifs d’un diagnostic - # Étape 2 : Verifier leur presence dans le contenu du dernier message - # Indice : combiner la condition de diagnostic avec un compteur maximum d’echanges

from typing import ClassVar

class DiagnosticTerminationStrategy(TerminationStrategy):
    # TODO etudiant : implementer la detection de diagnostic
    DIAGNOSTIC_KEYWORDS: ClassVar[list] = []  # Etape 1 : mots-cles de diagnostic
    MAX_EXCHANGES: ClassVar[int] = 8
    
    async def should_terminate(self, agent, history):
        # Etape 2 : verifier diagnostic OU limite d'echanges
        result = False  # TODO etudiant : remplacer par la logique
        return result

print("Exercice a completer : DiagnosticTerminationStrategy")
Exercice a completer : DiagnosticTerminationStrategy

Création du chat groupé avec stratégie de terminaison

La classe MedicalTerminationStrategy herite de TerminationStrategy et implemente should_terminate. Ici, la condition est simple : après 6 messages dans l’historique, le dialogue s’arrete. Cette approche evite les boucles infinies tout en laissant suffisamment d’echanges pour un diagnostic complet.

chat = AgentGroupChat(
    agents=[doctor_agent, ai_medical_agent, pharmacist_agent],
    termination_strategy=MedicalTerminationStrategy()  # Ajout de la stratégie
)
print("Chat de groupe médical configuré")
print("Prompts medicaux configures")
print("Chat de groupe medical configure")
Chat de groupe médical configuré
Prompts medicaux configures
Chat de groupe medical configure

Lecture du résultat : chat de groupe médical configuré

"Chat de groupe médical configuré" valide la chaîne AgentGroupChat(agents=[...], termination_strategy=MedicalTerminationStrategy(), selection_strategy=DefaultSelectionStrategy()). Le groupe de chat orchestre la conversation multi-agent : à chaque tour, le selection_strategy choisit l’agent actif (round-robin par défaut, ou basé sur le dernier message), le termination_strategy détecte la fin (limite de 6 messages dans l’historique). C’est le cœur du pattern multi-agent : sans orchestration explicite, les agents parleraient en parallèle. Ce notebook est un cas d’usage type de synthetic clinical reasoning où 3 LLM agents simulent une consultation réelle.

Lecture du résultat : squelette multi-agent complet, prêt pour l’exécution

À ce stade du notebook, toute la machinerie multi-agent est en place : kernel partagé (1), 3 plugins médicaux enregistrés (médecin/IA/pharmacien — le squelette AllergyPlugin de l’exercice 1, lui, n’est pas enregistré et reste à compléter), 3 agents conversationnels avec leurs prompts respectifs, 1 stratégie de terminaison médicale, 1 groupe de chat orchestré, 1 fonction run_medical_chat() async. Ce qui sépare ce notebook d’un squelette mort, c’est la cellule d’exécution (try/except await run_medical_chat(), ci-dessous) : l’appel asynchrone déclenche réellement l’orchestration et l’étudiant voit la conversation se dérouler tour par tour. Pattern clé : la complexité d’un système multi-agent est cachée dans le setup (tout ce qui précède) et visible dans l’exécution (les dernières cellules). L’étudiant doit comprendre ce distinguo pour scripter ses propres use cases.

Fonction pour exécuter le dialogue

La fonction run_medical_chat orchestre le dialogue complet : elle amorce la consultation avec les symptômes du patient, les transmet à l’AgentGroupChat, puis itère sur les réponses des agents jusqu’à ce que la stratégie de terminaison déclare la consultation terminée (limite de 6 échanges posée par MedicalTerminationStrategy).

Deux modes d’amorçage :

  • Batch (BATCH_MODE = True, le mode Papermill/CI) : un cas clinique fixé (SYMPTOMES_DEMO) démarre la consultation. En exécution headless, stdin n’existe pas — appeler input() lève StdinNotImplementedError avant que le moindre agent ne parle, et la consultation n’a pas lieu. C’est le même patron que les deux autres études de cas du répertoire : Fort-Boyard amorce avec un mot à deviner fixé, Barbie-Schreck avec une contrainte de style tirée au sort.
  • Interactif (BATCH_MODE = False) : les symptômes initiaux sont saisis au clavier via input().

La consultation est ensuite agent-driven : les trois agents se répondent sans intervention. Le try/except de la cellule d’exécution n’intercepte plus que EOFError/KeyboardInterrupt — un échec d’orchestration (clé API, réseau, quota) doit rester visible, pas absorbé silencieusement.

from semantic_kernel.contents import ChatMessageContent, AuthorRole

SYMPTOMES_DEMO = ("Depuis trois jours, j'ai une fievre a 38,5 degres avec des maux de tete "
                  "et une legere toux seche. Je n'ai pas de douleur thoracique.")

async def run_medical_chat():
    logger.info("Début de la consultation médicale IA")

    # En mode batch (Papermill/CI), stdin n'existe pas : on amorce la consultation
    # avec un cas clinique fixe -- meme patron que Fort-Boyard et Barbie-Schreck.
    if BATCH_MODE:
        symptoms = SYMPTOMES_DEMO
        print(f"[Batch] Cas clinique démo : {symptoms}")
    else:
        symptoms = input("Décrivez vos symptômes : ")

    # Le message patient amorce l'historique INTERNE de l'AgentGroupChat (via
    # add_chat_message) : sans lui, la premiere invocation n'a aucun message
    # auquel repondre et echoue.
    await chat.add_chat_message(ChatMessageContent(role=AuthorRole.USER, content=symptoms))

    # Consultation agent-driven : les trois agents se repondent jusqu'a la limite
    # de 6 echanges posee par MedicalTerminationStrategy.
    while True:
        async for message in chat.invoke():
            logger.info(f"[{message.role}] {message.name}: {message.content}")
            print(f"{message.name}: {message.content}")

        if chat.is_complete:
            break

    logger.info("Consultation terminée.")

print("Fonction de chat médical prête")
Fonction de chat médical prête

Lecture du résultat : fonction de chat médical prête

"Fonction de chat médical prête" marque l’aboutissement du squelette : la fonction async run_medical_chat() peut être appelée pour démarrer la consultation simulée. Le logger.info("Début de la consultation médicale IA") qui ouvre run_medical_chat() est le premier signal d’exécution quand l’étudiant lance la cellule d’exécution de la consultation (ci-dessous). À ce stade, le notebook a instancié 3 agents, 1 kernel partagé, 3 plugins enregistrés, 1 stratégie de terminaison, 1 groupe de chat — toute la machinerie multi-agent est en place. La cellule d’exécution lance await run_medical_chat() qui bouclera jusqu’à ce que MedicalTerminationStrategy.should_terminate() retourne True (limite de 6 messages dans l’historique du groupe).

# except resserre : plus d'Exception nue. EOFError/KeyboardInterrupt = session
# interactive interrompue par l'utilisateur ; tout autre echec (API, cle, reseau)
# doit rester VISIBLE dans la sortie, pas etre absorbe.
try:
    await run_medical_chat()
except (EOFError, KeyboardInterrupt) as e:
    print(f"[Session interactive interrompue ({type(e).__name__}) - la consultation n'a pas eu lieu, relancez la cellule.]")
[Batch] Cas clinique démo : Depuis trois jours, j'ai une fievre a 38,5 degres avec des maux de tete et une legere toux seche. Je n'ai pas de douleur thoracique.
Docteur_Humain: Merci — j'aimerais poser quelques questions pour mieux comprendre votre état avant de proposer un diagnostic probable.

Questions (répondez autant que possible) :
1. Avez-vous des frissons, sueurs ou fatigue importante ?  
2. Avez-vous des courbatures, douleurs musculaires ou articulaires ?  
3. Votre toux produit-elle des expectorations (crachats) ou est-elle entièrement sèche ?  
4. Avez-vous un mal de gorge, une congestion nasale ou un écoulement nasal ?  
5. Avez-vous des difficultés à respirer, une respiration rapide ou un essoufflement à l'effort ?  
6. Avez-vous des nausées, vomissements, diarrhée ou perte d'appétit ?  
7. Avez-vous vos antécédents vaccinaux à jour (grippe, COVID-19) ou été en contact récent avec une personne malade ?  
8. Prenez-vous des médicaments actuellement (y compris antalgiques) ? Avez-vous déjà pris du paracétamol/ibuprofène pour faire baisser la fièvre et cela a-t-il aidé ?  
9. Avez-vous des conditions médicales chroniques (diabète, maladies pulmonaires, immunosuppression, cœur, etc.) ?  
10. Avez-vous remarqué une évolution : la fièvre augmente-t-elle, diminue-t-elle ou est-elle stable depuis 3 jours ?

Répondez à ces questions et j'indiquerai un diagnostic probable et les conseils à suivre (soins à domicile, signes d'alerte, nécessité de test/santé publique, et si besoin prise en charge médicale urgente).
IA_Medicale: Merci — avec les éléments fournis (fièvre 38,5 °C depuis 3 jours, maux de tête, toux sèche légère, pas de douleur thoracique) voici une analyse et des conseils pragmatiques.

Hypothèses probables (par ordre de probabilité)
- Infection virale des voies respiratoires hautes (rhume/bronchite virale) — la cause la plus fréquente chez un adulte ambulatoire avec fièvre modérée et toux sèche.  
- Infection à SARS‑CoV‑2 (COVID‑19) — présente fréquemment par fièvre, céphalées et toux sèche ; reste une possibilité importante à tester.  
- Grippe (influenza) — peut donner fièvre élevée, céphalées et toux; plus probable si début brutal et courbatures importantes ou épidémie saisonnière en cours.  
- Bronchite aiguë non compliquée — souvent virale, toux prédominante.  
- Pneumonie bactérienne — moins probable en absence de douleur thoracique, de dyspnée ou de signes respiratoires focaux, mais à envisager si aggravation (fièvre persistante, dyspnée, expectorations purulentes).  

Contexte statistique succinct
- Dans les consultations ambulatoires pour toux/fièvre sans détresse respiratoire, la majorité (la plupart des séries, ≈70–90%) sont d’origine virale (rhinovirus, influenza, SARS‑CoV‑2, etc.). Les pneumonies bactériennes sont relativement rares chez des patients sans signes de gravité (<10% dans ce type de population), mais doivent être recherchées si signes d’aggravation.

Conseils immédiats (soins à domicile)
- Testez-vous pour le COVID‑19 dès que possible (test antigénique rapide ou PCR selon disponibilité). Si positif, suivez les recommandations locales d’isolement et de traitement.  
- Repos, hydratation, nutrition légère.  
- Antipyrétique/analgésique : paracétamol 500–1000 mg toutes les 4–6 h si nécessaire, maximum environ 3 g/24 h (suivre posologie locale et conditions personnelles). Les AINS (ibuprofène) peuvent être utilisés si absence de contre‑indication, mais paracétamol est souvent préféré pour la fièvre.  
- Soulagement de la toux : inhalations de vapeur, boissons chaudes, miel (si >1 an), pastilles pour la gorge.  
- Évitez les antibiotiques sauf si diagnostic de surinfection bactérienne confirmé ou très probable (prescrit par médecin).

Quand consulter en urgence / signes d’alerte
Consultez ou rendez‑vous aux urgences immédiatement si apparition de l’un des signes suivants :
- Difficulté à respirer, essoufflement important, respiration rapide.  
- Saturation en oxygène < 94% (si vous avez un oxymètre) ou coloration bleutée des lèvres/visage.  
- Douleur thoracique intense ou oppression.  
- Confusion, somnolence marquée, incapacité à boire/tenir les liquides.  
- Fièvre très élevée (>40 °C) ou fièvre qui s’aggrave malgré antipyrétiques, ou fièvre persistante au-delà de 72 heures sans amélioration.

Quand voir son médecin / faire un test complémentaire
- Si vous êtes âgé(e) > 65 ans, immunodéprimé(e), ou avez une maladie chronique (diabète, insuffisance cardiaque, BPCO, etc.), contactez votre médecin rapidement pour évaluation et éventuels tests/traitement.  
- Si la fièvre ne baisse pas après 48–72 heures ou que les symptômes empirent, consulter pour examen clinique, éventuelle radiographie pulmonaire et examen sanguin.

Informations que j’ai besoin pour affiner le diagnostic
Merci de me dire, si possible :
- Votre âge et antécédents médicaux (diabète, BPCO, immunosuppression, grossesse, etc.).  
- Avez‑vous des courbatures, frissons, perte d’appétit, nausées, ou diarrhée ?  
- La toux est‑elle sèche sans expectoration ? Avez‑vous une perte d’odorat/goût ?  
- Avez‑vous été en contact récent avec une personne malade ou pas vacciné contre la grippe/COVID récemment ?  
- Avez‑vous pris des antipyrétiques et ont‑ils diminué la fièvre ?

Répondez à ces points et je préciserai la probabilité des diagnostics et les actions à suivre (test(s) recommandés, besoin d’antibiotiques ou d’examens complémentaires, etc.). Si vous avez des signes de gravité décrits ci‑dessus, rendez‑vous sans délai aux urgences.
Pharmacien: Merci — d’après vos signes (fièvre 38,5 °C depuis 3 jours, maux de tête, toux sèche légère, pas de douleur thoracique) voici des recommandations pharmaceutiques pratiques. Avant toute prise de médicament, consultez un médecin ou votre pharmacien si vous avez des facteurs de risque (âge avancé, grossesse, maladies chroniques, prise d’autres traitements).

Médicaments pouvant aider (adultes)
- Paracétamol (antipyrétique/antalgique)  
  - Posologie usuelle : 500–1000 mg toutes les 4–6 heures si besoin, maximum ≈ 3 g/24 h.  
  - Précautions : attention en cas d’insuffisance hépatique, consommation régulière d’alcool (dans ce cas demander conseil, dose maximale plus basse). Ne pas dépasser la dose recommandée.

- Anti‑inflammatoires non stéroïdiens (AINS) — ex. ibuprofène  
  - Posologie OTC : 200–400 mg toutes les 4–6 h si besoin, maximum ~1200 mg/24 h (selon recommandation locale).  
  - Précautions : éviter si antécédent d’ulcère, saignement digestif, insuffisance rénale sévère, insuffisance cardiaque, prise d’anticoagulant, asthme sensible aux AINS, ou grossesse (surtout 3e trimestre). Si doute, préférez paracétamol.

- Pour la toux sèche (si elle vous gêne)  
  - Dextrométhorphane (antitussif) : posologie adulte ~10–20 mg toutes les 4–6 h, max ~120 mg/24 h (respecter notice).  
  - Précautions : contre‑indiqué avec inhibiteurs de la MAO, à utiliser prudemment si vous prenez certains antidépresseurs (risque de syndrome sérotoninergique).  
  - Alternatives non médicamenteuses : miel (si >1 an), boissons chaudes, inhalations de vapeur, pastilles adoucissantes.

- Si toux productive (expectoration)  
  - Expectorant comme guaifenesin (posologie selon notice) ou simplement hydratation + humidification. Antibiotique non indiqué sans confirmation d’infection bactérienne.

Soins non médicamenteux utiles
- Repos, hydratation régulière, humidification de l’air, lavages nasaux au sérum physiologique.  
- Si suspicion COVID‑19 : test antigénique ou PCR et isolement selon règles locales.

Contre‑indications et interactions importantes (à vérifier avant prise)
- Paracétamol : prudence si maladie du foie ou consommation importante d’alcool.  
- Ibuprofène/AINS : éviter selon antécédents cardiaques, rénaux, digestifs, traitement anticoagulant ou certains médicaments antihypertenseurs.  
- Dextrométhorphane : éviter avec IMAO et surveiller avec certains antidépresseurs/psychotropes.  
- Si vous êtes enceinte, allaitante, âgé(e) ou immunodéprimé(e) : demandez conseil médical avant toute automédication.

Antibiotiques
- Ne pas prendre d’antibiotique sans avis médical et sans signe de surinfection bactérienne (expectorations purulentes persistantes, fièvre qui s’aggrave, examen médical).

Signes d’alerte — consultez sans délai ou allez aux urgences si l’un des signes suivants apparaît
- Difficultés respiratoires, essoufflement marquant.  
- Douleur thoracique, oppression.  
- Confusion, somnolence importante, incapacité à boire.  
- Saturation en O2 < 94 % si vous avez un oxymètre.  
- Fièvre très élevée ou fièvre qui s’aggrave malgré antipyrétiques et persiste >72 h.

Pour affiner la recommandation
Merci de préciser : âge, grossesse possible, antécédents (insuffisance hépatique/ rénale, ulcère, hypertension, maladies cardiaques, asthme), traitements en cours (anticoagulants, antidépresseurs, etc.), consommation d’alcool, et si vous avez déjà pris paracétamol/ibuprofène et si cela a aidé. Je pourrai alors vous proposer une posologie personnalisée et vérifier les interactions/contre‑indications.

Rappel légal et sécurité : ces conseils ne remplacent pas une consultation médicale. En cas de doute ou de signes de gravité, consultez rapidement un professionnel de santé.
Docteur_Humain: Merci — quelques questions rapides pour affiner et pouvoir poser un diagnostic probable et des conseils adaptés. Répondez autant que possible :

1. Quel âge avez‑vous ? Êtes‑vous enceinte ?  
2. Avez‑vous des antécédents : diabète, hypertension, maladie cardiaque, BPCO/asthme, insuffisance rénale, immunodépression ?  
3. Avez‑vous été en contact récent avec quelqu’un malade (COVID/grippe) ? Avez‑vous eu un test COVID (antigénique ou PCR) ? résultat ?  
4. Avez‑vous des courbatures, frissons ou une fatigue importante ? Perte d’odorat/goût ?  
5. La toux est‑elle complètement sèche ? y a‑t‑il des crachats (couleur, quantité) ?  
6. Avez‑vous mal de gorge, nez bouché ou écoulement nasal ?  
7. Avez‑vous des nausées, vomissements, diarrhée ?  
8. Avez‑vous pris des médicaments (paracétamol, ibuprofène, antitussifs) ? la fièvre a‑t‑elle baissé ?  
9. Fumez‑vous ? avez‑vous un oxymètre à domicile (SpO2) et si oui quelle saturation ?  
10. Depuis ce début de symptômes, la situation s’améliore, stagne ou s’aggrave ?

Une fois que j’ai ces informations je vous indiquerai le diagnostic le plus probable, les mesures à prendre immédiatement (soins à domicile, tests), et les signes qui nécessitent une consultation urgente. Si vous avez déjà des signes de gravité (essoufflement, confusion, lèvres bleues, fièvre très élevée), dites‑le tout de suite ou consultez les urgences.
IA_Medicale: Merci — avec les éléments que vous avez donnés (fièvre 38,5 °C depuis 3 jours, maux de tête, toux sèche légère, pas de douleur thoracique) voici une synthèse rapide et des recommandations pratiques.

Hypothèses probables (par ordre de probabilité)
- Infection virale des voies respiratoires hautes (rhume/bronchite virale) — la plus probable.  
- COVID‑19 — possibilité importante (tousse sèche + fièvre + céphalée) ; à tester pour le dépister.  
- Grippe (influenza) — possible surtout en période épidémique ou si début brutal et courbatures intenses.  
- Bronchite aiguë non compliquée (souvent virale).  
- Pneumonie bactérienne — moins probable en l’absence de douleur thoracique, d’essoufflement ou d’expectoration purulente, mais à garder en tête si aggravation.

Probabilités générales (estimation)
- Dans ce contexte ambulatoire sans signes de gravité, la majorité (~70–90%) des cas sont d’origine virale. Les causes bactériennes sévères restent rares.

Mesures immédiates (à domicile)
- Faites un test COVID‑19 (antigénique ou PCR) dès que possible. Isolement si test positif.  
- Repos et hydratation.  
- Antipyrétique : paracétamol 500–1000 mg toutes les 4–6 h si besoin, sans dépasser ≈ 3 g/24 h (adapter si problèmes hépatiques).  
- AINS (ibuprofène) possible si pas de contre‑indication (ulcère, insuffisance rénale, insuffisance cardiaque, asthme sensible, anticoagulants, grossesse) — sinon préférez paracétamol.  
- Pour la toux sèche : inhalations de vapeur, miel (si >1 an), pastilles, éventuellement déxtrométhorphane si gênante et pas de contre‑indication (IMAO, certains antidépresseurs).  
- Évitez les antibiotiques sans avis médical.

Quand consulter en urgence
Rendez‑vous aux urgences ou appelez le 112/15 si apparition de l’un des signes suivants :
- Difficultés respiratoires ou essoufflement important.  
- Saturation en O2 < 94 % (si oxymètre).  
- Douleur ou oppression thoracique.  
- Confusion, somnolence anormale, incapacité à boire.  
- Fièvre très élevée (>40 °C) ou fièvre qui s’aggrave malgré antipyrétiques, ou persistance >72 h sans amélioration.

Quand voir son médecin
- Si vous êtes âgé(e) > 65 ans, immunodéprimé(e), enceinte, ou avez une maladie chronique (diabète, BPCO, insuffisance cardiaque, etc.), contactez votre médecin rapidement.  
- Si pas d’amélioration sous 48–72 h ou symptôme qui s’aggrave (essoufflement, expectorations purulentes, fièvre persistante).

Questions pour affiner le diagnostic (répondez si vous pouvez)
1) Quel âge avez‑vous et avez‑vous des antécédents (diabète, cœur, poumons, immunosuppression, etc.) ?  
2) Avez‑vous pris paracétamol/ibuprofène et la fièvre a‑t‑elle baissé ?  
3) Avez‑vous des courbatures, frissons, perte d’odorat/goût, mal de gorge ou nez bouché ?  
4) La toux est‑elle strictement sèche ? y a‑t‑il des crachats (couleur) ?  
5) Avez‑vous fait un test COVID et quel est le résultat ? Êtes‑vous vacciné(e) contre la grippe/COVID récemment ?  
6) Les symptômes s’améliorent, stagnent ou s’aggravent depuis 3 jours ?

Si vous répondez à ces questions je préciserai la probabilité des diagnostics et vous indiquerai les examens ou traitements à envisager. Si vous avez déjà un signe de gravité, consultez sans délai.

Lecture du résultat : exécution effective de la consultation simulée

La sortie ci-dessus est une consultation réelle (5 appels gpt-5-mini comptés dans les logs HTTP). Le log Début de la consultation médicale IA ouvre la trace, puis le cas clinique démo amorce l’historique du groupe. L’étudiant observe :

  1. La rotation round-robin des agents — les logs Selected agent at index 0/1/2 montrent la selection_strategy par défaut passer le bâton : Docteur_Humain → IA_Medicale → Pharmacien → Docteur_Humain → IA_Medicale (5 tours d’agents).
  2. L’auto function calling en action — dès son premier tour, le médecin invoque 2 plugins en parallèle (doctor-ask_followup_questions + medical-check_symptom_severity) : FunctionChoiceBehavior.Auto() s’exécute réellement, ce n’est pas une description.
  3. La terminaison par limite d’échanges — 1 message patient + 5 réponses d’agents = 6 messages : MedicalTerminationStrategy met fin à la consultation (Consultation terminée.). La détection d’un diagnostic final par mot-clé n’a pas eu lieu : c’est l’exercice laissé à l’étudiant (DiagnosticTerminationStrategy, stub ci-dessus).

Cette trace rejouable est ce qui rend le notebook pédagogique : l’étudiant peut relire la séquence async pour comprendre le mécanisme de sélection d’agent, plutôt que de lire une boîte noire.

Ce que nous avons construit

Ce cas d’usage illustre plusieurs concepts avances de Semantic Kernel :

Concept Implementation
Agents specialises Trois rôles distincts (Medecin, IA Medicale, Pharmacien) avec instructions système dediees
Plugins @kernel_function Chaque agent dispose d’un plugin avec des fonctions spécifiques (questions de suivi, evaluation de gravite, recommandations medicamenteuses)
AgentGroupChat Orchestration multi-agent avec passage de baton automatique entre les trois participants
Stratégie de terminaison MedicalTerminationStrategy arrete le dialogue après 6 echanges pour eviter les boucles infinies
FunctionChoiceBehavior.Auto() L’agent IA Medicale peut appeler automatiquement les plugins du kernel pour enrichir ses reponses

Points cles a retenir

  1. Separation des responsabilites : chaque agent a un rôle précis, ses propres instructions et ses propres outils. Cette modularite facilite le debug et l’evolution du système.

  2. Plugins comme outils : les @kernel_function exposent des capacites que les agents peuvent invoquer via FunctionChoiceBehavior.Auto(). Le LLM decide quand et quel plugin appeler en fonction du contexte.

  3. Stratégies de contrôle : la TerminationStrategy est indispensable dans un AgentGroupChat pour eviter que les agents ne dialoguent indefiniment. D’autres stratégies existent (sélection d’agent, filtre de messages).

Pour aller plus loin

  • Ajouter un agent Patient simule qui decrit des symptomes de maniere realiste
  • Implementer un historique de consultations persistant (stockage dans une base de données)
  • Utiliser un modèle de vecteurs pour rechercher des cas medicaux similaires dans une base de connaissances
  • Ajouter des garde-fous ethiques (refus de diagnostic pour certaines pathologies, orientation systématique vers un professionnel de sante)
Retour au sommet