Criar chatbots personalizados que conhecem profundamente sua área técnica usando RAG (Retrieval-Augmented Generation)
Criar chatbots personalizados que conhecem profundamente sua área técnica usando RAG (Retrieval-Augmented Generation)
Ao final deste módulo, você será capaz de:
✅ Entender como RAG funciona e por que é revolucionário ✅ Criar chatbots personalizados com conhecimento específico do seu domínio ✅ Implementar sistemas de perguntas e respostas sobre documentação técnica ✅ Construir assistentes que ajudam pessoas com problemas reais da sua área ✅ Integrar conhecimento técnico (docs, código, tickets) em IA conversacional
Resultado prático: Chatbot funcionando que responde perguntas sobre SUA área técnica com precisão.
---
Cenário real: Alguém pergunta no Slack:
> "Como faço deploy da nossa API em staging?"
Opções tradicionais: - ❌ Você responde manualmente (15 min) - ❌ Procura na wiki desatualizada (20 min de frustração) - ❌ Pede pra alguém mais velho explicar (interrompe 2 pessoas) - ❌ Usa ChatGPT genérico que inventa comandos errados
Com RAG: - ✅ Chatbot responde em 10 segundos - ✅ Baseado na SUA documentação real - ✅ Com comandos corretos do SEU ambiente - ✅ Links para docs relevantes - ✅ Você economizou 15 minutos + ajudou permanentemente
RAG = Retrieval-Augmented Generation
Tradução prática: 1. Retrieval: Busca informação relevante nos SEUS documentos 2. Augmented: Injeta essa informação no prompt 3. Generation: ChatGPT responde baseado no SEU conteúdo
Analogia: - ChatGPT normal: Estudante respondendo de memória (às vezes inventa) - ChatGPT com RAG: Estudante com seus livros abertos fazendo consulta ao vivo
| Aspecto | ChatGPT Normal | ChatGPT com RAG |
|---|---|---|
| --------- | ---------------- | ----------------- |
| Conhecimento | Genérico até 2023 | SEU domínio, atualizado |
| Precisão | Inventa quando não sabe | Cita fontes reais |
| Contexto | Limitado (8k-32k tokens) | Acessa toda sua base |
| Atualização | Fixo no tempo | Atualiza com novos docs |
| Confiabilidade | 70-80% | 90-95% (se docs bons) |
---
┌─────────────────────────────────────────────────────────┐
│ 1. PREPARAÇÃO (fazer 1x) │
├─────────────────────────────────────────────────────────┤
│ │
│ Seus Documentos (docs, wikis, READMEs) │
│ ↓ │
│ Chunking (quebra em pedaços) │
│ ↓ │
│ Embeddings (transforma em vetores) │
│ ↓ │
│ Vector Database (Pinecone, Chroma, FAISS) │
│ │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ 2. QUANDO ALGUÉM PERGUNTA (tempo real) │
├─────────────────────────────────────────────────────────┤
│ │
│ Pergunta do usuário │
│ ↓ │
│ Embedding da pergunta │
│ ↓ │
│ Busca vetorial (acha docs relevantes) │
│ ↓ │
│ Top 3-5 trechos mais relevantes │
│ ↓ │
│ Monta prompt: contexto + pergunta │
│ ↓ │
│ ChatGPT responde baseado no contexto │
│ ↓ │
│ Resposta + fontes citadas │
│ │
└─────────────────────────────────────────────────────────┘
`
1. Embeddings (Vetores Semânticos)
Transforma texto em números que capturam significado:
# Texto original
"Como fazer deploy em staging?"
# Vira vetor (exemplo simplificado) [0.23, -0.45, 0.78, ..., 0.12] # 1536 dimensões
# Textos similares têm vetores próximos
"Deploy para ambiente de testes" → vetor parecido ✅
"Como fazer café?" → vetor distante ❌
`
2. Vector Database
Banco de dados especializado em buscar vetores similares:
# Busca semântica (não precisa palavras exatas)
pergunta = "subir API pra homologação"
# Acha documentos sobre:
# - "deploy em staging" ✅
# - "publicar em ambiente de teste" ✅
# - "CI/CD pipeline" ✅
#
# Mesmo sem usar palavras exatas!
`
3. Chunking (Quebrar Documentos)
Divide docs grandes em pedaços úteis:
# Doc original: 10 páginas sobre deploy
# Chunks (pedaços de 500-1000 caracteres) Chunk 1: "Para fazer deploy em staging..." Chunk 2: "Configuração do ambiente..." Chunk 3: "Comandos necessários..." ...
# Por que?
# ChatGPT só vê 3-5 chunks mais relevantes
# Não precisa ler 10 páginas inteiras
`
---
Vamos criar um chatbot que responde perguntas sobre SUA documentação técnica.
Stack: - LangChain (framework RAG) - OpenAI API (embeddings + chat) - Chroma (vector database local) - Streamlit (interface)
Passo 1: Setup
# Instalar dependências
pip install langchain openai chromadb tiktoken streamlit
# Criar estrutura
mkdir meu-chatbot-rag
cd meu-chatbot-rag
mkdir docs # Coloque seus documentos aqui
`
Passo 2: Indexar Documentos (indexar.py)
from langchain.document_loaders import DirectoryLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
import os
# Configurar API key os.environ["OPENAI_API_KEY"] = "sua-api-key-aqui"
# 1. Carregar documentos print("📂 Carregando documentos...") loader = DirectoryLoader('docs/', glob="*/.md", loader_cls=TextLoader) documents = loader.load() print(f"✅ {len(documents)} documentos carregados")
# 2. Quebrar em chunks print("✂️ Quebrando em chunks...") text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, # Tamanho do pedaço chunk_overlap=200, # Sobreposição (contexto) separators=["\n\n", "\n", " ", ""] ) chunks = text_splitter.split_documents(documents) print(f"✅ {len(chunks)} chunks criados")
# 3. Criar embeddings e salvar
print("🧠 Criando embeddings...")
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db" # Salva localmente
)
vectorstore.persist()
print("✅ Base de conhecimento criada!")
`
Passo 3: Interface Streamlit (app.py)
import streamlit as st
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
import os
# Configuração os.environ["OPENAI_API_KEY"] = "sua-api-key-aqui"
st.title("🤖 Assistente de Documentação Técnica") st.caption("Pergunte qualquer coisa sobre nossa stack!")
# Carregar base de conhecimento @st.cache_resource def load_qa_chain(): embeddings = OpenAIEmbeddings() vectorstore = Chroma( persist_directory="./chroma_db", embedding_function=embeddings )
llm = ChatOpenAI( model_name="gpt-4", temperature=0 # Respostas mais precisas )
qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", # Tipo de chain retriever=vectorstore.as_retriever( search_kwargs={"k": 3} # Top 3 chunks ), return_source_documents=True # Retorna fontes )
return qa_chain
qa_chain = load_qa_chain()
# Interface de chat pergunta = st.text_input("Faça sua pergunta:")
if pergunta: with st.spinner("🔍 Buscando na documentação..."): result = qa_chain({"query": pergunta})
# Mostrar resposta st.markdown("### 💡 Resposta") st.write(result["result"])
# Mostrar fontes st.markdown("### 📚 Fontes") for i, doc in enumerate(result["source_documents"], 1): with st.expander(f"Fonte {i}: {doc.metadata.get('source', 'Documento')}"): st.text(doc.page_content)
# Sidebar com exemplos
st.sidebar.title("Exemplos de perguntas")
st.sidebar.markdown("""
- Como fazer deploy em staging?
- Qual é o processo de code review?
- Como rodar os testes localmente?
- Onde fica a documentação da API?
- Como configurar ambiente de dev?
""")
`
Passo 4: Rodar
# 1. Colocar seus docs .md na pasta docs/
# 2. Indexar (fazer 1x ou quando docs mudarem)
python indexar.py
# 3. Rodar chatbot
streamlit run app.py
`
OpenAI agora tem RAG embutido! Não precisa gerenciar vector database.
Código completo:
import openai
import streamlit as st
client = openai.OpenAI(api_key="sua-api-key")
# 1. Criar assistente (fazer 1x) def criar_assistente(): # Upload arquivos file1 = client.files.create( file=open("docs/deploy.md", "rb"), purpose="assistants" ) file2 = client.files.create( file=open("docs/api-docs.md", "rb"), purpose="assistants" )
# Criar assistente com file search (RAG) assistant = client.beta.assistants.create( name="Assistente Técnico", instructions="""Você é um assistente técnico especializado. Responda baseado nos documentos fornecidos. Sempre cite as fontes.""", model="gpt-4-turbo", tools=[{"type": "file_search"}], tool_resources={ "file_search": { "vector_stores": [{ "file_ids": [file1.id, file2.id] }] } } )
return assistant.id
# 2. Interface Streamlit st.title("🤖 Assistente com RAG (OpenAI)")
# Inicializar if "assistant_id" not in st.session_state: st.session_state.assistant_id = "asst_xxxxx" # Seu ID aqui if "thread_id" not in st.session_state: thread = client.beta.threads.create() st.session_state.thread_id = thread.id
# Chat pergunta = st.text_input("Sua pergunta:")
if pergunta: # Enviar mensagem client.beta.threads.messages.create( thread_id=st.session_state.thread_id, role="user", content=pergunta )
# Rodar assistente with st.spinner("Pensando..."): run = client.beta.threads.runs.create_and_poll( thread_id=st.session_state.thread_id, assistant_id=st.session_state.assistant_id )
# Pegar resposta messages = client.beta.threads.messages.list( thread_id=st.session_state.thread_id )
resposta = messages.data[0].content[0].text.value
st.markdown(f"Resposta: {resposta}")
`
Vantagens: - ✅ Não precisa gerenciar vector database - ✅ OpenAI cuida de tudo (chunking, embeddings, busca) - ✅ Código mais simples - ✅ Escala automaticamente
Desvantagens: - ❌ Mais caro (paga por storage de arquivos) - ❌ Menos controle sobre chunking - ❌ Depende 100% da OpenAI
---
Problema: Novos devs fazem as mesmas perguntas
Solução RAG:
# Documentos indexados:
# - README.md
# - CONTRIBUTING.md
# - ARCHITECTURE.md
# - Onboarding wiki
# - FAQs do Slack (exportados)
# Chatbot responde:
# "Como rodar o projeto local?"
# "Qual é o fluxo de PR?"
# "Onde fica a staging?"
# "Preciso de acesso a quê?"
`
Resultado: - ⏱️ Dev júnior demora 3 dias → 1 dia pra ser produtivo - 🕐 Você economiza 5h de onboarding manual - 📈 Satisfação de novos devs sobe 40%
Problema: Suporte pergunta "como resolver erro X" toda semana
Solução RAG:
# Base de conhecimento:
# - Post-mortems de incidentes
# - Runbooks
# - Issues do GitHub resolvidos
# - Logs de troubleshooting
# Bot ajuda com:
# "API retornando 502, o que fazer?"
# "Build falhou com erro XYZ"
# "Como fazer rollback de deploy?"
`
Resultado: - 🚀 70% dos problemas resolvidos sem escalar - ⏱️ MTTR (Mean Time To Resolution) cai 50% - 😊 Time de suporte feliz
Problema: Documentação de API complexa, difícil de navegar
Solução RAG:
# Indexa:
# - OpenAPI/Swagger spec
# - Exemplos de código
# - Changelog
# - Guias de autenticação
# Desenvolvedor pergunta naturalmente:
# "Como autenticar na API?"
# "Exemplo de request pra criar usuário"
# "Rate limits da API de payments?"
# "O que mudou na v2?"
`
Resultado: - 📉 Tickets de suporte sobre API: -60% - ⚡ Time to first successful API call: -70% - 💰 Adoção da API aumenta
---
| Ferramenta | Quando usar | Custo |
|---|---|---|
| ------------ | ------------- | ------- |
| Chroma | Projetos pequenos, local | Grátis |
| Pinecone | Produção, escala | $70/mês |
| Weaviate | Self-hosted, controle total | Grátis (infra sua) |
| FAISS | Pesquisa rápida, offline | Grátis |
| Qdrant | Open source, produção | Grátis ou pago |
LangChain: `python
# Mais completo, muitos integrações
from langchain.chains import RetrievalQA
qa = RetrievalQA.from_chain_type(...)
`
LlamaIndex: `python
# Especializado em RAG, mais simples
from llama_index import VectorStoreIndex
index = VectorStoreIndex.from_documents(docs)
`
Haystack: `python
# Focado em NLP pipelines
from haystack.nodes import DensePassageRetriever
retriever = DensePassageRetriever(...)
`
1. ChatBase (chatbase.co) - Upload docs → chatbot pronto - Embeddable widget - $19/mês
2. CustomGPT (customgpt.ai) - RAG sem código - Integrações prontas - $89/mês
3. Dante AI (dante-ai.com) - Treinamento rápido - Multi-plataforma - $30/mês
Quando usar no-code: - ✅ Validar ideia rápido - ✅ Não tem time de dev - ✅ Volume baixo de perguntas
Quando fazer custom: - ✅ Integração com sistemas internos - ✅ Controle total sobre dados - ✅ Alto volume (mais barato)
---
Chunking inteligente:
# ❌ Ruim: quebra no meio de seção
RecursiveCharacterTextSplitter(chunk_size=500)
# ✅ Bom: respeita estrutura markdown from langchain.text_splitter import MarkdownHeaderTextSplitter
splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]
)
`
Metadados úteis:
# Adicionar metadados aos chunks
for i, chunk in enumerate(chunks):
chunk.metadata = {
"source": "deploy.md",
"section": "Staging",
"last_updated": "2025-01-15",
"author": "DevOps Team"
}
# Usar em filtros
vectorstore.similarity_search(
"como fazer deploy",
filter={"section": "Staging"} # Busca só em Staging
)
`
Prompt engineering:
# Template de prompt otimizado
template = """Use os seguintes documentos para responder a pergunta.
Se não souber, diga "não encontrei essa informação".
NÃO invente informações.
Contexto: {context}
Pergunta: {question}
Resposta (em português, cite fontes):"""
`
Embeddings mais baratos:
# OpenAI embeddings: $0.0001/1K tokens
embeddings = OpenAIEmbeddings()
# Alternativa grátis (roda local):
from langchain.embeddings import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2"
)
`
Caching agressivo:
# Cachear respostas comuns
import hashlib
import json
cache = {}
def ask_with_cache(question): key = hashlib.md5(question.encode()).hexdigest()
if key in cache: return cache[key] # Hit!
answer = qa_chain(question)
cache[key] = answer
return answer
`
Modelo mais barato para retrieval:
# Use GPT-4 só quando necessário
from langchain.chat_models import ChatOpenAI
# Retrieval + ranqueamento: GPT-3.5 (mais barato) cheap_llm = ChatOpenAI(model="gpt-3.5-turbo")
# Resposta final: GPT-4 (melhor qualidade)
good_llm = ChatOpenAI(model="gpt-4")
`
Hybrid search (keyword + semantic):
from langchain.retrievers import BM25Retriever, EnsembleRetriever
# Busca semântica semantic_retriever = vectorstore.as_retriever()
# Busca por palavras-chave bm25_retriever = BM25Retriever.from_documents(documents)
# Combina os dois!
ensemble_retriever = EnsembleRetriever(
retrievers=[semantic_retriever, bm25_retriever],
weights=[0.5, 0.5] # 50% cada
)
`
Reranking:
# Busca 10 docs, rerankeia com modelo melhor, usa top 3
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CohereRerank
compressor = CohereRerank()
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=vectorstore.as_retriever(search_kwargs={"k": 10})
)
`
---
---
Objetivo: Criar chatbot que responde perguntas sobre SUA área técnica.
Passo a passo:
Critérios de sucesso: - ✅ Responde 8/10 perguntas corretamente - ✅ Cita fontes relevantes - ✅ Tempo de resposta < 10 segundos - ✅ Pelo menos 1 colega diz "isso é útil!"
---
Como saber se seu RAG está funcionando?
1. Precisão da Busca
`python
# Porcentagem de perguntas que retornam docs relevantes
# Meta: > 85%
def avaliar_retrieval(perguntas_teste):
acertos = 0
for q in perguntas_teste:
docs = vectorstore.similarity_search(q['pergunta'], k=3)
if q['doc_esperado'] in [d.metadata['source'] for d in docs]:
acertos += 1
return acertos / len(perguntas_teste)
`
2. Qualidade da Resposta - Usuário dá 👍/👎 após resposta - Meta: > 80% de 👍
3. Latência - Tempo de resposta end-to-end - Meta: < 5 segundos
1. Redução de Perguntas Repetidas - Antes vs Depois de ter chatbot - Meta: -50% em canais de suporte
2. Time to Answer - Quanto tempo demora pra pessoa obter resposta - Antes: 2h (espera humano) → Depois: 10s (chatbot)
3. Satisfação (CSAT) - Survey rápido: "O chatbot ajudou?" (1-5) - Meta: > 4.0
4. Adoção - % do time que usa o chatbot - Meta: > 60% após 1 mês
---
---
# ❌ Prompt genérico
"Responda a pergunta baseado nos documentos."
# ✅ Prompt específico
"""Você é especialista em DevOps na empresa X.
Responda baseado APENAS nos documentos fornecidos.
Se não souber, diga claramente.
Cite comandos exatos e links quando relevante.
Seja conciso mas completo."""
`
# Adicionar botões de feedback
col1, col2 = st.columns(2)
if col1.button("👍 Útil"):
salvar_feedback(pergunta, resposta, positivo=True)
if col2.button("👎 Não ajudou"):
salvar_feedback(pergunta, resposta, positivo=False)
# Rastreie custos de API
import tiktoken
def estimar_custo(text): encoding = tiktoken.get_encoding("cl100k_base") tokens = len(encoding.encode(text)) custo_por_mil = 0.0001 # embeddings return (tokens / 1000) * custo_por_mil
print(f"Custo estimado: ${estimar_custo(all_docs):.4f}")
`
---
O que você aprendeu:
✅ RAG = ChatGPT + Seus Documentos - Busca informação relevante nos seus docs - Injeta no prompt - ChatGPT responde baseado no SEU conteúdo
✅ Arquitetura: - Embeddings → Vector Database → Retrieval → Generation
✅ Implementação: - LangChain + Chroma (controle total) - OpenAI Assistants (mais fácil) - No-code (validação rápida)
✅ Casos de uso: - Onboarding de devs - Troubleshooting - Documentação de API - FAQs técnicos
Próximo passo no Módulo 4: Vamos criar seu portfólio técnico no GitHub que mostra todos esses projetos incríveis que você está construindo!
---
Tutoriais: - LangChain RAG Tutorial - OpenAI Assistants Guide - Pinecone RAG Guide
Ferramentas: - LangSmith - Debug RAG chains - Ragas - Avaliar qualidade RAG - Chroma - Vector database
Comunidades: - r/LangChain (Reddit) - LangChain Discord - OpenAI Developer Forum
---
Tempo estimado de conclusão: 3-4 horas (incluindo exercício prático)
Prerequisitos: Conhecimento básico de Python, familiaridade com APIs
Próximo módulo: Módulo 4 - GitHub como Portfólio de Solucionador Técnico