paint-brush
Lancez sans effort les API LangChain avec l'intégration LangServe et MinIOpar@minio
5,582 lectures
5,582 lectures

Lancez sans effort les API LangChain avec l'intégration LangServe et MinIO

par MinIO15m2024/06/21
Read on Terminal Reader

Trop long; Pour lire

Dans cet article, nous nous appuierons sur les concepts abordés dans « Autonomiser les agents Langchain avec MinIO ». Nous allons étendre les fonctionnalités d'un agent MinIO pour encapsuler des capacités supplémentaires et déployer l'agent personnalisé via LangServe. Nous approfondirons le processus d'intégration de MinIO avec LangChain dans les étapes suivantes.
featured image - Lancez sans effort les API LangChain avec l'intégration LangServe et MinIO
MinIO HackerNoon profile picture
0-item
1-item
2-item


Notre voyage à travers le monde innovant de LangChain a dévoilé ses capacités substantielles à transformer la gestion des données et les fonctionnalités des applications.


Au cours de discussions précédentes, nous avons abordé plusieurs sujets tout en explorant les capacités complexes de LangChain. Dans cet article, nous nous appuierons sur les concepts abordés dans « Autonomiser les agents Langchain avec MinIO » à mesure que nous étendons les fonctionnalités d'un agent MinIO pour encapsuler des capacités supplémentaires et déployer l'agent personnalisé via LangServe.


  • Récupération innovante du bucket S3 avec LangChain : Présentation pas à pas de l'exploitation des chargeurs S3 de LangChain et de l'API OpenAI pour créer des agents d'IA conversationnels personnalisés, établissant ainsi une approche rationalisée pour la gestion des données.


  • Autonomiser les agents LangChain avec MinIO : Une plongée approfondie dans l'exploitation de MinIO, montrant comment LangChain, associé au GPT d'OpenAI, ouvre de nouvelles frontières dans le traitement des données d'IA et de ML.


Forts de ces connaissances, nous nous concentrons désormais sur LangServe , un outil essentiel dans la transition des applications LangChain du développement au déploiement, simplifiant le processus de lancement d'API prêtes pour la production.

LangServe : simplifier le déploiement des applications LangChain

LangServe constitue la pierre angulaire pour les développeurs, éliminant les complexités traditionnellement associées au déploiement d'API. Il permet une transition en douceur des applications LangChain intégrées à MinIO vers des API accessibles et conviviales. Voici comment LangServe redéfinit le paysage du déploiement :


  • Création automatique de points de terminaison d'API : les capacités d'automatisation de LangServe génèrent sans effort les points de terminaison d'API nécessaires, rationalisant les efforts de développement et réduisant considérablement le temps de déploiement.


  • Génération et validation de schémas : grâce à son inférence de schéma intelligente, LangServe garantit que les API offrent des interfaces bien définies, facilitant une intégration plus facile et une expérience utilisateur transparente.


  • Configuration des points de terminaison personnalisable : LangServe offre une variété de points de terminaison pour répondre à divers besoins d'applications, des opérations synchrones aux mises à jour en temps réel, offrant aux développeurs une flexibilité inégalée.


  • Intégration sans effort : Peut-être sa fonctionnalité la plus intéressante, la capacité de LangServe à s'intégrer de manière transparente au code LangChain existant signifie que les développeurs peuvent exploiter leur base de code et leur expertise actuelles sans modifications significatives.


Documentation générée automatiquement de l'application LangServe/FastAPI /docs

Plonger profondément dans LangChain et Langserve

Nous approfondirons le processus d'intégration de MinIO avec LangChain dans les étapes suivantes.


  1. Créez une application LangChain avec langchain-cli .
  2. Développez un agent LangChain personnalisé dans un fichier agent.py .
  3. Implémentez notre agent dans server.py pour qu'il s'exécute en tant qu'API LangServe.

Utilisation de l'interface de ligne de commande de LangChain pour créer des applications

Le déploiement d'applications LangChain avec LangServe apporte un parcours d'intégration transparent, comblant le fossé entre les fonctionnalités complexes d'IA et l'exposition aux API RESTful, permettant aux développeurs d'exploiter efficacement l'ensemble des capacités de LangChain, établissant ainsi une nouvelle norme pour le déploiement d'applications intelligentes dans le paysage numérique en évolution rapide d'aujourd'hui. .


LangChain offre une méthode pratique et simple pour créer des applications à l'aide de leur langchain-cli bibliothèque qui peut être installé avec pip . Ce package fournit une interface qui permet aux utilisateurs de créer facilement de nouvelles applications en utilisant les applications existantes. Modèles d'applications LangChain ou créer le vôtre.


Remarque : Tous les fichiers nécessaires se trouvent dans le référentiel MinIO « blog-assets » sous le répertoire nommé «minio-langserve-deployment ».


Pour créer une nouvelle application LangChain, nous pouvons commencer avec les commandes suivantes pour créer un environnement virtuel et installer le package langchain-cli :


 mkdir minio-langserve-testing cd minio-Langserve-testing python -m venv .myenv source .myenv/bin/activate pip install langchain-cli 


Capture d'écran de langchain-cli


Afin de créer une nouvelle application à l'aide langchain-cli nous pouvons taper langchain dans notre terminal, la commande suivante est écrite pour créer un nouveau répertoire d'application nommé my-app .


 langchain app new my-app


L'application langchain créée avec les commandes ci-dessus fait tout le gros du travail en créant un environnement cohérent pour le développement. La structure d’une nouvelle application LangChain prête à l’emploi ressemble à ceci :


 ./my-app ├── Dockerfile ├── README.md ├── app │ ├── __init__.py │ └── server.py ⇐ (This is where we will import our agent into) ├── packages ⇐ (This directory is where we will write our agent) │ └── README.md └── pyproject.toml


Dans les étapes suivantes, nous apporterons des modifications à l'application LangChain nouvellement créée ( my-app ) en écrivant un nouveau fichier nommé packages/agent.py et en apportant des modifications à app/server.py .


Voici les fichiers dont nous parlerons dans cet article :


  • my-app/packages/agent.py
  • my-app/app/server.py

Développement d'un agent LangChain MinIO à déployer avec LangServe

Pour illustrer le déploiement d'un agent LangChain intégré à MinIO avec LangServe, nous commencerons par enregistrer le code de la chaîne d'agents dans agent.py .


Tout d'abord, initialisons un minio_client qui se connecte au serveur public "play.min.io:443". Ce fichier finira par appeler agent_executor de LangChain, nous permettant de le transmettre au wrapper add_route de LangServe.


Remarque : Lecture de la publication précédente " Outil MinIO Langchain " fournira des informations précieuses sur le développement conjoint avec LangChain et MinIO. Nous suivrons une approche conceptuelle similaire mais avec une logique d'outil MinIO supplémentaire.


Pour commencer, ouvrez le fichier agent.py à l'aide d'un éditeur de texte :


 sudo nano packages/agent.py


Au début du fichier, importez les packages nécessaires, tels que os , io , minio et ChatOpenAI :


 import os import io from minio import Minio from minio.error import S3Error from langchain_openai import ChatOpenAI os.environ["OPENAI_API_KEY"] = "<<Your API Key Here>>" # Initialize llm llm = ChatOpenAI(api_key=os.environ["OPENAI_API_KEY"]) # Initialize MinIO client minio_client = Minio('play.min.io:443', access_key='minioadmin', secret_key='minioadmin', secure=True)


Dans cet extrait de code, nous importons les packages requis et initialisons le modèle de langage ChatOpenAI avec la clé API OpenAI stockée dans la variable d'environnement OPENAI_API_KEY . Nous initialisons également le minio_client en fournissant les détails de connexion nécessaires au serveur public "play.min.io".


Ensuite, définissons le bucket MinIO et créons-le s'il n'existe pas :


 # This variable will check if bucket exists bucket_name = "test" try: # Check if bucket exists if not minio_client.bucket_exists(bucket_name): # Create the bucket because it does not exist minio_client.make_bucket(bucket_name) print(f"Bucket '{bucket_name}' created successfully.") else: print(f"Bucket '{bucket_name}' already exists.") except S3Error as err: print(f"Error encountered: {err}")


Ici, nous définissons le bucket_name comme "test" et vérifions s'il existe déjà à l'aide de la méthode minio_client.bucket_exists() . Si le bucket n'existe pas, nous le créons en utilisant minio_client.make_bucket() . Si le bucket existe déjà, nous imprimons un message l'indiquant. Nous incluons également la gestion des erreurs à l'aide d'un bloc try-sauf pour détecter et imprimer toute S3Error pouvant survenir pendant le processus.


Une fois la configuration de base en place, nous pouvons maintenant procéder à la définition des fonctions de l'outil MinIO et à la création de l'exécuteur d'agent, que nous aborderons dans les prochaines étapes.

Utilisation du décorateur de fonctions de LangChain pour les outils d'agent

Langchain et Langserve proposent tous deux une approche similaire pour encapsuler la logique et les fonctionnalités, ce qui permet de les intégrer de manière transparente dans la logique des agents et de la chaîne. Ceci est réalisé grâce à l'utilisation du décorateur @tool avec une docstring détaillée à l'intérieur de la fonction définie, qui marque les fonctions comme des composants réutilisables pouvant être utilisés et interprétés par l'agent IA.


Examinons de plus près les exemples de code fournis :


 from langchain.agents import tool @tool def upload_file_to_minio(bucket_name: str, object_name: str, data_bytes: bytes): """ Uploads a file to MinIO. Parameters: bucket_name (str): The name of the bucket. object_name (str): The name of the object to create in the bucket. data_bytes (bytes): The raw bytes of the file to upload. """ data_stream = io.BytesIO(data_bytes) minio_client.put_object(bucket_name, object_name, data_stream, length=len(data_bytes)) return f"File {object_name} uploaded successfully to bucket {bucket_name}."


La fonction upload_file_to_minio est décorée de @tool , indiquant qu'il s'agit d'un composant réutilisable. Il prend en compte les paramètres nécessaires pour télécharger un fichier dans un compartiment MinIO, tels que le nom du compartiment, le nom de l'objet et les octets bruts du fichier. La fonction utilise minio_client pour effectuer l'opération de téléchargement de fichier et renvoie un message de réussite une fois terminée.


 @tool def download_file_from_minio(file_info): """ Custom function to download a file from MinIO. Expects file_info dict with 'bucket_name', 'object_name', and 'save_path' keys. 'save_path' should be the local path where the file will be saved. """ bucket_name = file_info['bucket_name'] object_name = file_info['object_name'] save_path = file_info['save_path'] minio_client.get_object(bucket_name, object_name, save_path)


De même, la fonction download_file_from_minio est également marquée par @tool . Il attend un dictionnaire file_info contenant les informations nécessaires pour télécharger un fichier à partir d'un compartiment MinIO, telles que le nom du compartiment, le nom de l'objet et le chemin local où le fichier doit être enregistré. La fonction utilise minio_client pour récupérer l'objet du compartiment spécifié et l'enregistrer dans le chemin local désigné.


 @tool def list_objects_in_minio_bucket(file_info): """ Custom function to list objects in a MinIO bucket. Expects file_info dict with 'bucket_name' key. Returns a list of dictionaries containing 'ObjectKey' and 'Size' keys. """ bucket_name = file_info['bucket_name'] response = minio_client.list_objects(bucket_name) return [{'ObjectKey': obj.object_name, 'Size': obj.size} for obj in response.items]


La fonction list_objects_in_minio_bucket , également agrémentée de @tool se charge de lister les objets présents dans un bucket MinIO. Il attend un dictionnaire file_info avec la clé bucket_name . La fonction utilise minio_client pour récupérer la liste des objets dans le compartiment spécifié et renvoie une liste de dictionnaires contenant la clé et la taille de l'objet pour chaque objet.


En encapsulant ces fonctionnalités sous forme d'outils, Langchain et Langserve permettent à l'agent IA de les intégrer de manière transparente dans sa logique et son processus décisionnel. L'agent peut sélectionner et exécuter intelligemment l'outil approprié en fonction de la tâche à accomplir, améliorant ainsi ses capacités et permettant des interactions plus complexes et dynamiques avec le système de stockage MinIO.

Comprendre la méthode exécutable de LangChain

LangChain propose une myriade de méthodes pour construire avec une logique personnalisée, l'une de ces approches est celle de « exécutables ». Quant à la logique démonstrative ci-dessus, RunnableLambda est une construction fournie par LangChain qui permet de traiter les fonctions comme des unités exécutables dans la logique de l'agent IA.


 from langchain_core.runnables import RunnableLambda upload_file_runnable = RunnableLambda(upload_file_to_minio) download_file_runnable = RunnableLambda(download_file_from_minio) list_objects_runnable = RunnableLambda(list_objects_in_minio_bucket)


En encapsulant les fonctions de l'outil avec RunnableLambda, nous créons des instances exécutables ( upload_file_runnable , download_file_runnable et list_objects_runnable ) qui peuvent être invoquées par l'agent lors de son exécution. Ces exécutables encapsulent les fonctions de l'outil correspondantes et fournissent une interface uniforme permettant à l'agent d'interagir avec elles.


 tools = [upload_file_to_minio, download_file_from_minio, list_objects_in_minio_bucket] llm_with_tools = llm.bind_tools(tools)


La liste des outils contient les fonctions de l'outil d'origine ( upload_file_to_minio , download_file_from_minio et list_objects_in_minio_bucket ), qui servent de blocs de construction pour les capacités de l'agent. La ligne llm.bind_tools(tools) lie les outils au modèle de langage ( llm ), établissant une connexion entre les capacités de raisonnement du modèle et les fonctionnalités spécifiques fournies par les outils. Le llm_with_tools résultant représente le modèle de langage amélioré avec les connaissances et la capacité d'utiliser les outils liés.


L'utilisation de RunnableLambda et la liaison d'outils au modèle de langage démontrent la flexibilité et l'extensibilité de LangChain et LangServe dans la création d'agents d'IA puissants et personnalisables. En combinant la puissance du modèle de langage avec les fonctionnalités spécifiques encapsulées dans les outils, l'agent IA acquiert la capacité d'effectuer des tâches complexes, telles que le téléchargement de fichiers vers MinIO, le téléchargement de fichiers depuis MinIO et la liste d'objets dans un compartiment MinIO.

Rédaction d'un modèle d'invite pour guider notre agent

Ensuite, nous nous concentrons sur le modèle d'invite qui guide l'agent IA dans la compréhension et la réponse aux entrées de l'utilisateur. Il est défini à l'aide de la méthode ChatPromptTemplate.from_messages() , qui prend une liste de messages représentés sous forme de tuples contenant le rôle et le contenu du message.


 from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.agents.format_scratchpad.openai_tools import format_to_openai_tool_messages from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser from langchain_core.messages import AIMessage, HumanMessage prompt_template = ChatPromptTemplate.from_messages([ ("system", "You are a powerful assistant equipped with file management capabilities."), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ])



L'invite se compose de trois messages :


  1. Un message « système » définissant le contexte de l'agent IA en tant qu'assistant puissant doté de capacités de gestion de fichiers.


  2. Un message "utilisateur" représentant l'entrée de l'utilisateur, utilisant l'espace réservé {input} .


  3. Un MessagesPlaceholder nommé "agent_scratchpad" pour stocker les étapes intermédiaires et le processus de réflexion de l'agent.


La fonction format_to_openai_tool_messages formate le bloc-notes de l'agent dans un format compatible pour les outils d'OpenAI, tandis que la classe OpenAIToolsAgentOutputParser analyse la réponse du modèle dans un format structuré interprétable par l'agent.


Les classes AIMessage et HumanMessage représentent les messages échangés entre l'agent et l'utilisateur, fournissant un moyen standardisé de gérer la communication au sein de la logique de l'agent.


En définissant le modèle d'invite, nous fournissons à l'agent IA une structure et un contexte clairs pour comprendre et répondre aux entrées de l'utilisateur, en utilisant l'espace réservé « agent_scratchpad » pour suivre ses étapes intermédiaires et son processus de réflexion tout en résolvant la tâche.

Définir l'agent avec ses outils

Enfin, pour compléter notre agent.py nous définissons notre agent et créons un AgentExecutor qui peut être importé et appelé à partir d'un script server.py à l'aide de la fonction add_route de la bibliothèque LangServe.


Nous instancions les composants nécessaires et les chaînons ensemble pour créer une variable d'agent unique.


 agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_tool_messages(x["intermediate_steps"]), } | prompt_template | llm_with_tools | OpenAIToolsAgentOutputParser() )


L'agent est défini à l'aide d'une combinaison de dictionnaires et d'opérations chaînées. La clé d'entrée extrait les entrées de l'utilisateur des données entrantes, tandis que la clé agent_scratchpad formate les étapes intermédiaires du processus de réflexion de l'agent à l'aide de la fonction format_to_openai_tool_messages . L'agent intègre également le modèle d'invite ( prompt_template ), le modèle de langage avec les outils ( llm_with_tools ) et l'analyseur de sortie ( OpenAIToolsAgentOutputParser() ).

Définition d'un AgentExecutor pour exécuter l'agent

Pour créer un AgentExecutor , nous lui fournissons l'agent défini, les outils disponibles et définissons verbose=True pour une sortie détaillée.


 from langchain.agents import tool, AgentExecutor agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)


AgentExecutor utilise l'agent et les outils fournis pour comprendre la tâche et sélectionner l'outil approprié en fonction de la saisie de l'utilisateur. Au lieu d'avoir des invites distinctes pour chaque outil, l'agent utilise un modèle d'invite unique qui le guide sur la façon d'utiliser les outils en fonction de l'entrée donnée. L'agent sélectionne dynamiquement l'outil approprié pendant le processus d'exécution.

Définir la route LangServe avec notre AgentExecutor

La configuration de notre application en l'intégrant à LangServe fournit un chemin simplifié pour déployer et gérer nos applications LangChain en tant qu'API. FastAPI est choisi pour ses performances et sa facilité d'utilisation, prenant en charge les opérations asynchrones et générant automatiquement la documentation de l'API.


Le Bibliothèque LangServe , construit avec FastAPI, enrichit cela en simplifiant le déploiement d'objets LangChain en tant qu'API REST, offrant un middleware intégré pour les paramètres CORS afin de garantir que notre API peut être appelée en toute sécurité à partir de différents domaines.


Pour des démonstrations plus approfondies/de cas d'utilisation, peuvent être explorées en visitant le langchain-ai/langserve Dépôt GitHub sous le répertoire d'exemples .


 from fastapi import FastAPI app = FastAPI( title="MinIO Agent API", version="1.0", description="A conversational agent facilitating data storage and retrieval with MinIO", )


Pour définir les en-têtes CORS, nous pouvons ajouter les lignes suivantes pour améliorer notre sécurité :


 from fastapi.middleware.cors import CORSMiddleware # Set all CORS enabled origins app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], expose_headers=["*"], )

Implémentation de l'agent à l'aide de LangServe

Maintenant que nous avons terminé avec packages/agent.py nous pouvons l'importer et utiliser la fonction add_route de la bibliothèque LangServe dans notre script app/server.py .


 from packages.agent import agent_executor from langserve import add_routes add_routes( app, agent_executor.with_types(input_type=Input, output_type=Output).with_config( {"run_name": "agent"} ), path=”/invoke” )


En appelant add_route(app, agent_executor(…), path="/invoke") , nous ajoutons une route à notre application serveur ( app ) qui mappe le chemin /invoke à la fonction agent_executor() . Cela permet à l'exécuteur de l'agent d'être invoqué lorsqu'une requête est adressée au point de terminaison /invoke .


Avec cette configuration, le serveur peut gérer les demandes entrantes, les transmettre à l'exécuteur de l'agent et renvoyer la réponse de l'agent au client. L'exécuteur d'agent utilise l'agent défini, qui intègre le modèle d'invite, le modèle de langage avec des outils et l'analyseur de sortie, pour traiter l'entrée de l'utilisateur et générer une réponse appropriée sur la base des outils disponibles.

Lancement de l'application LangServe via Uvicorn

Pour démarrer l'application LangServe, nous utilisons Uvicorn comme serveur ASGI, préparant ainsi le terrain pour l'exécution de notre application. Cet extrait de code est essentiel car il active le serveur, en spécifiant l'hôte universel et le port désigné pour les points d'accès de l'application.


 if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)


En intégrant ce bloc dans l'entrée principale de l'application, nous garantissons qu'Uvicorn prend la barre lorsque le script est exécuté directement, éclairant ainsi notre application FastAPI sur un hôte et un port prédéfinis. Cette approche simplifie non seulement le processus de déploiement, mais marque également une entrée claire pour exécuter l'application dans un environnement de développement ou de production.

Démarrage de l'application serveur

Le code ci-dessus a démontré une approche modulaire qui inclut l'utilisation de la bibliothèque « langchain-cli », la création d'une nouvelle application langchain et l'enregistrement de la logique de la chaîne dans agent.py tandis que l'implémentation de FastAPI et LangServe est enregistrée dans server.py .


Ceci étant notre dernière étape, nous enregistrerons notre code d'application sur server.py dans le but démonstratif de créer notre application.


La façon la plus simple d'exécuter notre service est de :


 python server.py


Cette commande exécutera l'application, tout en renvoyant tous les journaux ou messages d'erreur qui doivent encore être débogués.


Capture d'écran de la sortie du terminal exécutant LangServe


Aire de jeux LangServe

Dans la sortie Python, les journaux LangServe identifient /invoke/playground comme point de terminaison de l'application. Nous pouvons maintenant visiter le WebUI du terrain de jeu ainsi que la documentation automatisée de notre API qui est disponible en visitant le chemin /docs de notre API ; nous offrant une approche simplifiée des tests et de la configuration en incluant le bouton Essayer pour chacune des fonctionnalités de nos applications, ainsi que des requêtes cURL prédéfinies que nous pouvons exécuter à partir de l'interface Web.


Capture d'écran du LangServe Playground déployé


Par conséquent, notre agent LangChain intégré à MinIO est désormais habilement transformé en une API déployable, prête à être développée et étendue pour les utilisateurs avec des fonctionnalités allant du traitement par lots aux interactions en temps réel.

Utilisation ultérieure de l'API LangServe

Une fois l'application LangServe opérationnelle, nous pouvons l'utiliser depuis l'extérieur de notre server.py , en ciblant notre point de terminaison et en l'encapsulant dans le module RemoteRunnable de Langserve :


 from langserve import RemoteRunnable remote_runnable = RemoteRunnable("http://localhost:8000/<path>/")


Ajouter


LangChain propose une vaste gamme de modules dans ses bibliothèques, présentant une boîte à outils diversifiée conçue pour permettre aux développeurs de créer des applications sophistiquées basées sur l'IA. Des constructions de chaînes complexes à l'intégration transparente avec divers modèles d'IA, l'architecture modulaire de LangChain facilite un large éventail de fonctionnalités, permettant la création de solutions hautement personnalisables et avancées dans le domaine de l'IA et de l'apprentissage automatique.

Développer des pipelines d'IA avec LangServe

LangServe non seulement démystifie mais simplifie considérablement le processus de déploiement des applications LangChain. En comblant le fossé entre le développement et le déploiement, il garantit que les applications innovantes tirant parti de MinIO et LangChain peuvent rapidement passer du concept à la réalité, prêtes à être intégrées dans l'écosystème plus large et à améliorer l'expérience utilisateur.


Grâce au développement couvert dans nos explorations, nous avons constaté l'intégration transparente de MinIO avec LangChaîne est tout à fait possible, et comment LangServe joue un rôle central dans le déploiement de ces solutions avancées. Alors que nous continuons à naviguer dans le paysage changeant de l’IA et du ML, des outils comme LangServe resteront déterminants pour mettre les technologies de pointe à l’avant-garde du développement d’applications.


Chez MinIO, nous sommes stimulés par la créativité et le potentiel de la communauté des développeurs en cette ère riche en technologies. Il n'y a pas de meilleur moment pour la collaboration et l'échange de connaissances. Nous sommes impatients de communiquer avec vous ! Rejoignez-nous sur notre Slack MinIO canal pour poursuivre la conversation et atteindre de nouveaux sommets ensemble.