Un copilote RAG peut retrouver de la documentation pertinente, résumer un texte de politique et aider un utilisateur à formuler une question. Il ne doit pas être l’autorité finale pour des totaux, des dates, des décisions d’éligibilité ou d’autres résultats où une valeur incorrecte change ce qu’un utilisateur peut faire.
La limite pratique est simple : utiliser la recherche documentaire pour les preuves explicatives, utiliser le modèle de langage pour interpréter les demandes et coordonner les opérations autorisées, et utiliser des services applicatifs déterministes pour le travail exact. Ce modèle de calculs déterministes pour copilote RAG conserve l’expérience conversationnelle tout en plaçant les résultats critiques pour l’activité dans du code au comportement défini et testé.
Pour les équipes Java, l’appel d’outils (tool calling) constitue le point de connexion. Spring AI et LangChain4j documentent des façons d’exposer des fonctions Java comme outils. Le modèle peut sélectionner une opération autorisée et fournir des arguments structurés, pendant que le service JVM calcule le résultat. La documentation des outils de Spring AI et le guide des outils de LangChain4j décrivent ces approches.
Utiliser le RAG pour les preuves et les outils pour les résultats exacts
La génération augmentée par récupération (RAG) fournit un contexte externe à un modèle. C’est utile lorsqu’un utilisateur demande ce que dit une politique, quelles conditions produit s’appliquent, ou où trouver la documentation pertinente. La récupération ne transforme pas un modèle de langage en évaluateur déterministe de la politique.
Les modèles de langage génèrent du texte de manière probabiliste. Une réponse peut sembler complète même si elle contient une erreur arithmétique, applique la mauvaise borne de date, ou omet une condition d’une règle. Les recherches sur le raisonnement mathématique identifient des modes de défaillance dans les tâches quantitatives à plusieurs étapes, y compris des erreurs qui peuvent s’accumuler tout au long d’une chaîne de raisonnement. Pour une application, une réponse plausible n’est pas la même chose qu’un résultat vérifié. Les recherches sur les défaillances de raisonnement mathématique des LLM apportent un éclairage utile sur cette limite.
Attribuez chaque partie d’une demande au composant le mieux placé pour la traiter :
- Récupération RAG : Trouve le texte de politique pertinent, la documentation, les notes de compte ou les spécifications produit.
- LLM : Interprète la demande, réclame les informations manquantes, sélectionne une opération autorisée et explique les résultats renvoyés.
- Service déterministe : Calcule des valeurs, évalue des règles versionnées et renvoie des données faisant autorité depuis les systèmes approuvés.
- Interface React : Distingue les sources explicatives des résultats d’opération vérifiés et présente clairement les états en attente, terminés ou indisponibles.
Il s’agit d’une répartition des responsabilités, pas d’un rejet de l’IA. Cela permet à un copilote de rester utile sans traiter le texte généré comme un moteur de règles.
Décider quelles demandes doivent passer par un service déterministe
Ne routez pas uniquement parce qu’une demande contient un nombre. « Pourquoi le prix de mon renouvellement a-t-il changé ? » peut nécessiter à la fois un calcul de devis déterministe et un contexte contractuel ou produit récupéré. Une meilleure question de routage est : une réponse incorrecte affecterait-elle de l’argent, une échéance, un droit, la conformité, un enregistrement ou une décision opérationnelle ?
| Caractéristique de la demande | Chemin principal | Exemple | Contenu de la réponse |
|---|---|---|---|
| Nécessite une explication de la documentation ou d’une politique | RAG plus LLM | « Que couvre la politique de voyage ? » | Explication avec références récupérées |
| Nécessite un calcul arithmétique ou une conversion | Outil de calcul déterministe | « Quel est le montant proratisé de la facture ? » | Résultat vérifié et entrées pertinentes |
| Dépend de dates, de fuseaux horaires ou de calendriers | Service de dates déterministe | « Quand se termine cet essai ? » | Date résolue et contexte applicable |
| Évalue une règle ou un droit | Service de règles versionné | « Ce client est-il éligible à un remboursement ? » | Décision et version de la règle |
| Combine explication et résultat spécifique | Récupérer, calculer, puis expliquer | « Pourquoi cette réclamation n’est-elle pas payable ? » | Résultat vérifié accompagné d’une explication |
| Demande un changement conséquent | Outil autorisé avec confirmation | « Appliquer la remise à cette commande. » | Changement proposé avant exécution |
Cela ne nécessite pas un microservice distinct pour chaque calcul. Une petite application peut commencer par un bean Spring ciblé ou un module de domaine. L’exigence importante est une implémentation faisant autorité en dehors du texte généré par le modèle, avec des entrées définies, une sémantique stable et des tests adaptés.
Concevoir les outils comme des contrats étroits et versionnés
Un outil est une interface entre un planificateur non déterministe et du code de domaine déterministe. Traitez-le comme un contrat produit, pas comme une méthode générique que le modèle peut invoquer.
Utiliser des types d’entrée explicites
Une opération financière doit recevoir des valeurs monétaires et une devise plutôt qu’un nombre décimal ambigu. Une opération de date doit recevoir une date locale ou un horodatage ISO-8601, un fuseau horaire nommé lorsque nécessaire, et tout contexte de calendrier pertinent. Une opération d’éligibilité doit recevoir des identifiants stables ou des faits de domaine validés, plutôt qu’un résumé libre produit par le modèle.
Le guide d’appel de fonctions d’OpenAI décrit la définition d’outils avec JSON Schema afin qu’un modèle puisse produire des arguments structurés pour des fonctions externes. La limite du schéma est précieuse car l’application peut valider la forme des arguments avant d’exécuter l’opération métier. La documentation d’appel de fonctions d’OpenAI couvre ce modèle d’appel d’outil structuré.
Renvoyer des métadonnées avec le résultat
Une valeur scalaire seule est rarement suffisante. Un résultat de devis peut inclure le total, la devise, la version de calcul et l’heure effective. Un résultat de règles peut inclure une décision, une version de jeu de règles, des faits contributifs adaptés à l’appelant, et un code de raison sûr pour l’utilisateur.
Renvoyez ces métadonnées depuis le service faisant autorité. Ne laissez pas le modèle les reconstruire à partir d’un nombre brut. L’interface peut alors afficher directement un résultat structuré, et les journaux opérationnels peuvent conserver le résultat versionné utilisé dans la conversation.
Séparer la sortie sûre pour l’utilisateur des diagnostics internes
Les résultats d’outils peuvent contenir des données sensibles ou des détails d’implémentation qui ne doivent pas entrer dans le contexte du modèle ou dans l’interface utilisateur. Définissez quels champs sont sûrs pour l’explication, lesquels sont sûrs pour l’affichage, et lesquels sont réservés aux journaux de service ou aux opérateurs autorisés. La mise en forme de la réponse relève de la limite du service et du modèle d’autorisation, pas uniquement d’une invite.
Versionner la sémantique des règles
La logique métier évolue. Inclure une version de calcul ou de politique dans le résultat donne aux équipes un moyen d’identifier quelle sémantique a produit une réponse. Cela facilite aussi les investigations lorsqu’un utilisateur voit un résultat différent après une mise à jour de règle.
Un modèle Java : le service de domaine d’abord, l’adaptateur d’outil ensuite
Commencez par du code de domaine appelable et testable de façon indépendante. Gardez l’adaptateur exposé au LLM léger : il accepte une requête validée, délègue au code de domaine, et sérialise une réponse approuvée.
Spring AI documente des méthodes d’outil annotées et des options basées sur des callbacks pour connecter des fonctions applicatives à des modèles de chat. LangChain4j documente également des outils annotés et des intégrations Java typées. Spring AI et LangChain4j sont des références d’implémentation, pas des substituts à la limite de domaine.
public record ProrationRequest(
BigDecimal monthlyPrice,
LocalDate serviceStart,
LocalDate serviceEnd,
ZoneId billingZone,
String currency
) {}
public record ProrationResult(
BigDecimal total,
String currency,
String calculationVersion,
LocalDate effectiveStart,
LocalDate effectiveEnd
) {}
@Service
public class ProrationService {
public ProrationResult calculate(ProrationRequest request) {
// La logique de domaine est implémentée et testée indépendamment du modèle.
throw new UnsupportedOperationException("Implement domain calculation");
}
}
L’exemple ne prescrit délibérément pas de formule de proratisation. Les produits diffèrent quant aux définitions de période, à l’inclusivité, à l’arrondi, aux avoirs et au traitement fiscal. Ces décisions relèvent de la logique de domaine approuvée et des cas de test, pas d’une description d’outil ou d’une invite.
L’adaptateur ne doit exposer que l’opération dont le copilote a besoin. Sa description doit indiquer ce que l’outil calcule, quelles entrées il requiert, et ce qu’il exclut. Évitez un outil générique qui donne accès à des opérations métier sans rapport.
Contraindre l’orchestration et l’exécution du modèle
Un modèle peut demander un appel d’outil, mais c’est le code applicatif qui doit le valider et l’exécuter. La documentation d’utilisation d’outils d’Anthropic décrit de même des outils définis par schéma qui sont exécutés par le code applicatif côté client. La documentation d’utilisation d’outils d’Anthropic illustre la même limite : une sortie de modèle structurée n’est pas une permission d’exécuter un travail sans restriction.
Appliquez des contrôles pratiques au moment de l’exécution :
- Autorisez l’utilisateur pour l’opération sous-jacente, pas seulement pour l’accès au chat.
- Validez les arguments de l’outil comme une entrée non fiable.
- Établissez une liste blanche des noms d’outils, identifiants, valeurs d’énumération et portées d’action.
- Renvoyez un état d’indisponibilité explicite lorsqu’un système faisant autorité ne peut pas vérifier un résultat.
- Enregistrez le nom de l’outil, les entrées normalisées, la version du résultat, l’identité de la requête et les informations de corrélation avec une minimisation appropriée des données.
- Exigez une confirmation avant les mutations ou autres actions conséquentes.
Le modèle peut toujours expliquer un résultat renvoyé de façon conversationnelle. Cependant, le montant, la décision, la date et la version affichés comme faisant autorité doivent provenir de la réponse déterministe plutôt que du texte généré par le modèle.
Construire l’expérience React autour de la provenance et du statut
Un backend fiable peut tout de même dérouter les utilisateurs si l’interface affiche les passages récupérés, l’explication générée et les résultats vérifiés comme du texte de chat indifférencié. Modélisez la conversation comme des événements typés plutôt que comme un flux markdown unique.
Les éléments de message utiles incluent les citations récupérées, une demande d’outil en attente, un résultat de calcul terminé, une demande d’approbation et une réponse narrative. Cela permet à React de rendre chaque élément avec un composant et un état appropriés.
Le Vercel AI SDK documente les définitions d’outils, l’exécution d’outils et les modèles d’intégration d’interface pour les applications de chat, y compris les états d’invocation d’outil. Sa documentation sur les outils est utile pour comprendre les implications sur l’interface de l’appel d’outils : l’exécution a des états au-delà du simple texte de l’assistant.
Afficher les résultats vérifiés comme une interface structurée
Placez un composant de résultat compact près de la réponse de l’assistant. Il peut afficher le libellé de l’opération, le résultat vérifié, les entrées pertinentes, la date effective ou le fuseau horaire le cas échéant, et la version de calcul. N’utilisez une formulation telle que « Calcul vérifié » que lorsqu’un service déterministe a réellement renvoyé le résultat.
Représenter honnêtement les vérifications en attente et échouées
Pendant qu’une opération s’exécute, montrez que le système vérifie une règle ou calcule une valeur. Lorsqu’une source faisant autorité est indisponible, indiquez que le résultat n’a pas pu être vérifié. Ne présentez pas de texte généré comme un substitut à une réponse vérifiée.
Garder distinctes les sources explicatives et opérationnelles
Un document de politique récupéré peut expliquer la règle, tandis qu’un service de règles tranche un cas particulier. Affichez les citations de documents avec le texte explicatif, et les métadonnées de version de règle avec la décision. Cette distinction aide les utilisateurs à comprendre à la fois la base de l’explication et la source du résultat exact.
Liste de contrôle de mise en œuvre
- Identifiez les intentions du copilote impliquant de l’argent, des dates, des permissions, l’éligibilité, la conformité ou un état opérationnel.
- Nommez le service faisant autorité et le responsable pour chaque intention.
- Définissez des contrats de requête et de réponse typés, incluant les unités, devises, fuseaux horaires et versions de règles le cas échéant.
- Testez le comportement de domaine pour les conditions limites, les entrées invalides et les règles historiques applicables.
- N’exposez que les opérations nécessaires via des adaptateurs d’outil ciblés.
- Validez et autorisez chaque appel d’outil au moment de son exécution.
- Renvoyez des métadonnées lisibles par machine à côté des champs explicatifs sûrs pour l’utilisateur.
- Affichez les sorties de récupération et déterministes comme des éléments de message React distincts.
- Ajoutez une confirmation pour les mutations et conservez un enregistrement d’audit adapté pour les actions exécutées.
- Testez les échecs d’outils, les arguments malformés, les données obsolètes et les permissions refusées comme des flux de chat.
FAQ
Un système RAG peut-il calculer des totaux simples ?
Il peut générer une réponse, mais un total qui compte pour les utilisateurs ou les opérations doit être calculé par du code déterministe. Un service fournit des entrées définies, un comportement reproductible et une couverture de tests.
Avons-nous besoin d’un microservice pour chaque calcul ?
Non. La limite peut commencer comme un module bien identifié ou un bean Spring. Extrayez un service séparé lorsque la propriété, le déploiement, la mise à l’échelle ou les besoins de réutilisation le justifient.
Le LLM doit-il recevoir le résultat complet de l’outil ?
Ne fournissez que les champs nécessaires à l’explication. Décidez séparément ce que l’interface React peut afficher, et gardez les diagnostics sensibles ou les données non pertinentes hors du contexte du modèle.
Comment l’interface peut-elle montrer qu’une réponse a été vérifiée ?
Associez des métadonnées structurées de résultat d’outil à l’événement de chat, incluant l’opération, le résultat et la version de la logique. Affichez-les dans un composant dédié plutôt que de compter sur le texte du modèle pour affirmer la vérification.
Sources
- Documentation de référence de l’appel d’outils de Spring AI
- Guide des outils et de l’appel de fonctions de LangChain4j
- Guide d’appel de fonctions d’OpenAI
- Documentation des outils et de l’appel d’outils du Vercel AI SDK
- Grands modèles de langage et défaillances de raisonnement mathématique
- Documentation d’utilisation d’outils d’Anthropic
Note éditoriale : l’IA a contribué à la recherche et à la rédaction. Les sources ont été sélectionnées pour vérification.
Full-Stack Developer & Solutions Architect · Casablanca, Morocco
8+ years building Java/Spring Boot/Angular enterprise solutions. Former Senior Software Engineer at NTT Data and Satec. Authorized Google Workspace and Microsoft 365 Partner for Morocco.