Ir para o conteúdo

Prática - Agent de agência de viagens

O projeto que iremos utilizar neste lab consiste num Agent voltado para a criação de roteiros de viagens personalizados. O resultado esperado consiste num arquivo Markdown, contendo uma opção de hospedagem, três opções gastronômicas e três opções de pontos turísticos no destino. As opções de acomodação, gastronomia e visitas turísticas serão escolhidas de acordo com o orçamento informado.

Código-fonte do projeto

Você pode baixar o projeto pronto clicando neste link.

Deploy e implantação do projeto:

  • Vamos realizar o deploy do projeto no Orquestrador. Em seguida, iremos inicializar uma tarefa para gerar o roteiro de viagem.

Sobre o deploy

Você pode acessar o tutorial passo-a-passo para realizar o deploy neste link da documentação.

Indicamos a seguinte configuração:

  • Label do bot: agente-viagens-v1
  • versão: 1.0

Explorando a estrutura do Agent:

Abaixo, listamos as características do Agent de viagens:

  • Objetivo: Criar um roteiro personalizado, trazendo opção de acomodações, restaurantes e pontos turísticos no destino indicado e no orçamento disponível para a viagem.

  • Resultado final: Retornar um roteiro em formato Markdown com informações sobre Hospedagem, e três opções de gastronomia local e pontos turísticos.

  • Ferramentas utilizadas: Para melhorar o resultado, iremos utilizar o SerperDevTool para realizar pesquisas no mecanismo de buscas Google.

  • Motor de raciocínio: Utilizaremos o motor de raciocínio GPT-4, para realizar as buscas de forma mais eficiente e filtrar resultados que estejam mais alinhados ao objetivo passado ao Agent.

  • Arquitetura utilizada: Utilizaremos a arquitetura Multi-Agent, pois podemos ter um agente voltado para realizar as pesquisas sobre turismo no destino, e outro Agent voltado para filtrar as pesquisas identificar resultados mais adequados ao orçamento e objetivo do cliente.

  • Framework utilizado para construir o Agent: O framework para construção do Agent será o CrewAI, pois sua robustez e segurança nos permitirá criar agents de forma descomplicada.

Aviso

Para explorar todos os recursos do framework CrewAI, acesse o link da documentação da CrewAI clicando aqui

Pré-configuração para usar ferramentas e motor de raciocínio

Para utilizar a ferramenta SerperDevTool e o motor de raciocínio _GPT-4, é necessário criar chaves de API para utilização desses recursos e armazená-las no Cofre de Credenciais da BotCity. Veja como obter as chaves:

Criando um Cofre de Credenciais na BotCity

Configure o cofre de credenciais da BotCity com os seguintes dados:

  • label do cofre: agents_credentials
  • chaves: SERPER_API_KEY e OPENAI_API_KEY

Arquivos do projeto

Abaixo, indicamos os arquivos existentes no projeto e a função de cada um deles.

Dependências utilizadas no projeto

Para este projeto, o arquivo requirements.txt contém as seguintes dependências:

botcity-maestro-sdk
crewai
crewai-tools

Crie um ambiente virtual

Sempre recomendamos a criação de um ambiente virtual para isolar o ambiente de execução do projeto e garantir que não haja nenhum conflito com outras dependências. Veja como criar um ambiente virtual clicando aqui

Definindo os agentes e suas tarefas

Iremos definir as características dos agentes e as tarefas que devem ser executadas. A configuração será feita em arquivos de extensão .yaml, segregados na pasta setup/config/, permitindo ajustes de comportamento, motor de raciocínio, objetivos e prompts de comando sem a necessidade de alterar o código-fonte principal.

agent-viagens/
    ├──setup/
    │   ├── config/
    │   │   ├── agents.yaml    # Definição das personalidades e funções (Quem)
    │   │   └── tasks.yaml     # Definição das missões e entregas (O quê)

Para o Agent de roteiro de viagens, iremos precisar de dois Atores (ou agentes):

  • Pesquisador: Responsável por gerar relatórios, pesquisando sobre os pontos turísticos, referências gastronômicas e acomodações existentes no destino.

  • Consultor de turismo: Responsável por filtrar o relatório do pesquisador e trazer opções que se adaptam às preferências e orçamento do cliente.

Tendo em mãos a função de cada Agente, iremos configurar o arquivo para definir as atribuições dos agentes, e definir o motor de raciocínio que cada um irá utilizar. No arquivo, iremos definir os seguintes pontos:

  • role: Descreve qual é o papel desempenhado pelo agente

  • goal: Define o objetivo principal que o agente deve cumprir. Nesta seção, é essencial fornecer um objetivo de forma clara e coesa, para trazer um resultado satisfatório.

  • backstory: Seção indicada para fornecer o contexto referente ao papel desempenhado pelo agente. Com isso, podemos indicar a forma que o agente pode atuar para trazer os resultados esperados. veja o exemplo:

    Você é um pesquisador experiente formado em Turismo. Possui grandes habilidades em identificar as características mais marcantes do destino. Você gera relatórios direto ao ponto, indicando os pontos turísticos mais conhecidos, hotéis excelentes e bons restaurantes.

  • LLM: Indica o motor de raciocínio empregado em cada agente. Em ambos os agentes, utilizaremos o openai/gpt-4

Saiba mais sobre a estruturação dos agentes

Visite a documentação do framework CrewAI para saber mais sobre as configurações possíveis dos agentes clicando aqui

Abaixo, veja o arquivo agents.yaml completo:

pesquisador_destinos:
  role: >
    Pesquisador de uma grande agencia de viagens
  goal: >
    Procurar por hotéis, pontos gastronômicos e turísticos da cidade de destino.
  backstory: >
    Você é um pesquisador experiente formado em Turismo. Possui grandes habilidades em identificar
    as características mais marcantes do destino. Você gera relatórios direto ao ponto, indicando os pontos
    turísticos mais conhecidos, hotéis excelentes e bons restaurantes.
  llm: openai/gpt-4


consultor_turismo:
  role: >
    Cria roteiros para viagens detalhados, com descrição de locais e preços médios dentro do budget.
  goal: >
    Cria roteiros para viagens indicando bons hotéis, passeios turísticos e restaurantes
    existentes no destino.
  backstory: >
    Você estuda meticulosamente os relatórios existentes do destino indicado, e cria roteiros com preços,
    descrições curtas e diretas sobre o que visitar no destino indicado.
  llm: openai/gpt-4

Em seguida, iremos configurar as tarefas desempenhadas pelos agentes. A configuração será feita no arquivo denominado tasks.yaml com os seguintes pontos:

  • description: Seção voltada para uma descrição objetiva explicando qual será a tarefa desempenhada pelo agent.

  • expected_output: Indica o resultado esperado.

  • agent: Indica o agent responsável pela tarefa.

Veja como o arquivo tasks.yaml está estruturado neste projeto:

pesquisar_task:
  description: >
    Realizar uma pesquisa sobre o destino {destino}, trazendo detalhes sobre hotéis localizados em pontos seguros e estratégicos, além dos passeios turisticos e referências gastronomicas pertencentes à região do {destino}
    Se certifique sobre encontrar informações relevantes e atuais, com uma média de preços diários de hotéis, passeios e média de preço de restaurantes. O ano atual é 2025.
  expected_output: >
    Uma lista com pelo menos 5 hotéis, 5 restaurantes e 5 passeios para serem feitos no {destino}.
  agent: pesquisador_destinos

roteirizar_task:
  description: >
    Ler o relatório que recebeu e, com base no orçamento do cliente e nos valores do relatório do destino, criar um roteiro de viagem personalizado.
  expected_output: >
    um roteiro com o hotel, 3 restaurantes a serem visiatdos e 3 passeios a serem feitos no destino, em formato markdown.
  agent: consultor_turismo

O código Python para ativar os agentes

Com as tasks e agentes devidamente configurados, precisaremos criar o arquivo para manipular os agentes e outro arquivo para orquestrar este AI Agent. A estrutura de arquivos do nosso projeto deve se alterar para o seguinte formato:

agent-viagens/
    ├──setup/
    │   ├── config/
    │   │   ├── agents.yaml    # Definição das personalidades e funções (Quem)
    │   │   └── tasks.yaml     # Definição das missões e entregas (O quê)
    └── crew.py        # Responsável por ativar os agentes e executar as tarefas.
├── bot.py             # Constitui a parte lógica do processo
└── requirements.txt   # Arquivo com as dependências utilizadas

A seguir, iremos indicar como o arquivo crew.py e bot.py estão estruturados.

Arquivo crew.py

Este arquivo define a estrutura lógica e a orquestração de uma equipe de agentes de IA utilizando o framework CrewAI. Ele estará localizado na pasta setup/

Vale destacar que este arquivo é o responsável por identificar os agentes, tarefas e identificar a forma como os agentes executarão as tarefas. Neste cenário, o arquivo configura a execução como um Processo Sequencial, garantindo que o consultor só comece a trabalhar após o pesquisador entregar os dados.

Veja o que este arquivo contém:

  • Orquestração de Agentes (CrewBase): Utiliza a classe BotTourCrew para organizar e instanciar agentes e tarefas de forma modular.

  • Definição de Agentes:

    • Pesquisador de Destinos: Equipado com a ferramenta SerperDevTool para realizar buscas reais na internet sobre locais e preços.

    • Consultor de Turismo: Focado na criação do roteiro final com base nos dados coletados.

  • Mapeamento de Tarefas: Integra as definições de tarefas (configuradas externamente no arquivo tasks.yaml) aos agentes correspondentes.

  • Gatilhos de Ciclo de Vida (Hooks):

    • before_kickoff: Exibe uma mensagem de boas-vindas antes de iniciar a execução.

    • after_kickoff: Exibe uma mensagem de conclusão após o processamento dos agentes.

Atenção

Na função pesquisador_destinos,a qual está exibida no código-fonte abaixo, iremos adicionar uma ferramenta (tool) para o agent obter informações de acomodações e locais para visitar realizando buscas na web. Existem ferramentas no mercado como o Tavily e o SerperDevTool. No caso, irei utilizar o SerperDevTool para otimizar as buscas usando o Google.

Saiba mais sobre como estruturar o crew.py

O arquivo crew.py pode receber diversas configurações para orquestrar a ação dos agentes de forma organizada e eficiente. Saiba mais sobre as configurações possíveis acessando este link

Código-fonte:

Veja o código-fonte do arquivo crew.py abaixo:

from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task, before_kickoff, after_kickoff
from crewai_tools import SerperDevTool
from crewai.agents.agent_builder.base_agent import BaseAgent
from typing import List

@CrewBase
class BotTourCrew():

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

    @agent
    def pesquisador_destinos(self) -> Agent:
        return Agent(
            config=self.agents_config['pesquisador_destinos'], 
            verbose=True,
            tools=[SerperDevTool()]
        )

    @agent
    def consultor_turismo(self) -> Agent:
        return Agent(
            config=self.agents_config['consultor_turismo'],
            verbose=True
        )

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

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

    @before_kickoff
    def before_kickoff_function(self, inputs):
        print('A BotTour vai criar o melhor roteiro de viagens da sua vida...')
        return inputs

    @after_kickoff
    def after_kickoff_function(self, result):
        print('Se prepare para boas experiências no seu destino...')
        return result

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

Arquivo bot.py

Este arquivo representa o ponto de entrada de uma automação que integra o BotCity Orchestrator com o framework de agentes de IA.

Neste arquivo, você encontrará recursos para:

  • Orquestração e Integração: Atua como a ponte entre o orquestrador BotCity Orchestrator e a equipe de agentes de IA (BotTourCrew). Iremos obter as credenciais armazenadas no cofre de credenciais, chamar a função principal para ativar os agents e por fim, reportar o status do Agent de Viagens no orquestrador.
import os

from botcity.maestro import *
from rich.console import Console
from rich.markdown import Markdown

from setup.crew import BotTourCrew

# Conexão com o BotCity Maestro
maestro = BotMaestroSDK.from_sys_args()
maestro.RAISE_NOT_CONNECTED = False
maestro.VERIFY_SSL_CERT = False

execution = maestro.get_execution()

#Função para inicializar o ativar o agent de viagens
def run(destino: str, budget: str) -> str:
    inputs = {
        'destino': destino,
        'budget': budget
    }
    output = BotTourCrew().crew().kickoff(inputs=inputs)
    return output.raw

if __name__ == '__main__':

    #Prepara o ambiente e chama a função run
    print(f"Inicializando tarefa {execution.task_id}...")
  • Gestão Segura de Credenciais: Recupera chaves de API (OpenAI, SerperDevTool) diretamente do cofre de credenciais do Orchestrator, evitando a exposição de segredos no código, e em seguida, as configura como variáveis de ambiente para o Framework CrewAI conseguir se conectar com o LLM e o SerperDevTool
if __name__ == '__main__':

    # Carrega credenciais do cofre
    SERPER_API_KEY = maestro.get_credential(label="agents_credentials", key="SERPER_API_KEY")
    OPENAI_API_KEY = maestro.get_credential(label="agents_credentials", key="OPENAI_API_KEY")

    # Configura credenciais como var. de ambiente
    os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
    os.environ['SERPER_API_KEY'] = SERPER_API_KEY
  • Processamento de Parâmetros: Podemos passar as opções de orçamento e destino diretamente no código, ou até mesmo realizando a captura dinamicamente os parâmetros de entrada (destino e budget) configurados para a tarefa no orquestrador.

Criando Parâmetros na automação com BotCity

Após realizarmos o deploy da automação, podemos seguir o passo-a-passo indicado na documentação para criar os parâmetros destino e budget na automação, e alterarmos sempre que criarmos uma nova task para esta automação. Veja como criar parâmetros acessando este link.

Veja a configuração recomendada:

  • parâmetro destino:

    • label: destino
    • type: TEXT
    • required: ativado
  • parâmetro budget:

    • label: budget
    • type: TEXT
    • required: ativado

Temos o snippet de código para obter os valores dos parâmetros:

if __name__ == '__main__':
    ...


    try:
        destino: str = execution.parameters.get("destino")
        budget: str = execution.parameters.get("budget")

        maestro.alert(
            task_id=execution.task_id,
            title="Info Alert",
            message="Agent de viagens procurando o melhor do destino...",
            alert_type=AlertType.INFO)

    except Exception as exc:
            maestro.error(maestro.task_id, exc)
            status = AutomationTaskFinishStatus.FAILED
            message = f"Houve falha de execução ==> erro :{exc}"

    finally:
        maestro.finish_task(maestro.task_id,status=status, message=message)
  • Execução dos Agentes: Dispara o processo do AI Agent (kickoff), passando os dados coletados para que os agentes gerem o roteiro de viagem. Temos a função run(), a qual foi implementada para chamar os agents e passar as informações de destino e budget.

  • Interface e Feedback Visual: Utiliza a biblioteca rich para renderizar e exibir o roteiro final formatado em Markdown diretamente no console.

  • Persistência e Artefatos: Gera um arquivo local de extensão .md com o nome personalizado conforme o destino.

    • Faz o upload automático desse arquivo como um artefato para o Orquestrador, permitindo o download posterior pelo portal.
  • Gestão de Ciclo de Vida e Erros: Envia alertas de status durante a execução.

    • Trata exceções para garantir que, em caso de erro, a falha seja reportada corretamente ao orquestrador.

    • Finaliza a tarefa oficialmente com o status de SUCCESS ou FAILED.

Código-fonte bot.py:
import os

from botcity.maestro import BotMaestroSDK, AutomationTaskFinishStatus, AlertType
from rich.console import Console
from rich.markdown import Markdown

from setup.crew import BotTourCrew

maestro = BotMaestroSDK.from_sys_args()
maestro.RAISE_NOT_CONNECTED = False
maestro.VERIFY_SSL_CERT = False

execution = maestro.get_execution()

def run(destino: str, budget: str) -> str:
    inputs = {
        'destino': destino,
        'budget': budget
    }
    output = BotTourCrew().crew().kickoff(inputs=inputs)
    return output.raw

if __name__ == '__main__':

    SERPER_API_KEY = maestro.get_credential(label="agents_credentials", key="SERPER_API_KEY")
    OPENAI_API_KEY = maestro.get_credential(label="agents_credentials", key="OPENAI_API_KEY")

    os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
    os.environ['SERPER_API_KEY'] = SERPER_API_KEY

    try:

        destino: str = execution.parameters.get("destino")
        budget: str = execution.parameters.get("budget")

        maestro.alert(
            task_id=execution.task_id,
            title="Info Alert",
            message="O Agent de viagens inicializou sua tarefa...",
            alert_type=AlertType.INFO)

        output = run(destino, budget)
        console = Console()
        console.print(Markdown(output))
        nome_arquivo = f"roteiro-viagem-{destino}.md"

        with open(nome_arquivo, 'w', encoding='utf-8') as arquivo:
            arquivo.write(output)

        print(f"Arquivo '{nome_arquivo}' gerado com sucesso!")

        # A extensão é de outros tipos de arquivo
        maestro.post_artifact(
            task_id=execution.task_id,
            artifact_name="roteiro",
            filepath= f"./{nome_arquivo}"
        )

        status = AutomationTaskFinishStatus.SUCCESS
        message = "Tarefa finalizada com sucesso!"
        item_processed = 1
        item_error = 0
    except Exception as exc:
        maestro.error(maestro.task_id, exc)
        status = AutomationTaskFinishStatus.FAILED
        message = f"Houve falha de execução ==> erro :{exc}"
        item_processed = 0
        item_error = 1
    finally:
        total_items = item_processed + item_error
        maestro.finish_task(maestro.task_id,
                            status=status,
                            message=message,
                            total_items=total_items,
                            processed_items=item_processed,
                            failed_items=item_error)

Executando o Agent de Viagem:

Após implantarmos o Agent e estudar a sua estrutura para entender como funcionará, vamos seguir com a criação de uma tarefa e checar o resultado gerado.

Passo 1: Criando uma nova tarefa

  • No Orquestrador, vamos acessar a opção "Nova Tarefa", localizada no menu lateral esquerdo.

  • Em seguida, iremos localizar a automação que implantamos no início deste lab, e clicar no botão "Nova Tarefa":

nova task

  • Em seguida, vamos definir os valores dos campos destino e budget. Aqui, você pode fornecer os valores que desejar. Neste exemplo, indiquei o destino como Belo Horizonte, Minas Gerais e um budget de 5000. Em seguida clicaremos no botão "Criar" para efetivar a criação da tarefa:

parametros

Passo 2: Executar

  • Com a tarefa criada, basta ativar o Runner vinculado à automação e aguardar a execução. Como resultado, teremos o arquivo roteiro-Belo Horizonte, Minas Gerais.md gerado e armazenado na seção Arquivos de Resultado, pronto para ser baixado e visualizado:

roteiro gerado