MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1
Profils de prompts
Nommer et versionner les instructions sans leur attribuer le choix du modèle ou le droit d’écrire.
Objectifs
- Séparer consignes et données
- Profils adaptés à la tâche
- Versionner et comparer sans garantie de sécurité
Une instruction modifiée change le comportement
Deux environnements utilisent le même programme mais pas la même consigne : l’un demande des hypothèses détaillées, l’autre trois phrases. Sans nom et version, il devient difficile d’expliquer la différence après coup. EP014 proposait de traiter le prompt comme un artefact applicatif. Demo390 rend ce choix visible avec deux profils d’instructions versionnés, tandis que la connexion reste configurée séparément.
Charger un contrat d’instructions identifié
appsettings.json est un tableau de profils Id, Version et Instructions, lu avec File.ReadAllTextAsync et JsonSerializer depuis AppContext.BaseDirectory. Le programme exige au moins un profil, des valeurs non blanches et des Id uniques avec comparaison ordinale. MAF_INSTRUCTION_PROFILE sélectionne support-cautious par défaut ou support-brief explicitement ; un nom inconnu échoue. L’ancien récit de chargement par IConfiguration et de menu comparant constante/fichier est corrigé : ce programme désérialise le tableau et s’exécute une fois.
var profiles = JsonSerializer.Deserialize<InstructionProfile[]>(
await File.ReadAllTextAsync(Path.Combine(AppContext.BaseDirectory, "appsettings.json")),
JsonSerializerOptions.Web) ?? throw new InvalidDataException("Missing instruction profiles.");
if (profiles.Length == 0 || profiles.Any(p => string.IsNullOrWhiteSpace(p.Id)
|| string.IsNullOrWhiteSpace(p.Version) || string.IsNullOrWhiteSpace(p.Instructions))
|| profiles.Select(p => p.Id).Distinct(StringComparer.Ordinal).Count() != profiles.Length)
throw new InvalidDataException("Instruction profiles must have unique IDs, versions, and instructions.");
string selected = global::Maf.DemoConnection.DemoConfiguration.GetSetting("MAF_INSTRUCTION_PROFILE") ?? "support-cautious";
var profile = profiles.SingleOrDefault(p => p.Id == selected)
?? throw new InvalidDataException("Unknown instruction profile.");
Console.WriteLine($"Instructions: {profile.Id}/{profile.Version}. Effective connection provider: {settings.ChatProvider}.");
Console.WriteLine("The instruction profile does not select a model; AI settings select the connection.");
Deux sélections indépendantes
support-cautious demande de distinguer faits et hypothèses, de demander les erreurs manquantes et d’éviter les actions destructrices. support-brief demande au plus trois phrases et la prochaine étape de diagnostic. Ces consignes ne modifient ni ChatProvider ni le nom du modèle ; MemoryDemo.Load et la configuration commune règlent la connexion. Changer un profil d’instructions ne doit pas être annoncé comme changement de client modèle. Aucun embedding n’est nécessaire.
- Configuration AI → fournisseur, endpoint et modèle → client
- appsettings.json + MAF_INSTRUCTION_PROFILE → Id/Version/Instructions → agent
- Même demande de support → réponse → usage fournisseur si disponible
- Une seule exécution ; aucune session persistée ni écriture métier
var agent = chat.AsAIAgent(name: profile.Id, instructions: profile.Instructions);
var response = await agent.RunAsync("Billing is blocked for three customers. No precise error is available. Suggest the next support action.", cancellationToken: stop.Token);
Console.WriteLine(response.Text);
MemoryDemo.PrintUsage(response);
Versionner pour comparer, sans promettre la qualité
Le programme affiche Id/Version et fournisseur effectif. Pour une comparaison reproductible, noter aussi révision des fichiers, modèle, options et demande fixe. L’affichage ne constitue pas un journal durable et ne permet pas à lui seul de retrouver toute configuration passée. Modifier le fichier copié près de l’exécutable change les instructions au prochain lancement ; un build peut recopier le fichier source. Travailler sur une copie de distribution et versionner les modifications plutôt que réécrire le profil de référence.
Une version identifie une intention, pas un résultat de qualité. Le programme ne valide pas la limite de trois phrases ni une règle sémantique « sans destruction » après génération. Aucun outil n’est exposé ici ; aucun refus d’outil ne découle du seul texte. Pour une session ou un workflow persistant, changer les instructions exige une politique de compatibilité ; Demo390 ne sérialise pas sa session et ne réalise pas cette migration. La décision durable du lot précédent reste un protocole séparé.
Changer le profil, puis provoquer un refus de configuration
$env:MAF_INSTRUCTION_PROFILE = "support-cautious"dotnet run --project demos/Demo390_PromptProfiles/Demo390.App.csproj -c Release --no-build$env:MAF_INSTRUCTION_PROFILE = "support-brief"dotnet run --project demos/Demo390_PromptProfiles/Demo390.App.csproj -c Release --no-buildComparer la même demande et relever l’en-tête Instructions ainsi que le fournisseur ; conserver les réponses comme observations datées, sans promettre un style constant. Tester ensuite unknown-profile : attendre Unknown instruction profile avant l’appel de génération. Rétablir ou retirer la variable de cette session PowerShell avec la commande ci-dessous. Le refus de profil inconnu peut être vérifié sans réponse du modèle ; les deux comparaisons valides demandent le chat.
Remove-Item Env:MAF_INSTRUCTION_PROFILE -ErrorAction SilentlyContinueUn profil n’est pas une autorisation
Le catalogue et les permissions ne changent pas parce qu’un profil dit « prudent » ou « administrateur ». Le programme n’a ni hot reload, ni registre distant de prompts, ni contrat de migration, ni évaluation automatique des deux styles. Il affiche une identité de profil et utilise les instructions choisies. L’usage fournisseur peut être indisponible ; il ne faut ni l’inventer ni en déduire un coût monétaire.
