Quando as empresas integram Large Language Models (LLM), como ChatGPT, em seus serviços empresariais, elas podem usar a tecnologia de novas maneiras. Os funcionários podem processar dados de voz e integrá-los aos sistemas existentes, e os desenvolvedores podem criar aplicativos complexos. LangChain, por exemplo, pode te ajudar com isso. A estrutura do software foi projetada para aproveitar, ampliar e otimizar os recursos do LLM.
Em conjunto com o Quarkus, uma estrutura baseada em JVM cuja força reside principalmente na implementação de soluções nativas da nuvem, estão surgindo novas abordagens para processar dados da empresa e interagir com os clientes.
Conecte LangChain com Quarkus
Para conectar LangChain ao Quarkus, primeiro um novo projeto Quarkus deve ser iniciado. Com apenas alguns cliques, os desenvolvedores selecionam a ferramenta de build desejada – por exemplo Maven, Gradle ou Gradle com Kotlin DSL -, a versão Java e as extensões a serem utilizadas.
As seguintes extensões são necessárias para o exemplo com LangChain:
io.quarkus:quarkus-resteasy-reactive
io.quarkiverse.langchain4j:quarkus-langchain4j-core:0.7.0
io.quarkiverse.langchain4j:quarkus-langchain4j-openai:0.7.0
Usando a extensão REST Easy, uma API simples é desenvolvida para consumir o serviço de IA. Se você preferir usar os modelos Hugging Face em vez dos modelos ChatGPT da OpenAI, substitua a terceira extensão por
io.quarkiverse.langchain4j:quarkus-langchain4j-hugging-face:0.7.0
.
Para usar um LLM como os modelos ChatGPT ou Hugging Face com Quarkus e LangChain, uma interface AiService deve primeiro ser registrada e a chave API OpenAI deve ser configurada.
Recomendações editoriais
Um AiService é uma interface que funciona com
@RegisterAiService
está anotado. Os métodos podem ser definidos na interface com a qual você pode interagir com um LLM. No exemplo o método permite
chatWithMailBot()
um ID de conversa e um prompt, ou seja, uma solicitação do usuário.
Além disso, o LLM pode usar a anotação
@SystemMessage
uma mensagem do sistema é passada. Diz ao modelo como ele deve se comportar e que papel deve assumir.
Para usar a API OpenAI, você deve estar no Quarkus
application.properties
. Arquivo das chaves API pode ser definido. Como a API atualmente tem tempos de resposta longos, especialmente para conversas maiores, também pode fazer sentido aumentar o tempo limite. O modelo ChatGPT desejado é selecionado usando o nome do modelo.
LLM como ChatGPT não têm estado, portanto você não pode ter uma conversa direta com eles porque eles só podem processar a solicitação atual. Para permitir uma conversa que se complemente, o histórico da conversa deve ser salvo e todas as perguntas e respostas antigas devem ser enviadas junto com cada nova solicitação. No entanto, isto aumenta o número de tokens de entrada e, portanto, os custos.
No Quarkus, os desenvolvedores podem definir um bean que representa a interface
ChatMemoryStore
implementado, permitindo que você mesmo gerencie as conversas. Caso contrário, o Quarkus usará automaticamente isso
InMemoryChatMemoryStore
, que mantém as conversas na memória. Para um exemplo simples, as configurações padrão são suficientes, onde o Quarkus salva as últimas dez mensagens. Para uso produtivo com muitos usuários paralelos, as mensagens devem ser armazenadas em um banco de dados, por exemplo.
Para fazer referência à conversa de um usuário, o
@MemoryId
Anotação passa o ID da conversa para o método do AiService.
Para o
MailAiService
Para usá-lo no Quarkus, ele simplesmente precisa ser injetado em outro bean, por exemplo, em um recurso REST Easy. Isso significa que ele pode ser resolvido por meio de um endpoint REST simples.
Para simplificar, o ID da conversa é passado por meio de um parâmetro de consulta. Numa aplicação real, este ID deve ser validado via autenticação.
Faça configurações RAG
Uma arquitetura de geração aumentada de recuperação (RAG) combina a recuperação de informações de grandes conjuntos de dados com a capacidade de geração de texto do LLM. O objetivo desta arquitetura é melhorar a qualidade e a relevância das respostas geradas, fornecendo dados contextuais para uma consulta.
- Prompt/Consulta: O sistema RAG recebe um prompt com uma consulta. Um prompt é uma solicitação ou indicação fornecida por um usuário para fazer com que o sistema execute uma ação ou resposta específica. Muitas vezes é feita uma distinção entre diferentes componentes do prompt:
a. O prompt do sistema é um formulário especial especificado pelo sistema RAG para responder com mais precisão aos requisitos do prompt original do usuário e para descrever as regras, capacidades e comportamentos básicos do sistema.
b. Contexto refere-se a informações adicionais associadas ao prompt. O contexto é enriquecido pela busca de informações relevantes em um banco de dados, resultando em respostas mais precisas e contextuais.
c. Uma consulta é a solicitação específica do usuário que o sistema RAG envia ao seu banco de dados ou fontes de conhecimento para coletar informações relevantes. - Consulta: A consulta é usada para procurar informações adequadas em uma ou mais fontes de conhecimento. Esta é a parte de recuperação da arquitetura, onde o sistema tenta encontrar dados que possam ajudar a responder à consulta. Bancos de dados vetoriais são frequentemente usados aqui, que armazenam não apenas seções de texto, mas também suas representações vetoriais, os chamados embeddings. Conteúdos semelhantes possuem vetores próximos uns dos outros. Os bancos de dados vetoriais podem encontrar rapidamente os vizinhos mais próximos de um vetor e, assim, identificar com eficiência informações semelhantes e, portanto, relevantes.
- Dados relevantes para enriquecer o contexto: As informações encontradas são utilizadas para enriquecer o contexto.
- Prompt do sistema, consulta e contexto enriquecido: o prompt do sistema original, a consulta e o contexto agora enriquecido são mesclados e enviados para uma API de modelo de linguagem grande.
- Resposta de texto gerada: O LLM processa os dados recebidos e, levando em consideração o contexto, gera uma resposta de texto que é retornada ao usuário.
Há também um banco de dados e fontes de conhecimento: aqui, informações específicas que normalmente ainda não são conhecidas pelo LLM por meio de seu treinamento são armazenadas e tornadas consultáveis de forma eficiente. No ambiente empresarial, esses bancos de dados geralmente contêm dados atuais específicos da empresa.
Quarkus suporta vários bancos de dados de documentos para RAG, por exemplo Chroma, Pinecone ou PgVector. Redis é usado no exemplo. Isso requer expansão
io.quarkiverse.langchain4j:quarkus-langchain4j-redis:0.7.0
para ser adicionado. Se o PDF for importado, a extensão vem
dev.langchain4j:langchain4j-document-parser-apache-pdfbox:0.25.0
adicionado.
As configurações RAG precisam ser complementadas no arquivo application.properties e garantir que o contêiner Redis iniciado no modo de desenvolvimento suporte pesquisa vetorial e fila suficiente. A dimensão do modelo de incorporação utilizado é retirada da respectiva documentação e também inserida. O modelo de incorporação do OpenAI cria vetores com dimensão 1536.
Com ajuda de um
EmbeddingStoreIngestors
Os documentos podem ser salvos no banco de dados vetorial. Isso é o que são
EmbeddingModel
e a
RedisEmbeddingStore
injetado no construtor. O
DocumentSplitter
define como documentos grandes são divididos em partes menores.
Por exemplo, os PDFs exportados da documentação do Quarkus são importados de uma pasta para o Redis sempre que ele é iniciado.
Para que o Quarkus identifique os documentos relevantes para uma solicitação do usuário, deve ser definido um bean que utilize a interface
Retriever
implementado. Para visualizar documentos relevantes usando o
EmbeddingModels
eu sou
RedisEmbeddingStore
encontrar será um
EmbeddingStoreRetriever
gerado. O
EmbeddingStoreRetriever
também requer o número máximo de documentos a serem extraídos como parâmetro. Este parâmetro requer um equilíbrio entre custos (mais documentos = mais tokens = custos mais elevados) e melhores respostas (mais documentos = mais contexto/conhecimento).
Para que Quarkus possa
DocumentsRetriever
Para que o RAG seja usado, a classe do bean deve estar no
@RegisterAiService
-Anotação sobre o parâmetro
retriever
ser especificado:
@RegisterAiService(retriever = {DocumentsRetriever.class})
Envolver agentes
Os agentes no contexto do LLM são programas ou algoritmos especializados que atuam de forma autônoma e assumem tarefas como consulta, processamento e análise de dados. Ampliam e melhoram a interação com o LLM, coletando e pré-processando informações relevantes em tempo real, aumentando a precisão e adaptabilidade das respostas. Eles aumentam a funcionalidade do LLM automatizando tarefas e otimizando o fluxo de informações entre o LLM e suas fontes de dados.
O processo de uma solicitação normalmente ocorre da seguinte forma:
- Cadastro de ferramentas disponíveis: Antes de iniciar o processo, todas as ferramentas e funções disponíveis são cadastradas no sistema. É assim que ele pode acessar essas ferramentas.
- Prompt/Consulta: O usuário inicia o processo inserindo um prompt.
- Prompt do sistema, consulta e ferramentas disponíveis: O sistema envia o prompt do sistema, a consulta e a lista de ferramentas disponíveis que podem ser usadas para responder à consulta ao LLM.
- “Chamar função A com parâmetro ‘xy’”: Com base na solicitação e nas ferramentas disponíveis, o LLM pode decidir chamar uma função específica com um parâmetro específico e retornar esta informação como resposta.
- Função A(‘xy’): O sistema agente executa a função A com o parâmetro ‘xy’.
- Resultado A(‘xy’): O resultado desta função é produzido e está disponível para uso posterior.
- Prompt do sistema, consulta, ferramentas disponíveis, resultado A(‘xy’): O sistema atualiza o contexto com o resultado da função executada. Este é um processo iterativo e, dependendo da complexidade da consulta, podem ser necessárias múltiplas rodadas de consultas ao agente antes que o LLM possa fornecer a resposta final.
- Resposta de texto gerada: Finalmente, o LLM gera uma resposta de texto final.
Esta abordagem permite a integração profunda de ferramentas e agentes especializados para ampliar as capacidades do LLM e gerar respostas mais precisas e contextualmente relevantes.
Assim que no Quarkus um método público de feijão com
@Tool
está anotado, esta função pode ser disponibilizada ao ChatGPT como uma ferramenta. O
@Tool
-A anotação recebe uma descrição legível da funcionalidade do método. É assim que o LLM entende o que pode conseguir chamando a função.
Será que o método
getContactForName
Definido como uma ferramenta, permite ao LLM consultar os endereços de e-mail e o nome da empresa por meio de nome e sobrenome. Já que está em
AddressBookService
é um bean normal, todas as funções e extensões do Quarkus podem ser acessadas. Por exemplo, consultas de banco de dados ou chamadas de API REST podem ser executadas.