Ottimizzare i sistemi multi-agente con Mistral Large, Mistral Nemo e Llama-agents
I sistemi agentici sono in crescita e aiutano gli sviluppatori a creare sistemi intelligenti e autonomi. I modelli linguistici di grandi dimensioni (LLM) stanno diventando sempre più capaci di seguire insiemi diversi di istruzioni, il che li rende ideali per gestire questi agenti. Questo progresso apre numerose possibilità per gestire attività complesse con un intervento umano minimo in moltissimi ambiti. Ad esempio, i sistemi agentici possono apportare benefici al servizio clienti, dove possono gestire le richieste dei clienti, risolvere problemi e persino proporre prodotti aggiuntivi in base alle preferenze dei clienti.
Questo post fornisce una guida completa alla creazione di agenti intelligenti utilizzando llama-agents, combinati con la potenza dei Mistral LLMs e di Milvus. Impareremo come sfruttare Mistral Nemo per un’esecuzione delle attività conveniente, Mistral Large per un’orchestrazione sofisticata e Milvus per l’archiviazione e il recupero efficienti dei dati vettoriali. Esploreremo esempi pratici, tra cui l’analisi di documenti finanziari e l’implementazione del filtraggio dei metadati per creare un sistema di agenti altamente scalabile e dinamico. Segui gli esempi di codice dettagliati e le istruzioni passo dopo passo per creare i tuoi agenti potenti.
Segui passo dopo passo
Ho illustrato questo tutorial in un webinar, che puoi seguire passo dopo passo qui sotto.
Introduzione a Llama-agents, Ollama & Mistral Nemo e Milvus Lite
Llama-agents è un’estensione di LlamaIndex per creare applicazioni multi-attore robuste e con stato con gli LLM.
Ollama & Mistral Nemo – Ollama è uno strumento di IA che consente agli utenti di eseguire modelli linguistici di grandi dimensioni, come Mistral Nemo, localmente sulle proprie macchine. Questo ti permette di lavorare con questi modelli alle tue condizioni, senza la necessità di una connettività internet costante o di dipendere da server esterni.
Milvus Lite è una versione locale e leggera di Milvus che può essere eseguita sul tuo laptop, su Jupyter Notebook o su Google Colab. Ti consente di archiviare e recuperare i tuoi dati non strutturati in modo efficiente.
Come funzionano Llama-agents
Llama-agents, sviluppato da LlamaIndex, è un framework async-first per creare, iterare e mettere in produzione sistemi multi-agente, inclusi comunicazione multi-agente, esecuzione distribuita degli strumenti, human-in-the-loop e altro ancora!
In Llama-agents, ogni agente è visto come un servizio che elabora incessantemente le attività in arrivo. Ogni agente preleva e pubblica messaggi da una coda di messaggi.
Figura- Come funzionano Llama-agents.png
Figura: Come funzionano Llama-agents
Installare le dipendenze
Per prima cosa installiamo tutte le dipendenze necessarie.
! 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()
Caricare i dati in Milvus
Scaricheremo alcuni dati di esempio da llama-index, che includono PDF su Uber e Lyft. Useremo questi dati durante tutto il 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'
Ora che abbiamo i dati sulla nostra macchina, possiamo estrarre il contenuto e archiviarlo nel database vettoriale Milvus. Per il modello di embedding, stiamo usando bge-small-en-v1.5, che è un modello compatto di embedding del testo con un basso utilizzo di risorse.
Successivamente, creiamo una collection in Milvus per archiviare e recuperare i nostri dati. Stiamo usando Milvus Lite, la versione leggera di Milvus, un database vettoriale ad alte prestazioni che alimenta applicazioni di IA con ricerca per similarità vettoriale. Puoi installare Milvus Lite con un semplice pip install pymilvus.
I nostri PDF vengono trasformati in vettori, e li archivieremo in 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)
Definire strumenti diversi
Definiremo due strumenti specifici per i nostri dati. Il primo fornisce informazioni su Lyft e il secondo riguarda Uber. Vedremo più avanti come possiamo creare uno strumento più generico.
# 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."
),
),
),
]
Configurare l’Agent usando Mistral Nemo 🐠
Per limitare il nostro utilizzo di risorse e potenzialmente ridurre i costi della nostra applicazione, stiamo usando Mistral Nemo con Ollama. Questa combinazione ci consente di eseguire il modello localmente. Mistral Nemo è un piccolo LLM che offre un’ampia finestra di contesto fino a 128k token, il che è molto utile quando si lavora con documenti di grandi dimensioni. È stato anche fine-tuned per seguire istruzioni precise per il ragionamento, gestire conversazioni multi-turn e generare codice.
Ora, configuriamo l’agent con Mistral Nemo.
from llama_index.llms.ollama import Ollama
from llama_index.core.agent import AgentRunner, ReActAgentWorker, ReActAgent
# Configurare l'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)
Questo LLM dovrebbe generare una risposta simile alla seguente:
> 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.
Utilizzare il filtro dei metadati con Milvus
Sebbene avere un agente con uno strumento definito per ogni diverso tipo di documento sia comodo, non scala bene se hai molte aziende da elaborare. Una soluzione migliore è utilizzare il Filtro dei metadati offerto da Milvus con il nostro Agent. In questo modo, possiamo archiviare i dati di diverse aziende in un'unica raccolta ma recuperare solo le parti rilevanti, risparmiando tempo e risorse."
Lo snippet di codice seguente mostra come possiamo utilizzare la funzionalità di meta-filtraggio.
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)
# Definisci gli strumenti del motore di query con il motore di query filtrato
query_engine_tools = [
QueryEngineTool(
query_engine=filtered_query_engine,
metadata=ToolMetadata(
name="company_docs",
description=(
"Fornisce informazioni sui dati finanziari di varie aziende per l'anno 2021. "
"Usa una domanda dettagliata in testo semplice come input per lo strumento."
),
),
),
]
# Configura l'agente con gli strumenti del motore di query aggiornati
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
Il nostro retriever ora filtra sui dati che provengono solo dal documento lyft_2021.pdf, e non dovremmo avere alcuna informazione su 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")
Ora, facciamo un test. Quando gli viene chiesto il fatturato di Uber nel 2021, l'Agente ha recuperato zero risultati.
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'Agente può trovare i dati quando gli viene chiesto il fatturato di Lyft nel 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")
Il risultato restituito è:
> Esecuzione del passaggio 7f1eebe3-2ebd-47ff-b560-09d09cdd99bd. Input del passaggio: Qual è il fatturato di Lyft nel 2021?
Thought: La lingua attuale dell'utente è: inglese. Devo usare uno strumento per aiutarmi a rispondere alla domanda.
Action: company_docs
Action Input: {'input': 'Lyft revenue 2021'}
Observation: Il fatturato di Lyft nel 2021 è stato generato principalmente dal suo marketplace di ridesharing che collega autisti e passeggeri. Il fatturato è stato rilevato dalle commissioni pagate dagli autisti per l'utilizzo delle offerte della Lyft Platform in conformità con ASC 606. Inoltre, il fatturato per Active Rider ha raggiunto un massimo storico nel quarto trimestre del 2021 grazie all'aumento della frequenza delle corse, a uno spostamento verso corse a più alto fatturato e ai ricavi derivanti da accordi di licenza e accesso ai dati.
> Esecuzione del passaggio 072a3253-7eee-44e3-a787-397c9cbe80d8. Input del passaggio: None
Thought: La lingua attuale dell'utente è inglese. Devo usare uno strumento per aiutarmi a rispondere alla domanda.
Action: company_docs
Action Input: {'input': 'Lyft revenue 2021'}
Observation: Il fatturato di Lyft nel 2021 è stato trainato da un aumento della frequenza delle corse, da uno spostamento verso corse a più alto fatturato come le corse aeroportuali, e dai ricavi derivanti da accordi di licenza e accesso ai dati. Ciò ha portato il fatturato per Active Rider a raggiungere un massimo storico nel quarto trimestre del 2021 rispetto al trimestre precedente.
> Esecuzione del passaggio 6494fe6d-27ad-484f-9204-0c4683bfa1c2. Input del passaggio: None
Thought: L'utente sta chiedendo il fatturato di Lyft nel 2021.
Action: company_docs
Action Input: {'input': 'Lyft revenue 2021'}
Observation: Il fatturato di Lyft nel 2021 è stato generato principalmente dal suo marketplace di ridesharing che collega autisti e passeggeri. Il fatturato per Active Rider ha raggiunto un massimo record nel quarto trimestre del 2021 grazie all'aumento della frequenza delle corse e a uno spostamento verso corse a più alto fatturato, come le corse aeroportuali. Inoltre, il fatturato è stato incrementato da accordi di licenza e accesso ai dati a partire dal secondo trimestre del 2021.
> Esecuzione del passaggio 0076b6dd-e7d0-45ac-a39a-4afa5f1aaf47. Input del passaggio: None
Answer: Observation: Il fatturato totale di Lyft nel 2021 è stato di 3,4 miliardi di dollari.
Response with metadata filtering:
Observation: Il fatturato totale di Lyft nel 2021 è stato di 3,4 miliardi di dollari.
Utilizzare un LLM per creare automaticamente filtri di metadati
Ora, usiamo un LLM per creare automaticamente filtri di metadati in base alla query dell'utente. Questo passaggio ci consente di avere un agente più dinamico.
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(
"Data la seguente domanda, estrai i filtri di metadati rilevanti.\n"
"Considera nomi di aziende, anni e qualsiasi altro attributo rilevante.\n"
"Non scrivere altro testo, solo l'oggetto MetadataFilters"
"Formattalo creando un MetadataFilters come mostrato nel seguente\n"
"MetadataFilters(filters=[ExactMatchFilter(key='file_name', value='lyft_2021.pdf')])\n"
"Se non sono menzionati filtri specifici, restituisce un MetadataFilters() vuoto\n"
"Domanda: {question}\n"
"Filtri di metadati:\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()
Possiamo quindi combinare questa funzione con il nostro Agent.
# Example usage with metadata filtering
question = "Qual è il fatturato di Uber? Questo dovrebbe essere nel file_name: uber_2021.pdf"
filtered_query_engine = create_query_engine(question)
# Definisci gli strumenti del motore di query con il motore di query filtrato
query_engine_tools = [
QueryEngineTool(
query_engine=filtered_query_engine,
metadata=ToolMetadata(
name="company_docs_filtering",
description=(
"Fornisce informazioni sui dati finanziari di varie aziende per l'anno 2021. "
"Usa come input per lo strumento una domanda dettagliata in testo semplice."
),
),
),
]
# Configura l'agente con gli strumenti del motore di query aggiornati
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
response = agent.chat(question)
print("Risposta con filtro dei metadati:")
print(response)
Ora, l'Agente ha creato Metadatafilters con la chiave file_name e il valore uber_2021.pdf. Con prompting più avanzato, sarebbe anche possibile generare filtri più avanzati.
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
Orchestrare tutto con Mistral Large
Mistral Large è un modello più potente di Mistral Nemo, ma è anche molto più grande e più intensivo in termini di risorse. Usandolo esclusivamente come orchestratore, possiamo conservare risorse continuando comunque a beneficiare di agenti intelligenti.
Perché usare Mistral Large come orchestratore?
Mistral Large è il modello di punta di Mistral, con ottime capacità di ragionamento, conoscenza e coding. È ideale per attività complesse che richiedono grandi capacità di ragionamento o sono altamente specializzate. Ha capacità avanzate di function-calling, esattamente ciò di cui abbiamo bisogno per orchestrare i nostri diversi agenti.
Orchestrare con Mistral Large ti consente di separare le responsabilità all'interno del tuo framework di agenti. Invece di appesantire il sistema con un modello pesante per ogni attività, Mistral Large può essere riservato al processo decisionale di alto livello, indirizzando altri agenti più adatti a compiti specifici e più piccoli. Questo approccio non solo ottimizza le prestazioni, ma riduce anche i costi operativi, rendendo il sistema più scalabile ed efficiente.
In questa configurazione, Mistral Large agisce come orchestratore centrale, coordinando le attività di più agenti gestiti da Llama-agents. Ecco una panoramica:
Delega delle attività: Quando viene ricevuta una query complessa, Mistral Large determina gli agenti e gli strumenti più appropriati per gestire ciascuna parte della query.
Coordinamento degli agenti: Llama-agents gestiscono l'esecuzione di queste attività, assicurando che ogni agente riceva gli input necessari e che i loro output siano elaborati e integrati correttamente.
Sintesi dei risultati: Mistral Large quindi compila gli output di vari agenti in una risposta coerente e completa, assicurando che l'output finale sia maggiore della somma delle sue parti.
Llama Agents
Ora, usiamo Mistral Large per orchestrare tutto e usare l'agente per generare la risposta per noi.
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
# crea i componenti del nostro framework multi-agente
message_queue = SimpleMessageQueue()
control_plane = ControlPlaneServer(
message_queue=message_queue,
orchestrator=AgentOrchestrator(llm=MistralAI('mistral-large-latest')),
)
# definisci il 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.
Conclusione
In questo post del blog, abbiamo esplorato come creare e utilizzare agenti con il framework Llama-agents, alimentato da due distinti modelli linguistici di grandi dimensioni: Mistral Nemo e Mistral Large. Abbiamo dimostrato come orchestrare efficacemente sistemi intelligenti ed efficienti nell’uso delle risorse sfruttando i punti di forza di diversi LLM.
Se ti è piaciuto questo post del blog, considera di lasciarci una stella su GitHub. Sei anche invitato a condividere le tue esperienze con la community di Milvus unendoti al nostro Discord.
Continua a leggere

Vector Lakebase: End the AI Data Silo
Learn how Vector Lakebase unifies vector search, data lakes, and AI data operations so teams can serve RAG and agents without copy-and-sync pipelines.

Zilliz Cloud Update: Smarter Autoscaling for Cost Savings, Stronger Compliance with Audit Logs, and More
What's new in Zilliz Cloud? Smarter autoscaling with scale-down, audit logs GA, enhanced SSO, and Milvus 2.6 in Private Preview.

Zilliz Cloud Enterprise Vector Search Powers High-Performance AI on AWS
Zilliz Cloud on AWS powers secure, scalable, ultra-fast vector search for enterprise AI apps, with BYOC, sub-10ms latency, and zero-DevOps simplicity.



