Оптимизация мультиагентных систем с Mistral Large, Mistral Nemo и Llama-agents
Агентные системы набирают популярность, помогая разработчикам создавать интеллектуальные автономные системы. Большие языковые модели (LLM) становятся всё более способными следовать разнообразным наборам инструкций, что делает их идеальными для управления такими агентами. Это развитие открывает множество возможностей для выполнения сложных задач с минимальным участием человека во многих областях. Например, агентные системы могут быть полезны в обслуживании клиентов, где они могут обрабатывать запросы клиентов, решать проблемы и даже предлагать дополнительные продукты на основе предпочтений клиентов.
В этой статье представлен подробный гид по созданию интеллектуальных агентов с использованием llama-agents в сочетании с возможностями Mistral LLMs и Milvus. Мы узнаем, как использовать Mistral Nemo для экономически эффективного выполнения задач, Mistral Large для сложной оркестрации и Milvus для эффективного хранения и поиска векторных данных. Мы рассмотрим практические примеры, включая анализ финансовых документов и реализацию фильтрации по метаданным для создания высокомасштабируемой и динамичной агентной системы. Следуйте подробным примерам кода и пошаговым инструкциям, чтобы создать собственных мощных агентов.
Следуйте вместе с нами
Я прошёл это руководство на вебинаре, который вы можете пошагово посмотреть ниже.
Введение в Llama-agents, Ollama & Mistral Nemo и Milvus Lite
Llama-agents — это расширение LlamaIndex для создания надёжных и сохраняющих состояние многоакторных приложений с LLM.
Ollama & Mistral Nemo – Ollama — это AI-инструмент, который позволяет пользователям запускать большие языковые модели, такие как Mistral Nemo, локально на своих компьютерах. Это позволяет работать с этими моделями на собственных условиях без необходимости постоянного подключения к интернету или зависимости от внешних серверов.
Milvus Lite — это локальная и легковесная версия Milvus, которую можно запускать на ноутбуке, в Jupyter Notebook или Google Colab. Она позволяет эффективно хранить и извлекать ваши неструктурированные данные.
Как работают Llama-agents
Llama-agents, разработанный LlamaIndex, — это async-first фреймворк для создания, итеративной разработки и вывода в продакшен мультиагентных систем, включая мультиагентную коммуникацию, распределённое выполнение инструментов, human-in-the-loop и многое другое!
В Llama-agents каждый агент рассматривается как сервис, бесконечно обрабатывающий входящие задачи. Каждый агент извлекает и публикует сообщения из очереди сообщений.
Рисунок- Как работают Llama-agents.png
Рисунок: Как работают Llama-agents
Установка зависимостей
Сначала установим все необходимые зависимости.
! 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()
Загрузка данных в Milvus
Мы загрузим некоторые примерные данные из llama-index, которые включают PDF-файлы об Uber и Lyft. Мы будем использовать эти данные на протяжении всего руководства.
!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'
Теперь, когда данные находятся на нашей машине, мы можем извлечь содержимое и сохранить его в векторной базе данных Milvus. В качестве модели эмбеддингов мы используем bge-small-en-v1.5 — компактную модель текстовых эмбеддингов с низким потреблением ресурсов.
Далее мы создаем коллекцию в Milvus для хранения и извлечения наших данных. Мы используем Milvus Lite, облегченную версию Milvus, высокопроизводительной векторной базы данных, которая обеспечивает работу AI-приложений с поиском по векторному сходству. Вы можете установить Milvus Lite с помощью простой команды pip install pymilvus.
Наши PDF-файлы преобразуются в векторы, и мы сохраним их в 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)
Определение разных инструментов
Мы определим два инструмента, специфичных для наших данных. Первый предоставляет информацию о Lyft, а второй — об Uber. Позже мы увидим, как можно создать более универсальный инструмент.
# 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."
),
),
),
]
Настройка агента с использованием Mistral Nemo 🐠
Чтобы ограничить использование ресурсов и потенциально снизить затраты нашего приложения, мы используем Mistral Nemo с Ollama. Эта комбинация позволяет запускать модель локально. Mistral Nemo — это небольшая LLM, которая предлагает большое контекстное окно до 128 тыс. токенов, что очень полезно при работе с большими документами. Она также была дообучена следовать точным инструкциям для рассуждений, ведения многоходовых диалогов и генерации кода.
Теперь настроим агента с Mistral Nemo.
from llama_index.llms.ollama import Ollama
from llama_index.core.agent import AgentRunner, ReActAgentWorker, ReActAgent
# Настройка агента
llm = Ollama(model="mistral-nemo", temperature=0.4)
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
# Пример использования
response = agent.chat("Сравните выручку Lyft и Uber в 2021 году.")
print(response)
Эта LLM должна сгенерировать ответ, похожий на следующий:
> Выполняется шаг 7ed275f6-b0de-4fd7-b2f2-fd551e58bfe2. Ввод шага: Сравните выручку Lyft и Uber в 2021 году.
Thought: Текущий язык пользователя: английский. Мне нужно использовать инструменты, чтобы помочь ответить на вопрос.
Action: lyft_10k
Action Input: {'input': "Какова была общая выручка Lyft в 2021 году?"}
huggingface/tokenizers: Текущий процесс только что был разветвлен после того, как параллелизм уже использовался. Отключение параллелизма во избежание взаимных блокировок...
Чтобы отключить это предупреждение, вы можете:
- По возможности избегать использования `tokenizers` до fork
- Явно задать переменную окружения TOKENIZERS_PARALLELISM=(true | false)
Observation: Общая выручка Lyft в 2021 году была получена главным образом от ее marketplace райдшеринга, соединяющего водителей и пассажиров, при этом выручка признавалась за счет сборов, уплачиваемых водителями за использование предложений Lyft Platform в соответствии с ASC 606.
> Выполняется шаг 33064fd3-3c3a-42c4-ab5a-e7ebf8a9325b. Ввод шага: None
Thought: Мне нужно сравнить выручку Lyft и Uber в 2021 году.
Action: uber_10k
Action Input: {'input': "Какова была общая выручка Uber в 2021 году?"}
Observation: $17,455
> Выполняется шаг 7eacfef4-d9da-4cbf-ac07-18f2ff6a3951. Ввод шага: None
Thought: Я получил общую выручку Uber за 2021 год. Теперь мне нужно сравнить ее с выручкой Lyft.
Action: lyft_10k
Action Input: {'input': "Какова была общая выручка Lyft в 2021 году?"}
Observation: Общая выручка Lyft в 2021 году была получена главным образом от их marketplace райдшеринга, соединяющего водителей и пассажиров. Выручка признавалась за счет сборов, уплачиваемых водителями за использование предложений Lyft Platform в соответствии с ASC 606.
> Выполняется шаг 88673e15-b74c-4755-8b9c-2b7ef3acea48. Ввод шага: None
Thought: Я получил общую выручку как Uber, так и Lyft за 2021 год. Теперь мне нужно их сравнить.
Action: Compare
Action Input: {'Uber': '$17,455', 'Lyft': '$3.6 billion'}
Observation: Ошибка: инструмента с именем `Compare` не существует.
> Выполняется шаг bed5941f-74ba-41fb-8905-88525e67b785. Ввод шага: None
Thought: Мне нужно сравнить выручку вручную, поскольку инструмента 'Compare' нет.
Answer: В 2021 году общая выручка Uber составила $17.5 млрд, тогда как общая выручка Lyft составила $3.6 млрд. Это означает, что Uber получил примерно в четыре раза больше выручки, чем Lyft, за тот же год.
Ответ без фильтрации метаданных:
В 2021 году общая выручка Uber составила $17.5 млрд, тогда как общая выручка Lyft составила $3.6 млрд. Это означает, что Uber получил примерно в четыре раза больше выручки, чем Lyft, за тот же год.
Использование фильтрации метаданных с Milvus
Хотя иметь агента с инструментом, определенным для каждого отдельного вида документа, удобно, это плохо масштабируется, если вам нужно обрабатывать много компаний. Лучшее решение — использовать фильтрацию метаданных, предлагаемую Milvus, с нашим Agent. Таким образом, мы можем хранить данные разных компаний в одной коллекции, но извлекать только релевантные части, экономя время и ресурсы."
Фрагмент кода ниже показывает, как можно использовать функциональность мета-фильтрации.
from llama_index.core.vector_stores import ExactMatchFilter, MetadataFilters
# Пример использования с фильтрацией метаданных
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)
Наш ретривер теперь фильтрует данные, которые поступают только из документа lyft_2021.pdf, и у нас не должно быть никакой информации об 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")
Теперь давайте проведём тест. Когда спросили о выручке Uber в 2021 году, Агент получил ноль результатов.
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
Агент может найти данные, когда его спрашивают о выручке Lyft в 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")
Возвращённый результат:
> Выполняется шаг 7f1eebe3-2ebd-47ff-b560-09d09cdd99bd. Входные данные шага: Какова выручка Lyft в 2021 году?
Мысль: Текущий язык пользователя: английский. Мне нужно использовать инструмент, чтобы помочь ответить на вопрос.
Действие: company_docs
Входные данные действия: {'input': 'Lyft revenue 2021'}
Наблюдение: Выручка Lyft в 2021 году в основном была получена от ее маркетплейса райдшеринга, соединяющего водителей и пассажиров. Выручка признавалась из комиссий, уплачиваемых водителями за использование предложений Lyft Platform в соответствии с ASC 606. Кроме того, выручка на активного пассажира достигла исторического максимума в четвертом квартале 2021 года благодаря увеличению частоты поездок, смещению в сторону поездок с более высокой выручкой, а также выручке от соглашений о лицензировании и доступе к данным.
> Выполняется шаг 072a3253-7eee-44e3-a787-397c9cbe80d8. Входные данные шага: None
Мысль: Текущий язык пользователя — английский. Мне нужно использовать инструмент, чтобы помочь ответить на вопрос.
Действие: company_docs
Входные данные действия: {'input': 'Lyft revenue 2021'}
Наблюдение: Выручка Lyft в 2021 году была обусловлена увеличением частоты поездок, смещением в сторону поездок с более высокой выручкой, таких как поездки в аэропорт, а также выручкой от соглашений о лицензировании и доступе к данным. Это привело к тому, что выручка на активного пассажира достигла исторического максимума в четвертом квартале 2021 года по сравнению с предыдущим кварталом.
> Выполняется шаг 6494fe6d-27ad-484f-9204-0c4683bfa1c2. Входные данные шага: None
Мысль: Пользователь спрашивает о выручке Lyft в 2021 году.
Действие: company_docs
Входные данные действия: {'input': 'Lyft revenue 2021'}
Наблюдение: Выручка Lyft в 2021 году в основном была получена от ее маркетплейса райдшеринга, соединяющего водителей и пассажиров. Выручка на активного пассажира достигла рекордного максимума в четвертом квартале 2021 года благодаря увеличению частоты поездок и смещению в сторону поездок с более высокой выручкой, таких как поездки в аэропорт. Кроме того, выручка была увеличена за счет соглашений о лицензировании и доступе к данным, начиная со второго квартала 2021 года.
> Выполняется шаг 0076b6dd-e7d0-45ac-a39a-4afa5f1aaf47. Входные данные шага: None
Ответ: Наблюдение: Общая выручка Lyft в 2021 году составила $3,4 миллиарда.
Ответ с фильтрацией метаданных:
Наблюдение: Общая выручка Lyft в 2021 году составила $3,4 миллиарда.
Использование LLM для автоматического создания фильтров метаданных
Теперь давайте используем LLM для автоматического создания фильтров метаданных на основе запроса пользователя. Этот шаг позволяет нам получить более динамичного агента.
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()
Затем мы можем объединить эту функцию с нашим агентом.
# 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)
Теперь Agent создал `Metadatafilters` с ключом `file_name` и значением `uber_2021.pdf`. При более продвинутом промптинге также было бы возможно генерировать более продвинутые фильтры.
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
## Оркестрация всего с помощью Mistral Large
Mistral Large — более мощная модель, чем Mistral Nemo, но она также намного больше и более ресурсоемкая. Используя ее исключительно как оркестратор, мы можем экономить ресурсы, при этом по-прежнему получая пользу от интеллектуальных агентов.
### Почему стоит использовать Mistral Large в качестве оркестратора?
Mistral Large — флагманская модель Mistral, обладающая очень хорошими возможностями рассуждения, знаниями и навыками программирования. Она идеально подходит для сложных задач, требующих больших возможностей рассуждения или высокой специализации. У нее есть продвинутые возможности вызова функций — именно то, что нам нужно для оркестрации наших различных агентов.
Оркестрация с помощью Mistral Large позволяет разделять зоны ответственности внутри вашего агентного фреймворка. Вместо того чтобы нагружать систему тяжелой моделью для каждой задачи, Mistral Large можно зарезервировать для принятия решений высокого уровня, направляя других агентов, лучше подходящих для конкретных, более мелких задач. Такой подход не только оптимизирует производительность, но и снижает операционные затраты, делая систему более масштабируемой и эффективной.
В этой конфигурации Mistral Large выступает центральным оркестратором, координируя действия нескольких агентов, управляемых Llama-agents. Вот обзор:
- **Делегирование задач**: Когда поступает сложный запрос, Mistral Large определяет наиболее подходящих агентов и инструменты для обработки каждой части запроса.
- **Координация агентов**: Llama-agents управляют выполнением этих задач, обеспечивая, чтобы каждый агент получал необходимые входные данные, а их выходные данные корректно обрабатывались и интегрировались.
- **Синтез результата**: Затем Mistral Large объединяет выходные данные от различных агентов в связный и всеобъемлющий ответ, гарантируя, что итоговый результат превосходит простую сумму его частей.
### Llama Agents
Теперь давайте используем Mistral Large, чтобы оркестрировать всё, и воспользуемся агентом для генерации ответа за нас.
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, )
определите здесь мета-инструменты
meta_tools = [ await MetaServiceTool.from_tool_service( t.metadata.name, message_queue=message_queue, tool_service=tool_service, ) for t in query_engine_tools ]
определите Agent и сервис агента
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="Используется для ответов на вопросы о различных компаниях и их финансовых результатах", service_name="Companies_analyst_agent", )
import logging
измените уровень логирования, чтобы включить или отключить более подробное логирование
logging.getLogger("llama_agents").setLevel(logging.INFO)
Определите Launcher
launcher = LocalLauncher( [agent_server_1, tool_service], control_plane, message_queue, )
query_str = "Каковы факторы риска для Uber?" print(launcher.launch_single(query_str))
Некоторые ключевые факторы риска для Uber включают колебания числа водителей и продавцов из-за неудовлетворенности брендом, моделями ценообразования и инцидентами, связанными с безопасностью. Инвестиции в автономные транспортные средства также могут привести к недовольству водителей, поскольку это может снизить потребность в водителях-людях. Кроме того, недовольство водителей ранее приводило к протестам, вызывая перебои в бизнесе.
## Заключение
В этой статье блога мы рассмотрели, как создавать и использовать агентов с помощью фреймворка Llama-agents, поддерживаемого двумя различными большими языковыми моделями: Mistral Nemo и Mistral Large. Мы продемонстрировали, как эффективно оркестрировать интеллектуальные, ресурсоэффективные системы, используя сильные стороны различных LLM.
Если вам понравилась эта статья блога, пожалуйста, поставьте нам звезду на [GitHub](https://github.com/milvus-io/milvus). Вы также можете поделиться своим опытом с сообществом Milvus, присоединившись к нашему [Discord](https://discord.gg/FG6hMJStWu).
Читать далее

VidTok: Rethinking Video Processing with Compact Tokenization
VidTok tokenizes videos to reduce redundancy while preserving spatial and temporal details for efficient processing.

OpenAI o1: What Developers Need to Know
In this article, we will talk about the o1 series from a developer's perspective, exploring how these models can be implemented for sophisticated use cases.

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.



