Optimización de sistemas multiagente con Mistral Large, Mistral Nemo y Llama-agents
Los sistemas agénticos están en auge, ayudando a los desarrolladores a crear sistemas inteligentes y autónomos. Los modelos de lenguaje grandes (LLMs) son cada vez más capaces de seguir diversos conjuntos de instrucciones, lo que los hace ideales para gestionar estos agentes. Este avance abre numerosas posibilidades para manejar tareas complejas con una intervención humana mínima en muchísimas áreas. Por ejemplo, los sistemas agénticos pueden beneficiar al servicio al cliente, donde pueden gestionar consultas de clientes, resolver problemas e incluso hacer ventas adicionales de productos según las preferencias de los clientes.
Esta publicación proporciona una guía completa para crear agentes inteligentes usando llama-agents, combinado con el poder de Mistral LLMs y Milvus. Aprenderemos cómo aprovechar Mistral Nemo para la ejecución rentable de tareas, Mistral Large para una orquestación sofisticada y Milvus para el almacenamiento y la recuperación eficientes de datos vectoriales. Exploraremos ejemplos prácticos, incluido el análisis de documentos financieros y la implementación de filtrado de metadatos para crear un sistema de agentes altamente escalable y dinámico. Sigue los ejemplos de código detallados y las instrucciones paso a paso para crear tus propios agentes potentes.
Sigue el tutorial
Recorrí este tutorial en un seminario web, que puedes seguir paso a paso a continuación.
Introducción a Llama-agents, Ollama y Mistral Nemo, y Milvus Lite
Llama-agents es una extensión de LlamaIndex para crear aplicaciones multi-actor robustas y con estado con LLMs.
Ollama y Mistral Nemo – Ollama es una herramienta de IA que permite a los usuarios ejecutar modelos de lenguaje grandes, como Mistral Nemo, localmente en sus máquinas. Esto te permite trabajar con estos modelos bajo tus propios términos sin necesitar conectividad constante a internet ni depender de servidores externos.
Milvus Lite es una versión local y ligera de Milvus que puede ejecutarse en tu laptop, Jupyter Notebook o Google Colab. Te permite almacenar y recuperar tus datos no estructurados de manera eficiente.
Cómo funcionan Llama-agents
Llama-agents, desarrollado por LlamaIndex, es un framework async-first para construir, iterar y llevar a producción sistemas multiagente, incluyendo comunicación multiagente, ejecución distribuida de herramientas, human-in-the-loop y más.
En Llama-agents, cada agente se considera un servicio que procesa sin cesar las tareas entrantes. Cada agente extrae y publica mensajes desde una cola de mensajes.
Figura- Cómo funcionan Llama-agents.png
Figura: Cómo funcionan Llama-agents
Instalar dependencias
Primero instalemos todas las dependencias necesarias.
! pip install llama-agents pymilvus python-dotenv
! pip install llama-index-vector-stores-milvus llama-index-readers-file llama-index-embeddings-huggingface llama-index-llms-ollama llama-index-llms-mistralai
# This is needed when running the code in a Notebook
import nest_asyncio
nest_asyncio.apply()
from dotenv import load_dotenv
import os
load_dotenv()
Cargar datos en Milvus
Descargaremos algunos datos de ejemplo de llama-index, que incluyen PDFs sobre Uber y Lyft. Usaremos estos datos a lo largo del tutorial.
!mkdir -p 'data/10k/'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/10k/uber_2021.pdf' -O 'data/10k/uber_2021.pdf'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/10k/lyft_2021.pdf' -O 'data/10k/lyft_2021.pdf'
Ahora que tenemos los datos en nuestra máquina, podemos extraer el contenido y almacenarlo en la base de datos vectorial Milvus. Para el modelo de embeddings, estamos usando bge-small-en-v1.5, que es un modelo compacto de embeddings de texto con bajo uso de recursos.
A continuación, creamos una colección en Milvus para almacenar y recuperar nuestros datos. Estamos usando Milvus Lite, la versión ligera de Milvus, una base de datos vectorial de alto rendimiento que impulsa aplicaciones de IA con búsqueda por similitud vectorial. Puedes instalar Milvus Lite con un simple pip install pymilvus.
Nuestros PDFs se transforman en vectores, y los almacenaremos en Milvus.
from llama_index.vector_stores.milvus import MilvusVectorStore
from llama_index.core import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, StorageContext, load_index_from_storage
from llama_index.core.tools import QueryEngineTool, ToolMetadata
# Define the default Embedding model used in this Notebook.
# bge-small-en-v1.5 is a small Embedding model, it's perfect to use locally
Settings.embed_model = HuggingFaceEmbedding(
model_name="BAAI/bge-small-en-v1.5"
)
input_files=["./data/10k/lyft_2021.pdf", "./data/10k/uber_2021.pdf"]
# Create a single Milvus vector store
vector_store = MilvusVectorStore(
uri="./milvus_demo_metadata.db",
collection_name="companies_docs"
dim=384,
overwrite=False,
)
# Create a storage context with the Milvus vector store
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# Load data
docs = SimpleDirectoryReader(input_files=input_files).load_data()
# Build index
index = VectorStoreIndex.from_documents(docs, storage_context=storage_context)
# Define the query engine
company_engine = index.as_query_engine(similarity_top_k=3)
Definir diferentes herramientas
Definiremos dos herramientas específicas para nuestros datos. La primera proporciona información sobre Lyft y la segunda trata sobre Uber. Más adelante veremos cómo podemos crear una herramienta más genérica.
# Define the different tools that can be used by our Agent.
query_engine_tools = [
QueryEngineTool(
query_engine=company_engine,
metadata=ToolMetadata(
name="lyft_10k",
description=(
"Provides information about Lyft financials for year 2021. "
"Use a detailed plain text question as input to the tool."
),
),
),
QueryEngineTool(
query_engine=company_engine,
metadata=ToolMetadata(
name="uber_10k",
description=(
"Provides information about Uber financials for year 2021. "
"Use a detailed plain text question as input to the tool."
),
),
),
]
Configurar el Agent usando Mistral Nemo 🐠
Para limitar nuestro uso de recursos y reducir potencialmente los costos de nuestra aplicación, estamos usando Mistral Nemo con Ollama. Esta combinación nos permite ejecutar el modelo localmente. Mistral Nemo es un LLM pequeño que ofrece una gran ventana de contexto de hasta 128k tokens, lo cual es muy útil al trabajar con documentos grandes. También ha sido ajustado para seguir instrucciones precisas de razonamiento, manejar conversaciones de varios turnos y generar código.
Ahora, configuremos el agent con Mistral Nemo.
from llama_index.llms.ollama import Ollama
from llama_index.core.agent import AgentRunner, ReActAgentWorker, ReActAgent
# Configurar el agente
llm = Ollama(model="mistral-nemo", temperature=0.4)
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
# Example usage
response = agent.chat("Compare the revenue of Lyft and Uber in 2021.")
print(response)
Este LLM debería generar una respuesta similar a la siguiente:
> Running step 7ed275f6-b0de-4fd7-b2f2-fd551e58bfe2. Step input: Compare the revenue of Lyft and Uber in 2021.
Thought: The current language of the user is: English. I need to use tools to help me answer the question.
Action: lyft_10k
Action Input: {'input': "What was Lyft's total revenue in 2021?"}
huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...
To disable this warning, you can either:
- Avoid using `tokenizers` before the fork if possible
- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)
Observation: The total revenue for Lyft in 2021 was generated primarily from its ridesharing marketplace connecting drivers and riders, with revenue recognized from fees paid by drivers for using the Lyft Platform offerings in accordance with ASC 606.
> Running step 33064fd3-3c3a-42c4-ab5a-e7ebf8a9325b. Step input: None
Thought: I need to compare the revenue of Lyft and Uber in 2021.
Action: uber_10k
Action Input: {'input': "What was Uber's total revenue in 2021?"}
Observation: $17,455
> Running step 7eacfef4-d9da-4cbf-ac07-18f2ff6a3951. Step input: None
Thought: I have obtained Uber's total revenue for 2021. Now, I need to compare it with Lyft's.
Action: lyft_10k
Action Input: {'input': "What was Lyft's total revenue in 2021?"}
Observation: The total revenue for Lyft in 2021 was generated primarily from their ridesharing marketplace connecting drivers and riders. The revenue was recognized from fees paid by drivers for using the Lyft Platform offerings in accordance with ASC 606.
> Running step 88673e15-b74c-4755-8b9c-2b7ef3acea48. Step input: None
Thought: I have obtained both Uber's and Lyft's total revenues for 2021. Now, I need to compare them.
Action: Compare
Action Input: {'Uber': '$17,455', 'Lyft': '$3.6 billion'}
Observation: Error: No such tool named `Compare`.
> Running step bed5941f-74ba-41fb-8905-88525e67b785. Step input: None
Thought: I need to compare the revenues manually since there isn't a 'Compare' tool.
Answer: In 2021, Uber's total revenue was $17.5 billion, while Lyft's total revenue was $3.6 billion. This means that Uber generated approximately four times more revenue than Lyft in the same year.
Response without metadata filtering:
In 2021, Uber's total revenue was $17.5 billion, while Lyft's total revenue was $3.6 billion. This means that Uber generated approximately four times more revenue than Lyft in the same year.
Uso del filtrado de metadatos con Milvus
Aunque tener un agente con una herramienta definida para cada tipo diferente de documento es conveniente, no escala bien si tienes muchas empresas que procesar. Una mejor solución es usar el filtrado de metadatos ofrecido por Milvus con nuestro agente. De esta manera, podemos almacenar datos de diferentes empresas en una sola colección pero recuperar solo las partes relevantes, ahorrando tiempo y recursos."
El fragmento de código a continuación muestra cómo podemos usar la funcionalidad de metafiltrado.
from llama_index.core.vector_stores import ExactMatchFilter, MetadataFilters
# Example usage with metadata filtering
filters = MetadataFilters(
filters=[ExactMatchFilter(key="file_name", value="lyft_2021.pdf")]
)
filtered_query_engine = index.as_query_engine(filters=filters)
# Define query engine tools with the filtered query engine
query_engine_tools = [
QueryEngineTool(
query_engine=filtered_query_engine,
metadata=ToolMetadata(
name="company_docs",
description=(
"Provides information about various companies' financials for year 2021. "
"Use a detailed plain text question as input to the tool."
),
),
),
]
# Set up the agent with the updated query engine tools
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
Nuestro recuperador ahora está filtrando datos que solo provienen del documento lyft_2021.pdf, y no deberíamos tener ninguna información sobre Uber.
try:
response = agent.chat("What is the revenue of uber in 2021?")
print("Response with metadata filtering:")
print(response)
except ValueError as err:
print("we couldn't find the data, reached max iterations")
Ahora, hagamos una prueba. Cuando se le preguntó sobre los ingresos de Uber en 2021, el agente recuperó cero resultados.
Thought: The user wants to know Uber's revenue for 2021.
Action: company_docs
Action Input: {'input': 'Uber Revenue 2021'}
Observation: I'm sorry, but based on the provided context information, there is no mention of Uber's revenue for the year 2021. The information primarily focuses on Lyft's revenue per active rider and critical accounting policies and estimates related to their financial statements.
> Running step c0014d6a-e6e9-46b6-af61-5a77ca857712. Step input: None
El agente puede encontrar los datos cuando se le pregunta sobre los ingresos de Lyft en 2021.
try:
response = agent.chat("What is the revenue of Lyft in 2021?")
print("Response with metadata filtering:")
print(response)
except ValueError as err:
print("we couldn't find the data, reached max iterations")
El resultado devuelto es:
> Ejecutando paso 7f1eebe3-2ebd-47ff-b560-09d09cdd99bd. Entrada del paso: ¿Cuál es el revenue de Lyft en 2021?
Pensamiento: El idioma actual del usuario es: inglés. Necesito usar una herramienta para ayudarme a responder la pregunta.
Acción: company_docs
Entrada de la acción: {'input': 'Lyft revenue 2021'}
Observación: El revenue de Lyft en 2021 se generó principalmente a partir de su mercado de ridesharing que conecta a conductores y pasajeros. El revenue se reconoció a partir de las tarifas pagadas por los conductores por usar las ofertas de la Lyft Platform de conformidad con ASC 606. Además, el revenue por Active Rider alcanzó un máximo histórico en el cuarto trimestre de 2021 debido al aumento de la frecuencia de viajes, un cambio hacia viajes de mayor revenue y revenues de acuerdos de licencia y acceso a datos.
> Ejecutando paso 072a3253-7eee-44e3-a787-397c9cbe80d8. Entrada del paso: Ninguna
Pensamiento: El idioma actual del usuario es inglés. Necesito usar una herramienta para ayudarme a responder la pregunta.
Acción: company_docs
Entrada de la acción: {'input': 'Lyft revenue 2021'}
Observación: El revenue de Lyft en 2021 fue impulsado por un aumento en la frecuencia de viajes, un cambio hacia viajes de mayor revenue, como viajes al aeropuerto, y revenues de acuerdos de licencia y acceso a datos. Esto dio como resultado que el revenue por Active Rider alcanzara un máximo histórico en el cuarto trimestre de 2021 en comparación con el trimestre anterior.
> Ejecutando paso 6494fe6d-27ad-484f-9204-0c4683bfa1c2. Entrada del paso: Ninguna
Pensamiento: El usuario está preguntando por el revenue de Lyft en 2021.
Acción: company_docs
Entrada de la acción: {'input': 'Lyft revenue 2021'}
Observación: El revenue de Lyft en 2021 se generó principalmente a partir de su mercado de ridesharing que conecta a conductores y pasajeros. El revenue por Active Rider alcanzó un máximo récord en el cuarto trimestre de 2021 debido al aumento de la frecuencia de viajes y a un cambio hacia viajes de mayor revenue, como viajes al aeropuerto. Además, el revenue se vio impulsado por acuerdos de licencia y acceso a datos a partir del segundo trimestre de 2021.
> Ejecutando paso 0076b6dd-e7d0-45ac-a39a-4afa5f1aaf47. Entrada del paso: Ninguna
Respuesta: Observación: El revenue total de Lyft en 2021 fue de 3.4 mil millones de dólares.
Respuesta con filtrado de metadatos:
Observación: El revenue total de Lyft en 2021 fue de 3.4 mil millones de dólares.
Usar un LLM para crear filtros de metadatos automáticamente
Ahora, usemos un LLM para crear filtros de metadatos automáticamente en función de la consulta del usuario. Este paso nos permite tener un agente más dinámico.
from llama_index.core.prompts.base import PromptTemplate
# Function to create a filtered query engine
def create_query_engine(question):
# Extract metadata filters from question using a language model
prompt_template = PromptTemplate(
"Given the following question, extract relevant metadata filters.\n"
"Consider company names, years, and any other relevant attributes.\n"
"Don't write any other text, just the MetadataFilters object"
"Format it by creating a MetadataFilters like shown in the following\n"
"MetadataFilters(filters=[ExactMatchFilter(key='file_name', value='lyft_2021.pdf')])\n"
"If no specific filters are mentioned, returns an empty MetadataFilters()\n"
"Question: {question}\n"
"Metadata Filters:\n"
)
prompt = prompt_template.format(question=question)
llm = Ollama(model="mistral-nemo")
response = llm.complete(prompt)
metadata_filters_str = response.text.strip()
if metadata_filters_str:
metadata_filters = eval(metadata_filters_str)
return index.as_query_engine(filters=metadata_filters)
return index.as_query_engine()
Luego podemos combinar esta función con nuestro Agent.
# Example usage with metadata filtering
question = "What is Uber revenue? This should be in the file_name: uber_2021.pdf"
filtered_query_engine = create_query_engine(question)
Define query engine tools with the filtered query engine
query_engine_tools = [ QueryEngineTool( query_engine=filtered_query_engine, metadata=ToolMetadata( name="company_docs_filtering", description=( "Provides information about various companies' financials for year 2021. " "Use a detailed plain text question as input to the tool." ), ), ), ]
Set up the agent with the updated query engine tools
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
response = agent.chat(question) print("Response with metadata filtering:") print(response)
Ahora, el Agent creó `Metadatafilters` con la clave `file_name` y el valor `uber_2021.pdf`. Con prompts más avanzados, también sería posible generar filtros más avanzados.
MetadataFilters(filters=[ExactMatchFilter(key='file_name', value='uber_2021.pdf')]) <class 'str'> eval: filters=[MetadataFilter(key='file_name', value='uber_2021.pdf', operator=<FilterOperator.EQ: '=='>)] condition=<FilterCondition.AND: 'and'>
Running step a2cfc7a2-95b1-4141-bc52-36d9817ee86d. Step input: What is Uber revenue? This should be in the file_name: uber_2021.pdf Thought: The current language of the user is English. I need to use a tool to help me answer the question. Action: company_docs Action Input: {'input': 'Uber revenue 2021'} Observation: $17,455 million
## Orquestar todo con Mistral Large
Mistral Large es un modelo más potente que Mistral Nemo, pero también es mucho más grande y consume más recursos. Al usarlo únicamente como orquestador, podemos conservar recursos sin dejar de beneficiarnos de agentes inteligentes.
### ¿Por qué usar Mistral Large como orquestador?
Mistral Large es el modelo insignia de Mistral, con muy buenas capacidades de razonamiento, conocimiento y programación. Es ideal para tareas complejas que requieren grandes capacidades de razonamiento o que son altamente especializadas. Tiene capacidades avanzadas de llamada a funciones, exactamente lo que necesitamos para orquestar nuestros diferentes agentes.
Orquestar con Mistral Large te permite separar responsabilidades dentro de tu framework de agentes. En lugar de cargar el sistema con un modelo pesado para cada tarea, Mistral Large puede reservarse para la toma de decisiones de alto nivel, dirigiendo a otros agentes más adecuados para tareas específicas y más pequeñas. Este enfoque no solo optimiza el rendimiento, sino que también reduce los costos operativos, haciendo que el sistema sea más escalable y eficiente.
En esta configuración, Mistral Large actúa como el orquestador central, coordinando las actividades de múltiples agentes gestionados por Llama-agents. Aquí tienes una visión general:
- **Delegación de tareas**: Cuando se recibe una consulta compleja, Mistral Large determina los agentes y herramientas más apropiados para gestionar cada parte de la consulta.
- **Coordinación de agentes**: Llama-agents gestionan la ejecución de estas tareas, asegurando que cada agente reciba las entradas necesarias y que sus salidas se procesen e integren correctamente.
- **Síntesis de resultados**: Mistral Large luego compila las salidas de varios agentes en una respuesta coherente y completa, asegurando que el resultado final sea mayor que la suma de sus partes.
### Llama Agents
Ahora, usemos Mistral Large para orquestarlo todo y usemos el agente para generar la respuesta por nosotros.
from llama_agents import ( AgentService, ToolService, LocalLauncher, MetaServiceTool, ControlPlaneServer, SimpleMessageQueue, AgentOrchestrator, )
from llama_index.core.agent import FunctionCallingAgentWorker from llama_index.llms.mistralai import MistralAI
create our multi-agent framework components
message_queue = SimpleMessageQueue() control_plane = ControlPlaneServer( message_queue=message_queue, orchestrator=AgentOrchestrator(llm=MistralAI('mistral-large-latest')), )
define Tool Service
tool_service = ToolService( message_queue=message_queue, tools=query_engine_tools, running=True, step_interval=0.5, )
define meta-tools here
meta_tools = [ await MetaServiceTool.from_tool_service( t.metadata.name, message_queue=message_queue, tool_service=tool_service, ) for t in query_engine_tools ]
define Agent and agent service
worker1 = FunctionCallingAgentWorker.from_tools( meta_tools, llm=MistralAI('mistral-large-latest') )
agent1 = worker1.as_agent() agent_server_1 = AgentService( agent=agent1, message_queue=message_queue, description="Used to answer questions over differnet companies for their Financial results", service_name="Companies_analyst_agent", )
import logging
change logging level to enable or disable more verbose logging
logging.getLogger("llama_agents").setLevel(logging.INFO)
Define Launcher
launcher = LocalLauncher( [agent_server_1, tool_service], control_plane, message_queue, )
query_str = "What are the risk factors for Uber?" print(launcher.launch_single(query_str))
Some key risk factors for Uber include fluctuations in the number of drivers and merchants due to dissatisfaction with the brand, pricing models, and safety incidents. Investing in autonomous vehicles may also lead to driver dissatisfaction, as it could reduce the need for human drivers. Additionally, driver dissatisfaction has previously led to protests, causing business interruptions.
## Conclusión
En esta publicación del blog, exploramos cómo crear y usar agentes con el framework Llama-agents, impulsado por dos modelos de lenguaje grandes distintos: Mistral Nemo y Mistral Large. Demostramos cómo orquestar eficazmente sistemas inteligentes y eficientes en recursos aprovechando las fortalezas de diferentes LLMs.
Si te gusta esta publicación del blog, considera darnos una estrella en [GitHub](https://github.com/milvus-io/milvus). También eres bienvenido a compartir tus experiencias con la comunidad de Milvus uniéndote a nuestro [Discord](https://discord.gg/FG6hMJStWu).
Sigue leyendo

Why Teams Are Migrating from Weaviate to Zilliz Cloud — and How to Do It Seamlessly
Explore how Milvus scales for large datasets and complex queries with advanced features, and discover how to migrate from Weaviate to Zilliz Cloud.

Creating Collections in Zilliz Cloud Just Got Way Easier
We've enhanced the entire collection creation experience to bring advanced capabilities directly into the interface, making it faster and easier to build production-ready schemas without switching tools.

DeepSeek Always Busy? Deploy It Locally with Milvus in Just 10 Minutes—No More Waiting!
Learn how to set up DeepSeek-R1 on your local machine using Ollama, AnythingLLM, and Milvus in just 10 minutes. Bypass busy servers and enhance AI responses with custom data.



