Nuestro viaje a través del mundo innovador de LangChain ha revelado sus capacidades sustanciales para transformar la gestión de datos y la funcionalidad de las aplicaciones.
A través de discusiones anteriores, profundizamos en varios temas mientras exploramos las intrincadas capacidades de LangChain. En este artículo, nos basaremos en los conceptos tratados en "Potenciar a los agentes Langchain con MinIO" a medida que ampliamos la funcionalidad de un agente MinIO para encapsular capacidades adicionales e implementar el agente personalizado a través de LangServe.
Sobre la base de estos conocimientos, ahora centraremos nuestra atención en
Creación automática de puntos finales API: las capacidades de automatización de LangServe generan sin esfuerzo los puntos finales API necesarios, agilizando los esfuerzos de desarrollo y reduciendo significativamente el tiempo de implementación.
Generación y validación de esquemas: con su inferencia inteligente de esquemas, LangServe garantiza que las API ofrezcan interfaces bien definidas, lo que facilita una integración más sencilla y una experiencia de usuario perfecta.
Configuración de puntos finales personalizable: LangServe ofrece una variedad de puntos finales para satisfacer diversas necesidades de aplicaciones, desde operaciones sincrónicas hasta actualizaciones en tiempo real, brindando a los desarrolladores una flexibilidad incomparable.
Integración sin esfuerzo: Quizás su característica más atractiva, la capacidad de LangServe para integrarse perfectamente con el código LangChain existente significa que los desarrolladores pueden aprovechar su base de código actual y su experiencia sin modificaciones significativas.
Profundizaremos en el proceso de integración de MinIO con LangChain en los siguientes pasos.
langchain-cli
.agent.py
.server.py
para ejecutarlo como una API LangServe.La implementación de aplicaciones LangChain con LangServe brinda un proceso de integración perfecto, cerrando la brecha entre las funcionalidades complejas de IA y la exposición a la API RESTful, permitiendo a los desarrolladores aprovechar todo el espectro de capacidades de LangChain de manera eficiente, estableciendo un nuevo estándar para implementar aplicaciones inteligentes en el acelerado panorama digital actual. .
LangChain ofrece un método conveniente y simple para crear aplicaciones usando su langchain-cli
pip
. Este paquete proporciona una interfaz que permite a los usuarios crear fácilmente nuevas aplicaciones utilizando las existentes.
Nota: Todos los archivos necesarios se encuentran en el repositorio “blog-assets” de MinIO en el directorio denominado “minio-langserve-deployment ”.
Para crear una nueva aplicación LangChain podemos comenzar con los siguientes comandos para crear un entorno virtual e instalar el paquete langchain-cli
:
mkdir minio-langserve-testing cd minio-Langserve-testing python -m venv .myenv source .myenv/bin/activate pip install langchain-cli
Para crear una nueva aplicación usando langchain-cli
podemos escribir langchain
en nuestra terminal, el siguiente comando está escrito para crear un nuevo directorio de aplicación llamado my-app
.
langchain app new my-app
La aplicación langchain creada con los comandos anteriores hace todo el trabajo pesado al crear un entorno consistente para el desarrollo. La estructura de una nueva aplicación LangChain lista para usar se ve así:
./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
En los siguientes pasos, realizaremos cambios en la aplicación LangChain recién creada ( my-app
) escribiendo un nuevo archivo llamado packages/agent.py y realizando cambios en app/server.py
.
Estos son los archivos que discutiremos en este artículo:
my-app/packages/agent.py
my-app/app/server.py
Para ilustrar la implementación de un agente LangChain integrado en MinIO con LangServe, comenzaremos guardando el código de la cadena del agente en agent.py
.
Primero, inicialicemos un minio_client
que se conecta al servidor público "play.min.io:443". Este archivo eventualmente llamará agent_executor
de LangChain, permitiéndonos pasarlo al contenedor add_route
de LangServe.
Nota: Leyendo la publicación anterior"
Para comenzar, abra el archivo agent.py usando un editor de texto:
sudo nano packages/agent.py
Al principio del archivo, importe los paquetes necesarios, como os
, io
, minio
y 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)
En este fragmento de código, importamos los paquetes necesarios e inicializamos el modelo de lenguaje ChatOpenAI con la clave API de OpenAI almacenada en la variable de entorno OPENAI_API_KEY
. También inicializamos minio_client proporcionando los detalles de conexión necesarios al servidor público "play.min.io".
A continuación, definamos el depósito MinIO y creémoslo si no existe:
# 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}")
Aquí, definimos el bucket_name
como "prueba" y verificamos si ya existe usando el método minio_client.bucket_exists()
. Si el depósito no existe, lo creamos usando minio_client.make_bucket()
. Si el depósito ya existe, imprimimos un mensaje indicándolo. También incluimos el manejo de errores mediante un bloque try-except para detectar e imprimir cualquier S3Error
que pueda ocurrir durante el proceso.
Con la configuración básica implementada, ahora podemos proceder a definir las funciones de la herramienta MinIO y crear el ejecutor del agente, que cubriremos en los siguientes pasos.
Langchain y Langserve proporcionan un enfoque similar para encapsular la lógica y la funcionalidad, lo que permite integrarlas perfectamente en la lógica del agente y de la cadena. Esto se logra mediante el uso del decorador @tool
con una cadena de documentación detallada dentro de la función definida, que marca las funciones como componentes reutilizables que el agente de IA puede utilizar e interpretar.
Echemos un vistazo más de cerca a los ejemplos de código proporcionados:
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 función upload_file_to_minio
está decorada con @tool
, lo que indica que es un componente reutilizable. Toma los parámetros necesarios para cargar un archivo en un depósito MinIO, como el nombre del depósito, el nombre del objeto y los bytes sin procesar del archivo. La función utiliza minio_client
para realizar la operación de carga de archivos y devuelve un mensaje de éxito al finalizar.
@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 manera similar, la función download_file_from_minio
también está marcada con @tool
. Espera un diccionario file_info
que contenga la información necesaria para descargar un archivo de un depósito MinIO, como el nombre del depósito, el nombre del objeto y la ruta local donde se debe guardar el archivo. La función utiliza minio_client
para recuperar el objeto del depósito especificado y guardarlo en la ruta local designada.
@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 función list_objects_in_minio_bucket
, también decorada con @tool
es responsable de enumerar los objetos presentes en un depósito MinIO. Espera un diccionario file_info
con la clave bucket_name
. La función utiliza minio_client
para recuperar la lista de objetos en el depósito especificado y devuelve una lista de diccionarios que contienen la clave y el tamaño del objeto para cada objeto.
Al encapsular estas funcionalidades como herramientas, Langchain y Langserve permiten que el agente de IA las incorpore sin problemas en su lógica y proceso de toma de decisiones. El agente puede seleccionar y ejecutar de forma inteligente la herramienta adecuada según la tarea en cuestión, mejorando sus capacidades y permitiendo interacciones más complejas y dinámicas con el sistema de almacenamiento MinIO.
LangChain ofrece una gran variedad de métodos para construir con lógica personalizada, uno de esos enfoques es el de "RunnableLambda
es una construcción proporcionada por LangChain que permite que las funciones se traten como unidades ejecutables dentro de la lógica del agente de 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)
Al empaquetar las funciones de la herramienta con RunnableLambda, creamos instancias ejecutables ( upload_file_runnable
, download_file_runnable
y list_objects_runnable
) que el agente puede invocar durante su ejecución. Estos ejecutables encapsulan las funciones de herramientas correspondientes y proporcionan una interfaz uniforme para que el agente interactúe con ellas.
tools = [upload_file_to_minio, download_file_from_minio, list_objects_in_minio_bucket] llm_with_tools = llm.bind_tools(tools)
La lista de herramientas contiene las funciones de herramientas originales ( upload_file_to_minio
, download_file_from_minio
y list_objects_in_minio_bucket
), que sirven como elementos básicos para las capacidades del agente. La línea llm.bind_tools(tools)
vincula las herramientas al modelo de lenguaje ( llm
), estableciendo una conexión entre las capacidades de razonamiento del modelo y las funcionalidades específicas proporcionadas por las herramientas. El llm_with_tools
resultante representa el modelo de lenguaje mejorado con el conocimiento y la capacidad de emplear las herramientas enlazadas.
El uso de RunnableLambda
y la vinculación de herramientas al modelo de lenguaje demuestran la flexibilidad y extensibilidad de LangChain y LangServe en la creación de agentes de IA potentes y personalizables. Al combinar el poder del modelo de lenguaje con las funcionalidades específicas encapsuladas en las herramientas, el agente de IA obtiene la capacidad de realizar tareas complejas, como cargar archivos a MinIO, descargar archivos de MinIO y enumerar objetos en un depósito de MinIO.
A continuación, cambiamos nuestro enfoque a la plantilla de mensajes que guía al agente de IA para comprender y responder a las entradas del usuario. Se define mediante el método ChatPromptTemplate.from_messages()
, que toma una lista de mensajes representados como tuplas que contienen la función y el contenido del mensaje.
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"), ])
El mensaje consta de tres mensajes:
Un mensaje de "sistema" que establece el contexto para el agente de IA como un poderoso asistente con capacidades de administración de archivos.
Un mensaje de "usuario" que representa la entrada del usuario, utilizando el marcador de posición {input}
.
Un MessagesPlaceholder
llamado "agent_scratchpad" para almacenar los pasos intermedios y el proceso de pensamiento del agente.
La función format_to_openai_tool_messages
formatea el bloc de notas del agente en un formato compatible para las herramientas de OpenAI, mientras que la clase OpenAIToolsAgentOutputParser analiza la respuesta del modelo en un formato estructurado interpretable por el agente.
Las clases AIMessage
y HumanMessage
representan los mensajes intercambiados entre el agente y el usuario, proporcionando una forma estandarizada de manejar la comunicación dentro de la lógica del agente.
Al definir la plantilla de solicitud, proporcionamos al agente de IA una estructura y un contexto claros para comprender y responder a las entradas del usuario, utilizando el marcador de posición "agent_scratchpad" para realizar un seguimiento de sus pasos intermedios y su proceso de pensamiento mientras resuelve la tarea.
Finalmente, para completar nuestro agent.py
definimos nuestro agente y creamos un AgentExecutor que se puede importar y llamar desde un script server.py
usando la función add_route
de la biblioteca LangServe.
Creamos instancias de los componentes necesarios y los encadenamos para crear una única variable de agente.
agent = ( { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_to_openai_tool_messages(x["intermediate_steps"]), } | prompt_template | llm_with_tools | OpenAIToolsAgentOutputParser() )
El agente se define mediante una combinación de diccionarios y operaciones encadenadas. La clave de entrada extrae la entrada del usuario de los datos entrantes, mientras que la clave agent_scratchpad
formatea los pasos intermedios del proceso de pensamiento del agente utilizando la función format_to_openai_tool_messages
. El agente también incorpora la plantilla de solicitud ( prompt_template
), el modelo de lenguaje con herramientas ( llm_with_tools
) y el analizador de salida ( OpenAIToolsAgentOutputParser()
).
Para crear un AgentExecutor
, le proporcionamos el agente definido, las herramientas disponibles y configuramos verbose=True
para obtener resultados detallados.
from langchain.agents import tool, AgentExecutor agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
AgentExecutor
utiliza el agente y las herramientas proporcionados para comprender la tarea y seleccionar la herramienta adecuada según la entrada del usuario. En lugar de tener indicaciones separadas para cada herramienta, el agente utiliza una única plantilla de indicaciones que lo guía sobre cómo usar las herramientas según la entrada proporcionada. El agente selecciona dinámicamente la herramienta adecuada durante el proceso de ejecución.
Configurar nuestra aplicación integrándola con LangServe proporciona una ruta simplificada para implementar y administrar nuestras aplicaciones LangChain como API. Se elige FastAPI por su rendimiento y facilidad de uso, ya que admite operaciones asincrónicas y genera automáticamente documentación API.
El
Para ver demostraciones más detalladas/de casos de uso, puede explorarlas visitando el
langchain-ai/langserve Repositorio de GitHub bajo eldirectorio de ejemplos .
from fastapi import FastAPI app = FastAPI( title="MinIO Agent API", version="1.0", description="A conversational agent facilitating data storage and retrieval with MinIO", )
Para configurar encabezados CORS podemos agregar las siguientes líneas para mejorar nuestra seguridad:
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=["*"], )
Ahora que hemos terminado con packages/agent.py
podemos importarlo y usar la función add_route
de la biblioteca LangServe en nuestro 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” )
Al llamar add_route(app, agent_executor(…), path="/invoke")
, agregamos una ruta a nuestra aplicación de servidor ( app
) que asigna la ruta /invoke
a la función agent_executor()
. Esto permite invocar al ejecutor del agente cuando se realiza una solicitud al punto final /invoke
.
Con esta configuración, el servidor puede manejar las solicitudes entrantes, pasarlas al ejecutor del agente y devolver la respuesta del agente al cliente. El ejecutor del agente utiliza el agente definido, que incorpora la plantilla de solicitud, el modelo de lenguaje con herramientas y el analizador de salida, para procesar la entrada del usuario y generar una respuesta adecuada basada en las herramientas disponibles.
Para iniciar la aplicación LangServe, empleamos Uvicorn como servidor ASGI, preparando el escenario para que se ejecute nuestra aplicación. Este fragmento de código es fundamental ya que activa el servidor, especificando el host universal y el puerto designado para los puntos de acceso de la aplicación.
if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
Al incorporar este bloque dentro de la entrada principal de la aplicación, nos aseguramos de que Uvicorn tome el mando cuando el script se ejecuta directamente, iluminando así nuestra aplicación FastAPI en un host y puerto predefinidos. Este enfoque no sólo simplifica el proceso de implementación, sino que también marca una entrada clara para ejecutar la aplicación en un entorno de desarrollo o producción.
Se ha demostrado que el código anterior es un enfoque modular que incluye el uso de la biblioteca "langchain-cli", la creación de una nueva aplicación langchain y guardar la lógica de la cadena en agent.py
mientras la implementación de FastAPI y LangServe se guarda en server.py
.
Siendo este nuestro paso final, guardaremos el código de nuestra aplicación en server.py
con el propósito demostrativo de construir nuestra aplicación.
La forma más sencilla de ejecutar nuestro servicio es con:
python server.py
Este comando ejecutará la aplicación y devolverá cualquier registro o mensaje de error que aún deba depurarse.
En la salida de Python, los registros de LangServe identifican /invoke/playground
como el punto final de la aplicación. Ahora podemos visitar la WebUI del área de juegos, así como la documentación automatizada de nuestra API que está disponible visitando la ruta /docs
de nuestra API; brindándonos un enfoque simplificado para las pruebas y la configuración al incluir el botón Pruébelo para cada una de las funciones de nuestras aplicaciones, así como solicitudes cURL predefinidas que podemos ejecutar desde la WebUI.
En consecuencia, nuestro agente LangChain integrado en MinIO ahora se ha transformado hábilmente en una API implementable, lista para ser desarrollada y extendida para usuarios con funcionalidades que van desde el procesamiento por lotes hasta interacciones en tiempo real.
Con la aplicación LangServe en funcionamiento, podemos usarla desde fuera de nuestro server.py
, dirigiéndonos a nuestro punto final y envolviéndolo en el módulo RemoteRunnable
de Langserve:
from langserve import RemoteRunnable remote_runnable = RemoteRunnable("http://localhost:8000/<path>/")
Agregar
LangChain cuenta con una amplia gama de módulos en sus bibliotecas, que muestran un conjunto de herramientas diverso diseñado para capacitar a los desarrolladores en la creación de aplicaciones sofisticadas impulsadas por IA. Desde intrincadas construcciones de cadenas hasta una integración perfecta con varios modelos de IA, la arquitectura modular de LangChain facilita una amplia gama de funcionalidades, lo que permite la creación de soluciones avanzadas y altamente personalizables en el ámbito de la IA y el aprendizaje automático.
LangServe no sólo desmitifica sino que simplifica significativamente el proceso de implementación de aplicaciones LangChain. Al cerrar la brecha entre el desarrollo y la implementación, garantiza que las aplicaciones innovadoras que aprovechan MinIO y LangChain puedan pasar rápidamente del concepto a la realidad, listas para integrarse en el ecosistema más amplio y mejorar las experiencias de los usuarios.
A través del desarrollo cubierto en nuestras exploraciones, hemos visto la perfecta integración de MinIO con
En MinIO, nos motiva la creatividad y el potencial dentro de la comunidad de desarrolladores durante esta era rica en tecnología. No hay mejor momento para la colaboración y el intercambio de conocimientos. ¡Estamos ansiosos por conectarnos con usted! Únase a nosotros en nuestro