Создание мультиагентной системы с Novita и CrewAI

Создание мультиагентной системы с Novita и CrewAI

По мере того как индустрия ИИ начинала признавать возможности больших языковых моделей (LLM) в области рассуждений, мы решили сделать их более агентными, позволив выполнять более сложные действия. Эти категории больших языковых моделей стали известны как агенты.

Так появились одноагентные системы. Но вскоре стало очевидно, что поручение нескольких действий одному агенту — не самый разумный способ создания агентных систем. Более эффективный подход — использование нескольких агентов, каждый из которых выполняет свою собственную задачу, совместно работая над достижением цели, заданной пользователем.

Однако возникла еще одна проблема. Управление несколькими агентами не так просто, как управление одним. Для решения этой проблемы было представлено несколько фреймворков для мультиагентных систем, и одним из самых перспективных является CrewAI.

CrewAI помогает разработчикам создавать мультиагентные системы. С помощью CrewAI вы можете управлять агентами, их задачами и рабочим процессом. В этой статье мы будем использовать CrewAI вместе с множеством LLM, доступных на Novita, для создания практичных и интеллектуальных мультиагентных систем.

Что такое мультиагентная система и зачем она нужна?

С момента появления больших языковых моделей (LLM) было исследовано несколько подходов к повышению их автономности. Одним из самых популярных стал паттерн ReAct, представленный в статье Синергия рассуждений и действий в языковых моделях. Фреймворки вроде LangChain быстро реализовали ReAct, чтобы наделить LLM агентными возможностями.

Инструменты вроде AutoGPT пошли еще дальше, создав более надежных ИИ-агентов, которые могли выполнять практически любую задачу, заданную пользователем, всего лишь текстовым запросом. Хотя эти одноагентные системы показали большой потенциал, у них были ограничения. Один агент обычно полагается на одну LLM для обработки всех задач, что приводит к нескольким критическим недостаткам:

  • Ограниченный контекст: Один агент должен управлять всеми задачами, используя одно окно контекста. По мере продвижения рабочего процесса у агента в итоге заканчивается место для контекста.
  • Повышенная сложность: По мере того как одному агенту передается все больше задач, рассуждения становится сложнее управлять, что делает агента более склонным к галлюцинациям или сбоям.
  • Единая точка отказа: Поскольку один агент отвечает за все, нет резервной копии. Если он не может обработать задачу, система полностью выходит из строя.
  • Отсутствие параллельной обработки: Задачи обрабатываются одна за другой. Нет встроенной поддержки параллельной работы агентов для ускорения процессов.

Мультиагентные системы были созданы для решения этих проблем. Вместо того чтобы полагаться на одного агента, выполняющего несколько задач, мультиагентная система распределяет обязанности между несколькими агентами, работающими в сотрудничестве. Это помогает избежать проблем, таких как превышение длины контекста, поскольку каждому агенту нужно управлять только своей частью рабочего процесса, и общая нагрузка на контекст снижается.

Мультиагентные конфигурации также позволяют использовать разные модели для разных целей: некоторые можно дообучить для конкретных задач, у некоторых могут быть предопределенные промпты, некоторые могут быть оснащены специализированными инструментами, а другие оптимизированы для рассуждений. Это разнообразие не только повышает производительность, но и позволяет параллельную обработку, делая мультиагентные системы быстрее и эффективнее, чем одноагентные аналоги.

Для создания мультиагентной системы вам нужны два ключевых компонента: провайдер моделей, который поставляет LLM, и фреймворк для мультиагентных систем для управления всем агентным рабочим процессом. В этой статье мы будем использовать Novita в качестве провайдера моделей, а CrewAI — в качестве выбранного нами фреймворка.

Зачем нужен фреймворк вроде CrewAI

Создание мультиагентной системы намного сложнее, чем создание одноагентной. Например, вы можете легко превратить любую модель на Novita в агента, предоставив ей инструменты с использованием вызова функций. Но как только вы начинаете соединять несколько агентов, сложность значительно возрастает. Теперь вам нужно управлять несколькими подвижными частями, включая:

  • Коммуникация и делегирование задач: Вам нужно координировать, как агенты общаются друг с другом и как задачи передаются между ними.
  • Управление инструментами: Без фреймворка вы вручную отвечаете за управление определениями инструментов и JSON-схемами, что может быстро превратиться в хаос.
  • Агентные архитектуры и паттерны: Мультиагентные фреймворки часто имеют встроенную поддержку хорошо зарекомендовавших себя агентных паттернов. Если вы создаете систему с нуля, вам нужно будет отслеживать обновление этих развивающихся паттернов и реализовывать их самостоятельно.
  • Наблюдаемость: Без фреймворка вы также отвечаете за настройку собственных инструментов для мониторинга, отладки и визуализации взаимодействия и работы ваших агентов.

Фреймворк для мультиагентных систем может помочь управлять всей этой сложностью. В этой статье мы будем использовать CrewAI в качестве выбранного нами фреймворка. CrewAI имеет несколько преимуществ перед другими фреймворками: он выделяется своей простотой, используя интуитивные понятия для моделирования мультиагентных систем; он зрелый и хорошо зарекомендовал себя; а также предоставляет отличный опыт для разработчиков.

Основные концепции CrewAI

Для создания мультиагентных систем с помощью CrewAI вам нужно ознакомиться с несколькими основными концепциями, представленными фреймворком. Вот краткий обзор основных из них, с которыми мы будем работать в этой статье:

  • Агенты
  • Задачи
  • Экипажи
  • Процессы
  • Потоки

Агенты

Агенты являются ядром CrewAI. Они представляют собой реальных ИИ-работников, работающих на основе LLM. Каждый агент в CrewAI определяется ролью, целью, которая направляет его принятие решений, и предысторией, которая формирует его личность. Все это представлено в виде текстовых промптов, которые отправляются в LLM. Агенты также могут быть оснащены инструментами, которые они могут выбирать для выполнения конкретных действий. Основная цель агента в CrewAI — выполнить назначенную ему задачу или задачи.

Задачи

Задачи определяют работу, которую необходимо выполнить. В CrewAI вы можете создавать задачи и либо назначать их напрямую конкретным агентам, либо позволять агентам брать их на себя, если они соответствуют требованиям задачи. Каждая задача обычно включает четкое описание, ожидаемый результат и другие соответствующие параметры, например, необязательного агента, который может обработать задачу.

Экипаж

Это ключевая концепция CrewAI. В CrewAI группа агентов, совместно работающих над выполнением задач, называется экипажем. Экипаж также определяет рабочий процесс агентов в его составе.

Процессы

Процесс — это предопределенный рабочий процесс, который указывает экипажу, как выполнять его задачи. CrewAI поддерживает два основных типа процессов:

  • Последовательный: Задачи обрабатываются по одной агентами в экипаже.
  • Иерархический: В этом процессе один агент выступает в роли менеджера, координирующего других агентов и делегирующего задачи по мере необходимости.

Потоки

В то время как процессы являются предопределенными рабочими процессами, потоки CrewAI дают разработчикам гибкость для проектирования пользовательских рабочих процессов агентов. Поток может включать агентов, задачи и даже целые экипажи, что позволяет реализовать более сложные взаимодействия.

Создание экипажей с Novita

Теперь, когда мы рассмотрели основные концепции CrewAI, давайте разберем процесс создания экипажа. В этом примере мы создадим экипаж, предназначенный для помощи пользователям в быстром создании минимально жизнеспособного продукта (MVP). Этот экипаж состоит из трех специализированных агентов:

  • Архитектор: Определяет структуру программного обеспечения и описывает объем MVP. Этот агент работает на модели moonshotai/kimi-k2-instruct, размещенной на Novita.
  • Разработчик: Реализует план Архитектора и пишет фактический код. Он использует инструмент FileWriter для создания всех файлов проекта и работает на модели Novita qwen/qwen3-coder-480b-a35b-instruct.
  • Ревьюер: Анализирует код, сгенерированный Разработчиком, и предлагает улучшения в виде отзывов в стиле diff. Как и Архитектор, он также использует модель moonshotai/kimi-k2-instruct.

Наш экипаж будет использовать последовательный процесс.

Установка и настройка

Теперь, когда у нас есть план, давайте начнем с настройки окружения. Сначала установим CrewAI вместе с встроенной поддержкой инструментов:

pip install 'crewai[tools]'

Далее вам понадобится ваш API-ключ Novita. Как только вы получите его, добавьте его в переменные окружения под именем NOVITA_API_KEY:

export NOVITA_API_KEY=your_api_key_here

После этого мы готовы начать создание экипажа.

Создание LLM

Давайте начнем с импорта необходимых зависимостей:

import os
from crewai import Agent, Task, Crew, Process, LLM
from crewai_tools import FileWriterTool

Далее мы создадим экземпляр FileWriterTool, который будет использоваться агентом-разработчиком для записи файлов на диск:

file_writer_tool = FileWriterTool()

После того как инструменты готовы, мы можем инициализировать LLM для каждого из наших агентов:

architect_llm = LLM(
   model="novita/moonshotai/kimi-k2-instruct",
   temperature=0.5,
   api_base="https://api.novita.ai/v3/openai",
   api_key=os.environ['NOVITA_API_KEY']
)

coder_llm = LLM(
   model="novita/qwen/qwen3-coder-480b-a35b-instruct",
   temperature=0.4,
   api_base="https://api.novita.ai/v3/openai",
   api_key=os.environ['NOVITA_API_KEY']
)

reviewer_llm = LLM(
   model="novita/moonshotai/kimi-k2-instruct",
   temperature=0.5,
   api_base="https://api.novita.ai/v3/openai",
   api_key=os.environ['NOVITA_API_KEY']
)

Эти три экземпляра LLM соответствуют моделям, указанным в нашем плане. Они размещены на Novita и доступны через CrewAI. Под капотом CrewAI использует LiteLLM для подключения и управления этими моделями.

Определение агентов

Теперь давайте создадим трех агентов:

architect = Agent(
   role="Software Architect for MVP Projects",
   goal="Define a basic system structure and simple feature set to guide MVP development",
   backstory="""You specialize in quickly outlining software architectures and project scopes for
minimum viable products. Your plans help guide coders with enough structure to get started while staying lean.""",
   llm=architect_llm,
   verbose=True
)

coder = Agent(
   role="Developer for MVP Projects",
   goal="Implement the MVP using simple, clear code, and write all necessary code files using the FileWriter tool",
   backstory="""You're a practical developer focused on speed. You prioritize working code over polish.
Simulate any runtime behavior if needed, and make sure to keep code clear and modular.""",
   llm=coder_llm,
   verbose=True,
   tools=[file_writer_tool]
)

reviewer = Agent(
   role="Code Reviewer for MVP Projects",
   goal="Read the code files, provide helpful feedback, and write improvements as diffs into a markdown file",
   backstory="""You're a fast but thoughtful reviewer. You check code for clarity, obvious bugs, and
provide improvements as diffs. Instead of modifying code directly, you 
save your suggestions in a markdown file
for easy inspection.""",
   llm=reviewer_llm,
   verbose=True,
   tools=[file_writer_tool]
)

Каждому агенту назначается конкретная роль, цель и предыстория.

Определение задач

Давайте создадим задачи агентов:

architect_task = Task(
   description="""
Create a basic plan for building a simple MVP version of a {project}.
Focus on the core features, basic file structure, and tech stack.
Make the structure minimal but enough to get a working demo.
""",
   expected_output="""
A simple architectural overview with:
- Project goals
- Key components or files
- Basic data flow or structure
""",
   agent=architect,
   output_file="architecture.md"
)

coder_task = Task(
   description="""
Based on the architect's plan, implement the core parts of the {project} MVP.
Keep it lean and functional. Use the FileWriter tool to save all your code files.
If you need to simulate behavior (e.g. without a real interpreter), do so with clear comments or mocked logic.
""",
   expected_output="""
Working code files saved using the FileWriter tool that implement the key features defined in the plan.
Code should be readable and logically structured.
""",
   agent=coder,
   context=[architect_task]
)

review_task = Task(
   description="""
Review the code files created for the {project} MVP. Read each file using the FileRead tool.
Suggest improvements using diffs. Do not modify the original code files directly.
Instead, save all your suggested diffs into a markdown file using the FileWriter tool.
""",
   expected_output="""
A markdown file containing diff-style suggestions for each file reviewed.
""",
   agent=reviewer,
   context=[coder_task],
   output_file="code_review_diffs.md"
)

Создание экипажа

Теперь, когда мы определили наших агентов, соответствующие им LLM и задачи, давайте соберем все вместе, создав экипаж:

code_crew = Crew(
   agents=[architect, coder, reviewer],
   tasks=[architect_task, coder_task, review_task],
   process=Process.sequential,
   verbose=True
)

После того как все настроено, мы можем запустить экипаж:

if __name__ == "__main__":
   code_crew.kickoff(inputs={"project": "Todo App"})

Теперь у нас есть полностью функционирующий экипаж, способный генерировать проект MVP на основе спецификации, заданной пользователем. В примере выше мы попросили экипаж создать простое приложение для списка задач.

Вот как это работает:

  1. Агент Архитектор начинает работу с проектирования архитектуры программного обеспечения и сохранения плана в файл с именем architecture.md.
  2. Затем агент Разработчик берет на вход вывод Архитектора и создает необходимые директории и файлы кода для реализации приложения для списка задач.
  3. Наконец, агент Ревьюер проверяет сгенерированный код и предоставляет предложения в виде diff, сохраняя свои отзывы в файл с именем code_review_diffs.md.

Этот рабочий процесс разработки на основе экипажа мощный и модульный, но у него есть несколько ограничений:

  • Жестко заданные промпты: При встраивании промптов напрямую в код со временем становится сложнее их поддерживать или улучшать.
  • Разрозненная структура: Агенты и задачи определяются внутри кода, что может привести к неорганизованному и сложному для навигации скрипту по мере роста проекта.

В следующем разделе мы рассмотрим, как упорядочить это, вынеся определения агентов и промпты задач во внешние YAML-файлы.

Создание экипажей на основе классов

CrewAI позволяет создавать экипажи на основе классов. Давайте обновим наш предыдущий код, чтобы соответствовать этой структуре. Сначала создайте папку с именем config. Эта папка будет содержать YAML-файлы, определяющие конфигурацию для агентов и задач.

Давайте создадим файл с именем agents.yaml, который будет служить конфигурационным файлом для агентов:

architect:
 role: >
   Software Architect for MVP Projects
 goal: >
   Define a basic system structure and simple feature set to guide MVP development
 backstory: >
   You specialize in quickly outlining software architectures and project scopes for minimum viable products.
  Your plans help guide coders with enough structure to get started while staying lean.

coder:
 role: >
   Developer for MVP Projects
 goal: >
   Implement the MVP using simple, clear code, and write all necessary code files using the FileWriter tool
 backstory: >
   You're a practical developer focused on speed. You prioritize working code over polish.
  Simulate any runtime behavior if needed, and make sure to keep code clear and modular.

reviewer:
 role: >
   Code Reviewer for MVP Projects
 goal: >
   Read the code files, provide helpful feedback, and write improvements as diffs into a markdown file
 backstory: >
   You're a fast but thoughtful reviewer. You check code for clarity, obvious bugs, and provide improvements
  as diffs. Instead of modifying code directly, you save your suggestions in a markdown file for easy inspection.

Этот файл определяет роли, цели и предыстории для каждого агента.

Далее мы создадим файл tasks.yaml для хранения конфигураций задач:

Вместо этого сохраните все предлагаемые вами diff в markdown-файл с использованием инструмента FileWriter.

architect_task:
 description: >
   Create a basic plan for building a simple MVP version of a {project}.
  Focus on the core features, basic file structure, and tech stack.
  Make the structure minimal but enough to get a working demo.
 expected_output: >
   A simple architectural overview with:
  - Project goals
  - Key components or files
  - Basic data flow or structure
 agent: architect
 output_file: architecture.md

coder_task:
 description: >
   Based on the architect's plan, implement the core parts of the {project} MVP.
  Keep it lean and functional. Use the FileWriter tool to save all your code files.
  If you need to simulate behavior (e.g. without a real interpreter), do so with clear comments or mocked logic.
 expected_output: >
   Working code files saved using the FileWriter tool that implement the key features defined in the plan.
  Code should be readable and logically structured.
 agent: coder
 context:
   - architect_task

review_task:
 description: >
   Review the code files created for the {project} MVP. Read each file using the FileRead tool.
  Suggest improvements using diffs. Do not modify the original code files directly.
  Instead, save all your suggested diffs into a markdown file using the FileWriter tool.
 expected_output: >
   A markdown file containing diff-style suggestions for each file reviewed.
 agent: reviewer
 context:
   - coder_task
 output_file: code_review_diffs.md

Далее давайте создадим наш экипаж на основе классов. Для этого мы определим класс и декорируем его декоратором @CrewBase, предоставляемым CrewAI.

@CrewBase
class CodeCrew():
   """Three-agent code crew: architect, coder, reviewer"""

   @agent
   def architect(self) -> Agent:
       pass

   @agent
   def coder(self) -> Agent:
       pass

   @agent
   def reviewer(self) -> Agent:
       pass

   @task
   def architect_task(self) -> Task:
       pass

   @task
   def code_task(self) -> Task:
       pass

   @task
   def review_task(self) -> Task:
       pass

   @crew
   def crew(self) -> Crew:
       pass

В этой структуре:

  • Декоратор @agent используется для определения методов, создающих агентов.
  • Декоратор @task отмечает методы, создающие задачи.
  • Декоратор @crew указывает метод, который собирает весь экипаж.

Теперь давайте рассмотрим полную реализацию:

import os
from crewai import Agent, Crew, Process, Task, LLM
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
from typing import List

from crewai_tools import FileWriterTool

# Instantiate tool
file_writer_tool = FileWriterTool()

@CrewBase
class CodeCrew():

   agents: List[BaseAgent]
   tasks: List[Task]

   agents_config = 'config/agents.yaml'
   tasks_config = 'config/tasks.yaml'
  
   @agent
   def architect(self) -> Agent:
       llm = LLM(
           model="novita/moonshotai/kimi-k2-instruct",
           temperature=0.5,
           api_base="https://api.novita.ai/v3/openai",
           api_key=os.environ['NOVITA_API_KEY']
       )
       return Agent(
           config=self.agents_config['architect'],
           llm=llm,
           verbose=True
       )

   @agent
   def coder(self) -> Agent:
       llm = LLM(
           model="novita/qwen/qwen3-coder-480b-a35b-instruct",
           temperature=0.4,
           api_base="https://api.novita.ai/v3/openai",
           api_key=os.environ['NOVITA_API_KEY']
       )
       return Agent(
           config=self.agents_config['coder'],
           llm=llm,
           verbose=True,
           tools=[file_writer_tool]
       )

   @agent
   def reviewer(self) -> Agent:
       llm = LLM(
           model="novita/moonshotai/kimi-k2-instruct",
           temperature=0.5,
           api_base="https://api.novita.ai/v3/openai",
           api_key=os.environ['NOVITA_API_KEY']
       )
       return Agent(
           config=self.agents_config['reviewer'],
           llm=llm,
           verbose=True,
       )

   @task
   def architect_task(self) -> Task:
       return Task(config=self.tasks_config['architect_task'])

   @task
   def coder_task(self) -> Task:
       return Task(config=self.tasks_config['coder_task'])

   @task
   def review_task(self) -> Task:
       return Task(config=self.tasks_config['review_task'])

   @crew
   def crew(self) -> Crew:
       return Crew(
           agents=self.agents,
           tasks=self.tasks,
           process=Process.sequential,
           verbose=True
       )

Этот код определяет все необходимые методы и включает атрибуты как для агентов, так и для задач. Он также указывает пути к конфигурационным файлам, которые используются в методах агентов и задач для загрузки соответствующих настроек.

Теперь вы можете запустить экипаж, добавив следующий код в скрипт:

def main():
   code_crew = CodeCrew()
   code_crew.crew().kickoff(inputs={"project": "Todo App"})
if __name__ == '__main__':
   main()

Создание потоков с Novita

Ранее мы создали экипаж, который использовал последовательный процесс. Теперь давайте рассмотрим, как создать поток, следующий пользовательскому рабочему процессу.

Наш рабочий процесс

Мы хотим спроектировать мультиагентную систему поддержки клиентов, в которой есть ведущий агент, отвечающий за классификацию проблем клиентов. На основе классификации система определит, какой специализированный агент лучше всего подходит для решения проблемы. Конфигурация состоит из четырех агентов:

  • Агент поддержки клиентов: Это ведущий агент. Он получает проблему клиента и классифицирует ее по одной из следующих категорий: Оплата, Техническая или Общая.
  • Агент по оплате: Обрабатывает все проблемы, связанные с оплатой.
  • Технический агент: Обрабатывает технические проблемы.
  • Общий агент: Обрабатывает любые проблемы, не попадающие в вышеперечисленные категории.

The Customer Support Flow

Определение состояния потока

Потоки в CrewAI имеют общее состояние. Это состояние доступно для всех агентов и экипажей внутри потока. Для нашего потока поддержки клиентов состояние содержит метку проблемы и запрос пользователя.

Давайте импортируем необходимые модули и определим наше состояние:

import json
import os
from typing import Literal, Dict, Any
from pydantic import BaseModel, ValidationError
from crewai import Agent, LLM
from crewai.flow.flow import Flow, start, router, listen

# Define the flow state
class SupportState(BaseModel):
   issue: Literal["billing", "technical", "general"] = "general"
   message: str = ""

Создание потока

Потоки в CrewAI основаны на графах и используют событийно-ориентированную систему для обработки переходов между узлами. Для создания нашего потока мы начнем с узла, который классифицирует проблему, за которым последует узловой маршрутизатор, определяющий, на какой обрабатывающий узел направить запрос на основе классификации.

class CustomerSupportFlow(Flow[SupportState]):

   @start()
   def classify_issue(self):
       pass

   @router(classify_issue)
   def route_based_on_issue(self) -> str:
       print(f"📨 Routing to agent for issue type: {self.state.issue}")
       if self.state.issue == "billing":
           return "billing"
       if self.state.issue == "technical":
           return "technical"
       else:
           return "general"       

   @listen("billing")
   def handle_billing(self):
       pass

   @listen("technical")
   def handle_technical(self):
       pass

   @listen("general")
   def handle_general(self):
       pass

Метод, декорированный @start(), является точкой входа в поток. В этом случае он обрабатывает классификацию проблемы. Метод, декорированный @router(), выполняется после classify_issue и определяет, на какой агент направить запрос. Остальные методы используют событийно-ориентированную систему для ответа, когда к ним направляют запрос.

Реализация методов потока

Теперь давайте реализуем каждый метод и назначим соответствующего агента для каждого:

class CustomerSupportFlow(Flow[SupportState]):

   @start()
   def classify_issue(self) -> Dict[str, Any]:
       intake_agent = Agent(
           role="User Intake Agent",
           goal="Classify user support issue and summarize the message",
           backstory="You classify the user query into billing, technical, or general categories.",
           llm=LLM(
               model="novita/qwen/qwen2.5-vl-72b-instruct",
               temperature=0.3,
               api_base="https://api.novita.ai/v3/openai",
               api_key=os.environ["NOVITA_API_KEY"]
           ),
           verbose=True
       )
      
       prompt = f"""
           A user submitted this message: "{self.state.message}"

           Your task:
           1. Identify whether the issue is "billing", "technical", or "general".
           2. Rephrase or extract the message clearly.

           Respond in valid JSON format like the example below:

           {{
               "issue": "billing",
               "message": "The user has been charged twice for their subscription and is requesting a refund."
           }}
       """

       output = intake_agent.kickoff(prompt, response_format=SupportState)
      
       try:
           # Parse the JSON string
           print(output.raw)
           parsed_json = json.loads(output.raw)

           # Validate with Pydantic
           validated = SupportState(**parsed_json)

           # Save to state
           self.state.issue = validated.issue
           self.state.message = validated.message

       except (json.JSONDecodeError, ValidationError) as e:
           print("❌ Failed to parse or validate response:", e)
           self.state.issue = "general"

   @router(classify_issue)
   def route_based_on_issue(self) -> str:
       print(f"📨 Routing to agent for issue type: {self.state.issue}")
       if self.state.issue == "billing":
           return "billing"
       if self.state.issue == "technical":
           return "technical"
       else:
           return "general"       

   @listen("billing")
   def handle_billing(self):
       agent = Agent(
           role="Billing Agent",
           goal="Handle billing questions, refunds, and invoice issues",
           backstory="You resolve billing-related queries effectively.",
           llm=LLM(
               model="novita/meta-llama/llama-3.3-70b-instruct",
               temperature=0.5,
               api_base="https://api.novita.ai/v3/openai",
               api_key=os.environ["NOVITA_API_KEY"]
           ),
           verbose=True
       )
       result = agent.kickoff(self.state.message)
       print("💰 Billing Agent Response:", result)

   @listen("technical")
   def handle_technical(self):
       agent = Agent(
           role="Technical Support Agent",
           goal="Help users resolve technical issues",
           backstory="You're a technical expert providing troubleshooting support.",
           llm=LLM(
               model="novita/meta-llama/llama-3.1-8b-instruct",
               temperature=0.5,
               api_base="https://api.novita.ai/v3/openai",
               api_key=os.environ["NOVITA_API_KEY"]
           ),
           verbose=True
       )
       result = agent.kickoff(self.state.message)
       print("🛠 Technical Agent Response:", result)

   @listen("general")
   def handle_general(self):
       agent = Agent(
           role="General Support Agent",
           goal="Provide helpful answers to non-technical and non-billing questions",
           backstory="You're friendly and well-informed about our services.",
           llm=LLM(
               model="novita/minimaxai/minimax-m1-80k",
               temperature=0.5,
               api_base="https://api.novita.ai/v3/openai",
               api_key=os.environ["NOVITA_API_KEY"]
           ),
           verbose=True
       )
       result = agent.kickoff(self.state.message)
       print("📋 General Agent Response:", result)

Метод classify_issue использует Pydantic для обеспечения возврата моделью корректного ответа. После завершения этой настройки мы можем запустить поток с помощью следующего кода:

def run():
   flow = CustomerSupportFlow()
   flow.plot("CustomerSupportFlowPlot")

   # Example input message
   example_input = {
       "message": "Hello, I was charged twice for my subscription and need a refund."
   }

   flow.kickoff(inputs=example_input)

if __name__ == "__main__":
   run()

Заключение

Для создания мультиагентной системы вам нужны два ключевых компонента: провайдер моделей, предлагающий широкий выбор моделей, и фреймворк для мультиагентных систем для оркестрации их взаимодействий. В этой статье мы показали, как Novita и CrewAI могут эффективно выполнять эти роли. Чтобы узнать больше о CrewAI, обязательно изучите их документацию. А если вы хотите поэкспериментировать с большим количеством моделей для ваших экипажей, загляните на площадку для тестирования LLM Novita.

Репозиторий с файлами — https://github.com/novitalabs/Novita-CollabHub/tree/main/examples/novita-crewai

О Novita AI

NovitaAI является облачной ИИ-платформой, которая предлагает разработчикам простой способ развертывания ИИ-моделей с использованием нашего простого API, а также предоставляет доступное и надежное облако GPU для построения и масштабирования решений.