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.
Forts de ces connaissances, nous nous concentrons désormais sur
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.
Nous approfondirons le processus d'intégration de MinIO avec LangChain dans les étapes suivantes.
langchain-cli
.agent.py
.server.py
pour qu'il s'exécute en tant qu'API LangServe.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
pip
. Ce package fournit une interface qui permet aux utilisateurs de créer facilement de nouvelles applications en utilisant les applications existantes.
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
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
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 "
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.
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.
LangChain propose une myriade de méthodes pour construire avec une logique personnalisée, l'une de ces approches est celle de «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.
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 :
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.
Un message "utilisateur" représentant l'entrée de l'utilisateur, utilisant l'espace réservé {input}
.
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.
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()
).
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.
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
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 leré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=["*"], )
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.
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.
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.
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.
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.
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.
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
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