La sortie de l'agent IA ajoute des caractères de saut de ligne \n lors de l'utilisation du modèle Mistral Large 4

Décrivez le problème/l’erreur/la question

Le nœud AI Agent génère un caractère de saut de ligne \n toutes les quelques jetons dans la sortie, lors de l’utilisation du modèle Mistral Large 4. Cela cause un rendu incorrect du markdown résultant. Les journaux d’exécution d’AI Agent affichent une sortie correcte du LLM, mais la sortie du nœud AI Agent contient des sauts de ligne parasites. Jusqu’à présent, j’ai trouvé ce problème uniquement avec ce modèle Mistral spécifique, les autres modèles fonctionnent correctement.

Veuillez partager votre workflow

Partagez la sortie renvoyée par le dernier nœud

[

{

“output”:
“Voici\n ce qu’il\n y a dans votre ensemble de données\n :\n\n—\n\n\n## Vue d’ensemble de l’ensemble de données\n\n\nEnsemble de données : \nCASUSER.CARS\n | Lignes\n : 428 |\n Colonnes : \n15\n\nCeci est\n un ensemble de données classique de caractéristiques automobiles\n — une ligne par\n modèle de voiture (année modèle 2\n004\n),\n avec le fabricant, le\n type\n de voiture, et ses\n spécifications\n mécaniques\n /\nprix\n .\n\n### Variables\n\n\n| Variable |\n Type | Manquant\n | Manquant\n % | Statut |\n\n|:\n--------\n-|:-----\n|\n--------:|----------\n:\n|:------\n|\n\n| Marque | Texte\n | 0 |\n 0\n% | :white_check_mark: (\n38 marques,\n p. ex. Toyota\n 28, Chevrolet\n 27,\n BMW 20\n ) |\n| Modèle\n | Texte | \n0 | 0\n% |\n :warning: \n425 distincts —\n essentiellement\n un identifiant unique\n par ligne |\n|\n Type | Texte |\n 0 | \n0% | :white_check_mark:\n \n6 catégories:\n Berline 262\n (\n61%), SUV\n 60\n , Voiture de sport\n 49, Break 30,\n Camionnette 24,\n Hybride 3\n |\n| Origine |\n Texte | 0\n | 0%\n | :white_check_mark: 3\n catégories\n : Asie 158\n (\n37\n%), États-Unis 147\n (34\n%), Europe 123\n (29\n%) |\n| Transmission\n | Texte |\n 0 | \n0% | :white_check_mark:\n 3 catégories:\n Avant 226\n (53\n%), Arrière 110\n (26\n%), Intégral 92\n (21\n%) |\n| PDSF | \nTexte\n :warning: | 0\n | 0%\n | stocké comme\n \"21\n 739 $\" — nécessite\n un nettoyage pour l’utiliser\n comme nombre |\n\n| Facture | \nTexte :warning:\n | 0 |\n 0% |\n stocké comme \"\n 20\n 189 $\n\" — même problème\n |\n| TailleMoteur\n | Nombre | \n0 | 0\n% | :white_check_mark: litres\n ,\n 1,3\n –\n 8,3\n , moyenne\n 3\n ,2 |\n|\n Cylindres |\n Nombre | \n2 | \n0,47%\n |\n :warning: seule variable\n avec des valeurs manquantes\n |\n| Puissance\n | Nombre | \n0 | 0\n% | :white_check_mark: \n73–500\n ch, moyenne 216 |\n| L100km_Ville\n | Nombre | 0\n | 0%\n | :white_check_mark: 10\n –60\n , moyenne 20\n ,\n 1 |\n| L100km_Route\n | Nombre | \n0 | 0\n% | :white_check_mark: \n12–66,\n moyenne 26,\n 8 |\n| Poids\n | Nombre | \n0 | 0\n% | :white_check_mark: kg\n , 840–3\n 265, moyenne\n 1 623\n |\n| Empattement\n | Nombre | \n0 | 0\n% | :white_check_mark: cm\n , 226\n –366\n , moyenne 274\n |\n| Longueur |\n Nombre | 0\n | 0%\n | :white_check_mark: cm\n , 363\n –604\n , moyenne 472\n |\n\n### Points à\n surveiller\n\n\n- PDSF et Facture sont\n du texte\n , pas des nombres\n — ils sont stockés\n avec\n $\n et des virgules\n (p. ex.\n \"36\n 945 $\").\n Toute\n analyse utilisant\n le prix\n doit\n d’abord éliminer\n ceux-ci.\n Nettoyée,\n PDSF varie\n de 10 280 $\n à\n 192 465 $\n (moyenne ≈\n 32 775 $\n ) et Facture\n de\n 9 875 $–\n 173 560 $\n (moyenne ≈ 30 015 $).\n\n- Cylindres a 2\n valeurs manquantes (\n0,47%)\n — négligeable, mais\n bon à savoir\n avant\n tout test\n .\n- Modèle\n a\n 425 valeurs distinctes\n sur 428 lignes\n ** — c’est\n effectivement\n un identifiant unique, pas\n une variable de regroupement\n .\n Ne l’utilisez\n pas comme\n catégorie dans\n un test.\n -\n Cylindres\n (\n 7 valeurs distinctes) est\n une colonne numérique qui se comporte vraiment comme une\n catégorie —\n 3, \n4, 5\n , 6,\n 8, \n10, 12\n .\n Traitez\n -la comme\n un libellé de groupe\n si\n vous comparez\n à travers\n celle-ci, pas comme\n une mesure continue\n .\n\n### Exemples de\n lignes\n\n| Marque\n | Modèle | Type\n | Origine | Transmission\n | PDSF\n | TailleMoteur\n | Cyl\n |\n Puissance\n | L100km_V\n | L100km_R\n | Poids |\n|:\n—|:—|:\n—|:—|:\n—|:—|\n—:|—:|\n—:|—:|\n—:|—:\n|\n| Acura\n | MDX |\n SUV | Asie |\n Intégral | 36\n 945 $ | \n3,5 |\n 6 | \n265 | 17\n | 23 |\n 2018 |\n\n| Acura |\n RSX Type S\n 2 portes |\n Berline | Asie\n | Avant | $\n 23 820 |\n 2,0\n | 4 |\n 200 | \n24 | 31\n | 1 260 |\n\n| Acura\n | TSX \n4 portes | Berline\n | Asie | Avant\n | 26\n 990 $ | 2\n ,4 | \n4 | 200\n | 22 |\n 29 | \n 1 465 |\n\n—\n\n\nEn\n résumé :** \n428 modèles de voitures\n avec\n marque\n , type de véhicule, origine,\n transmission, prix\n (en texte\n ), et huit spécifications\n numériques. Les\n données sont très\n propres — seulement\n 2 cellules manquantes\n dans\n l’ensemble du tableau\n — et la principale\n difficulté pratique est que les\n deux colonnes de prix doivent avoir leurs\n $/\nvirgules supprimées avant\n que vous\n puissiez les utiliser pour les calculs\n .\n\nSi vous\n voulez aller plus loin\n — p. ex. \nla puissance diffère-t-elle selon\n le type de voiture,\n ou selon l’origine ?\n — c’est une\n question d’hypothèse, et vous\n sélectionneriez\n le bloc **Tester l’hypothèse\n **. Voulez-vous que je configure cela ?”

}
]

Informations sur votre configuration n8n

  • Version n8n :
    2.45.6
  • Base de données (par défaut : SQLite) : Postgres
  • Paramètre n8n EXECUTIONS_PROCESS (par défaut : own, main) : par défaut
  • Exécuter n8n via (Docker, npm, n8n cloud, application de bureau) : Docker
  • Système d’exploitation : Linux

Salut @J_Bom, en attente d’une réponse ? Voici quelques ressources qui pourraient t’aider :

Ressources suggérées

Automatiquement associées à ta question.

Documentation :

Forum :

@ihortom, @Akif, @GollyJer - vous avez déjà aidé sur des problèmes similaires, pouvez-vous jeter un œil ?

Suggéré automatiquement par le bot communautaire de n8n. C’est un projet pilote - n’hésitez pas à nous faire part de vos commentaires ici.

Salut @J_Bom, le motif dans votre résultat est un bon indice. Le \n supplémentaire apparaît tous les quelques tokens et divise les mots (« Here\n’s », « 2\n004 », « MS\nRP »), donc on dirait qu’il est inséré aux limites des chunks lorsque les morceaux de la réponse sont joints, et non quelque chose que le modèle écrit. Cela expliquerait aussi pourquoi le journal d’exécution du modèle semble propre tandis que la sortie du nœud Agent ne l’est pas, et pourquoi seul ce modèle est affecté (les modèles Mistral plus récents peuvent retourner le contenu du message sous forme de liste de parties au lieu d’une seule chaîne, et si ces parties sont jointes avec une nouvelle ligne, vous obtenez exactement ceci).

Choses à essayer :

  1. Si votre nœud Agent dispose de l’option streaming, désactivez-la et réexécutez-la. Si les sauts de ligne disparaissent, cela confirme que c’est la jonction des chunks.
  2. Contournement qui contourne généralement le problème : l’API de Mistral est compatible avec OpenAI, vous pouvez donc utiliser le nœud OpenAI Chat Model avec une nouvelle credential OpenAI dont l’URL de base est https://api.mistral.ai/v1 et votre clé API Mistral, puis tapez le nom du modèle. Branchez-le dans le même Agent et comparez.
  3. N’essayez pas de le nettoyer avec un remplacement ensuite. Vous ne pouvez pas distinguer le mauvais \n des vrais dans votre tableau markdown, vous casseriez donc la mise en forme de toute façon.

Si 1 ou 2 résout le problème, c’est worth d’ouvrir un problème GitHub avec votre version n8n, l’ID de modèle exact et la sortie avant/après, puisque le nœud Mistral Cloud Chat Model devrait gérer cette forme de réponse.

J’obtiens le même résultat avec Streaming activé ou Streaming désactivé.

L’option 2 a fonctionné, la solution de contournement avec un nœud OpenAI Model au lieu d’un nœud Mistral Model.

Peux-tu ajouter le problème Github ? Toutes les informations sont dans ce message

Heureux que la route du nœud OpenAI fonctionne. Le fait que le streaming ne fasse aucune différence réduit les possibilités : le journal du modèle est propre, et le même modèle se comporte via le point de terminaison compatible OpenAI, donc cela pointe probablement vers la gestion des réponses du nœud Mistral Chat Model plutôt que vers le modèle ou l’Agent.

Mieux vaut que tu signales toi-même le problème, puisque tu as la reproduction et peux répondre aux questions de suivi. Recherche d’abord les problèmes existants pour « Mistral » au cas où il serait déjà signalé. Inclus : n8n 2.45.6 (Docker, Postgres), l’ID exact du modèle, que le streaming activé et désactivé échouent tous les deux, un workflow minimal (nœud Mistral vers l’Agent, pas d’outils, invite courte), un petit échantillon de la mauvaise sortie, et que le nœud OpenAI avec l’URL de base Mistral fonctionne bien.

Si les logs semblent propres mais que la sortie du nœud est cassée, il est probable que des chunks de streaming soient joints avec des sauts de ligne. Essayez de désactiver le streaming dans les options de l’agent, ou ajoutez un nœud Code après celui-ci qui supprime les \n parasites entre les tokens. Essayez aussi le nœud du modèle Mistral sur une route API différente pour voir si c’est le fournisseur.

Le streaming n’en est pas la cause. J_Bom a déjà désactivé le streaming et a obtenu le même résultat, et le journal d’exécution est propre, donc la nouvelle ligne est ajoutée pendant que le nœud Mistral assemble la réponse, et non par le modèle. Au lieu de corriger l’invite, normalise après : un nœud Code qui supprime une nouvelle ligne quand elle se trouve entre deux caractères non-espace, en conservant le moteur de rendu markdown en aval.

C’est la même limite dont parle l’argument de décompilation cette semaine : correct quand une personne lit la sortie, peu fiable quand quelque chose en aval en a besoin octet par octet.