Optimisation des systèmes multi-agents avec Mistral Large, Mistral Nemo et Llama-agents
Les systèmes agentiques sont en plein essor, aidant les développeurs à créer des systèmes intelligents et autonomes. Les grands modèles de langage (LLMs) deviennent de plus en plus capables de suivre des ensembles variés d’instructions, ce qui les rend idéaux pour gérer ces agents. Cette avancée ouvre de nombreuses possibilités pour traiter des tâches complexes avec une intervention humaine minimale dans de très nombreux domaines. Par exemple, les systèmes agentiques peuvent bénéficier au service client, où ils peuvent gérer les demandes des clients, résoudre les problèmes et même vendre des produits supplémentaires en fonction des préférences des clients.
Cet article fournit un guide complet pour créer des agents intelligents à l’aide de llama-agents, combinés à la puissance des LLMs Mistral et de Milvus. Nous apprendrons à tirer parti de Mistral Nemo pour une exécution des tâches rentable, de Mistral Large pour une orchestration sophistiquée, et de Milvus pour un stockage et une récupération efficaces des données vectorielles. Nous explorerons des exemples pratiques, notamment l’analyse de documents financiers et la mise en œuvre du filtrage par métadonnées afin de créer un système d’agents hautement évolutif et dynamique. Suivez les exemples de code détaillés et les instructions étape par étape pour créer vos propres agents puissants.
Suivre le tutoriel
J’ai présenté ce tutoriel lors d’un webinaire, que vous pouvez suivre étape par étape ci-dessous.
Introduction à Llama-agents, Ollama & Mistral Nemo, et Milvus Lite
Llama-agents est une extension de LlamaIndex pour créer des applications multi-acteurs robustes et avec état à l’aide de LLMs.
Ollama & Mistral Nemo – Ollama est un outil d’IA qui permet aux utilisateurs d’exécuter localement sur leurs machines de grands modèles de langage, tels que Mistral Nemo. Cela vous permet de travailler avec ces modèles selon vos propres conditions, sans avoir besoin d’une connectivité Internet constante ni de dépendre de serveurs externes.
Milvus Lite est une version locale et légère de Milvus qui peut s’exécuter sur votre ordinateur portable, Jupyter Notebook ou Google Colab. Elle vous permet de stocker et de récupérer efficacement vos données non structurées.
Fonctionnement de Llama-agents
Llama-agents, développé par LlamaIndex, est un framework async-first pour créer, itérer et mettre en production des systèmes multi-agents, incluant la communication multi-agents, l’exécution distribuée d’outils, l’humain dans la boucle, et plus encore !
Dans Llama-agents, chaque agent est considéré comme un service qui traite indéfiniment les tâches entrantes. Chaque agent récupère et publie des messages depuis une file de messages.
Figure- Fonctionnement de Llama-agents.png
Figure : Fonctionnement de Llama-agents
Installer les dépendances
Installons d’abord toutes les dépendances nécessaires.
! 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()
Charger les données dans Milvus
Nous allons télécharger quelques données d’exemple depuis llama-index, qui incluent des PDF sur Uber et Lyft. Nous utiliserons ces données tout au long du tutoriel.
!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'
Maintenant que nous avons les données sur notre machine, nous pouvons extraire le contenu et le stocker dans la base de données vectorielle Milvus. Pour le modèle d’embedding, nous utilisons bge-small-en-v1.5, qui est un modèle compact d’embedding de texte avec une faible consommation de ressources.
Ensuite, nous créons une collection dans Milvus pour stocker et récupérer nos données. Nous utilisons Milvus Lite, la version légère de Milvus, une base de données vectorielle haute performance qui alimente les applications d’IA grâce à la recherche de similarité vectorielle. Vous pouvez installer Milvus Lite avec un simple pip install pymilvus.
Nos PDF sont transformés en vecteurs, et nous les stockerons dans 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)
Définir différents outils
Nous allons définir deux outils spécifiques à nos données. Le premier fournit des informations sur Lyft et le second concerne Uber. Nous verrons plus tard comment créer un outil plus générique.
# 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."
),
),
),
]
Configurer l’Agent avec Mistral Nemo 🐠
Pour limiter notre consommation de ressources et potentiellement réduire les coûts de notre application, nous utilisons Mistral Nemo avec Ollama. Cette combinaison nous permet d’exécuter le modèle localement. Mistral Nemo est un petit LLM qui offre une grande fenêtre de contexte allant jusqu’à 128k tokens, ce qui est très utile lorsque l’on travaille avec de grands documents. Il a également été affiné pour suivre des instructions précises de raisonnement, gérer des conversations à plusieurs tours et générer du code.
Maintenant, configurons l’agent avec Mistral Nemo.
from llama_index.llms.ollama import Ollama
from llama_index.core.agent import AgentRunner, ReActAgentWorker, ReActAgent
# Configurer l’agent
llm = Ollama(model="mistral-nemo", temperature=0.4)
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
# Exemple d’utilisation
response = agent.chat("Compare the revenue of Lyft and Uber in 2021.")
print(response)
Ce LLM devrait générer une réponse similaire à la suivante :
> 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.
Réponse sans filtrage des métadonnées :
En 2021, le chiffre d’affaires total d’Uber était de 17,5 milliards de dollars, tandis que celui de Lyft était de 3,6 milliards de dollars. Cela signifie qu’Uber a généré environ quatre fois plus de chiffre d’affaires que Lyft la même année.
Utilisation du filtrage des métadonnées avec Milvus
Bien qu’avoir un agent avec un outil défini pour chaque type de document différent soit pratique, cela ne passe pas bien à l’échelle si vous avez de nombreuses entreprises à traiter. Une meilleure solution consiste à utiliser le filtrage des métadonnées proposé par Milvus avec notre agent. De cette façon, nous pouvons stocker les données de différentes entreprises dans une seule collection, mais récupérer uniquement les parties pertinentes, ce qui permet de gagner du temps et d’économiser des ressources."
L’extrait de code ci-dessous montre comment nous pouvons utiliser la fonctionnalité de méta-filtrage.
from llama_index.core.vector_stores import ExactMatchFilter, MetadataFilters
# Exemple d’utilisation avec filtrage des métadonnées
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)
Notre retriever filtre maintenant les données provenant uniquement du document lyft_2021.pdf, et nous ne devrions disposer d’aucune information sur 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")
Maintenant, faisons un test. Lorsqu’on l’interroge sur le chiffre d’affaires d’Uber en 2021, l’Agent n’a récupéré aucun résultat.
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
L’Agent peut trouver les données lorsqu’on l’interroge sur le chiffre d’affaires 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")
Le résultat renvoyé est :
> Exécution de l’étape 7f1eebe3-2ebd-47ff-b560-09d09cdd99bd. Entrée de l’étape : Quel est le chiffre d’affaires de Lyft en 2021 ?
Réflexion : La langue actuelle de l’utilisateur est : l’anglais. Je dois utiliser un outil pour m’aider à répondre à la question.
Action : company_docs
Entrée de l’action : {'input': 'Lyft revenue 2021'}
Observation : Le chiffre d’affaires de Lyft en 2021 provenait principalement de sa place de marché de covoiturage mettant en relation les chauffeurs et les passagers. Le chiffre d’affaires était comptabilisé à partir des frais payés par les chauffeurs pour utiliser les offres de la plateforme Lyft conformément à l’ASC 606. De plus, le chiffre d’affaires par passager actif a atteint un niveau record au quatrième trimestre 2021 en raison de l’augmentation de la fréquence des trajets, d’un glissement vers des trajets à chiffre d’affaires plus élevé, et des revenus provenant d’accords de licence et d’accès aux données.
> Exécution de l’étape 072a3253-7eee-44e3-a787-397c9cbe80d8. Entrée de l’étape : None
Réflexion : La langue actuelle de l’utilisateur est l’anglais. Je dois utiliser un outil pour m’aider à répondre à la question.
Action : company_docs
Entrée de l’action : {'input': 'Lyft revenue 2021'}
Observation : Le chiffre d’affaires de Lyft en 2021 a été porté par une augmentation de la fréquence des trajets, un glissement vers des trajets à chiffre d’affaires plus élevé tels que les trajets vers l’aéroport, et des revenus provenant d’accords de licence et d’accès aux données. Cela a permis au chiffre d’affaires par passager actif d’atteindre un niveau record au quatrième trimestre 2021 par rapport au trimestre précédent.
> Exécution de l’étape 6494fe6d-27ad-484f-9204-0c4683bfa1c2. Entrée de l’étape : None
Réflexion : L’utilisateur demande le chiffre d’affaires de Lyft en 2021.
Action : company_docs
Entrée de l’action : {'input': 'Lyft revenue 2021'}
Observation : Le chiffre d’affaires de Lyft en 2021 provenait principalement de sa place de marché de covoiturage mettant en relation les chauffeurs et les passagers. Le chiffre d’affaires par passager actif a atteint un niveau record au quatrième trimestre 2021 en raison de l’augmentation de la fréquence des trajets et d’un glissement vers des trajets à chiffre d’affaires plus élevé, tels que les trajets vers l’aéroport. De plus, le chiffre d’affaires a été stimulé par des accords de licence et d’accès aux données à partir du deuxième trimestre 2021.
> Exécution de l’étape 0076b6dd-e7d0-45ac-a39a-4afa5f1aaf47. Entrée de l’étape : None
Réponse : Observation : Le chiffre d’affaires total de Lyft en 2021 était de 3,4 milliards de dollars.
Réponse avec filtrage des métadonnées :
Observation : Le chiffre d’affaires total de Lyft en 2021 était de 3,4 milliards de dollars.
Utiliser un LLM pour créer automatiquement des filtres de métadonnées
Maintenant, utilisons un LLM pour créer automatiquement des filtres de métadonnées à partir de la requête de l’utilisateur. Cette étape nous permet d’avoir un agent plus dynamique.
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()
Nous pouvons ensuite combiner cette fonction avec notre 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)
Maintenant, l’agent a créé Metadatafilters avec la clé file_name et la valeur uber_2021.pdf. Avec un prompting plus avancé, il serait également possible de générer des filtres plus avancés.
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
Tout orchestrer avec Mistral Large
Mistral Large est un modèle plus puissant que Mistral Nemo, mais il est aussi beaucoup plus grand et plus gourmand en ressources. En l’utilisant uniquement comme orchestrateur, nous pouvons économiser des ressources tout en bénéficiant d’agents intelligents.
Pourquoi utiliser Mistral Large comme orchestrateur ?
Mistral Large est le modèle phare de Mistral, doté de très bonnes capacités de raisonnement, de connaissances et de codage. Il est idéal pour les tâches complexes qui nécessitent de grandes capacités de raisonnement ou qui sont hautement spécialisées. Il dispose de capacités avancées d’appel de fonctions, exactement ce dont nous avons besoin pour orchestrer nos différents agents.
L’orchestration avec Mistral Large vous permet de séparer les responsabilités au sein de votre framework d’agents. Au lieu de surcharger le système avec un modèle lourd pour chaque tâche, Mistral Large peut être réservé à la prise de décision de haut niveau, en dirigeant d’autres agents mieux adaptés à des tâches spécifiques et plus petites. Cette approche optimise non seulement les performances, mais réduit également les coûts opérationnels, rendant le système plus évolutif et efficace.
Dans cette configuration, Mistral Large agit comme l’orchestrateur central, coordonnant les activités de plusieurs agents gérés par Llama-agents. Voici un aperçu :
Délégation des tâches : Lorsqu’une requête complexe est reçue, Mistral Large détermine les agents et outils les plus appropriés pour traiter chaque partie de la requête.
Coordination des agents : Llama-agents gère l’exécution de ces tâches, en veillant à ce que chaque agent reçoive les entrées nécessaires et que leurs sorties soient correctement traitées et intégrées.
Synthèse des résultats : Mistral Large compile ensuite les sorties de différents agents en une réponse cohérente et complète, en veillant à ce que le résultat final soit supérieur à la somme de ses parties.
Llama Agents
Maintenant, utilisons Mistral Large pour tout orchestrer et utiliser l’agent afin de générer la réponse pour nous.
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.
Conclusion
Dans cet article de blog, nous avons exploré comment créer et utiliser des agents avec le framework Llama-agents, alimenté par deux grands modèles de langage distincts : Mistral Nemo et Mistral Large. Nous avons montré comment orchestrer efficacement des systèmes intelligents et économes en ressources en exploitant les forces de différents LLM.
Si vous avez aimé cet article de blog, pensez à nous donner une étoile sur GitHub. Vous êtes également invité à partager vos expériences avec la communauté Milvus en rejoignant notre Discord.
Continuer à lire

Why and How to Migrate from Self-Hosted Milvus to Zilliz Cloud
A simple, step-by-step guide to migrating from Milvus to Zilliz Cloud. Learn both endpoint and backup methods for a smooth, scalable vector database migration.

The Real Bottlenecks in Autonomous Driving — And How AI Infrastructure Can Solve Them
Autonomous driving faces a data bottleneck. Learn how AI-native vector databases like Zilliz solve scale, cost, and insight challenges across AV pipelines.

DeepSeek-VL2: Mixture-of-Experts Vision-Language Models for Advanced Multimodal Understanding
Explore DeepSeek-VL2, the open-source MoE vision-language model. Discover its architecture, efficient training pipeline, and top-tier performance.



