Agentes de IA no Azure Cosmos DB
Os agentes de IA são projetados para executar tarefas específicas, responder perguntas e automatizar processos para os usuários. Esses agentes variam amplamente em complexidade. Eles vão desde chatbots simples, passando por copilots, até assistentes avançados de IA na forma de sistemas digitais ou robóticos que podem executar fluxos de trabalho complexos de forma autônoma.
Este artigo fornece visões gerais conceituais e amostras detalhadas de implementação de agentes de IA.
O que são agentes de IA?
Ao contrário dos modelos de linguagem grandes (LLMs) autônomos ou sistemas de software/hardware baseados em regras, os agentes de IA possuem os seguintes recursos comuns:
- Planejamento: os agentes de IA são capazes de planejar e executar ações sequencialmente para atingir objetivos específicos. A integração de LLMs revolucionou esses recursos de planejamento.
- Uso de ferramentas: os agentes de IA avançados podem utilizar várias ferramentas, como execução de código, pesquisa e recursos de computação, para executar tarefas com eficiência. Os agentes de IA geralmente usam ferramentas por meio de chamadas de função.
- Percepção: os agentes de IA podem perceber e processar informações de seu ambiente, o que os tornam mais interativos e conscientes do contexto. Essas informações incluem elementos visuais, auditivos e outros dados sensoriais.
- Memória: os agentes de IA possuem a capacidade de lembrar-se de interações (uso de ferramentas e percepção) e comportamentos (uso de ferramentas e planejamento) anteriores. Eles armazenam essas experiências e fazem até mesmo uma autorreflexão para fundamentar ações futuras. Esse componente de memória permite continuidade e o aprimoramento do desempenho do agente ao longo do tempo.
Observação
O uso do termo memória no contexto dos agentes de IA é diferente do conceito de memória do computador (como memória volátil, não volátil e persistente).
Copilots
Os copilots são um tipo de agente de IA. Eles trabalham lado a lado com os usuários em vez de operar de forma independente. Ao contrário dos agentes totalmente automatizados, os copilots fornecem sugestões e recomendações para ajudar os usuários na execução de tarefas.
Por exemplo, quando um usuário está escrevendo um email, um copilot pode sugerir expressões, frases ou parágrafos. O usuário também pode pedir ao copilot para encontrar informações relevantes em outros emails ou arquivos para respaldar uma sugestão (confira geração aumentada de recuperação). O usuário pode aceitar, rejeitar ou editar as passagens sugeridas.
Agentes autônomos
Os agentes autônomos podem operar com mais independência. Ao configurar agentes autônomos para ajudar na composição de um email, você poderá capacitá-los a executar as seguintes tarefas:
- Consultar emails, chats, arquivos existentes e outras informações internas e públicas relacionadas ao assunto em questão.
- Executar análises qualitativas ou quantitativas das informações coletadas e tirar conclusões relevantes para o email.
- Escrever o email completo com base nas conclusões e incorporar evidências comprobatórias.
- Anexar arquivos relevantes ao email.
- Revisar o email para garantir que todas as informações incorporadas sejam factualmente corretas e as afirmativas sejam válidas.
- Selecionar os destinatários adequados para as opções Para, Cc e Cco, e procurar os respectivos endereços de email.
- Agendar um horário apropriado para enviar o email.
- Fazer o acompanhamento se respostas forem esperadas, mas não recebidas.
Você pode configurar os agentes para executar cada uma das tarefas anteriores com ou sem aprovação humana.
Sistemas multiagente
Uma estratégia popular para alcançar agentes autônomos com desempenho é o uso de sistemas multiagente. Nos sistemas multiagente, diversos agentes autônomos, em formato digital ou robótico, interagem ou trabalham em conjunto para alcançar objetivos individuais ou coletivos. Os agentes em um sistema podem operar de forma independente e possuir seus próprios conhecimentos ou informações. Cada agente também tem a capacidade de perceber seu ambiente, tomar decisões e executar ações com base em seus objetivos.
Principais características dos sistemas multiagente:
- Autônomos: cada agente funciona de forma independente. Toma suas próprias decisões sem intervenção humana direta ou controle por outros agentes.
- Interativos: os agentes se comunicam e colaboram entre si para compartilhar informações, negociar e coordenar suas ações. Essa interação pode ocorrer por meio de vários protocolos e canais de comunicação.
- Orientados a objetivos: os agentes em um sistema multiagente são projetados para cumprir metas específicas, que podem ser alinhadas a objetivos individuais ou a um objetivo comum compartilhado entre os agentes.
- Distribuídos: sistemas multiagente funcionam de maneira distribuída, sem um ponto de controle único. Essa distribuição aumenta a consistência, a escalabilidade e a eficiência dos recursos do sistema.
Um sistema multiagente fornece as seguintes vantagens com relação a um copilot ou a uma única instância de inferência de LLM:
- Raciocínio dinâmico: se comparados às solicitações baseadas em cadeias de pensamento ou árvores de pensamento, os sistemas multiagente permitem uma navegação dinâmica por meio de diversos caminhos de raciocínio.
- Habilidades sofisticadas: os sistemas multiagente podem lidar com problemas complexos ou em larga escala ao executar processos de tomada de decisão minuciosos e distribuir tarefas entre vários agentes.
- Memória aprimorada: os sistemas multiagente com memória podem superar as janelas de contexto de LLMs para permitir uma melhor compreensão e retenção de informações.
Implementação de agentes de IA
Raciocínio e planejamento
Planejamento e raciocínio complexo são a marca registrada dos agentes autônomos avançados. Estruturas populares para agentes autônomos incorporam uma ou mais das seguintes metodologias (com links para páginas de arquivos arXiv) para raciocínio e planejamento:
-
Aprimora a cadeia de pensamento quando o modelo se autoquestiona explicitamente e responde às perguntas de acompanhamento antes de responder à pergunta inicial.
-
Usa os LLMs tanto para gerar rastreamentos de raciocínio quanto ações específicas por tarefa de forma intercalada. Os rastreamentos de raciocínio ajudam o modelo a induzir, acompanhar e atualizar planos de ação, juntamente com o tratamento de exceções. As ações permitem que o modelo se conecte com fontes externas, como bases de dados de conhecimento ou ambientes, para coletar informações adicionais.
-
Elabora um plano para dividir a tarefa inteira em subtarefas menores e, em seguida, executar as subtarefas de acordo com o plano. Essa abordagem atenua os erros de cálculo, erros de ausência de etapas e erros de mal-entendidos semânticos que costumam aparecer nas solicitações de cadeia de pensamento sem treinamento prévio.
-
Usa agentes de reflexão que refletem verbalmente sobre sinais de comentários de tarefa. Esses agentes mantêm seu próprio texto reflexivo em um buffer de memória episódico para induzir uma melhor tomada de decisão em ensaios subsequentes.
Estruturas
Várias estruturas e ferramentas podem facilitar o desenvolvimento e a implantação de agentes de IA.
Para a percepção e uso de ferramentas que não requerem um planejamento sofisticado e memória, algumas das estruturas de orquestração de LLMs mais populares são: LangChain, LlamaIndex, Prompt Flow e Kernel Semântico.
Para fluxos de trabalho avançados e autônomos de planejamento e execução, o AutoGen impulsionou uma onda multiagente que teve início no final de 2022. A API de Assistentes da OpenAI permite que seus usuários criem agentes nativamente dentro do ecossistema do GPT. Os LangChain Agents e LlamaIndex Agents também surgiram mais ou menos na mesma ocasião.
Dica
O exemplo de implementação posteriormente neste artigo mostra como criar um sistema multiagente simples usando uma das estruturas populares e um sistema de memória de agente unificado.
Sistema de memória de agentes de IA
A prática predominante para experimentar aplicativos aprimorados por IA desde 2022 até 2024 tem incluído o uso de sistemas de gerenciamento de banco de dados autônomos para diversos fluxos de trabalho ou tipos de dados. Por exemplo, um banco de dados em memória para armazenamento em cache, um banco de dados relacional para dados operacionais (incluindo rastreamento/logs de atividade e histórico de conversação do LLM) e um banco de dados vetorial puro para o gerenciamento de incorporações.
No entanto, essa prática de usar uma rede complexa de bancos de dados autônomos pode prejudicar o desempenho do agente de IA. Integrar todos esses bancos de dados diferentes em um sistema de memória coeso, interoperável e resiliente para agentes de IA é um desafio por si só.
Além disso, muitos dos serviços de banco de dados usados com frequência não são otimizados para a velocidade e a escalabilidade de que os sistemas de agentes de IA precisam. Os pontos fracos individuais desses bancos de dados ficam exacerbados nos sistemas multiagente.
Bancos de dados na memória
Bancos de dados em memória são excelentes em termos de velocidade, mas podem ter dificuldades com a persistência de dados em larga escala que um agente de IA requer.
Bancos de dados relacionais
Bancos de dados relacionais não são ideais para as diversas modalidades e esquemas fluidos dos dados com os quais os agentes lidam. Além disso, os bancos de dados relacionais requerem esforços manuais e até mesmo tempo de inatividade para gerenciar o provisionamento, particionamento e fragmentação.
Bancos de dados vetoriais puros
Bancos de dados vetoriais puros tendem a ser menos eficazes para operações transacionais, atualizações em tempo real e cargas de trabalho distribuídas. Os bancos de dados vetoriais puros mais populares hoje em dia oferecem de modo geral:
- Nenhuma garantia sobre leituras e gravações.
- Rendimento de ingestão limitado.
- Pouca disponibilidade (abaixo de 99,9%, ou uma indisponibilidade anualizada de quase 9 horas ou mais).
- Um único nível de consistência (eventual).
- Índice vetorial dentro da memória com uso intensivo de recursos.
- Opções multilocatário limitadas.
- Segurança limitada.
Características de um sistema de memória robusto de agente de IA
Assim como sistemas de gerenciamento de banco de dados eficientes são essenciais para o desempenho dos aplicativos de software, é crucial fornecer aos agentes alimentados por LLMs informações relevantes e úteis para orientar sua inferência. Sistemas de memória robustos permitem organizar e armazenar tipos diferentes de informações que os agentes podem recuperar no momento da inferência.
Atualmente, os aplicativos alimentados por LLM costumam usar a geração aumentada de recuperação, que usa pesquisa semântica básica ou busca em vetores para recuperar passagens ou documentos. A busca em vetores pode ser útil para localizar informações gerais. Mas a busca em vetores pode não capturar o contexto, a estrutura ou as relações específicas relevantes para uma determinada tarefa ou domínio.
Por exemplo, se a tarefa for escrever código, a busca em vetores poderá não ser capaz de recuperar a árvore de sintaxe, o layout do sistema de arquivos, os resumos de código ou as assinaturas de API importantes para gerar um código coerente e correto. Da mesma forma, se a tarefa for trabalhar com dados tabulares, a busca em vetores poderá não ser capaz de recuperar o esquema, as chaves estrangeiras, os procedimentos armazenados ou os relatórios úteis para consultar ou analisar os dados.
Compor uma estrutura que inclua uma rede de bancos de dados em memória, relacionais e vetoriais autônomos (como descrito anteriormente) tampouco é uma solução ideal para os diversos tipos de dados. Essa abordagem pode funcionar para sistemas de agentes prototípicos. No entanto, adiciona gargalos de complexidade e desempenho que podem dificultar o desempenho de agentes autônomos avançados.
Portanto, um sistema de memória robusto deve ter as seguintes características.
Multimodal
Os sistemas de memória de um agente de IA devem fornecer coleções diferentes que armazenam metadados, relações, entidades, resumos ou outros tipos de informações que podem ser úteis para diferentes tarefas e domínios. Essas coleções podem ser baseadas na estrutura e no formato dos dados, como documentos, tabelas ou código. Ou elas podem ser baseadas no conteúdo e no significado dos dados, como conceitos, associações ou etapas processuais.
Os sistemas de memória não são apenas essenciais para os agentes de IA. Eles também são importantes para as pessoas que desenvolvem, mantêm e usam esses agentes.
Por exemplo, pode ser necessária a supervisão humana dos fluxos de trabalho de planejamento e execução dos agentes em tempo quase real. Durante essa supervisão, pode ser necessário interferir fornecendo diretrizes ou fazer edições embutidas nos diálogos ou monólogos dos agentes. A auditoria humana do raciocínio e das ações dos agentes pode se fazer necessária para verificar a validade do resultado final.
As interações entre agentes e pessoas provavelmente se darão em linguagens naturais ou de programação, enquanto os agentes "pensam", "aprendem" e "lembram" por meio de incorporações. Essa diferença modal dos dados impõe um outro requisito para a consistência dos sistemas de memória entre as diversas modalidades de dados.
Operacional
Os sistemas de memória devem fornecer bancos de memória diferentes que armazenem informações relevantes para a interação com o usuário e com o ambiente. Essas informações podem incluir históricos de chat, preferências do usuário, dados sensoriais, decisões tomadas, fatos aprendidos ou outros dados operacionais que são atualizados com muita frequência e em grandes volumes.
Esses bancos de memória podem ajudar os agentes a lembrar informações de curto e longo prazo, evitar se repetir ou se contradizer e manter a coerência da tarefa. Esses requisitos precisam se provar verdadeiros mesmo se os agentes executarem uma infinidade de tarefas sucessivas não relacionadas. Em casos avançados, os agentes também podem simular vários planos de ramificação divergentes ou convergentes em diferentes pontos.
Compartilhável, mas também separável
Em nível macro, os sistemas de memória devem permitir que vários agentes de IA colaborem em um problema ou processem diferentes aspectos do problema fornecendo uma memória compartilhada acessível a todos os agentes. A memória compartilhada pode facilitar o intercâmbio de informações e a coordenação das ações entre os agentes.
Ao mesmo tempo, o sistema de memória deve permitir que os agentes preservem suas próprias personas e características, como suas coleções exclusivas de prompts e memórias.
Como criar um sistema de memória consistente para o agente de IA
As características acima exigem que os sistemas de memória de um agente de IA sejam altamente escalonáveis e ágeis. Unir meticulosamente bancos de dados em memória, relacionais e vetoriais díspares (conforme descrito anteriormente) pode funcionar para aplicativos habilitados para IA em estágio inicial. No entanto, essa abordagem adiciona gargalos de complexidade e desempenho que podem dificultar o desempenho de agentes autônomos avançados.
Ao substituir todos os bancos de dados autônomos, o Azure Cosmos DB pode atuar como uma solução unificada para sistemas de memória de agentes de IA. Sua consistência foi bem-sucedida ao capacitar o serviço do ChatGPT da OpenAI a se ampliar dinamicamente com alta confiabilidade e pouca manutenção. Alimentado por um mecanismo de átomos, registros e sequências, trata-se do primeiro serviço de banco de dados NoSQL, relacional e vetorial globalmente distribuído que oferece um modo sem servidor. Os agentes de IA criados tendo como base o Azure Cosmos DB oferecem velocidade, escala e simplicidade.
Velocidade
O Azure Cosmos DB fornece latência de milissegundo de dígito único. Essa funcionalidade o torna adequado para processos que exigem acesso e gerenciamento rápidos de dados. Esses processos incluem cache (cache tradicional e cache semântico), transações e cargas de trabalho operacionais.
Essa baixa latência é crucial para os agentes de IA que precisam executar um raciocínio complexo, tomar decisões em tempo real e fornecer respostas imediatas. Além disso, o uso do algoritmo DiskANN pelo serviço fornece uma busca em vetores precisa e rápida com consumo mínimo de memória.
Escala
O Azure Cosmos DB é projetado para distribuição global e escalabilidade horizontal. Ele oferece suporte para E/S de várias regiões e multilocação.
O serviço ajuda a garantir que os sistemas de memória possam se expandir perfeitamente e acompanhar agentes em rápido crescimento e dados associados. A garantia de disponibilidade em seu contrato de nível de serviço (SLA) se traduz em menos de 5 minutos de tempo de inatividade por ano. Os serviços de banco de dados vetoriais puro, por outro lado, vêm com 9 horas ou mais de tempo de inatividade. Essa disponibilidade fornece uma base sólida para cargas de trabalho críticas. Ao mesmo tempo, os vários modelos de serviço no Azure Cosmos DB, como Capacidade Reservada ou Sem Servidor, podem ajudar a reduzir os custos financeiros.
Simplicidade
O Azure Cosmos DB pode simplificar o gerenciamento de dados e a arquitetura ao integrar várias funcionalidades de banco de dados em uma única plataforma coesa.
Suas funcionalidades de banco de dados vetoriais integrados podem armazenar, indexar e consultar incorporações junto com os dados correspondentes em linguagens naturais ou de programação. Essa funcionalidade permite maior consistência de dados, escala e desempenho.
Sua flexibilidade dá suporte às diversas modalidades e esquemas fluidos de metadados, relações, entidades, resumos, históricos de chat, preferências do usuário, dados sensoriais, decisões, fatos aprendidos ou outros dados operacionais envolvidos nos fluxos de trabalho de um agente. O banco de dados indexa todos os dados automaticamente sem requerer gerenciamento de índice ou esquema, permitindo que os agentes de IA executem consultas complexas com rapidez e eficiência.
O Azure Cosmos DB é totalmente gerenciado, o que elimina a sobrecarga de tarefas de administração de banco de dados, como escala, aplicação de patch e backups. Assim, os desenvolvedores podem se concentrar na criação e otimização dos agentes de IA sem se preocupar com a infraestrutura de dados subjacente.
Recursos avançados
O Azure Cosmos DB incorpora recursos avançados, como o feed de alterações, que permite acompanhar e responder às alterações de dados em tempo real. Essa funcionalidade é útil para os agentes de IA que precisam reagir a novas informações imediatamente.
Além disso, o suporte integrado às gravações de vários mestres permite uma alta disponibilidade e resiliência, garantindo a operação contínua dos agentes de IA mesmo em caso de falhas regionais.
Os cinco níveis de consistência disponíveis (de forte a eventual) também podem suprir várias cargas de trabalho distribuídas, dependendo dos requisitos do cenário.
Dica
Você pode escolher entre duas APIs do Azure Cosmos DB para criar o sistema de memória do seu agente de IA:
- O Azure Cosmos DB for NoSQL, que oferece 99,999% de garantia de disponibilidade e fornece três algoritmos de busca em vetores: IVF, HNSW e DiskANN
- O Azure Cosmos DB for MongoDB, baseado em vCore, que oferece garantia de disponibilidade de 99,995% e fornece dois algoritmos de busca em vetores: IVF e HNSW (DiskANN chegando em breve)
Para obter informações sobre as garantias de disponibilidade para essas APIs, consulte os SLAs do serviço.
Amostra de implementação
Esta seção explora a implementação de um agente autônomo para processar consultas e reservas de passageiros em um aplicativo de viagem de uma empresa de cruzeiros marítimos.
Os chatbots são um conceito de longa data, mas os agentes de IA estão avançando além da conversa humana básica para realizar tarefas baseadas na linguagem natural. Essas tarefas tradicionalmente exigiam lógica codificada. O agente de viagens de IA neste exemplo de implementação usa a estrutura do LangChain Agent para planejamento de agente, uso de ferramentas e percepção.
Seu sistema de memória unificada usa as o banco de dados vetorial e as funcionalidades do repositório de documentos do Azure Cosmos DB para lidar com as consultas dos passageiros e facilitar as reservas de passagens. Usar o Azure Cosmos DB para essa finalidade ajuda a garantir velocidade, escala e simplicidade, conforme descrito anteriormente.
O agente de exemplo opera em um back-end do FastAPI Python. Ele dá suporte a interações do usuário por meio de uma interface do usuário do React JavaScript.
Pré-requisitos
- Uma assinatura do Azure. Se você não tiver uma, poderá experimentar o Azure Cosmos DB gratuitamente por 30 dias sem criar uma conta do Azure. A avaliação gratuita não requer um cartão de crédito e nenhum compromisso após o período de avaliação.
- Um conta da API da OpenAI ou do Serviço OpenAI do Azure.
- Um cluster vCore no Azure Cosmos DB for MongoDB. Você pode criar um seguindo este início rápido.
- Um ambiente de desenvolvimento integrado, como o Visual Studio Code.
- Python 3.11.4 instalado no ambiente de desenvolvimento.
Baixe o projeto
Todos os conjuntos de dados de código e de exemplo estão disponíveis neste repositório GitHub. O repositório inclui estas pastas:
- carregador: essa pasta contém código Python para carregar amostras de documentos e incorporações de vetor no Azure Cosmos DB.
- api: essa pasta contém o projeto do FastAPI Python para hospedar o agente de viagens de IA.
- web: essa pasta contém código para a interface web do React.
Carregar documentos de viagem no Azure Cosmos DB
O repositório GitHub contém um projeto Python no diretórioloader. Ele destina-se a carregar os documentos de viagem de exemplo no Azure Cosmos DB.
Configurar o ambiente
Configure seu ambiente virtual do Python no diretório loader executando o seguinte:
python -m venv venv
Ative seu ambiente e instale as dependências no diretório carregador:
venv\Scripts\activate
python -m pip install -r requirements.txt
Crie um arquivo chamado .env no diretório loader para armazenar as variáveis de ambiente a seguir:
OPENAI_API_KEY="<your OpenAI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"
Carregar documentos e vetores
O arquivo Python main.py funciona como o ponto de entrada central para carregar dados no Azure Cosmos DB. Esse código processa as amostras de dados de viagem do repositório do GitHub, incluindo informações sobre navios e destinos. O código também gera pacotes de itinerário de viagem para cada navio e destino, para que os viajantes possam armazená-los usando o agente de IA. A ferramenta CosmosDBLoader é responsável por criar coleções, incorporações de vetor e índices na instância do Azure Cosmos DB.
Este é o conteúdo do main.py:
from cosmosdbloader import CosmosDBLoader
from itinerarybuilder import ItineraryBuilder
import json
cosmosdb_loader = CosmosDBLoader(DB_Name='travel')
#read in ship data
with open('documents/ships.json') as file:
ship_json = json.load(file)
#read in destination data
with open('documents/destinations.json') as file:
destinations_json = json.load(file)
builder = ItineraryBuilder(ship_json['ships'],destinations_json['destinations'])
# Create five itinerary packages
itinerary = builder.build(5)
# Save itinerary packages to Cosmos DB
cosmosdb_loader.load_data(itinerary,'itinerary')
# Save destinations to Cosmos DB
cosmosdb_loader.load_data(destinations_json['destinations'],'destinations')
# Save ships to Cosmos DB, create vector store
collection = cosmosdb_loader.load_vectors(ship_json['ships'],'ships')
# Add text search index to ship name
collection.create_index([('name', 'text')])
Carregue os documentos e vetores e crie índices simplesmente executando o seguinte comando no diretório loader:
python main.py
Aqui está a saída do main.py:
--build itinerary--
--load itinerary--
--load destinations--
--load vectors ships--
Criar o agente de viagens de IA usando o FastAPI Python
O agente de viagens de IA é hospedado em uma API de back-end por meio do FastAPI Python, que facilita a integração com a interface do usuário front-end. O projeto da API processa solicitações do agente ao contextualizar os prompts do LLM de acordo com a camada de dados, especificamente os vetores e documentos no Azure Cosmos DB.
Além disso, o agente faz uso de várias ferramentas, especialmente as funções do Python fornecidas na camada de serviço da API. Este artigo se concentra no código necessário para os agentes de IA dentro do código da API.
O projeto da API no repositório do GitHub é estruturado da seguinte maneira:
- Componentes de modelagem de dados usam modelos Pydantic.
- Componentes da camada da web são responsáveis por rotear as solicitações e gerenciar a comunicação.
- Componentes da camada de serviço são responsáveis pela lógica de negócios principal e pela interação com a camada de dados, o LangChain Agent e as ferramentas do agente.
- Componentes da camada de dados responsáveis por interagir com o armazenamento de documentos e busca em vetores do Azure Cosmos DB for MongoDB.
Configurar o ambiente para a API
Usamos o Python versão 3.11.4 para desenvolvimento e testes da API.
Configure seu ambiente virtual do Python no diretório api:
python -m venv venv
Ative seu ambiente e instale as dependências usando o arquivo requirements no diretório api:
venv\Scripts\activate
python -m pip install -r requirements.txt
Crie um arquivo chamado .env no diretório api para armazenar suas variáveis de ambiente:
OPENAI_API_KEY="<your Open AI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"
Agora que você configurou o ambiente e configurou variáveis, execute o seguinte comando no diretório api para iniciar o servidor:
python app.py
O servidor do FastAPI é iniciado na porta 8000 do loopback 127.0.0.1 do localhost por padrão. Você pode acessar os documentos do Swagger usando o seguinte endereço do localhost: http://127.0.0.1:8000/docs
.
Usar uma sessão para a memória do agente de IA
É imperativo que o agente de viagens tenha a capacidade de fazer referência a informações fornecidas anteriormente na conversa em andamento. Essa capacidade é comumente conhecida como memória no contexto dos LLMs.
Para atingir esse objetivo, use o histórico de mensagens de chat armazenado na instância do Azure Cosmos DB. O histórico de cada sessão de chat é armazenado usando uma ID de sessão para garantir que somente as mensagens da sessão de conversa em curso fiquem acessíveis. Essa necessidade é a razão por trás da existência de um método Get Session
na API. Trata-se de um método de espaço reservado para gerenciar sessões da web com o objetivo de ilustrar o uso do histórico de mensagens de chat.
Selecione Experimentar para /session/
.
{
"session_id": "0505a645526f4d68a3603ef01efaab19"
}
Para o agente de IA, só precisamos simular uma sessão. Assim, o método stubbed-out simplesmente retorna uma ID de sessão gerada para acompanhar o histórico de mensagens. Em uma implementação prática, essa sessão seria armazenada no Azure Cosmos DB e, possivelmente, no localStorage
do React.
Este é o conteúdo de web/session.py:
@router.get("/")
def get_session():
return {'session_id':str(uuid.uuid4().hex)}
Iniciar uma conversa com o agente de viagens de IA
Use a ID da sessão obtida na etapa anterior para iniciar um novo diálogo com o agente de IA, para que você possa validar sua funcionalidade. Vamos conduzir nosso teste enviando a seguinte frase: "Quero tirar umas férias relaxantes".
Selecione Experimentar para /agent/agent_chat
.
Use este parâmetro de exemplo:
{
"input": "I want to take a relaxing vacation.",
"session_id": "0505a645526f4d68a3603ef01efaab19"
}
A execução inicial resulta em uma recomendação para os cruzeiros marítimos "Tranquil Breeze" e "Fantasy Seas Adventure", já que são considerados os cruzeiros mais relaxantes disponíveis por meio da busca em vetores. Esses documentos têm a pontuação mais alta para similarity_search_with_score
que é chamada na camada de dados da nossa API, data.mongodb.travel.similarity_search()
.
As pontuações de pesquisa de similaridade são exibidas como saídas da API para fins de depuração. Aqui está a saída após uma chamada para data.mongodb.travel.similarity_search()
:
0.8394561085977978
0.8086545112328692
2
Dica
Se a busca em vetores não estiver retornando documentos, modifique o limite similarity_search_with_score
ou o valor do filtro de pontuação conforme necessário ([doc for doc, score in docs if score >=.78]
) em data.mongodb.travel.similarity_search()
.
Chamar o agent_chat
pela primeira vez cria uma nova coleção chamada history
no Azure Cosmos DB para armazenar a conversa para cada sessão. Essa chamada permite que o agente acesse o histórico de mensagens do chat armazenado, na medida do necessário. Execuções subsequentes do agent_chat
com os mesmos parâmetros produzem resultados variados, na medida em que os extraem da memória.
Explorar o agente de IA
Quando você integra o agente de IA dentro da API, os componentes de pesquisa na web são responsáveis por iniciar todas as solicitações. Os componentes de pesquisa na web são seguidos pelo serviço de pesquisa e, por fim, os componentes de dados.
Nesse caso específico, você usa uma pesquisa de dados do MongoDB que se conecta ao Azure Cosmos DB. As camadas facilitam o intercâmbio de componentes do modelo, com o agente de IA e o código da ferramenta do agente de IA residindo na camada de serviço. Essa abordagem permite a intercambiabilidade perfeita das fontes de dados. Ela também estende as capacidades do agente de IA com funcionalidades ou ferramentas adicionais e mais complexas.
Camada de serviço
A camada de serviço forma a pedra fundamental da nossa lógica de negócios básica. Nesse cenário específico, a camada de serviço desempenha um papel crucial como o repositório para o código do LangChain Agent. Ela facilita a integração perfeita de solicitações de usuário com dados do Azure Cosmos DB, memória de conversa e funções de agente para o agente de IA.
A camada de serviço emprega um módulo no padrão Singleton para lidar com as inicializações relacionadas ao agente no arquivo init.py. Este é o conteúdo de serviço/init.py:
from dotenv import load_dotenv
from os import environ
from langchain.globals import set_llm_cache
from langchain_openai import ChatOpenAI
from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain.agents import AgentExecutor, create_openai_tools_agent
from service import TravelAgentTools as agent_tools
load_dotenv(override=False)
chat : ChatOpenAI | None=None
agent_with_chat_history : RunnableWithMessageHistory | None=None
def LLM_init():
global chat,agent_with_chat_history
chat = ChatOpenAI(model_name="gpt-3.5-turbo-16k",temperature=0)
tools = [agent_tools.vacation_lookup, agent_tools.itinerary_lookup, agent_tools.book_cruise ]
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are a helpful and friendly travel assistant for a cruise company. Answer travel questions to the best of your ability providing only relevant information. In order to book a cruise you will need to capture the person's name.",
),
MessagesPlaceholder(variable_name="chat_history"),
("user", "Answer should be embedded in html tags. {input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
#Answer should be embedded in HTML tags. Only answer questions related to cruise travel, If you can not answer respond with \"I am here to assist with your travel questions.\".
agent = create_openai_tools_agent(chat, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: MongoDBChatMessageHistory( database_name="travel",
collection_name="history",
connection_string=environ.get("MONGO_CONNECTION_STRING"),
session_id=session_id),
input_messages_key="input",
history_messages_key="chat_history",
)
LLM_init()
O arquivo init.py inicia o carregamento de variáveis de ambiente de um arquivo .env usando o método load_dotenv(override=False)
. Em seguida, uma variável global nomeada agent_with_chat_history
é instanciada para o agente. Este agente destina-se a ser usado por TravelAgent.py.
O método LLM_init()
é invocado durante a inicialização do módulo para configurar o agente de IA para conversar por meio da camada web da API. O objeto OpenAI chat
é instanciado por meio do modelo GPT-3.5 e incorpora parâmetros específicos, como nome do modelo e temperatura. O objeto AgentExecutor
, a lista de ferramentas e o modelo de solicitação são combinados para gerar um chat
, que funciona como o agente de viagens de IA.
O agente com histórico,agent_with_chat_history
, é estabelecido por meio de RunnableWithMessageHistory
com o histórico de chat (MongoDBChatMessageHistory
). Essa ação permite manter um histórico de conversa completo por meio do Azure Cosmos DB.
Prompt
O prompt do LLM inicialmente começou com uma afirmação simples: "Você é um assistente de viagens útil e simpático para uma empresa de cruzeiros". No entanto, os testes mostraram que você poderia obter resultados mais consistentes, incluindo a instrução "Responder perguntas de viagem da melhor maneira possível, fornecendo apenas informações relevantes. Para reservar um cruzeiro, capturar o nome da pessoa é essencial". Os resultados aparecem no formato HTML para aprimorar o apelo visual da interface web.
Ferramentas do agente
Ferramentas são interfaces que um agente pode usar para interagir com o mundo, o que geralmente é feito por meio da chamada de uma função.
Ao criar um agente, você deve fornecer a ele um conjunto de ferramentas que ele pode usar. O decorador @tool
oferece a abordagem mais simples possível para definir uma ferramenta personalizada.
Por padrão, o decorador usa o nome da função como o nome da ferramenta, embora isso possa ser mudado se você fornecer uma cadeia de caracteres como o primeiro argumento. O decorador usa a docstring da função como descrição da ferramenta, portanto, requer o provisionamento de uma docstring.
Aqui está o conteúdo do serviço/TravelAgentTools.py:
from langchain_core.tools import tool
from langchain.docstore.document import Document
from data.mongodb import travel
from model.travel import Ship
@tool
def vacation_lookup(input:str) -> list[Document]:
"""find information on vacations and trips"""
ships: list[Ship] = travel.similarity_search(input)
content = ""
for ship in ships:
content += f" Cruise ship {ship.name} description: {ship.description} with amenities {'/n-'.join(ship.amenities)} "
return content
@tool
def itinerary_lookup(ship_name:str) -> str:
"""find ship itinerary, cruise packages and destinations by ship name"""
it = travel.itnerary_search(ship_name)
results = ""
for i in it:
results += f" Cruise Package {i.Name} room prices: {'/n-'.join(i.Rooms)} schedule: {'/n-'.join(i.Schedule)}"
return results
@tool
def book_cruise(package_name:str, passenger_name:str, room: str )-> str:
"""book cruise using package name and passenger name and room """
print(f"Package: {package_name} passenger: {passenger_name} room: {room}")
# LLM defaults empty name to John Doe
if passenger_name == "John Doe":
return "In order to book a cruise I need to know your name."
else:
if room == '':
return "which room would you like to book"
return "Cruise has been booked, ref number is 343242"
O arquivo TravelAgentTools.py define três ferramentas:
vacation_lookup
realiza uma busca em vetores no Azure Cosmos DB. Essa ferramenta usasimilarity_search
para recuperar material relevante relacionado à viagem.itinerary_lookup
recupera os detalhes e os itinerários do pacote de cruzeiro para um navio de cruzeiro especificado.book_cruise
faz a reserva de um pacote de cruzeiro para um passageiro.
Instruções específicas ("Para fazer a reserva de um cruzeiro, preciso saber seu nome") podem ser necessárias para garantir a captura do nome do passageiro e o número do quarto para reservar o pacote de cruzeiro, mesmo que você tenha incluído tais instruções na solicitação do LLM.
Agente de IA
O conceito fundamental dos agentes subjacentes é utilizar um modelo de linguagem para selecionar uma sequência de ações a serem executadas.
Aqui está o conteúdo de serviço/TravelAgent.py:
from .init import agent_with_chat_history
from model.prompt import PromptResponse
import time
from dotenv import load_dotenv
load_dotenv(override=False)
def agent_chat(input:str, session_id:str)->str:
start_time = time.time()
results=agent_with_chat_history.invoke(
{"input": input},
config={"configurable": {"session_id": session_id}},
)
return PromptResponse(text=results["output"],ResponseSeconds=(time.time() - start_time))
O arquivo TravelAgent.py é simples, já que o agent_with_chat_history
e suas dependências (ferramentas, solicitação e LLM) são inicializados e configurados no arquivo init.py. Nesse arquivo, o agente é chamado usando a entrada de dados recebida do usuário, juntamente com a ID da sessão para a memória de conversação. Posteriormente, a (solicitação/modelo) PromptResponse
é retornada com a saída e a hora da resposta do agente.
Integração do agente de IA com a interface do usuário do React
Com o carregamento bem-sucedido dos dados e a acessibilidade do nosso agente de IA por meio de nossa API, agora podemos concluir a solução estabelecendo uma interface web do usuário (usando o React) para o nosso site de viagens. Usar os recursos do React ajuda a ilustrar a integração perfeita do agente de IA em um site de viagens. Essa integração aprimora a experiência do usuário com um assistente de viagem de conversa para consultas e reservas.
Configurar o ambiente para o React
Instale o Node.js e as dependências antes de testar a interface do React.
Execute o comando a seguir a partir do diretório web para fazer uma instalação limpa das dependências do projeto, o que pode levar algum tempo. A instalação pode levar algum tempo.
npm ci
Em seguida, é essencial criar um arquivo chamado .env dentro do diretório web para facilitar o armazenamento de variáveis de ambiente. Inclua os detalhes a seguir no arquivo .env que acabou de criar:
REACT_APP_API_HOST=http://127.0.0.1:8000
Agora, execute o seguinte comando no diretório web para iniciar a interface web do usuário do React:
npm start
A execução do comando anterior abre o aplicativo Web do React.
Percorrer a interface web do React
O projeto web do repositório do GitHub é um aplicativo simples para facilitar a interação entre o usuário e o agente de IA. Os componentes primários necessários para conversar com o agente são TravelAgent.js e ChatLayout.js. O arquivo Main.js funciona como o módulo central ou a página de aterrissagem do usuário.
Principal
O componente principal serve como o gerenciador central do aplicativo. Ele atua como o ponto de entrada designado para roteamento. Dentro da função de renderização, produz o código JSX para delinear o layout da página principal. Esse layout abrange elementos de espaço reservado para o aplicativo, como logotipos e links, uma seção que abriga o componente do agente de viagens e um rodapé que contém um exemplo de isenção de responsabilidade sobre a natureza do aplicativo.
Este é o conteúdo do main.js:
import React, { Component } from 'react'
import { Stack, Link, Paper } from '@mui/material'
import TravelAgent from './TripPlanning/TravelAgent'
import './Main.css'
class Main extends Component {
constructor() {
super()
}
render() {
return (
<div className="Main">
<div className="Main-Header">
<Stack direction="row" spacing={5}>
<img src="/mainlogo.png" alt="Logo" height={'120px'} />
<Link
href="#"
sx={{ color: 'white', fontWeight: 'bold', fontSize: 18 }}
underline="hover"
>
Ships
</Link>
<Link
href="#"
sx={{ color: 'white', fontWeight: 'bold', fontSize: 18 }}
underline="hover"
>
Destinations
</Link>
</Stack>
</div>
<div className="Main-Body">
<div className="Main-Content">
<Paper elevation={3} sx={{p:1}} >
<Stack
direction="row"
justifyContent="space-evenly"
alignItems="center"
spacing={2}
>
<Link href="#">
<img
src={require('./images/destinations.png')} width={'400px'} />
</Link>
<TravelAgent ></TravelAgent>
<Link href="#">
<img
src={require('./images/ships.png')} width={'400px'} />
</Link>
</Stack>
</Paper>
</div>
</div>
<div className="Main-Footer">
<b>Disclaimer: Sample Application</b>
<br />
Please note that this sample application is provided for demonstration
purposes only and should not be used in production environments
without proper validation and testing.
</div>
</div>
)
}
}
export default Main
Agentes de viagem
O componente do agente de viagem tem uma finalidade simples: capturar entradas de dados do usuário e mostrar respostas. Desempenha um papel fundamental no gerenciamento da integração com o agente de IA de back-end, principalmente ao capturar sessões e encaminhar as solicitações de usuário para o nosso serviço do FastAPI. As respostas resultantes são armazenadas em uma matriz para serem exibidas, um arranjo facilitado pelo componente do layout de chat.
Aqui está o conteúdo de TripPlanning/TravelAgent.js:
import React, { useState, useEffect } from 'react'
import { Button, Box, Link, Stack, TextField } from '@mui/material'
import SendIcon from '@mui/icons-material/Send'
import { Dialog, DialogContent } from '@mui/material'
import ChatLayout from './ChatLayout'
import './TravelAgent.css'
export default function TravelAgent() {
const [open, setOpen] = React.useState(false)
const [session, setSession] = useState('')
const [chatPrompt, setChatPrompt] = useState(
'I want to take a relaxing vacation.',
)
const [message, setMessage] = useState([
{
message: 'Hello, how can I assist you today?',
direction: 'left',
bg: '#E7FAEC',
},
])
const handlePrompt = (prompt) => {
setChatPrompt('')
setMessage((message) => [
...message,
{ message: prompt, direction: 'right', bg: '#E7F4FA' },
])
console.log(session)
fetch(process.env.REACT_APP_API_HOST + '/agent/agent_chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ input: prompt, session_id: session }),
})
.then((response) => response.json())
.then((res) => {
setMessage((message) => [
...message,
{ message: res.text, direction: 'left', bg: '#E7FAEC' },
])
})
}
const handleSession = () => {
fetch(process.env.REACT_APP_API_HOST + '/session/')
.then((response) => response.json())
.then((res) => {
setSession(res.session_id)
})
}
const handleClickOpen = () => {
setOpen(true)
}
const handleClose = (value) => {
setOpen(false)
}
useEffect(() => {
if (session === '') handleSession()
}, [])
return (
<Box>
<Dialog onClose={handleClose} open={open} maxWidth="md" fullWidth="true">
<DialogContent>
<Stack>
<Box sx={{ height: '500px' }}>
<div className="AgentArea">
<ChatLayout messages={message} />
</div>
</Box>
<Stack direction="row" spacing={0}>
<TextField
sx={{ width: '80%' }}
variant="outlined"
label="Message"
helperText="Chat with AI Travel Agent"
defaultValue="I want to take a relaxing vacation."
value={chatPrompt}
onChange={(event) => setChatPrompt(event.target.value)}
></TextField>
<Button
variant="contained"
endIcon={<SendIcon />}
sx={{ mb: 3, ml: 3, mt: 1 }}
onClick={(event) => handlePrompt(chatPrompt)}
>
Submit
</Button>
</Stack>
</Stack>
</DialogContent>
</Dialog>
<Link href="#" onClick={() => handleClickOpen()}>
<img src={require('.././images/planvoyage.png')} width={'400px'} />
</Link>
</Box>
)
}
Selecione Planejar sua viagem sem esforço para abrir o assistente de viagem.
Layout do chat
O componente de layout de chat supervisiona a disposição do chat. Processa sistematicamente as mensagens do chat e implementa a formatação designada especificada no objeto JSON message
.
Este é o conteúdo do TripPlanning/ChatLayout.js:
import React from 'react'
import { Box, Stack } from '@mui/material'
import parse from 'html-react-parser'
import './ChatLayout.css'
export default function ChatLayout(messages) {
return (
<Stack direction="column" spacing="1">
{messages.messages.map((obj, i = 0) => (
<div className="bubbleContainer" key={i}>
<Box
key={i++}
className="bubble"
sx={{ float: obj.direction, fontSize: '10pt', background: obj.bg }}
>
<div>{parse(obj.message)}</div>
</Box>
</div>
))}
</Stack>
)
}
As solicitações do usuário estão no lado direito e em azul. As respostas do agente de viagens de IA estão no lado esquerdo e em verde. Como mostra a imagem a seguir, as respostas formatadas em HTML são levadas em consideração na conversa.
Quando o agente de IA estiver pronto para entrar em produção, você poderá usar o cache semântico para aprimorar o desempenho da consulta em 80% e reduzir os custos de inferência do LLM e das chamada à API. Para implementar o cache semântico, consulte esta postagem no blog Coder Stochastic.