LangChain: Construindo um ChatPDF com RAG (Retrieval-Augmented Generation), OpenAI e Streamlit

Rhian Lopes da Costa
Fretebras Tech
Published in
10 min readJul 15, 2024

Introdução

Quem nunca precisou responder a uma dúvida que estava em um dos muitos PDFs na pasta de Downloads, e teve que abrir cada um deles e procurar por palavras-chave?

Neste artigo, vamos explorar a criação de um ChatPDF utilizando LangChain com a técnica de RAG (Retrieval-Augmented Generation), OpenAI e Streamlit. O texto detalha os conceitos do LangChain e a técnica de RAG, aplicando-os de maneira prática.

LangChain

LangChain é uma biblioteca open-source que tem como objetivo facilitar a criação de aplicações utilizando LLMs, ou seja, modelos de linguagem.

Dessa forma, o LangChain disponibiliza diversos tipos de componentes e funcionalidades que facilitam desde a importação de diversos tipos de documentos e dados, criação e reutilização de templates de promtps, simplificar o uso e conexão com uma ou várias LLMs (Como ChatGPT, BERT, Llama, etc).

O encadeamento de operações ou etapas de processamentos, sendo o o famoso "Chain" do nome, que permite por exemplo um encadeamento em sequência de processos como buscar informações de contexto em uma base de dados, compor o contexto em um template de prompt e enviar para um modelo de linguagem para gerar uma resposta.

A criação de agentes, que permitem a execução de tarefas complexas de maneira dinâmica baseadas em inputs, onde geram ações que podem envolver desde chamadas a APIs, consultas a banco de dados, entre outras tarefas, podemos aplicar por exemplo em um input de Chatbot onde o cliente solicita o status do pedido x e a partir desse input executa um agente que consulta uma API a fim de obter o status do pedido.

São esses alguns dos diversos componentes e funcionalidades que o LangChain disponibiliza. Além disso, possui uma comunidade muito ativa que contribui de maneira frequente e enriquecedora, com novos módulos a cada dia, que facilitam muito no momento em que desejamos realizar integrações com outras ferramentas ou customizações na nossa solução.

Retrieval-Augmented Generation (RAG)

Retrieval-Augmented Generation (RAG) é uma técnica utilizada em soluções de inteligência artificial generativa para melhorar a qualidade do texto gerado, combinando grandes modelos de linguagem (LLM) com sistemas de recuperação de informações.

A ideia principal é aumentar a capacidade do modelo de gerar respostas precisas e informadas, utilizando informações contextuais relevantes que são recuperadas com base no input e fornecidas ao modelo como dados complementares.

Com a técnica de RAG, aumentamos a precisão das respostas dos modelos, além de expandir seu alcance e flexibilidade de aplicação para uma variedade de tipos de dados. Isso é possível ao utilizar dados externos, o que aprimora a capacidade de conhecimento e resposta do sistema.

O RAG é amplamente utilizado em assistentes virtuais, sistemas de perguntas e respostas, e sistemas de geração de conteúdo, auxiliando na criação de artigos, relatórios e outros tipos de conteúdo informativo.

Preparando o Ambiente

Antes de iniciarmos a construção do nosso ChatPDF, são dois os pré-requisitos para seguirmos com o passo a passo, sendo eles:

Com isso em mãos podemos seguir nosso passo a passo! Em uma pasta de sua preferência, via terminal podemos executar o comando abaixo:

python3 -m venv .venv

O venv é um módulo nativo do Python utilizado para criar ambientes virtuais. Um ambiente virtual é uma pasta específica que contém uma instalação independente do Python, incluindo um conjunto próprio de pacotes e bibliotecas.

Isso permite que diferentes projetos Python mantenham suas dependências isoladas, evitando conflitos entre versões de pacotes e garantindo que cada projeto funcione com os pacotes necessários em suas versões específicas.

Para ativarmos o nosso ambiente virtual podemos executar o comando abaixo:

source .venv/bin/activate

Feito isso, na raiz do projeto podemos criar um arquivo chamado "requirements.txt" para instalarmos todas as dependências necessárias.

Em seguida podemos executar o seguinte comando para realizarmos a instalação das dependências:

pip install -r requirements.txt

Além disso, iremos realizar a criação de um novo arquivo chamado ".env" a fim de guardarmos as nossas variáveis de ambiente, nesse caso, a nossa API KEY gerada da OpenAI.

Por fim, é sempre importante criarmos um arquivo de ".gitignore" caso desejarmos disponibilizar o projeto em algum repositório público e expormos de maneira despercebida chaves importantes ou arquivos desnecessários.

Para evitarmos isso, indico a criação do seguinte arquivo:

Primeiros passos com LangChain

Antes de iniciarmos a construção do ChatPDF, vamos criar um projeto mais simples a fim de entendermos alguns conceitos e componentes. Podemos criar um novo arquivo chamado "albums.py".

Nesse arquivo iremos construir uma função com o objetivo de informar o nome de um artista e receber de resposta a quantidade de albuns que esse artista possui, perguntando a OpenAI via modelo "gpt-3.5-turbo" a reposta para essa pergunta.

Para executarmos esse código, basta executar:

$ python albums.py

=========================================
Resposta direta do gpt-3.5-turbo:
Até o momento, Taylor Swift lançou 9 álbuns de estúdio em sua carreira. São eles:

1. Taylor Swift (2006)
2. Fearless (2008)
3. Speak Now (2010)
4. Red (2012)
5. 1989 (2014)
6. Reputation (2017)
7. Lover (2019)
8. Folklore (2020)
9. Evermore (2020)
=========================================

Com isso, obtemos a informação que a artista informada, nesse caso, a Taylor Swift possui 9 álbuns, mas ao verificarmos essa informação em algum site observamos que essa informação está desatualizada, podemos ver a informação atualizada no Wikipedia:

https://pt.wikipedia.org/wiki/Discografia_de_Taylor_Swift

Apesar do texto introdutório estar também com a informação desatualizada, nesse site temos já a informação do 11º álbum de estúdio lançado no início de 2024. Essa diferença entre a informação atualizada e a resposta do modelo “gpt-3.5-turbo” da OpenAI, se deve ao fato que o modelo foi treinado com informações até Setembro de 2021.

Mas ainda assim, existe uma forma de atualizarmos as informações do modelo, utilizando a técnica de RAG que vimos anteriormente. Para isso, vamos criar uma nova função onde além de recebermos o nome do artista, iremos receber uma url de site, que deve conter a informação atualizada com o contexto que devemos responder.

Vimos anteriormente que para utilizarmos a técnica de RAG, precisamos ter as informações externas em um banco de dados, para essa nossa aplicação simples com fins experimentais, iremos utilizar o FAISS.

Facebook AI Similarity Search (FAISS) é biblioteca open-source desenvolvida pelo Facebook AI Research, iremos utiliza-lá como uma espécie de banco de dados vetorial temporário. A partir dos nossos documentos, nesse caso, o texto que será extraído da url informada junto com os Embeddings da OpenAI, transformaremos o conteúdo do site em vetores formando um banco de dados vetorial.

Por fim, utilizaremos esse banco de dados vetorial como contexto em nosso template de prompt a fim de responder a nossa pergunta, podemos conferir esse código no exemplo abaixo:

Para executarmos esse código, basta executar:

$ python albums.py

=========================================
Resposta via RAG com o gpt-3.5-turbo:
Taylor Swift lançou um total de 11 álbuns de estúdio em sua carreira. Os álbuns são:

1. Taylor Swift (2006)
2. Fearless (2008)
3. Speak Now (2010)
4. Red (2012)
5. 1989 (2014)
6. Reputation (2017)
7. Lover (2019)
8. Folklore (2020)
9. Evermore (2020)
10. Midnights (2022)
11. The Tortured Poets Department (2024)
=========================================

Dessa forma, obtemos a resposta com a informação atualizada, baseada no contexto do conteúdo do site, utilizando a técnica de RAG. 🎉

ChatPDF

Depois do nosso primeiro contato com um exemplo mais simples com LangChain e utilizando a técnica de RAG, iremos partir para a construção do nosso ChatPDF.

O objetivo do nosso sistema será fazer o upload de arquivos PDF e a fim de utilizarmos as informações do mesmo em forma de contexto para responder nossas perguntas.

A lógica de RAG é muito semelhante a que realizamos anteriormente, exceto pela lógica extra para construção de componentes visuais com Streamlit e a lógica de upload de documentos.

Para prosseguirmos podemos criar um novo arquivo chamado "chatpdf.py" e uma pasta chamada "uploaded" onde concentrará de maneira temporária os arquivos que realizaremos o upload até que realizemos a extração de seus dados para um banco de dados vetorial.

Outro ponto que devemos nos atentar, é nosso novo template prompt, nele especificaremos o contexto e a pergunta, dessa forma especificamos que resposta a pergunta deve ser beaseada no Contexto e caso a resposta não esteja presente no contexto deve informar que não consegue responder a pergunta.

prompt = """ Você é um assistente que deve responder a Pergunta baseada no Contexto informado.
O contexto e a pergunta do utilizador são apresentados a seguir.
Contexto = {context}
Pergunta = {question}
Se a resposta não estiver no pdf, responda "Não consigo responder a essa pergunta com minha base de informações"
"""

Abaixo segue a primeira parte do arquivo com as funções necessárias para realizar a lógica de upload e formatação do arquivo além do carregamento de componentes necessários:

Além das funções acima, que serão necessárias para processamento do conteúdo do arquivo, diferente do exemplo introdutório onde consideramos todo o conteúdo do site como contexto do prompt, em caso de um ou mais PDFs, esse contexto pode ser inviável de ser enviado em um prompt por conta da limitação de tokens de input.

Dessa forma, iremos utilizar uma outra funcionalidade do FAISS que é a busca por similaridade baseada na pergunta realizada, com isso, iremos extrair um novo banco vetorial menor que será utilizado como contexto baseado na similaridade entre o banco de dados maior e a pergunta, diminuindo o conteúdo tornando viável continuarmos enviando no prompt.

Segue abaixo o restante do código com a lógica de componentes visuais do streamlit e a lógica de busca por similaridade a partir da pergunta para servir como contexto do prompt, além de utilizar as funções apresentadas no trecho anterior:

Para executarmos o código completo, basta executar o comando abaixo:

python -m streamlit run chatpdf.py

Com isso, podemos acessar o endereço http://localhost:8501 para acessarmos a aplicação streamlit em execução:

Antes de realizarmos as perguntas, é necessário realizarmos o upload do PDF que desejamos que seja o contexto, para isso utilizei o PDF da revista Computação Brasil de número 39 da Sociedade Brasileira de Computação. Para realizar o upload basta clicar no botão "Browse files" no canto superior esquerdo e selecionar o PDF com a revista, caso possua outro PDF que seja do seu interesse, fique a vontade em utilizá-lo.

Feito isso, basta clicar no botão "Processar" para extrair as informações do PDF para o banco de dados vetorial.

Por fim, podemos realizar as perguntas que desejamos e obtermos as respostas baseadas no contexto do PDF.

Com sucesso obtemos a resposta para nossa pergunta baseada em nosso PDF. 🎉

Para entendermos em parte a origem do contexto diretamente no PDF, podemos pesquisar por algumas palavras chaves da própria resposta, como "Platão", mas podemos observar que ele retirou informações de diversos pontos do nosso PDF relacionados a pergunta "O que é IA?" para enfim responder nossa pergunta.

Podemos validar também o comportamento do modelo em caso de uma pergunta fora do contexto do PDF.

Onde obtemos a resposta que desejamos, onde o mesmo informa que não consegue responder baseado no contexto que o mesmo possui, evitando dessa forma, as famosas Alucinações dos modelos, sendo essa hoje uma das maiores implicações no uso em soluções reais utilizando LLMs.

As alucinações são um fenômeno que ocorre no uso de modelos de LLM, onde o modelo gera texto que parece plausível, mas é incorreto, sem fundamento, ou completamente fabricado como se a resposta fosse uma verdade.

Encerrando o .venv

Por fim, para encerrarmos o .venv, basta executar o seguinte comando abaixo:

deactivate

Garantindo um ambiente isolado para nossas aplicações!

Conclusão

Escrevi esse artigo com o objetivo de ser uma introdução ao LangChain e a técnica de RAG, com um exemplo prático de aplicação, a fim de fomentar as mais diversas soluções que podemos criar com essas tecnologias.

São essas tecnologias que estão em alta no mercado hoje, pois é com elas que tornamos possível a criação de soluções reais utilizando IAs generativas.

E é com a técnica de RAG que torna possível o uso de dados internos, por exemplo passo a passo de soluções internas que muitas vezes estão públicas em sites, serem entregues de maneira inteligente por meio de assistentes virtuais que auxiliam os clientes finais com a resposta e a fonte da informação.

Como comentei ao fim do penúltimo tópico, hoje um dos maiores impeditivos para novas soluções utilizando IAs generativas, são as famosas alucinações dos modelos, que tenho certeza que já perceberam alguma ao perguntar sobre um assunto que dominam bem.

Apesar disso, existem técnicas e ferramentas de monitoramento para medir e controlar as alucinações, aliado a técnicas de Prompt que auxiliam a inibir ao máximo as alucinações. Pretendo futuramente trazer um novo artigo com exemplos práticos já avançado para entrarmos ao mérito dos pontos acima, explorando uma arquitetura completa de uma solução com IA generativa.

Agradecimento Especial

Por fim, gostaria de agradecer a cada um que desejou forças ou apoiou de qualquer forma o povo gaúcho, como alguns sabem fui diretamente afetado pelas enchentes de Maio de 2024 que ocorreram no Rio Grande do Sul, aos poucos estamos reconstruindo o estado e auxiliando amigos e familiares para voltamos mais fortes.

Por conta desses acontecimentos, fiquei por um tempo afastado dos meus estudos. Mas por meio desse artigo compartilho meu retorno e comprometimento com os estudos, que sempre gosto de compartilhar por aqui, por meio de artigos, um pouco sobre eles.

Obrigado pela sua atenção! E até breve 😄

--

--

Rhian Lopes da Costa
Fretebras Tech

Olá! Me chamo Rhian, sou apaixonado por resolver problemas utilizando Tecnologia e Inovações