G
Glaucia_Lemos
No cenário em rápida evolução da Inteligência Artificial e do Processamento de Linguagem Natural ao criar aplicações Inteligentes, o uso da técnica de Retrieval Augmented Generation (RAG) emergiu como uma solução poderosa para melhorar a precisão e a relevância das respostas geradas por modelos de linguagem.
Neste artigo, vamos explorar a palestra dada durante o evento Hack Together: RAG Hack, a qual Glaucia Lemos, que é Cloud Advocate na Microsoft e Yohan Lasorsa, que é Senior Cloud Advocate também na Microsoft, apresentaram como o LangChain.Js está revolucionando o desenvolvimento de aplicações RAG, facilitando a criação de aplicações inteligentes que combinam grandes modelos de linguagem (LLMs) com suas prórias fontes de dados.
Participe do Hack Together: RAG Hack!
O Hack Together: RAG Hack é um hackathon global e gratuito que está acontecendo entre os dias 03 à 16 de Setembro de 2024, focado em explorar e desenvolver aplicações utilizando a técnica de Retrieval Augmented Generation (RAG).
Este evento reunirá desenvolvedores, pesquisadores e entusiastas de IA de todo o munndo com o intuito de criar aplicações inovadoras e inteligentes que combinam grandes modelos de linguagem (LLMs) com suas próprias fontes de dados usando o RAG.
O evento contará com 25 transmissões ao vivo, demonstrando como criar aplicações RAG utilizando Azure AI em diferentes linguagens de programação, tais como: Python, Java, JavaScript/TypeScript e C#. E, incluso também com diversos serviços de IA do Azure tais como: AI Search, PostgreSQL, Azure SQL e Azure CosmosDB. Os participantes tem a oportunidade de aprender sobre frameworks populares como o LangChain e Semantic Kernel, além de tecnologias de ponta como agentes e modelos de visão.
A melhor parte é que, caso a sua aplicação seja escolhida você pode ganhar um prêmio de USD 500,00! Nas seguintes categorias:
- Melhor Aplicação
- Melhor em JavaScript/TypeScript
- Melhor em Java
- Melhor em .NET
- Melhor em Python
- Melhor uso do AI Studio
- Melhor uso do AI Search
- Melhor uso do PostgreSQL
- Melhor uso do Cosmos DB
- Melhor uso do Azure SQL
- Melhor uso do Azure SQL
Quer saber mais sobre todos os detalhes do evento, como participar e como submeter a sua aplicação? Acesse o site do evento aqui e participe!
Live Session: Criando Aplicações RAG com LangChain.js
No último dia 04 de Setembro de 2024, aconteceu a live session com o tema: Criando Aplicações RAG com LangChain.Js, onde Glaucia Lemos e Yohan Lasorsa explicaram a importância do uso do LangChain.Js para o desenvolvimento de aplicações RAG com uma baita demonstração de um AI Chat Serverless.
Se você perdeu essa live, não se preocupe! Você pode assistir a gravação abaixo:
Aplicação Contoso Real Estate AI Chat
Durante a live session, Glaucia Lemos e Yohan Lasorsa apresentaram uma aplicação de exemplo chamada Contoso Real Estate AI Chat, que é uma aplicação de chatbot que permite aos usuários fazer perguntas sobre imóveis disponíveis para venda.
Vocês podem ver a aplicação em ação no gif abaixo:
Inclusive, você pode acessar a aplicação diretamente no repositório do GitHub aqui!
Curtiu? Então, fork agora mesmo o projeto direto no repositório e faça a sua própria versão da aplicação Contoso Real Estate AI Chat! E, não esqueça de dar uma estrela no repositório!
Bom... vamos agora ao que foi apresentado durante a live session!
O Desafio da IA e a Solução com uso do RAG
Durante a primeira parte da live session, Glaucia Lemos explorou o desafio da IA e a solução com uso do RAG.
Ao trabalhar com modelos LLMs, nos deparamos com vários desafios. Esses modelos, apesar de sua capacidade impressionante de gerar linguagem natural, às vezes produzem informações imprecisas e não tão acuradas. Justo porque utilizam dados desatualizados ou se baseiam em fontes não confiáveis.
É justo aí que entra a técnica RAG, pois ela permite que os desenvolvedores combinem grandes modelos de linguagem com suas próprias fontes de dados, melhorando a precisão e a relevância das respostas geradas.
RAG, ou Retrieval Augmented Generation, é uma técnica que combina dois componentes principais:
- Retrieval: que recupera informações relevantes de uma base de conhecimento que está sob seu controle.
- Generator: um modelo de linguagem que gera respostas com base nas informações recuperadas, criando assim as respostas finais.
Como o RAG Funciona?
O processo do RAG pode ser dividido em algumas etapas. Mas, principalmente, ele funciona da seguinte forma:
- Envio de uma pergunta para o modelo de linguagem.
- O modelo de linguagem recupera (retriever) buscará as informações na base de conhecimento para que possa retornar as informações relevantes para que possa responder a pergunta.
- Em seguida, você envia a pergunta e os documentos para o gerador (generator), que finalmente criará a resposta com base nas informações fornecidas.
O gif abaixo ilustra perfeitamente todo o processo do RAG:
E, um dos fatores mais importantes nesse processo é a criação da base de conhecimento. Mas, como ele é implementado? Vamos ver a seguir!
Criando a Base de Conhecimento
A base de conhecimento é um conjunto de documentos que contém informações relevantes para responder perguntas. Esses documentos podem ser de diferentes tipos, como: texto, imagens, tabelas, etc.
Tudo isso se resume a um processo de duas etapas:
1. Construção da Base de Conhecimento
- Os documento sejam processados para extrair o texto
- O texto será dividido em chunks menores
- Os embeddings serão armaenados em um banco de dados vetorial
2. Processo de Recuperação e Geração
- A pergunta do usuário é transformada num embedding
- Este embedding será usado para buscar documentos relevantes no banco de dados vetorial
- Os documentos recuperados são injetados no prompt do modelo de linguagem
- O modelo gerará uma resposta baseada na pergunta e nos documentos relevantes.
Além desse processo se repetir, ele também permite obter respostas mais precisas e relevantes, utilizando dados específicos em vez de aprender apenas dos dados do modelo de linguagem.
Se ficou confuso como todo esse processo funciona, o gif abaixo ilustra perfeitamente como ocorre:
Depois que você criou sua base de conhecimento, é a vez de fazer uso da recuperação e aumento de contexto. E, esse processo se resumo em três etapas:
- Primeiro transformamos a consulta do usuário num vetor, enviando para o mesmo modelo de incorporação (embedding) que usamos para criar a base de conhecimento.
- Em seguida, usamos o vetor para pesquisar documentos relevantes em nosso banco de dados de vetores e selecionamos os N melhores resultados.
- Por fim, pegamos o texto dos documentos mais relevantes, bem como a pergunta inicial do usuário, e a usamos para criar o prompt. E, finalmente o usuário envia o prompt ao LLM para obter a resposta solicitada.
Deixemos que o gif demonstre como ocorre todo esse processo:
Quais vantagens do uso do RAG?
As vantagens do uso do RAG são inúmeras, mas podemos destacar algumas, tais como:
1. Não Requer Treinamento Adicional: você pode utilizar modelos de linguagem existentes, economizando tempo e recursos significativos.
2. Dados Sempre Atualizados: A base de conhecimento pode ser facilmente atualizada sem necessidade de retreinar o modelo, garantindo informações sempre atuais.
3. Fundamentação Sólida: As respostas são baseadas em fontes específicas e confiáveis, aumentando a precisão e confiabilidade.
4. Aumento da Confiança do Usuário: É possível mostrar aos usuários as fontes utilizadas para gerar as respostas, proporcionando transparência e credibilidade.
Agora que entendemos profundamente como o RAG funciona e suas vantagens, vamos ver como o LangChain.Js auxilia no desenvolvimento de Aplicações RAG!
LangChain.js: Simplificando o Desenvolvimento de Aplicações RAG
Nessa segunda parte da live session, Yohan Lasorsa apresentou o LangChain.js, um framework open-source que simplifica o desenvolvimento de aplicações RAG. E, como foi simples a implementação de um AI Chat Serverless com o LangChain.js.
O Langchain.js é uma biblioteca JavaScript de código aberto projetada para simplificar o trabalho com grandes modelos de linguagem (LLMs) e implementar técnicas avançadas como RAG. Ela oferece abstrações de alto nível para todos os componentes necessários ao criar aplicações de IA, facilitando a integração de modelos, bancos de dados vetoriais e agentes complexos.
O Langchain.js permite a criação de fluxos de trabalho de inteligência artificial (IA) altamente personalizados e flexíveis, combinando diferentes etapas de processamento em uma sequência lógica. Vamos entender como isso funciona através de um exemplo prático que gera uma piada baseada em um tema específico usando um modelo de linguagem natural.
Code:
type Joke = { joke: string };
const model = new ChatOpenAI({ model: "gpt-4o-mini" });
const prompt = ChatPromptTemplate.fromTemplate(
"Tell a joke about {topic}. Answer with valid JSON, containing one field: 'joke'"
);
const parser = new JsonOutputParser<Joke>();
const chain = prompt
.pipe(model)
.pipe(parser);
await chain.invoke({ topic: "bears" });
O código acima utiliza o LangChain.js para criar um fluxo de trabalho de IA que gera uma piada sobre um tema específico. Primeiro, define-se o tipo de saída como um objeto
Joke
. Em seguida, inicializa-se o modelo de linguagem gpt-4o-mini
e cria-se um template de prompt que instrui o modelo a retornar uma piada em formato JSON. Um parser é configurado para transformar a resposta em um objeto JavaScript. Por fim, o fluxo de trabalho é montado encadeando o prompt, o modelo e o parser, e é executado com o tema “bears”.Você pode aprender mais sobre o LangChain.js e como usá-lo em sua aplicação acessando a documentação oficial aqui.
Implementação do AI Chat Serverless com LangChain.js e RAG
Agora, vamos explorar como foi implementado um sistema RAG completo usando Langchain.js, baseado no projeto de exemplo apresentado durante a live. O projeto é um chatbot de suporte para uma empresa fictícia de aluguel de imóveis chamada Contoso Real Estate.
Arquitetura do Projeto
O projeto foi desenvolvido fazendo uso de uma arquitetura serverless, utilizando vários serviços Azure:
As principais tecnologias utilizadas foram:
- Node.js/TypeScript: linguagem de programação no backend
- LangChain.js: para a integração com modelos de linguagem
- Azure Functions: hospedagem do backend API
- Azure Static Web Apps: hospedagem do frontend
- Azure Cosmos DB for MongoDb: para armazenamento de dados vetoriais
- Azure Blob Storage: para armazenar documentos originais
- Azure OpenAI: para modelos de linguagem e embeddings
- Lit.dev: para criação de web components
O melhor ponto desse projeto é que todos os serviços utilizados do Azure estão na camada gratuita, o que significa que você pode testar e experimentar sem custos adicionais. Sensacional, não é mesmo?
Processamento de Documentos
O primeiro passo na implementação do RAG é o processamento dos documentos que formarão nossa base de conhecimento. Vejamos como isso é feito usando Langchain.js com base no código desenvolvido no projeto:
Code:
(... some imports here...)
export async function postDocuments(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
const storageUrl = process.env.AZURE_STORAGE_URL;
const containerName = process.env.AZURE_STORAGE_CONTAINER_NAME;
const azureOpenAiEndpoint = process.env.AZURE_OPENAI_API_ENDPOINT;
try {
// Get the uploaded file from the request
const parsedForm = await request.formData();
if (!parsedForm.has('file')) {
return badRequest('"file" field not found in form data.');
}
// Type mismatch between Node.js FormData and Azure Functions FormData
const file = parsedForm.get('file') as any as File;
const filename = file.name;
// Extract text from the PDF
const loader = new PDFLoader(file, {
splitPages: false,
});
const rawDocument = await loader.load();
rawDocument[0].metadata.source = filename;
// Split the text into smaller chunks
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1500,
chunkOverlap: 100,
});
const documents = await splitter.splitDocuments(rawDocument);
(... more code ...)
Esse arquivo,
documents-post.ts
, é responsável por processar os documentos enviados pelo usuário. Primeiro, ele extrai o texto de um arquivo PDF usando a biblioteca PDFLoader
. Em seguida, divide o texto em chunks menores com o RecursiveCharacterTextSplitter
. Por fim, os documentos são armazenados no Azure Blob Storage para uso posterior.Implementação do Chat RAG
O coração do sistema RAG está na função de
chat
, onde as perguntas dos usuários são processadas e respondidas com base nos documentos relevantes recuperados. Vejamos como isso é implementado:
Code:
(... some imports here...)
const systemPrompt = `Assistant helps the Consto Real Estate company customers with questions and support requests. Be brief in your answers. Answer only plain text, DO NOT use Markdown.
Answer ONLY with information from the sources below. If there isn't enough information in the sources, say you don't know. Do not generate answers that don't use the sources. If asking a clarifying question to the user would help, ask the question.
If the user question is not in English, answer in the language used in the question.
Each source has the format "[filename]: information". ALWAYS reference the source filename for every part used in the answer. Use the format "[filename]" to reference a source, for example: [info1.txt]. List each source separately, for example: [info1.txt][info2.pdf].
Generate 3 very brief follow-up questions that the user would likely ask next.
Enclose the follow-up questions in double angle brackets. Example:
<<Am I allowed to invite friends for a party?>>
<<How can I ask for a refund?>>
<<What If I break something?>>
Do no repeat questions that have already been asked.
Make sure the last question ends with ">>".
SOURCES:
{context}`;
export async function postChat(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
const azureOpenAiEndpoint = process.env.AZURE_OPENAI_API_ENDPOINT;
try {
const requestBody = (await request.json()) as AIChatCompletionRequest;
const { messages } = requestBody;
if (!messages || messages.length === 0 || !messages.at(-1)?.content) {
return badRequest('Invalid or missing messages in the request body');
}
let embeddings: Embeddings;
let model: BaseChatModel;
let store: VectorStore;
if (azureOpenAiEndpoint) {
const credentials = getCredentials();
const azureADTokenProvider = getAzureOpenAiTokenProvider();
// Initialize models and vector database
embeddings = new AzureOpenAIEmbeddings({ azureADTokenProvider });
model = new AzureChatOpenAI({
// Controls randomness. 0 = deterministic, 1 = maximum randomness
temperature: 0.7,
azureADTokenProvider,
});
store = new AzureCosmosDBNoSQLVectorStore(embeddings, { credentials });
} else {
// If no environment variables are set, it means we are running locally
context.log('No Azure OpenAI endpoint set, using Ollama models and local DB');
embeddings = new OllamaEmbeddings({ model: ollamaEmbeddingsModel });
model = new ChatOllama({
temperature: 0.7,
model: ollamaChatModel,
});
store = await FaissStore.load(faissStoreFolder, embeddings);
}
// Create the chain that combines the prompt with the documents
const combineDocsChain = await createStuffDocumentsChain({
llm: model,
prompt: ChatPromptTemplate.fromMessages([
['system', systemPrompt],
['human', '{input}'],
]),
documentPrompt: PromptTemplate.fromTemplate('[{source}]: {page_content}\n'),
});
// Create the chain to retrieve the documents from the database
const chain = await createRetrievalChain({
retriever: store.asRetriever(3),
combineDocsChain,
});
const lastUserMessage = messages.at(-1)!.content;
const responseStream = await chain.stream({
input: lastUserMessage,
});
const jsonStream = Readable.from(createJsonStream(responseStream));
return data(jsonStream, {
'Content-Type': 'application/x-ndjson',
'Transfer-Encoding': 'chunked',
});
(... more code ...)
Nesse arquivo,
chat-post.ts
, a função postChat
processa as mensagens enviadas pelo usuário e retorna respostas baseadas nos documentos relevantes recuperados. O código cria uma cadeia de processamento que combina o prompt do sistema com os documentos disponíveis e, em seguida, recupera os documentos relevantes do banco de dados vetorial. Por fim, a resposta é gerada e enviada de volta ao usuário.Desenvolvimento Local com Ollama
Uma característica notável deste projeto é a capacidade de executá-lo localmente, sem depender do Azure OpenAI. Isso é possível graças ao Ollama, uma ferramenta que permite executar modelos de linguagem open-source localmente.
O arquivo
constants.ts
contém as configurações necessárias para executar o projeto localmente com Ollama:
Code:
export const ollamaEmbeddingsModel = 'all-minilm:l6-v2';
export const ollamaChatModel = 'mistral:v0.2';
export const faissStoreFolder = '.faiss';
Aqui, vemos que o projeto utiliza o modelo
all-minilm:l6-v2
para embeddings e mistral:v0.2
para chat. Isso permite que os desenvolvedores experimentem com o sistema RAG usando modelos de código aberto, como o Mistral, diretamente em suas máquinas locais.Para usar esses modelos localmente, os desenvolvedores precisam instalar o Ollama e baixar os modelos especificados. Isso proporciona uma experiência de desenvolvimento flexível e acessível, especialmente útil para fases iniciais de desenvolvimento e testes.
Nota: O Ollama é uma ferramenta open-source que permite executar modelos de linguagem localmente. Para saber mais sobre o Ollama e como usá-lo, acesse o site oficial aqui. Para fazer uso desse modelo requer uma máquina com uma GPU NVIDIA e CUDA instalado.
Quero Implementa em Produção! Como Fazer?
Para implantação em produção, o projeto utiliza o Azure Developer CLI (azd), simplificando o processo de provisionamento e implantação dos recursos necessários na Azure. Com apenas alguns comandos, é possível implantar toda a infraestrutura e o código:
Code:
azd auth login --use-device-code
azd env new
azd up
Esses comandos criam um novo ambiente de desenvolvimento, implantam os recursos necessários na Azure e iniciam o projeto localmente. O Azure Static Web Apps é usado para hospedar o frontend, enquanto o Azure Functions hospeda o backend API.
Se desejar entender melhor como isso foi implementado no projeto há uma pasta chamada
infra
que contém todos os arquivos de configuração necessários para implantar o projeto na Azure e nesse caso foi utilizado o BicepLang para provisionar a infraestrutura.Depois que você implementa a aplicação você verá ela em ação, como mostra o gif abaixo:
Conclusão
O Langchain.js, como demonstrado neste projeto com o RAG, oferece uma plataforma robusta e flexível para a implementação de sistemas de IA avançados. Combinando o poder dos grandes modelos de linguagem com a capacidade de recuperar informações relevantes de fontes externas, o Langchain.js permite criar aplicações de IA mais inteligentes e contextuais.
Se você gostou do projeto e deseja experimentar por conta própria, pode acessar o repositório do GitHub aqui e seguir as instruções para executá-lo localmente ou implantá-lo na Azure. O projeto é uma excelente oportunidade para aprender mais sobre RAG, Langchain.js e como integrar modelos de linguagem em suas aplicações. Sem contar que você pode executar o projeto localmente com Ollama e experimentar com modelos de código aberto.
A jornada para criar aplicações de IA mais inteligentes e contextuais começa aqui. O RAG e o LangchainJ.js abrem um mundo de possibilidades para desenvolvedores, permitindo a criação de sistemas de IA que não apenas respondem perguntas, mas o fazem com precisão, relevância e confiabilidade baseadas em dados específicos e atualizados.
Agora chegou a sua vez de explorar o projeto e quem sabe até mesmo participar do Hack Together: RAG Hack para criar sua própria aplicação RAG e concorrer a prêmios incríveis! Acesse o site do evento aqui e participe!
E, até a próxima!
Continue reading...