Otimizando sistemas multiagentes com Mistral Large, Mistral Nemo e Llama-agents
Sistemas agênticos estão em ascensão, ajudando desenvolvedores a criar sistemas inteligentes e autônomos. Grandes modelos de linguagem (LLMs) estão se tornando cada vez mais capazes de seguir conjuntos diversos de instruções, tornando-os ideais para gerenciar esses agentes. Esse avanço abre inúmeras possibilidades para lidar com tarefas complexas com mínima intervenção humana em muitas áreas. Por exemplo, sistemas agênticos podem beneficiar o atendimento ao cliente, onde podem lidar com consultas de clientes, resolver problemas e até mesmo fazer upsell de produtos com base nas preferências dos clientes.
Este post fornece um guia abrangente para criar agentes inteligentes usando llama-agents, combinado com o poder dos LLMs Mistral e do Milvus. Aprenderemos como aproveitar o Mistral Nemo para execução de tarefas com boa relação custo-benefício, o Mistral Large para orquestração sofisticada e o Milvus para armazenamento e recuperação eficientes de dados vetoriais. Exploraremos exemplos práticos, incluindo a análise de documentos financeiros e a implementação de filtragem de metadados para criar um sistema de agentes altamente escalável e dinâmico. Acompanhe os exemplos de código detalhados e as instruções passo a passo para criar seus próprios agentes poderosos.
Acompanhe
Eu percorri este tutorial em um webinar, que você pode acompanhar passo a passo abaixo.
Introdução ao Llama-agents, Ollama & Mistral Nemo e Milvus Lite
Llama-agents é uma extensão do LlamaIndex para criar aplicações multiator robustas e com estado usando LLMs.
Ollama & Mistral Nemo – Ollama é uma ferramenta de IA que permite aos usuários executar grandes modelos de linguagem, como o Mistral Nemo, localmente em suas máquinas. Isso permite que você trabalhe com esses modelos nos seus próprios termos, sem precisar de conectividade constante com a internet ou depender de servidores externos.
Milvus Lite é uma versão local e leve do Milvus que pode ser executada no seu laptop, Jupyter Notebook ou Google Colab. Ela permite que você armazene e recupere seus dados não estruturados de forma eficiente.
Como os Llama-agents funcionam
Llama-agents, desenvolvido pela LlamaIndex, é um framework assíncrono por padrão para criar, iterar e colocar em produção sistemas multiagente, incluindo comunicação multiagente, execução distribuída de ferramentas, humano no circuito e muito mais!
No Llama-agents, cada agente é visto como um serviço que processa tarefas recebidas continuamente. Cada agente puxa e publica mensagens de uma fila de mensagens.
Figura- Como os Llama-agents funcionam.png
Figura: Como os Llama-agents funcionam
Instalar dependências
Vamos primeiro instalar todas as dependências necessárias.
! 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()
Carregar dados no Milvus
Vamos baixar alguns dados de exemplo do llama-index, que incluem PDFs sobre a Uber e a Lyft. Usaremos esses dados ao longo do 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'
Agora que temos os dados em nossa máquina, podemos extrair o conteúdo e armazená-lo no banco de dados vetorial Milvus. Para o modelo de embeddings, estamos usando bge-small-en-v1.5, que é um modelo compacto de embeddings de texto com baixo uso de recursos.
Em seguida, criamos uma coleção no Milvus para armazenar e recuperar nossos dados. Estamos usando o Milvus Lite, a versão leve do Milvus, um banco de dados vetorial de alto desempenho que impulsiona aplicações de IA com busca por similaridade vetorial. Você pode instalar o Milvus Lite com um simples pip install pymilvus.
Nossos PDFs são transformados em vetores, e vamos armazená-los no 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 ferramentas
Vamos definir duas ferramentas específicas para nossos dados. A primeira fornece informações sobre a Lyft e a segunda é sobre a Uber. Veremos mais tarde como podemos criar uma ferramenta mais 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 o Agent usando Mistral Nemo 🐠
Para limitar nosso uso de recursos e potencialmente reduzir os custos da nossa aplicação, estamos usando Mistral Nemo com Ollama. Essa combinação nos permite executar o modelo localmente. Mistral Nemo é um LLM pequeno que oferece uma grande janela de contexto de até 128k tokens, o que é muito útil ao trabalhar com documentos grandes. Ele também foi ajustado para seguir instruções precisas de raciocínio, lidar com conversas de múltiplos turnos e gerar código.
Agora, vamos configurar o agent com Mistral Nemo.
from llama_index.llms.ollama import Ollama
from llama_index.core.agent import AgentRunner, ReActAgentWorker, ReActAgent
# Configurar o 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 deve gerar uma resposta semelhante à seguinte:
> 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.
Usando Filtragem de Metadados com Milvus
Embora ter um agente com uma ferramenta definida para cada tipo diferente de documento seja conveniente, isso não escala bem se você tiver muitas empresas para processar. Uma solução melhor é usar Metadata Filtering oferecido pelo Milvus com nosso Agente. Dessa forma, podemos armazenar dados de diferentes empresas em uma coleção, mas recuperar apenas as partes relevantes, economizando tempo e recursos."
O trecho de código abaixo mostra como podemos usar a funcionalidade de meta-filtragem.
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)
Nosso retriever agora está filtrando dados que vêm apenas do documento lyft_2021.pdf, e não deveríamos ter nenhuma informação sobre a 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")
Agora, vamos fazer um teste. Quando perguntado sobre a receita da Uber em 2021, o Agent recuperou zero 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
O Agent consegue encontrar os dados quando perguntado sobre a receita da Lyft em 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")
O resultado retornado é:
> Executando etapa 7f1eebe3-2ebd-47ff-b560-09d09cdd99bd. Entrada da etapa: Qual é a receita da Lyft em 2021?
Pensamento: O idioma atual do usuário é: inglês. Preciso usar uma ferramenta para me ajudar a responder à pergunta.
Ação: company_docs
Entrada da ação: {'input': 'receita da Lyft 2021'}
Observação: A receita da Lyft em 2021 foi gerada principalmente a partir de seu marketplace de compartilhamento de viagens, conectando motoristas e passageiros. A receita foi reconhecida a partir de taxas pagas pelos motoristas pelo uso das ofertas da Lyft Platform de acordo com o ASC 606. Além disso, a receita por Passageiro Ativo atingiu um recorde histórico no quarto trimestre de 2021 devido ao aumento da frequência de viagens, a uma mudança para viagens de maior receita e a receitas de acordos de licenciamento e acesso a dados.
> Executando etapa 072a3253-7eee-44e3-a787-397c9cbe80d8. Entrada da etapa: Nenhuma
Pensamento: O idioma atual do usuário é inglês. Preciso usar uma ferramenta para me ajudar a responder à pergunta.
Ação: company_docs
Entrada da ação: {'input': 'receita da Lyft 2021'}
Observação: A receita da Lyft em 2021 foi impulsionada por um aumento na frequência de viagens, uma mudança para viagens de maior receita, como viagens para aeroportos, e receitas de acordos de licenciamento e acesso a dados. Isso resultou em a Receita por Passageiro Ativo atingir um recorde histórico no quarto trimestre de 2021 em comparação com o trimestre anterior.
> Executando etapa 6494fe6d-27ad-484f-9204-0c4683bfa1c2. Entrada da etapa: Nenhuma
Pensamento: O usuário está perguntando sobre a receita da Lyft em 2021.
Ação: company_docs
Entrada da ação: {'input': 'receita da Lyft 2021'}
Observação: A receita da Lyft em 2021 foi gerada principalmente a partir de seu marketplace de compartilhamento de viagens, conectando motoristas e passageiros. A Receita por Passageiro Ativo atingiu um recorde no quarto trimestre de 2021 devido ao aumento da frequência de viagens e a uma mudança para viagens de maior receita, como viagens para aeroportos. Além disso, a receita foi impulsionada por acordos de licenciamento e acesso a dados a partir do segundo trimestre de 2021.
> Executando etapa 0076b6dd-e7d0-45ac-a39a-4afa5f1aaf47. Entrada da etapa: Nenhuma
Resposta: Observação: A receita total da Lyft em 2021 foi de US$ 3,4 bilhões.
Resposta com filtragem de metadados:
Observação: A receita total da Lyft em 2021 foi de US$ 3,4 bilhões.
Usando um LLM para Criar Filtros de Metadados Automaticamente
Agora, vamos usar um LLM para criar filtros de metadados automaticamente com base na consulta do usuário. Esta etapa nos permite ter um agente mais 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()
Podemos então combinar esta função com nosso Agente.
# 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)
Agora, o Agente criou `Metadatafilters` com a chave `file_name` e o valor `uber_2021.pdf`. Com prompting mais avançado, também seria possível gerar filtros mais avançados.
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
## Orquestrando Tudo com o Mistral Large
O Mistral Large é um modelo mais poderoso do que o Mistral Nemo, mas também é muito maior e mais intensivo em recursos. Ao usá-lo exclusivamente como orquestrador, podemos conservar recursos enquanto ainda nos beneficiamos de agentes inteligentes.
### Por que Usar o Mistral Large como Orquestrador?
O Mistral Large é o modelo principal da Mistral, com capacidades muito boas de raciocínio, conhecimento e programação. É ideal para tarefas complexas que exigem grandes capacidades de raciocínio ou que são altamente especializadas. Ele tem capacidades avançadas de chamada de funções, exatamente o que precisamos para orquestrar nossos diferentes agentes.
Orquestrar com o Mistral Large permite separar responsabilidades dentro da sua estrutura de agentes. Em vez de sobrecarregar o sistema com um modelo pesado para cada tarefa, o Mistral Large pode ser reservado para a tomada de decisões de alto nível, direcionando outros agentes mais adequados a tarefas específicas e menores. Essa abordagem não apenas otimiza o desempenho, mas também reduz os custos operacionais, tornando o sistema mais escalável e eficiente.
Nesta configuração, o Mistral Large atua como o orquestrador central, coordenando as atividades de múltiplos agentes gerenciados pelo Llama-agents. Aqui está uma visão geral:
- **Delegação de Tarefas**: Quando uma consulta complexa é recebida, o Mistral Large determina os agentes e ferramentas mais apropriados para lidar com cada parte da consulta.
- **Coordenação de Agentes**: O Llama-agents gerencia a execução dessas tarefas, garantindo que cada agente receba as entradas necessárias e que suas saídas sejam processadas e integradas corretamente.
- **Síntese de Resultados**: O Mistral Large então compila as saídas de vários agentes em uma resposta coerente e abrangente, garantindo que a saída final seja maior do que a soma de suas partes.
### Agentes Llama
Agora, vamos usar o Mistral Large para orquestrar tudo e usar o agente para gerar a resposta para nós.
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.
## Conclusão
Nesta publicação do blog, exploramos como criar e usar agentes com o framework Llama-agents, impulsionado por dois modelos de linguagem grandes distintos: Mistral Nemo e Mistral Large. Demonstramos como orquestrar de forma eficaz sistemas inteligentes e eficientes em recursos, aproveitando os pontos fortes de diferentes LLMs.
Se você gostou desta publicação do blog, considere nos dar uma estrela no [GitHub](https://github.com/milvus-io/milvus). Você também está convidado a compartilhar suas experiências com a comunidade Milvus juntando-se ao nosso [Discord](https://discord.gg/FG6hMJStWu).
Continue lendo

Optimizing Embedding Model Selection with TDA Clustering: A Strategic Guide for Vector Databases
Discover how Topological Data Analysis (TDA) reveals hidden embedding model weaknesses and helps optimize vector database performance.

Vector Databases vs. Graph Databases
Use a vector database for AI-powered similarity search; use a graph database for complex relationship-based queries and network analysis.

Proactive Monitoring for Vector Database: Zilliz Cloud Integrates with Datadog
we're excited to announce Zilliz Cloud's integration with Datadog, enabling comprehensive monitoring and observability for your vectorDB deployments.



