programa
RAG autêntico: Tutorial passo a passo com projeto de demonstração
Com que frequência você deseja que sua IA possa fazer mais do que apenas repetir o que ela já sabe? Como alguém que passou inúmeras horas refinando e ajustando sistemas de IA, posso dizer a você que os modelos tradicionais, embora impressionantes, muitas vezes parecem estar presos em uma bolha limitada ao que foi treinado. É aqui queo Agentic RAG entra em cena.
No RAG autêntico, as habilidades de tomada de decisão da IA autêntica encontram a adaptabilidade da geração aumentada por recuperação (RAG). Juntos, eles formam um sistema que pode acessar, raciocinar e gerar informações relevantes de forma independente.
Escrevi anteriormente um artigo sobre RAG autêntico que ajudará você a entender tudo sobre ele do ponto de vista teórico. Este artigo será mais prático, portanto, vamos nos concentrar nisso.
Visão geral do projeto Agentic RAG
Deixe-me mostrar a você o que estamos construindo, passo a passo. Trata-se de criar um pipeline RAG com base na arquitetura mostrada aqui:
Etapa 1: Consulta do usuário
Quer seja uma consulta simples ou um problema complexo, tudo começa com uma pergunta do usuário. Essa é a faísca que coloca nosso pipeline em movimento.
Etapa 2: Roteamento da consulta
Em seguida, o sistema verifica: Posso responder a isso?
Sim? Ele extrai o conhecimento existente e fornece a resposta imediatamente.
Não? É hora de ir mais fundo! A consulta é encaminhada para a próxima etapa.
Etapa 3: Recuperação de dados
Se a resposta não estiver prontamente disponível, o pipeline se aprofunda em duas fontes possíveis:
- Documentos locais: Usaremos um PDF pré-processado como nossa base de conhecimento, na qual o sistema procura por partes relevantes de informações.
- Pesquisa na Internet: Se você precisar de mais contexto, o pipeline poderá entrar em contato com fontes externas para obter informações atualizadas.
Etapa 4: Criando o contexto
Os dados recuperados, seja do PDF ou da Web, são compilados em um contexto coerente e recuperado. Pense nisso como se você reunisse todas as peças do quebra-cabeça antes de montá-las.
Etapa 5: Geração da resposta final
Por fim, esse contexto é passado para um modelo de linguagem ampla (LLM) para criar uma resposta clara e precisa. Não se trata apenas de recuperar dados, mas de entendê-los e apresentá-los da melhor maneira possível.
Ao final, teremos um pipeline RAG inteligente e eficiente que poderá responder dinamicamente a consultas com contexto do mundo real.
Fonte de dados local
Para começar, vou usar um documento do mundo real como nossa fonte de dados local. O documento com o qual trabalharemos é nada menos que Princípios de IA generativa. Ele está repleto de insights valiosos, portanto, será o caso de teste perfeito para nosso pipeline. Você também precisaria de um resumo do arquivo que estou usando para fins de roteamento. Você pode obter o arquivo de resumo em aqui.
Aqui está tudo o que você precisa para começar, passo a passo.
Pré-requisitos
Antes de começarmos, há alguns aspectos que você precisa ter em mente:
- Chave de API do Groq: Você precisará de uma chave de API do Groq, que pode ser obtida aqui: Console da API do Groq
- Chave de API da Gemini: O Gemini ajudará você na orquestração com agentes, o Groq fornece respostas super rápidas, mas pode ficar preso aos limites de taxa atuais que eles têm: Console da API Gemini
- Chave de API do Serper.dev: Para qualquer funcionalidade de pesquisa na Internet, usaremos o Serper.dev. Obtenha sua chave de API aqui: Serper.dev API Key
Instalação de pacotes
Vamos nos certificar de que você tem as ferramentas certas instaladas. Abra o terminal e execute os seguintes comandos para instalar os pacotes Python necessários:
pip install langchain-groq faiss-cpu crewai serper pypdf2 python-dotenv setuptools sentence-transformers huggingface distutils`
Configuração do ambiente
Depois de ter as chaves e os pacotes prontos, você está pronto para ir! Recomendo que você salve suas chaves de API em um arquivo.env
ou de forma segura em sua base de código. Aqui está um exemplo de como o arquivo .env
pode parecer:
import os from dotenv
import load_dotenv from langchain.vectorstores
import FAISS from langchain.document_loaders
import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_huggingface.embeddings import HuggingFaceEmbeddings
from langchain_groq import ChatGroq
from crewai_tools import SerperDevTool
from crewai import Agent, Task, Crew, LLM
load_dotenv()
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
SERPER_API_KEY = os.getenv("SERPER_API_KEY")
GEMINI=os.getenv("GEMINI")
Carreguei variáveis de ambiente para poder gerenciar com segurança as chaves de API e os dados confidenciais sem codificá-los. Isso garante que o script permaneça seguro e que eu possa alterar as chaves em um só lugar ( arquivo.env
), se necessário.
Em poucas palavras, você verá o que esses pacotes e funções importados farão:
- os: Fornece utilitários de interface do sistema operacional.
- dotenv: Carrega variáveis de ambiente dos arquivos
.env
. - FAISS: Armazenamento de vetores para pesquisa e recuperação de similaridade.
- PyPDFLoader: Extrai conteúdo de texto de documentos PDF.
- RecursiveCharacterTextSplitter: Divide o texto em partes gerenciáveis de forma recursiva.
- HuggingFaceEmbeddings: Gera embeddings de texto usando modelos HuggingFace.
- ChatGroq: Interface de bate-papo com a aceleração de hardware do Groq.
- SerperDevTool: Ferramenta para realizar pesquisas na Web.
- ScrapeWebsiteTool: Extrai dados de páginas da Web.
- Agente: Define uma entidade de IA com funções e objetivos.
- Tarefa: Representa um objetivo ou uma ação específica para um agente.
- Tripulação: Orquestra agentes e tarefas para fluxos de trabalho coordenados.
- LLM: Interface de modelo de linguagem grande para gerar respostas de texto.
Inicialização dos LLMs
Começamos com a inicialização de dois modelos de linguagem:
llm
: Para tarefas gerais, como roteamento e geração de respostas. Usaremos o modelollama-3.3-70b-specdec
.crew_llm
: Especificamente para o agente de raspagem da Web, pois ele precisa de uma configuração ligeiramente diferente (como temperatura para resultados mais criativos). Usaremos o modelogemini/gemini-1.5-flash
.
# Initialize LLM
llm = ChatGroq(
model="llama-3.3-70b-specdec",
temperature=0,
max_tokens=500,
timeout=None,
max_retries=2,
)
crew_llm = LLM(
model="gemini/gemini-1.5-flash",
api_key=GEMINI,
max_tokens=500,
temperature=0.7
)
Adicionando o tomador de decisões
A função check_local_knowledge()
abaixo atua como um tomador de decisões. Criei um prompt no qual passei a consulta do usuário e algum contexto local (do PDF). O modelo responde com "Yes" (Sim) ou "No" (Não), informando se ele tem informações suficientes localmente para responder à consulta. Caso contrário, recorreremos à coleta de dados da Web.
def check_local_knowledge(query, context):
"""Router function to determine if we can answer from local knowledge"""
prompt = '''Role: Question-Answering Assistant
Task: Determine whether the system can answer the user's question based on the provided text.
Instructions:
- Analyze the text and identify if it contains the necessary information to answer the user's question.
- Provide a clear and concise response indicating whether the system can answer the question or not.
- Your response should include only a single word. Nothing else, no other text, information, header/footer.
Output Format:
- Answer: Yes/No
Study the below examples and based on that, respond to the last question.
Examples:
Input:
Text: The capital of France is Paris.
User Question: What is the capital of France?
Expected Output:
Answer: Yes
Input:
Text: The population of the United States is over 330 million.
User Question: What is the population of China?
Expected Output:
Answer: No
Input:
User Question: {query}
Text: {text}
'''
formatted_prompt = prompt.format(text=context, query=query)
response = llm.invoke(formatted_prompt)
return response.content.strip().lower() == "yes"
Agente de pesquisa e raspagem da Web
Em seguida, configuramos um agente de pesquisa e raspagem da Web usando a crewai
biblioteca. Esse agente usa uma ferramenta de pesquisa (SerperDevTool
) para encontrar artigos relacionados à consulta do usuário. A descrição da tarefa garante que o agente saiba o que recuperar e resume o conteúdo relevante da Web. É como enviar um trabalhador especializado para buscar dados na Internet.
Em seguida, a função get_web_content()
executa o agente de raspagem da Web. Ele envia a consulta como entrada e recupera um resumo conciso do artigo mais relevante. Ele retorna o resultado bruto, que se torna nosso contexto se o roteador decidir que não temos informações locais suficientes.
def setup_web_scraping_agent():
"""Setup the web scraping agent and related components"""
search_tool = SerperDevTool() # Tool for performing web searches
scrape_website = ScrapeWebsiteTool() # Tool for extracting data from websites
# Define the web search agent
web_search_agent = Agent(
role="Expert Web Search Agent",
goal="Identify and retrieve relevant web data for user queries",
backstory="An expert in identifying valuable web sources for the user's needs",
allow_delegation=False,
verbose=True,
llm=crew_llm
)
# Define the web scraping agent
web_scraper_agent = Agent(
role="Expert Web Scraper Agent",
goal="Extract and analyze content from specific web pages identified by the search agent",
backstory="A highly skilled web scraper, capable of analyzing and summarizing website content accurately",
allow_delegation=False,
verbose=True,
llm=crew_llm
)
# Define the web search task
search_task = Task(
description=(
"Identify the most relevant web page or article for the topic: '{topic}'. "
"Use all available tools to search for and provide a link to a web page "
"that contains valuable information about the topic. Keep your response concise."
),
expected_output=(
"A concise summary of the most relevant web page or article for '{topic}', "
"including the link to the source and key points from the content."
),
tools=[search_tool],
agent=web_search_agent,
)
# Define the web scraping task
scraping_task = Task(
description=(
"Extract and analyze data from the given web page or website. Focus on the key sections "
"that provide insights into the topic: '{topic}'. Use all available tools to retrieve the content, "
"and summarize the key findings in a concise manner."
),
expected_output=(
"A detailed summary of the content from the given web page or website, highlighting the key insights "
"and explaining their relevance to the topic: '{topic}'. Ensure clarity and conciseness."
),
tools=[scrape_website],
agent=web_scraper_agent,
)
# Define the crew to manage agents and tasks
crew = Crew(
agents=[web_search_agent, web_scraper_agent],
tasks=[search_task, scraping_task],
verbose=1,
memory=False,
)
return crew
def get_web_content(query):
"""Get content from web scraping"""
crew = setup_web_scraping_agent()
result = crew.kickoff(inputs={"topic": query})
return result.raw
Criando o banco de dados de vetores
A função setup_vector_db()
configura o banco de dados vetorial a partir de um arquivo PDF. Veja como eu fiz isso passo a passo:
- Carregue o PDF: Usei o site
PyPDFLoader
para extrair o conteúdo. - Separe o texto em partes: Dividi o conteúdo do PDF em partes menores (1000 caracteres com 50 caracteres sobrepostos) usando
RecursiveCharacterTextSplitter
. Isso torna os dados gerenciáveis e pesquisáveis. - Criar o Vector DB: Incorporei os blocos usando um modelo de transformador de frases e os armazenei em um arquivo FAISS e os armazenei em um banco de dados de vetores FAISS. Isso me permite pesquisar textos relevantes com eficiência.
Depois disso, a função get_local_content()
consulta o banco de dados de vetores para obter os 5 blocos mais relevantes relacionados à consulta do usuário. Ele combina esses blocos em uma única cadeia de contexto.
def setup_vector_db(pdf_path):
"""Setup vector database from PDF"""
# Load and chunk PDF
loader = PyPDFLoader(pdf_path)
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=50
)
chunks = text_splitter.split_documents(documents)
# Create vector database
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-mpnet-base-v2"
)
vector_db = FAISS.from_documents(chunks, embeddings)
return vector_db
def get_local_content(vector_db, query):
"""Get content from vector database"""
docs = vector_db.similarity_search(query, k=5)
return " ".join([doc.page_content for doc in docs])
Gerando a resposta final
Quando tenho o contexto (de documentos locais ou de raspagem da Web), eu o passo para o modelo de linguagem junto com a consulta do usuário. O LLM gera a resposta final combinando o contexto e a consulta em um formato de conversação.
Aqui está o fluxo do processamento da consulta principal:
- Roteamento: Utilizo o site
check_local_knowledge()
para decidir se o conteúdo do PDF local tem dados suficientes para responder à consulta. - Se você "Sim"eu busco os pedaços relevantes no banco de dados de vetores.
- Se "Não", eu busco artigos relevantes na Web.
- Resposta final: Depois de obter o contexto, eu o passo para o LLM para gerar a resposta final.
def generate_final_answer(context, query):
"""Generate final answer using LLM"""
messages = [
(
"system",
"You are a helpful assistant. Use the provided context to answer the query accurately.",
),
("system", f"Context: {context}"),
("human", query),
]
response = llm.invoke(messages)
return response.content
def process_query(query, vector_db, local_context):
"""Main function to process user query"""
print(f"Processing query: {query}")
# Step 1: Check if we can answer from local knowledge
can_answer_locally = check_local_knowledge(query, local_context)
print(f"Can answer locally: {can_answer_locally}")
# Step 2: Get context either from local DB or web
if can_answer_locally:
context = get_local_content(vector_db, query)
print("Retrieved context from local documents")
else:
context = get_web_content(query)
print("Retrieved context from web scraping")
# Step 3: Generate final answer
answer = generate_final_answer(context, query)
return answer
Por fim, unimos tudo com a função main()
:
def main():
# Setup
pdf_path = "genai-principles.pdf"
# Initialize vector database
print("Setting up vector database...")
vector_db = setup_vector_db(pdf_path)
# Get initial context from PDF for routing
local_context = get_local_content(vector_db, "")
# Example usage
query = "What is Agentic RAG?"
result = process_query(query, vector_db, local_context)
print("\nFinal Answer:")
print(result)
if __name__ == "__main__":
main()
Acima, nós:
- Configure o banco de dados de vetores: Carregar e processar o PDF.
- Inicializou o contexto local: Obtivemos algum conteúdo geral do PDF para passar como contexto para o roteador.
- Executou uma consulta de exemplo: Executamos uma consulta de amostra (
"What is Agentic RAG?"
) e imprimimos a resposta final.
Este é o resultado do programa:
Agentic RAG is a technique for building Large Language Model (LLM) powered applications that incorporates AI agents. It is an extension of the traditional Retrieval-Augmented Generation (RAG) approach, which uses an external knowledge source to provide the LLM with relevant context and reduce hallucinations.
In traditional RAG pipelines, the retrieval component is typically composed of an embedding model and a vector database, and the generative component is an LLM. At inference time, the user query is used to run a similarity search over the indexed documents to retrieve the most similar documents to the query and provide the LLM with additional context.
Agentic RAG, on the other hand, introduces AI agents that are designed to interact with the user query and provide additional context to the LLM. These agents can be thought of as "virtual assistants" that help the LLM to better understand the user's intent and retrieve relevant documents.
The key components of Agentic RAG include:
1. AI agents: These are the virtual assistants that interact with the user query and provide additional context to the LLM.
2. Retrieval component: This is the component that retrieves the most similar documents to the user query.
3. Generative component: This is the component that uses the retrieved documents to generate the final output.
Agentic RAG has several benefits, including:
1. Improved accuracy: By providing additional context to the LLM, Agentic RAG can improve the accuracy of the generated output.
2. Enhanced user experience: Agentic RAG can help to reduce the complexity of the user interface and provide a more natural and intuitive experience.
3. Increased flexibility: Agentic RAG can be easily extended to support new use cases and applications.
However, Agentic RAG also has some limitations, including:
1. Increased complexity: Agentic RAG requires additional components and infrastructure, which can increase the complexity of the system.
2. Higher computational requirements: Agentic RAG requires more computational resources to handle the additional complexity of the AI agents and the retrieval component.
3. Training requirements: Agentic RAG requires more data and training to learn the behaviour of the AI agents and the retrieval component.
Explicação da saída
Quando fiz a pergunta "O que é Agentic RAG?" que não estava explicitamente disponível no documento fornecido, o sistema demonstrou sua flexibilidade e inteligência. Os agentes da crewAI encaminharam a consulta corretamente, usando o entendimento do roteador de que o contexto externo era necessário. Os agentes colaboraram para extrair o artigo mais relevante da Web, analisar seu conteúdo e gerar uma resposta bem informada.
O sistema forneceu uma explicação clara do RAG autêntico, seus componentes (agentes de IA, recuperação e elementos geradores), benefícios (precisão, experiência do usuário e flexibilidade) e limitações (complexidade, necessidades computacionais e requisitos de treinamento).
Isso destaca a capacidade do pipeline de buscar contexto dinamicamente e fornecer insights precisos, concisos e valiosos, mesmo quando confrontado com consultas que vão além do conjunto de dados inicial.
Conclusão
O pipeline que criamos é um processo dinâmico e de várias etapas que lida com eficiência com as consultas dos usuários combinando conhecimentos existentes e externos.
O sistema pode se adaptar dinamicamente a diversas consultas e fornecer respostas precisas e fáceis de usar. Com a integração de dados locais, pesquisas ao vivo na Internet e uma interface de usuário perfeita, o pipeline RAG prova ser uma solução robusta e prática para aplicações do mundo real. Como próxima etapa, tente criar algo próprio usando o fluxo de trabalho que abordamos.
Engenheiro sênior de GenAI e criador de conteúdo que obteve 20 milhões de visualizações ao compartilhar conhecimento sobre GenAI e ciência de dados.
Aprenda IA com estes cursos!
curso
Retrieval Augmented Generation (RAG) with LangChain
curso
Fine-Tuning with Llama 3
tutorial
RAG With Llama 3.1 8B, Ollama e Langchain: Tutorial

Ryan Ong
12 min
tutorial
Tutorial do DeepChecks: Automatizando os testes de machine learning
tutorial
Tutorial da API de assistentes da OpenAI
tutorial
Dominando a retropropagação: Um guia abrangente para redes neurais
tutorial