L'équipe d'ingénierie d'Aptible AI a passé les environ 4 derniers mois à créer un agent IA pour aider notre équipe SRE à enquêter et à résoudre les problèmes de production. Parce que nous avons discuté avec de nombreux premiers testeurs et partenaires de conception qui étaient en train de créer leur propre agent à des fins similaires, nous avons décidé de rédiger un guide qui explique ce que nous avons fait avec notre propre agent et comment vous pouvez le créer. un vous-même.
Dans le didacticiel suivant, étape par étape, nous allons vous montrer comment :
Mais d’abord, quelques considérations et conseils de pro.
? Considérations : Si vous n’avez pas besoin de construire quelque chose de nouveau, vous ne devriez pas le faire. Il y en a tellement. beaucoup. outils sur le marché. Et en fonction de votre cas d'utilisation spécifique, vous pourrez peut-être en trouver un qui vous convient.
La motivation d'Aptible pour rechercher et développer éventuellement notre propre réponse aux incidents était que nous luttions contre les silos de connaissances et avions tendance à nous appuyer sur trois ou quatre experts en la matière chaque fois que nous rencontrions un problème avec un système particulier.
Nous avons donc commencé avec un outil open source appelé Danswer pour améliorer la récupération d'informations (similaire à son concurrent commercial populaire, Glean). Il se connectait directement à Slack et pouvait récupérer des réponses aux questions en langage naturel à partir de diverses sources d'informations. Le problème était qu'il était limité aux données indexées uniquement (c'est-à-dire uniquement nos documents et notre historique de discussion).
⚒️ Ce que nous avons construit : Ce dont nous avions besoin, c'était d'un outil capable de s'intégrer à tous nos autres systèmes (pas seulement à Docs et Slack). Nous devions récupérer les journaux et les métriques, l'état de santé des applications et générer des rapports et des post-mortems une fois nos incidents terminés. Nous avons donc conçu un agent IA qui repose essentiellement sur une série d’intégrations qui vous permettent de vous connecter à des données en temps réel et indexées. Nous en reparlerons plus tard !
? Conseil de pro : Avant de décider de créer votre propre produit, examinez ce qui est déjà disponible. Un bon point de départ pourrait être le crowdsourcing d'idées sur Reddit (consultez ce fil de discussion, par exemple) ou consultez certains des outils open source disponibles (voici un bon point de départ dans github si vous recherchez spécifiquement des outils de réponse aux incidents) ). Il existe également une longue liste d’agents IA open source que vous pourriez commencer à utiliser dès demain.
? Considérations : Comme mentionné ci-dessus, la plus grande considération ici est la suivante : à quel type d'informations votre agent doit-il avoir accès ? Vous pourriez peut-être simplement l'intégrer à des fournisseurs tiers via une API, mais si vous avez besoin que l'intégration soit plus spécifique à vos besoins, vous devrez alors être plus attentif au fonctionnement de vos intégrations.
En réfléchissant attentivement à ce que vous devrez intégrer avant de commencer à construire, vous vous épargnerez des maux de tête plus tard. Avez-vous besoin que votre agent puisse exécuter des scripts personnalisés pour interroger vos bases de données ? Avez-vous besoin d'une récupération en temps réel des journaux et des métriques, et comment allez-vous concevoir l'agent pour récupérer ces informations ? Est-ce que cela renverra le lien vers la source ? Renverra-t-il un morceau de lignes de journaux que vous devrez encore parcourir manuellement, ou sera-t-il capable de déduire où peut se trouver l'anomalie ?
⚒️ Ce que nous avons construit : À la base, Aptible AI repose sur une série d'intégrations. Une intégration est plus qu'une simple connexion à un fournisseur tiers, c'est aussi un ensemble de configurations propres à la façon dont notre équipe utilise ce fournisseur. Par exemple, Aptible AI prend en charge plusieurs intégrations pour le même fournisseur, car nous pouvons souhaiter utiliser ce fournisseur de différentes manières. Différentes équipes utilisent Datadog différemment et se soucient de différentes métriques ou utilisent différentes balises, afin que chaque équipe puisse utiliser l'intégration du même outil comme elle en a besoin.
Aptible AI prend en charge une gamme d'outils SRE courants, notamment :
La mise en œuvre réelle de ces intégrations s'inscrit dans l'une des trois catégories de personnalisation :
Pour commencer, vous disposez d'une intégration de base qui ne nécessite aucune personnalisation (PagerDuty en est un exemple). Puisqu'il s'agit simplement d'extraire des données de PagerDuty et de les ajouter au contexte de l'IA, chaque équipe qui exploite l'intégration de PagerDuty l'utilise de la même manière.
Ensuite, nous avons des intégrations plus personnalisables (comme l'exemple Datadog précédent) qui sont construites sur une intégration générique d'InfluxDB mais personnalisées en fonction des cas d'utilisation spécifiques de recherche de métriques de conteneur et de recherche d'activité de redémarrage.
Enfin, il existe des outils entièrement personnalisés qui n'auraient probablement aucun sens pour quiconque en dehors d'Aptible (un exemple ici serait notre intégration qui obtient des conteneurs pour une application). Ceux-ci sont entièrement spécifiques à la façon dont nous gérons notre infrastructure et peuvent être implémentés soit par une interface PubSub légère, soit par un proxy « sécurisé » basé sur Websocket.
? Conseil de pro :Moins, c'est plus ! Si vous donnez au modèle trop d’outils parmi lesquels choisir, il peut commencer à choisir des outils incorrects et se confondre. Plus d'informations à ce sujet dans la section suivante
? Considérations : Voici le problème avec les modèles… de nouveaux apparaissent chaque jour, et il y a plusieurs considérations à garder à l'esprit lors du choix d'un modèle (principalement liées à vos cas d'utilisation spécifiques). Faut-il s'auto-héberger ? Avez-vous besoin que votre agent soit conversationnel ou basé sur des tâches, ou les deux ? Réalisera-t-il des tâches simples ou complexes ? Avez-vous besoin de performances en temps réel ?
Nous n'avons pas besoin de passer en revue tous les modèles qui existent puisque ce contenu est déjà partout (si vous voulez une analyse approfondie, c'est une excellente ressource), mais nous pouvons passer en revue les décisions que nous avons prises. à faire lors de la création d'Aptible AI et des options que nous avons envisagées.
C’est un processus délicat car on ne peut pas vraiment éviter les compromis. Si vous avez besoin de votre agent pour effectuer des tâches complexes, vous devrez alors sacrifier un peu la rapidité et le coût.
La taille, la capacité et l'architecture du modèle dépendent fortement du fait que les tâches nécessitent une classification simple ou un raisonnement et une interaction très complexes. S'il est simple, un modèle plus petit et léger comme un arbre de décision, une forêt aléatoire ou un simple réseau neuronal suffirait. S'il est plus complexe, vous pouvez envisager un modèle plus puissant comme GPT-4, BERT ou une architecture similaire basée sur un transformateur.
Si vous choisissez de vous auto-héberger pour éviter les problèmes de sécurité, vous devrez probablement sacrifier les fonctionnalités, car votre version auto-hébergée sera à la traîne par rapport aux options hébergées.
Si vous avez besoin que votre agent soit formé sur des connaissances spécifiques à un domaine, vous devrez alors organiser ou créer vos propres ensembles de données pour les affiner. Voyez si vous pouvez utiliser un modèle pré-entraîné qui a déjà été formé sur de grands ensembles de données pour éviter le problème de qualité des données (bien que cela puisse être impossible en fonction des données auxquelles votre agent doit avoir accès).
⚒️ Ce que nous avons construit : Nous utilisons actuellement GPT-4o pour Aptible AI car nous pensons qu'il est le plus susceptible de nous donner des réponses de la plus haute qualité. Cependant, nous reconnaissons que les clients utilisant Aptible AI peuvent souhaiter utiliser leurs propres modèles (y compris des modèles auto-hébergés). C’est pourquoi nous gardons cela à l’esprit pendant que nous construisons.
? Conseil de pro : Votre agent sera aussi intelligent que les informations que vous lui donnez. Les LLM ont besoin d'aide pour comprendre comment et quand utiliser les informations que vous leur fournissez, et si vous ne leur donnez pas d'instructions sur la façon d'interpréter les informations, ils inventeront simplement quelque chose. Dépensez de réels efforts dès le départ pour organiser les informations que vous fournissez à votre LLM !
? Considérations : Vous pourriez être tenté de récupérer autant de données que possible (documentation, conversations Slack, référentiels de code, suivi des problèmes, etc.), de tout jeter dans une application RAG*, * et posez-lui des questions. Mais d’après notre expérience, il y aura presque toujours trop de bruit pour que cela soit utile. C'est là qu'intervient l'ingénierie rapide.
Nous y avons déjà fait allusion, mais l'ingénierie des invites est ici une pièce essentielle du puzzle (pour un bon aperçu des techniques d'invite, consultez ceci). Plus votre ingénierie rapide est bonne, meilleur sera votre agent.
Pour le contexte, en voici quelques-uns que nous avons pris en compte (au fil du temps) lors de la création d'Aptible AI :
Invite Zero-shot : c'est ce que font la plupart des gens lorsqu'ils parlent à ChatGPT ; ils lui posent simplement une question, puis ils obtiennent une réponse. Si la réponse est mauvaise, alors ils posent simplement la question différemment.
Invites en quelques étapes : c'est ce que font les personnes légèrement plus expérimentées lorsqu'elles parlent à ChatGPT ; ils lui posent une question et incluent des exemples du résultat qu'ils souhaitent. Vous pouvez utiliser des invites à zéro et/ou à quelques tirs pour des tâches très simples que le modèle sous-jacent sait déjà effectuer.
Retrieval Augmented Generation (RAG) : il s'agit d'une technique qui permet au modèle de récupérer du contexte supplémentaire et de l'utiliser pour répondre à la question. Ceci est particulièrement utile pour la recherche de documents basée sur l'IA (voir aussi : Glean et Danswer).
ReAct : cette technique permet à un agent de générer des « pensées » et de prendre des « actions » de manière itérative pour résoudre un problème, très similaire au raisonnement humain. ReAct est idéal pour les problèmes moyennement complexes, comme la navigation dans les références dans la documentation et les outils en temps réel pour rédiger une réponse.
Une chose importante à garder à l’esprit est que vous pouvez mélanger et assortir ces techniques (nous aborderons ensuite l’approche multi-agents). Voici ce que nous avons fait…
⚒️ Ce que nous avons construit : Parce qu'Aptible AI a une structure multi-agents (nous en parlerons plus tard), nous avons implémenté un mélange de ReAct et de RAG en fonction de la complexité de la tâche/question.
Ainsi, lorsque vous posez une question à l'IA, nous transmettons toutes les intégrations (avec des instructions sur la façon de les utiliser) à l'IA. L’IA prend ensuite des décisions sur les outils à appeler en fonction des informations dont elle dispose. Après chaque appel d'intégration, l'IA a la possibilité de décider qu'elle dispose de suffisamment d'informations pour fournir une réponse, ou de décider que des intégrations supplémentaires sont pertinentes et pourraient potentiellement fournir des informations supplémentaires.
Tout au long du processus, nous essayons d'aider l'IA à prendre de meilleures décisions quant aux intégrations à exploiter via quelques mécanismes différents :
Ingénierie approfondie des invites pour les intégrations, pour s'assurer qu'il est vraiment clair quand et comment utiliser chaque intégration, ainsi que comment interpréter le résultat.
Nous avons construit un système d'auto-évaluation qui demande à l'IA d'évaluer elle-même la valeur de la réponse d'une intégration. Même lorsque l’IA prend une décision stupide en appelant une intégration (ou fournit de mauvaises entrées), elle est généralement capable de le reconnaître après coup si vous lui demandez d’évaluer elle-même si le résultat de l’intégration a été utile ou non. Nous pouvons ensuite utiliser cela pour influencer la mesure dans laquelle un résultat spécifique est pris en compte dans une réponse. Nous pouvons également empêcher l’IA de continuer si elle prend constamment de mauvaises décisions.
Nous avons implémenté Naïve Bayes sur la base de notre expérience passée. Par exemple, si la plupart du temps vous appelez l’intégration A puis B, et que cela donne des résultats utiles, il est probablement utile de continuer à le faire. L'agent peut également utiliser des éléments tels que la comparaison avec des incidents similaires précédents pour affiner davantage les intégrations utiles et à quel moment, dans des scénarios spécifiques.
? Conseil de pro : Pour éviter les réponses absurdes qui semblent correctes mais qui ne le sont pas, assurez-vous de prendre du recul et de réfléchir à la provenance généralement de vos informations les plus utiles pour les problèmes que vous essayez de résoudre avec l'IA. – puis concevez votre agent sur cette base.
? Considérations : Les approches multi-agents sont de plus en plus populaires, mais elles peuvent être compliquées et potentiellement inutiles selon votre cas d'utilisation. Il peut être très utile d'avoir une équipe d'agents travaillant ensemble avec différentes techniques pour résoudre des problèmes complexes.
Par exemple, si vous posez à votre bot une question dans Slack qui n'a rien à voir avec votre infrastructure spécifique (peut-être voulez-vous simplement savoir qui a remporté les World Series en 1995), vous pourriez avoir un agent construit sur zéro tir. invitant à agir simplement comme un ChatGPT intégré à votre Slack (ou partout où vous l'avez).
Mais si votre question ou votre besoin est complexe, il serait utile d'avoir une équipe d'agents qui agissent essentiellement comme votre petite équipe de recherche, rassemblant et analysant des données provenant de sources disparates de manière intelligente.
⚒️ Ce que nous avons construit : Aptible AI utilise une approche multi-agents, en commençant par un agent courtier qui détermine le type de question ou de tâche à traiter.
? Conseil de pro : Il est plus facile de refactoriser vers une approche multi-agents que d'en sortir ! Assurez-vous donc d'en avoir besoin avant de commencer à créer votre agent de cette façon.
? Considérations : Voici un sujet qui revient souvent lorsque nous discutons avec les premiers utilisateurs d'Aptible AI. La plupart des équipes d'ingénierie doivent finalement faire face à leur équipe de sécurité lorsqu'il s'agit de mettre en œuvre de nouveaux outils, et il est essentiel de garantir la sécurité des données (surtout si vous travaillez dans un secteur hautement réglementé). La première chose que vous devez faire est donc de connaître la politique de sécurité de l’IA de votre organisation, puis vous pouvez prendre certaines mesures pour vous protéger contre d’éventuelles fuites de données ou menaces externes.
⚒️ Ce que nous avons construit : Pour commencer, nous utilisons un modèle qui ne s'entraîne pas sur nos données. Nous faisons encore beaucoup de découvertes sur ce dont les clients ont besoin en matière de sécurité, qu'il s'agisse d'auto-hébergement ou autre ! Restez à l'écoute.
? Conseil de pro : Soyez prudent avec les données auxquelles vous donnez accès à votre IA ou que vous incluez dans les invites, surtout si ces données ne doivent pas être partagées avec l'utilisateur final ! Si vous devez inclure des données imprévisibles telles que des journaux, envisagez d'utiliser un outil comme Nightfall pour vous assurer que ce qui est transmis au LLM et aux utilisateurs finaux est nettoyé
Oh, et bien sûr, il doit être utilisable !
? Considérations : Comment comptez-vous utiliser votre agent ? Est-il nécessaire d'avoir une interface utilisateur ? Sera-t-il utilisé dans toute l’organisation ?
Vous n'avez probablement pas besoin de passer du temps à réinventer la roue en ce qui concerne l'UX autour de votre bot. Des frameworks tels que Chainlit, Gradio et Streamlit vous offrent des outils prêts à l'emploi pour créer des interfaces utilisateur et/ou s'intégrer à vos autres outils de flux de travail comme Slack. Utilisez l'un de ces outils pour commencer afin de pouvoir vous concentrer sur l'obtention de bonnes réponses de votre agent !
⚒️ Ce que nous avons construit : Parce que notre agent a été conçu spécifiquement pour la réponse aux incidents – et parce que nous gérons les incidents au sein de Slack – nous utilisons principalement Slack comme interface utilisateur. Il a cependant ses limites, c'est pourquoi nous faisons de notre mieux pour les contourner (c'est-à-dire qu'au lieu de montrer que l'agent répond en imitant la saisie comme on le voit dans ChatGPT, le bot réagit à la question dans Slack avec un emoji ?). Nous avons également conçu une interface utilisateur Web pour la configuration, le reporting, l'audit et l'analyse.
? Conseil de pro : Assurez-vous de garder votre code LLM aussi découplé que possible, afin de pouvoir facilement le refactoriser dans un autre UX si le besoin s'en fait sentir.
Bon, passons du discours théorique sur les modèles, les techniques et les frameworks ! Il est temps de mettre la main à la pâte et de commencer à créer votre propre agent.
Avant de nous plonger dans le terrier sans fin de la création d'IA, nous allons nous préparer au succès en mettant en place Chainlit, un framework populaire pour créer des interfaces d'assistant conversationnel.
Chainlit fournit un ensemble d'éléments de base avisés pour modéliser les interactions conversationnelles - comme les fils de discussion, les messages et les étapes - ainsi qu'une interface utilisateur de type ChatGPT pour interagir avec le LLM.
Il propose également des intégrations prêtes à l'emploi avec des outils de chat populaires comme Slack et Teams, ainsi que des bibliothèques pour s'interfacer avec des outils populaires comme React et FastAPI, afin que vous puissiez l'intégrer dans une application plus grande, si vous le souhaitez. .
En bref : Chainlit va éliminer une grande partie de l'échafaudage et du travail fastidieux pour nous afin que nous puissions nous concentrer sur le développement de notre assistant IA et obtenir les commentaires de nos utilisateurs, au lieu de jouer avec l'interface utilisateur et la configuration.
À la fin de cet atelier, vous disposerez d'une application Chainlit fonctionnelle qui fera simplement écho à ce que vous dites. Nous passerons à l’intégration de l’IA dans le prochain article.
Avant de commencer, vous devrez vous préparer à quelques éléments :
Une fois que vous êtes configuré, continuez.
Tout d'abord, configurez votre projet et ajoutez chainlit comme dépendance :
mkdir roger cd roger poetry init --no-interaction poetry add chainlit
Ensuite, créez un fichier app.py à la racine de votre projet avec le contenu suivant :
import chainlit as cl @cl.on_message async def handle_message(message: cl.Message) -> None: # Echo the message back to the user. await cl.Message( content=f"Received: {message.content}", ).send()
Le code ci-dessus enregistre la fonction handle_message auprès de Chainlit, de sorte que chaque fois qu'un message est reçu, cette fonction s'exécutera.
Pour le moment, notre fonction renvoie simplement le message à l'utilisateur, préfixé par « Reçu : ».
Enfin, lancez-le ! Vous pouvez utiliser --watch pour recharger à chaud votre code lorsque vous apportez des modifications.
poetry run chainlit run app.py --watch
L'exécution de cette commande démarrera votre application Chainlit et ouvrira votre navigateur sur son interface utilisateur, où vous pourrez envoyer un message et obtenir une réponse :
Avec notre application Chainlit échafaudée, nous pouvons la connecter à un LLM afin de pouvoir lui parler et obtenir une réponse humaine.
Nous utiliserons le modèle gpt-4o hébergé d'OpenAI pour plus de simplicité, mais l'utilisation d'un autre fournisseur n'est qu'une question de syntaxe.
À la fin de cet article, vous serez en mesure d'inviter le modèle gpt-4o et d'obtenir une réponse, similaire à la façon dont vous interagiriez avec ChatGPT. Nous veillerons également à ce que le bot maintienne le contexte de la conversation afin que vous puissiez poser des questions de suivi.
Avant de commencer, vous aurez besoin de :
Un compte OpenAI et une clé API
Tout d’abord, nous allons configurer un client API pour s’interfacer avec les API d’OpenAI. Ajoutez le code suivant en haut de votre app.py :
mkdir roger cd roger poetry init --no-interaction poetry add chainlit
Ensuite, nous devrons mettre à jour notre fonction handle_message pour envoyer le message de l'utilisateur à OpenAI et obtenir une réponse au lieu de simplement le renvoyer. Remplacez votre fonction handle_message par celle-ci :
import chainlit as cl @cl.on_message async def handle_message(message: cl.Message) -> None: # Echo the message back to the user. await cl.Message( content=f"Received: {message.content}", ).send()
Maintenant, si vous exécutez votre application (ou si vous l'avez laissée fonctionner avec l'indicateur --watch), vous pourrez poser une question et obtenir une réponse.
Si vous avez joué un peu et posé des questions complémentaires, vous avez peut-être remarqué que le bot ne « se souvient » de rien de ce dont vous avez parlé. Par exemple :
Cela se produit parce que chaque fois que nous envoyons un message, nous envoyons uniquement ce message au LLM, qui n'a aucune notion de « conversation » par défaut.
Pour guérir cette amnésie, nous devrons envoyer tous les messages de la conversation à chaque fois que nous en enverrons un nouveau.
Chainlit nous facilite la tâche en fournissant un assistant cl.chat_context.to_openai(), qui nous donne tous les messages échangés jusqu'à présent, de manière pratique dans le format attendu par OpenAI (et la plupart des autres fournisseurs).
Mettez à jour votre fonction handle_message pour ajouter les messages historiques avant le dernier :
poetry run chainlit run app.py --watch
Nous pouvons désormais poser des questions complémentaires !
Après avoir suivi les premières étapes de la première partie, vous avez peut-être remarqué que lorsque vous posez des questions qui nécessitent une longue réponse, il y a un délai avant de voir quoi que ce soit.
Cela peut donner lieu à une mauvaise expérience utilisateur (surtout plus tard dans la partie 3, lorsque nous commençons à ajouter des appels d'outils de longue durée), alors réparons cela.
À la fin de cette étape, vous pourrez voir votre bot « taper » en temps réel, similaire à ChatGPT.
Pour obtenir des mises à jour des messages en temps réel, nous devons mettre à jour notre implémentation pour utiliser un « flux ». Fondamentalement, chaque fois que nous recevons un message, nous répondrons immédiatement avec un message vide, démarrerons un flux avec le LLM et mettrons à jour notre message vide chaque fois que nous recevrons un nouveau morceau de réponse du flux.
Cela peut paraître compliqué, mais c’est étonnamment simple ! Mettez à jour votre fonction handle_message comme suit :
mkdir roger cd roger poetry init --no-interaction poetry add chainlit
?? Alors, voici le code complet jusqu'à présent :
import chainlit as cl @cl.on_message async def handle_message(message: cl.Message) -> None: # Echo the message back to the user. await cl.Message( content=f"Received: {message.content}", ).send()
Désormais, lorsque vous posez une question, vous devriez voir votre bot « taper » en temps réel !
À ce stade, nous avons construit un clone léger de ChatGPT. C'est cool et tout, mais ce que nous voulons vraiment, c'est un assistant qui nous aidera à effectuer une tâche spécifique : dans ce cas, nous voulons qu'il résolve les incidents, comme le ferait un SRE.
Pour y arriver, nous allons commencer par refactoriser notre agent dans un assistant OpenAI personnalisé, qui nous donnera le contrôle de l'invite système (ainsi que la possibilité de donner au LLM l'accès à des outils tels que la recherche de fichiers et les appels de fonctions, que nous aborderons plus tard).
À la fin de cette étape, vous aurez refactorisé votre bot en un « Assistant » personnalisé et personnalisé son invite système pour lui donner sa propre « personnalité ». Votre code utilisera également un « thread », qui conservera les messages à l'aide de l'API OpenAI, au lieu d'avoir à envoyer tous les messages à chaque fois que nous en recevrons un nouveau.
Créer un assistant est simple : il suffit d'appeler l'API OpenAI Assistants. Cependant, nous ne souhaitons le faire qu'une seule fois au démarrage de l'application, nous ne pouvons donc pas mettre cet appel API dans la fonction handle_message.
Au lieu de cela, nous utiliserons un autre hook Chainlit — on_chat_start, qui ne s'exécutera qu'une seule fois au premier démarrage de l'application — pour configurer notre assistant.
Ajoutez ceci à votre app.py :
poetry run chainlit run app.py --watch
Remarque : il est techniquement possible de donner à l'assistant une invite système personnalisée en fournissant un message initial de type système dans l'historique des messages dans handle_message. Cependant, nous sommes en train de refactoriser un assistant avec des instructions personnalisées, car il débloque plusieurs autres fonctionnalités que nous utiliserons dans un avenir proche.
Maintenant que nous avons un assistant et un fil de discussion pour la conversation, nous pouvons refactoriser notre gestionnaire de messages pour les utiliser.
Tout d'abord, nous avons besoin d'un AssistantEventHandler pour indiquer à notre nouvel objet Assistant comment gérer les différents événements qui se produisent au cours d'une conversation.
Ajoutez ce qui suit à votre app.py :
import os from openai import AsyncOpenAI ## # Settings # try: OPENAI_API_KEY = os.environ["OPENAI_API_KEY"] except KeyError as ex: raise LookupError(f"Missing required environment variable: {ex}") client = AsyncOpenAI(api_key=OPENAI_API_KEY) # ...
Maintenant, il ne nous reste plus qu'à ajuster notre fonction handle_message pour utiliser tous nos nouveaux jouets ! Mettez à jour votre fonction handle_message comme suit :
# ... @cl.on_message async def handle_message(message: cl.Message) -> None: # Retrieve the response from the LLM response = await client.chat.completions.create( messages=[{"content": message.content, "role": "user"}], model="gpt-4o", ) await cl.Message(content=response.choices[0].message.content).send()
?? Voici maintenant le code complet jusqu'à présent :
mkdir roger cd roger poetry init --no-interaction poetry add chainlit
Maintenant que nous utilisons les assistants et les fils de discussion, nous pouvons commencer à personnaliser le comportement. Pour commencer, nous donnerons à notre Assistant l'accès à une partie de notre documentation interne afin qu'il puisse fournir des réponses plus adaptées à notre cas d'utilisation.
À la fin de cette section, vous aurez donné à votre bot la possibilité de rechercher une collection de fichiers (par exemple, vos runbooks SRE et autres documentations internes) lorsqu'il répond aux invites.
Pour plus de simplicité, nous implémenterons ceci sous la forme d'un dossier rempli de fichiers qui seront téléchargés dans un magasin de vecteurs et fournis à notre assistant.
La première chose que nous devons faire est de créer un magasin de vecteurs et de le fournir à notre assistant.
Tout d'abord, mettez à jour le début de notre fonction handle_chat_start pour inclure les éléments suivants :
import chainlit as cl @cl.on_message async def handle_message(message: cl.Message) -> None: # Echo the message back to the user. await cl.Message( content=f"Received: {message.content}", ).send()
Ensuite, mettez à jour l'appel à client.beta.assistants.update() pour donner à l'assistant l'accès au magasin de vecteurs et activer l'outil file_search.
poetry run chainlit run app.py --watch
Enfin, nous devrons télécharger notre documentation à laquelle nous souhaitons que notre assistant fasse référence lorsqu'il répond aux invites.
Tout d’abord, nous devrons créer un dossier dans lequel nous placerons nos documents :
import os from openai import AsyncOpenAI ## # Settings # try: OPENAI_API_KEY = os.environ["OPENAI_API_KEY"] except KeyError as ex: raise LookupError(f"Missing required environment variable: {ex}") client = AsyncOpenAI(api_key=OPENAI_API_KEY) # ...
Ensuite, nous rassemblerons notre documentation et la placerons dans ce dossier. À des fins de test, j'ai ajouté le faux document suivant à mon dossier :
# ... @cl.on_message async def handle_message(message: cl.Message) -> None: # Retrieve the response from the LLM response = await client.chat.completions.create( messages=[{"content": message.content, "role": "user"}], model="gpt-4o", ) await cl.Message(content=response.choices[0].message.content).send()
Enfin, nous mettrons à jour notre fonction handle_chat_start pour télécharger automatiquement nos documents dans le magasin de vecteurs que nous avons créé précédemment. Ajoutez le code suivant juste après l'endroit où nous créons le magasin de vecteurs :
# ... @cl.on_message async def handle_message(message: cl.Message) -> None: # Retrieve the response from the LLM response = await client.chat.completions.create( messages=[ # Prepend all previous messages to maintain the conversation. *cl.chat_context.to_openai(), {"content": message.content, "role": "user"} ], model="gpt-4o", ) await cl.Message(content=response.choices[0].message.content).send()
ℹ️ Remarque : Pour l'instant, nous ne prendrons en charge que les fichiers .md, mais OpenAI prend en charge de nombreux types de fichiers différents, alors n'hésitez pas à mettre à jour le modèle global selon ce qui est logique pour votre cas d'utilisation !
Cela téléchargera automatiquement tous les fichiers du dossier ./docs et les ajoutera à notre magasin de vecteurs.
La recherche de fichiers peut parfois prendre un certain temps, en particulier pour les ensembles de données plus volumineux. Dans ces cas-là, vous souhaiterez probablement informer l’utilisateur de ce qui se passe afin qu’il ne soit pas frustré.
Heureusement, Chainlit facilite cela en fournissant une classe Step que nous pouvons utiliser pour indiquer à l'utilisateur que quelque chose se passe en arrière-plan. Nous pouvons utiliser la classe Step en conjonction avec le MessageEventHandler que nous avons construit précédemment et ajouter un indicateur à chaque fois qu'un outil est appelé.
Ajoutez ce qui suit à votre MessageEventHandler :
# ... @cl.on_message async def handle_message(message: cl.Message) -> None: # Send an empty initial message that we can update with a streaming # response. message = cl.Message(content="") await message.send() # Stream the response from the LLM stream = await client.chat.completions.create( messages=[ # Prepend all previous messages to maintain the conversation. *cl.chat_context.to_openai(), {"content": message.content, "role": "user"} ], model="gpt-4o", stream=True, ) # Update the existing (initially-empty) message with new content # from each "chunk" in the stream. async for chunk in stream: if token := chunk.choices[0].delta.content: await message.stream_token(token) # Send a final update to let the message know it's complete. await message.update()
Maintenant que vous avez téléchargé une partie de votre propre documentation, essayez de poser des questions plus spécifiques à votre cas d'utilisation et voyez ce que vous obtenez !
Pour notre scénario de test, il a correctement référencé notre runbook lorsqu'on lui a posé des questions sur l'utilisation élevée du processeur sur une base de données client :
?? Pour référence, voici le code complet jusqu'à présent :
mkdir roger cd roger poetry init --no-interaction poetry add chainlit
Notre agent est désormais capable de récupérer des données de notre documentation interne organisée, ce qui est utile si vous disposez d'une bonne documentation. Cependant, la gestion des incidents passe souvent beaucoup de temps à enquêter sur des éléments qui ne sont pas couverts par la documentation : analyse des alertes, lecture des journaux, interprétation des métriques, etc.
Pour ces choses, nous souhaitons donner à notre assistant la possibilité d'appeler des API externes - et plus largement, d'exécuter des fonctions que nous définissons - afin qu'il puisse recueillir plus de contexte selon les besoins.
Pour ce faire, nous exploiterons les capacités « d'appel de fonction » du modèle pour exécuter les fonctions que nous définissons.
À la fin de cette section, vous aurez donné à votre bot la possibilité d'utiliser un outil externe (un faux outil PagerDuty) pour récupérer des informations lorsqu'il répond aux invites.
Tout d'abord, ajoutons une nouvelle fonction à notre app.py appelée get_pagerduty_alert_details.
import chainlit as cl @cl.on_message async def handle_message(message: cl.Message) -> None: # Echo the message back to the user. await cl.Message( content=f"Received: {message.content}", ).send()
Ensuite, nous devons indiquer au LLM comment appeler notre outil. OpenAI attend les définitions d'outils au format JSONSchema.
Mettez à jour votre appel à client.beta.assistants.update() pour inclure une nouvelle définition d'outil après l'outil file_search que nous avons déjà.
poetry run chainlit run app.py --watch
Notre MessageEventHandler gère actuellement les événements de message aller-retour, mais l'appel d'outils nécessite une gestion particulière.
En répondant à votre invite, le LLM décidera quels outils il doit appeler (le cas échéant) et vous renverra une ou plusieurs définitions « d'appel d'outil » dans la charge utile de réponse, et vous indiquera que la réponse « nécessite une action ». Afin d'exécuter réellement la fonction, nous devons gérer ces réponses « nécessite une action ».
Nous pouvons le faire en mettant à jour notre classe MessageEventHandler pour implémenter la méthode on_event, ainsi qu'une nouvelle méthode handle_requires_action pour exécuter notre appel de fonction et ajouter le résultat au thread en cours d'exécution :
import os from openai import AsyncOpenAI ## # Settings # try: OPENAI_API_KEY = os.environ["OPENAI_API_KEY"] except KeyError as ex: raise LookupError(f"Missing required environment variable: {ex}") client = AsyncOpenAI(api_key=OPENAI_API_KEY) # ...
Il peut souvent être utile de rappeler au LLM qu'il doit tenter d'utiliser les outils que vous avez fournis, le cas échéant. Ajoutez une ligne comme celle-ci à la fin de votre invite :
Utilisez les outils fournis pour recueillir du contexte supplémentaire sur l'incident, le cas échéant.
Une fois vos outils configurés, vous pourrez inclure des liens PagerDuty dans vos invites, et le LLM utilisera ces outils pour recueillir le contexte avant de répondre :
?? Voici le code complet :
mkdir roger cd roger poetry init --no-interaction poetry add chainlit
Vous êtes maintenant prêt à créer un agent IA utile pour votre équipe SRE ! Si vous avez des questions sur tout ce que nous avons abordé dans ce guide, n'hésitez pas à nous contacter et nous serons heureux de vous aider. En attendant, s'il manque quelque chose ou toute autre chose liée à l'agent IA que vous aimeriez apprendre, faites-le nous savoir !
Si vous êtes curieux d'essayer Aptible AI par vous-même plutôt que de créer votre propre agent, vous pouvez visiter www.aptible.ai pour vous inscrire.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!