Skip to content

inematds/MegaRAG

Repository files navigation

MegaRAG

Next.js TypeScript Supabase Gemini

Converse com Seus Arquivos Usando IA

Faça upload de qualquer documento, vídeo ou imagem. Faça perguntas. Receba respostas com fontes.


Índice

  1. Entendendo RAG: O Que É Isso?
  2. A Tecnologia: Como Funciona?
  3. Pré-requisitos: O Que Você Precisa Antes de Começar
  4. Guia de Configuração Passo a Passo
  5. Usando a Aplicação
  6. Entendendo o Código
  7. Guia de Solução de Problemas
  8. Deploy em Produção
  9. Recursos Adicionais

🤔 Entendendo RAG: O Que É Isso?

O Problema Que Estamos Resolvendo

Digamos que você trabalha em uma empresa com milhares de documentos: contratos, atas de reunião, relatórios, vídeos de treinamento e mais. Um dia, alguém pergunta:

"O que combinamos no contrato Smith sobre prazos de entrega?"

Sem um sistema RAG, você precisaria:

  1. Lembrar em qual pasta está o contrato Smith
  2. Abrir o documento
  3. Procurar manualmente pelas páginas para encontrar a seção de entrega
  4. Ler e entender o que encontrou
  5. Formular uma resposta

Isso pode levar de 5 a 30 minutos. E se você receber 50 perguntas assim por dia?

Com um sistema RAG como o MegaRAG, você:

  1. Digita sua pergunta
  2. Recebe uma resposta em segundos, com a fonte exata destacada

O Que Significa "RAG"?

Retrieval-Augmented Generation (Geração Aumentada por Recuperação)

Vamos detalhar:

  • Retrieval (Recuperação): Encontrar informações relevantes nos seus documentos
  • Augmented (Aumentada): O conhecimento da IA é "aumentado" (aprimorado) com seus documentos específicos
  • Generation (Geração): A IA gera uma resposta em linguagem natural

Como o RAG Funciona: Uma Analogia Simples

Pense no RAG como um bibliotecário muito inteligente:

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│   IA TRADICIONAL (como ChatGPT sozinho)                                             │
│   ═════════════════════════════════════                                             │
│                                                                                     │
│   Você: "O que está no contrato Smith?"                                             │
│   IA: "Não tenho acesso aos seus documentos. Só posso usar meu conhecimento geral." │
│                                                                                     │
│   A IA é inteligente, mas ela não leu SEUS documentos.                              │
│                                                                                     │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                     │
│   SISTEMA RAG (IA + Seus Documentos)                                                │
│   ══════════════════════════════════                                                │
│                                                                                     │
│   Você: "O que está no contrato Smith?"                                             │
│                                                                                     │
│   RAG Passo 1 (Recuperação):                                                        │
│   "Deixe-me buscar nos seus documentos algo sobre 'contrato Smith'..."              │
│   → Encontrado: Seção 4.2 do smith_contrato.pdf menciona prazos de entrega          │
│                                                                                     │
│   RAG Passo 2 (Geração Aumentada):                                                  │
│   "Baseado na Seção 4.2 do seu contrato Smith, o prazo de entrega é..."             │
│                                                                                     │
│   Agora a IA pode responder perguntas sobre SEUS documentos específicos!            │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

O Pipeline RAG: Passo a Passo

Aqui está exatamente o que acontece quando você usa o MegaRAG:

Fase 1: Upload e Processamento de Documentos

Passo 1: UPLOAD
═══════════════
Você arrasta um PDF para o app.

    📄 relatorio_trimestral.pdf
         │
         ▼
    ┌─────────────────┐
    │  MegaRAG        │
    │  recebe arquivo │
    └─────────────────┘


Passo 2: ARMAZENAR O ARQUIVO
════════════════════════════
O arquivo original é salvo no Supabase Storage (como Google Drive, mas para nosso app).

    📄 relatorio_trimestral.pdf
         │
         ▼
    ┌──────────────────────────────────┐
    │  Supabase Storage                │
    │  ════════════════                │
    │                                  │
    │  📁 documents/                   │
    │     └── relatorio_trimestral.pdf │
    │                                  │
    │  (Arquivo salvo com segurança)   │
    └──────────────────────────────────┘


Passo 3: EXTRAIR CONTEÚDO
═════════════════════════
A IA lê o arquivo e extrai todo o conteúdo.

    Para um PDF, isso significa:
    • Todo texto de cada página
    • Tabelas convertidas em texto estruturado
    • Descrições de imagens e gráficos

    📄 relatorio_trimestral.pdf
         │
         ▼
    ┌────────────────────────────────┐
    │  Google Gemini AI              │
    │  ═════════════════             │
    │                                │
    │  "Vejo que este PDF tem 15     │
    │   páginas. Página 1 é a capa...│
    │   Página 4 tem tabela de       │
    │   receita..."                  │
    │                                │
    │  SAÍDA: Todo texto extraído    │
    └────────────────────────────────┘


Passo 4: DIVIDIR O CONTEÚDO EM CHUNKS
═════════════════════════════════════
O texto extraído é dividido em pedaços menores chamados "chunks".

    Por que chunks?
    • Modelos de IA têm limites de quanto texto podem processar de uma vez
    • Pedaços menores são mais fáceis de pesquisar
    • Recuperamos apenas os chunks RELEVANTES, não o documento inteiro

    Texto Completo do Documento (10.000 palavras)
         │
         ▼
    ┌──────────────────────────────────────────────┐
    │  Processo de Chunking                        │
    │  ════════════════════                        │
    │                                              │
    │  Dividido em pedaços de ~800 palavras        │
    │  com sobreposição                            │
    │                                              │
    │  Chunk 1: "Relatório Q3 2024. Resumo         │
    │            Executivo: Receita cresceu 15%..."│
    │                                              │
    │  Chunk 2: "...continuação do anterior.       │
    │            O mercado norte-americano..."     │
    │                                              │
    │  Chunk 3: "...despesas diminuíram devido     │
    │            a eficiências operacionais..."    │
    │                                              │
    │  (12 chunks no total)                        │
    └──────────────────────────────────────────────┘


Passo 5: CRIAR EMBEDDINGS (A Mágica)
════════════════════════════════════
Cada chunk é convertido em números que representam seu significado.

    O que são embeddings?

    Computadores não entendem significado. Para um computador, "cachorro" e "cão"
    são sequências de caracteres completamente diferentes, mesmo significando
    a mesma coisa.

    EMBEDDINGS convertem texto em números que capturam o significado:

    ┌────────────────────────────────────────────────────────────────────┐
    │                                                                    │
    │  "Eu amo cachorros"    → [0.21, 0.85, 0.12, 0.53, 0.77, ...]       │
    │                           (768 números)                            │
    │                                                                    │
    │  "Eu adoro filhotes"   → [0.22, 0.84, 0.11, 0.55, 0.76, ...]       │
    │                           (768 números - MUITO SIMILARES!)         │
    │                                                                    │
    │  "Eu odeio vegetais"   → [0.89, 0.12, 0.76, 0.23, 0.11, ...]       │
    │                           (768 números - MUITO DIFERENTES!)        │
    │                                                                    │
    └────────────────────────────────────────────────────────────────────┘

    Note como "cachorros" e "filhotes" têm números similares? Isso porque
    têm significados similares! É assim que a IA "entende" texto.

    Por que 768 números?
    É o tamanho que o modelo de embedding do Google usa. Mais números =
    entendimento mais detalhado do significado. Pense nisso como coordenadas
    em um espaço de 768 dimensões onde significados similares ficam próximos.


Passo 6: ARMAZENAR TUDO
═══════════════════════
Os chunks e seus embeddings são salvos no banco de dados.

    ┌──────────────────────────────────────────────────────────────────┐
    │  Banco de Dados Supabase (PostgreSQL + pgvector)                 │
    │  ════════════════════════════════════════════                    │
    │                                                                  │
    │  tabela documents:                                               │
    │  ┌─────┬───────────────────────────┬────────┬───────────┐        │
    │  │ id  │ file_name                 │ status │ chunks    │        │
    │  ├─────┼───────────────────────────┼────────┼───────────┤        │
    │  │ abc │ relatorio_trimestral.pdf  │ pronto │ 12        │        │
    │  └─────┴───────────────────────────┴────────┴───────────┘        │
    │                                                                  │
    │  tabela chunks:                                                  │
    │  ┌─────┬─────────────────────┬───────────────────────────┐       │
    │  │ id  │ content             │ content_vector            │       │
    │  ├─────┼─────────────────────┼───────────────────────────┤       │
    │  │ 001 │ "Relatório Q3..."   │ [0.21, 0.85, 0.12, ...]   │       │
    │  │ 002 │ "Norte-americano..."│ [0.33, 0.67, 0.45, ...]   │       │
    │  │ ... │ ...                 │ ...                       │       │
    │  └─────┴─────────────────────┴───────────────────────────┘       │
    │                                                                  │
    └──────────────────────────────────────────────────────────────────┘

Fase 2: Fazendo Perguntas (Query)

Passo 7: FAZER UMA PERGUNTA
═══════════════════════════
Você digita: "Qual foi a receita do Q3?"

    ┌─────────────────────────┐
    │                         │
    │  Sua Pergunta           │
    │  ═════════════          │
    │                         │
    │  "Qual foi a            │
    │   receita do Q3?"       │
    │                         │
    └───────────┬─────────────┘
                │
                ▼

Passo 8: CONVERTER PERGUNTA EM EMBEDDING
════════════════════════════════════════
Sua pergunta é convertida no mesmo formato de 768 números.

    "Qual foi a receita do Q3?"
              │
              ▼
    ┌────────────────────────────────────────┐
    │  Modelo de Embedding Google Gemini     │
    │  ══════════════════════════════════    │
    │                                        │
    │  Entrada: "Qual foi a receita do Q3?"  │
    │  Saída: [0.19, 0.82, 0.15, 0.51, ...]  │
    │          (768 números)                 │
    │                                        │
    └────────────────────────────────────────┘


Passo 9: BUSCAR CHUNKS SIMILARES (Busca Vetorial)
═════════════════════════════════════════════════
Comparamos o embedding da sua pergunta com todos os embeddings dos chunks.

    ┌────────────────────────────────────────────────────────────────────┐
    │  Busca por Similaridade Vetorial                                   │
    │  ═══════════════════════════════                                   │
    │                                                                    │
    │  Sua pergunta:  [0.19, 0.82, 0.15, 0.51, ...]                      │
    │                                                                    │
    │  Comparar com cada chunk:                                          │
    │                                                                    │
    │  Chunk 001: [0.21, 0.85, 0.12, 0.53, ...]                          │
    │             Similaridade: 94% ✅ ALTA CORRESPONDÊNCIA!             │
    │             Conteúdo: "Receita Q3 2024 foi R$50 milhões..."        │
    │                                                                    │
    │  Chunk 002: [0.33, 0.67, 0.45, 0.89, ...]                          │
    │             Similaridade: 67%                                      │
    │             Conteúdo: "O departamento de marketing..."             │
    │                                                                    │
    │  Chunk 003: [0.88, 0.12, 0.95, 0.11, ...]                          │
    │             Similaridade: 23%                                      │
    │             Conteúdo: "Móveis do escritório foram trocados..."     │
    │                                                                    │
    │  Resultado: Retornar os 5 chunks mais similares                    │
    │                                                                    │
    └────────────────────────────────────────────────────────────────────┘


Passo 10: GERAR RESPOSTA
════════════════════════
A IA lê os chunks relevantes e escreve uma resposta.

    ┌────────────────────────────────────────────────────────────────────┐
    │  Google Gemini AI                                                  │
    │  ═══════════════                                                   │
    │                                                                    │
    │  PROMPT ENVIADO PARA IA:                                           │
    │  ════════════════════════                                          │
    │                                                                    │
    │  "Você é um assistente útil. Responda a pergunta do usuário        │
    │   baseado APENAS nas seguintes fontes. Cite suas fontes.           │
    │                                                                    │
    │   FONTE 1: Receita Q3 2024 foi R$50 milhões, representando         │
    │   aumento de 15% em relação ao Q2...                               │
    │                                                                    │
    │   FONTE 2: A divisão por região mostra que América do Norte        │
    │   contribuiu R$30 milhões...                                       │
    │                                                                    │
    │   PERGUNTA: Qual foi a receita do Q3?"                             │
    │                                                                    │
    │  RESPOSTA DA IA:                                                   │
    │  ════════════════                                                  │
    │                                                                    │
    │  "Baseado no Relatório Q3 2024, a receita foi R$50 milhões,        │
    │   um aumento de 15% em relação ao Q2 [Fonte 1]. América do Norte   │
    │   foi o maior contribuidor com R$30 milhões [Fonte 2]."            │
    │                                                                    │
    └────────────────────────────────────────────────────────────────────┘


Passo 11: EXIBIR RESPOSTA COM FONTES
════════════════════════════════════
Você vê a resposta com referências de fonte clicáveis.

    ┌────────────────────────────────────────────────────────────────────┐
    │  Interface de Chat                                                 │
    │  ═════════════════                                                 │
    │                                                                    │
    │  Você: Qual foi a receita do Q3?                                   │
    │                                                                    │
    │  Assistente: Baseado no Relatório Q3 2024, a receita foi           │
    │  R$50 milhões, um aumento de 15% em relação ao Q2 [Fonte 1].       │
    │  América do Norte foi o maior contribuidor com R$30 milhões        │
    │  [Fonte 2].                                                        │
    │                                                                    │
    │  Fontes:                                                           │
    │  ┌────────────────────────────────────────────────────────────┐    │
    │  │ [1] relatorio_trimestral.pdf (94% correspondência)         │    │
    │  │     "Receita Q3 2024 foi R$50 milhões, representando..."   │    │
    │  ├────────────────────────────────────────────────────────────┤    │
    │  │ [2] relatorio_trimestral.pdf (89% correspondência)         │    │
    │  │     "A divisão por região mostra América do Norte..."      │    │
    │  └────────────────────────────────────────────────────────────┘    │
    │                                                                    │
    └────────────────────────────────────────────────────────────────────┘

O Que Torna o MegaRAG Especial?

A maioria dos sistemas RAG só funciona com documentos de texto. O MegaRAG funciona com tudo:

Tipo de Arquivo O Que o MegaRAG Faz Como Funciona
PDF Extrai texto, tabelas, imagens IA lê cada página e descreve conteúdo visual
Word (.docx) Extrai todo texto e formatação Parser de documento extrai conteúdo
PowerPoint (.pptx) Extrai conteúdo dos slides Cada slide se torna texto pesquisável
Excel (.xlsx) Extrai dados das células Tabelas convertidas em texto pesquisável
Imagens Descreve o que está na imagem IA Vision analisa: "Um gráfico de barras mostrando vendas por região..."
Vídeos Analisa conteúdo do vídeo ao longo do tempo IA assiste em intervalos: "Aos 0:30, o apresentador discute..."
Áudio Transcreve fala para texto IA ouve e converte fala em texto pesquisável
Arquivos texto Lê diretamente Extração direta de texto

🔧 A Tecnologia: Como Funciona?

A Stack Tecnológica

Aqui está cada peça de tecnologia no MegaRAG e por que a usamos:

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│                              SEU NAVEGADOR WEB                                      │
│                              ═════════════════                                      │
│                                                                                     │
│   O quê: Chrome, Firefox, Safari ou Edge                                            │
│   Por quê: Você interage com o MegaRAG através de um app web                        │
│                                                                                     │
│   Você vê:                                                                          │
│   • Página de upload de documentos                                                  │
│   • Interface de chat                                                               │
│   • Resultados de busca                                                             │
│                                                                                     │
└────────────────────────────────────────────┬────────────────────────────────────────┘
                                             │
                                             │ Requisições HTTP (como carregar página)
                                             │
                                             ▼
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│                              APLICAÇÃO NEXT.JS                                      │
│                              ═════════════════                                      │
│                                                                                     │
│   O quê: Um framework React que lida com frontend e backend                         │
│   Por quê: Uma base de código para tudo, ótima experiência de desenvolvimento       │
│                                                                                     │
│   ┌─────────────────────────────────┐    ┌─────────────────────────────────┐        │
│   │       FRONTEND (React)          │    │       BACKEND (Rotas API)       │        │
│   │       ═════════════════         │    │       ═════════════════════     │        │
│   │                                 │    │                                 │        │
│   │  • src/app/page.tsx            │    │  • src/app/api/upload/          │        │
│   │    (Página inicial)             │    │    (Gerencia uploads)           │        │
│   │                                 │    │                                 │        │
│   │  • src/app/dashboard/          │    │  • src/app/api/query/           │        │
│   │    (Aplicação principal)        │    │    (Gerencia perguntas)         │        │
│   │                                 │    │                                 │        │
│   │  • src/components/             │    │  • src/app/api/documents/       │        │
│   │    (Partes de UI reutilizáveis) │    │    (Listar, deletar docs)       │        │
│   │                                 │    │                                 │        │
│   │  Escrito em: TypeScript        │    │  Escrito em: TypeScript         │        │
│   │  Estilização: Tailwind CSS      │    │  Roda em: Servidor Node.js      │        │
│   └─────────────────────────────────┘    └─────────────────────────────────┘        │
│                                                                                     │
└────────────┬────────────────────────────────────────────────────────┬───────────────┘
             │                                                        │
             │ Queries do banco                                       │ Chamadas API IA
             │ Armazenamento de arquivos                              │
             ▼                                                        ▼
┌─────────────────────────────────────────┐    ┌─────────────────────────────────────────┐
│                                         │    │                                         │
│            SUPABASE                     │    │            GOOGLE GEMINI                │
│            ════════                     │    │            ═════════════                │
│                                         │    │                                         │
│   O quê: "Backend as a Service"         │    │   O quê: Modelo de IA do Google         │
│   Por quê: Não precisamos gerenciar     │    │   Por quê: Melhor custo-benefício       │
│   servidores                            │    │                                         │
│                                         │    │   Fornece:                              │
│   Fornece:                              │    │   ┌───────────────────────────────┐     │
│   ┌───────────────────────────────┐     │    │   │   Entendimento de Texto      │     │
│   │   Banco PostgreSQL            │     │    │   │   ════════════════════       │     │
│   │   ════════════════            │     │    │   │                               │     │
│   │                               │     │    │   │   • Ler e entender PDFs       │     │
│   │   Armazena todos os dados:    │     │    │   │   • Descrever imagens         │     │
│   │   • Metadados de documentos   │     │    │   │   • Analisar conteúdo vídeo   │     │
│   │   • Chunks de texto           │     │    │   │   • Transcrever áudio         │     │
│   │   • Embeddings (vetores)      │     │    │   │   • Gerar respostas           │     │
│   │   • Entidades e relações      │     │    │   │                               │     │
│   │   • Histórico de chat         │     │    │   ├───────────────────────────────┤     │
│   │                               │     │    │   │   Geração de Embedding        │     │
│   │   Com extensão pgvector:      │     │    │   │   ══════════════════════      │     │
│   │   • Armazena vetores 768-dim  │     │    │   │                               │     │
│   │   • Busca rápida por similar. │     │    │   │   • Converte texto em números │     │
│   │                               │     │    │   │   • Vetores 768 dimensões     │     │
│   ├───────────────────────────────┤     │    │   │   • Entendimento semântico    │     │
│   │   Armazenamento de Arquivos   │     │    │   │                               │     │
│   │   ═══════════════════════     │     │    │   ├───────────────────────────────┤     │
│   │                               │     │    │   │   File API                    │     │
│   │   Armazena arquivos originais:│     │    │   │   ════════                    │     │
│   │   • PDFs                      │     │    │   │                               │     │
│   │   • Vídeos                    │     │    │   │   • Upload arquivos grandes   │     │
│   │   • Imagens                   │     │    │   │   • Processa vídeos (até 1GB) │     │
│   │   • Áudio                     │     │    │   │   • Processa áudio            │     │
│   └───────────────────────────────┘     │    │   └───────────────────────────────┘     │
│                                         │    │                                         │
│   Tier grátis: 500MB banco, 1GB storage │    │   Tier grátis: 15 req/min, 1M tokens/dia│
│                                         │    │                                         │
└─────────────────────────────────────────┘    └─────────────────────────────────────────┘

Entendendo Conceitos-Chave

O Que é pgvector?

PostgreSQL (o banco de dados) é ótimo para armazenar e buscar dados normais. Mas não suporta nativamente busca por similaridade.

Por exemplo, busca normal em banco:

-- Encontra correspondência exata: só retorna "Contrato Smith"
SELECT * FROM documents WHERE name = 'Contrato Smith';

Mas com embeddings, precisamos de busca por similaridade:

-- Encontra documentos SIMILARES a "acordo Smith"
-- Deveria retornar: "Contrato Smith", "Acordo J. Smith", "Contrato com Smith Inc."
SELECT * FROM documents
ORDER BY embedding <=> query_embedding  -- Encontra mais similares
LIMIT 5;

pgvector é uma extensão que adiciona essa capacidade:

  • Tipo de dado VECTOR(768): Armazena vetores de 768 dimensões
  • Operador <=>: Calcula distância cosseno entre vetores
  • Índice HNSW: Torna busca por similaridade rápida (sem ele, compararíamos com cada linha)

O Que é HNSW?

HNSW significa "Hierarchical Navigable Small World" (Mundo Pequeno Navegável Hierárquico).

Sem entrar muito em detalhes técnicos, é uma forma de organizar vetores para encontrar similares rapidamente:

Sem HNSW (lento):
══════════════════
Embedding da pergunta: [0.1, 0.2, 0.3, ...]

Comparar com chunk 1... 45% similar
Comparar com chunk 2... 23% similar
Comparar com chunk 3... 87% similar  ← Encontrou um bom!
Comparar com chunk 4... 12% similar
Comparar com chunk 5... 67% similar
... comparar com TODOS os 10.000 chunks (lento!)


Com HNSW (rápido):
══════════════════
Embedding da pergunta: [0.1, 0.2, 0.3, ...]

Começa em ponto aleatório, pula para vizinhos mais próximos:
Chunk 500 (45%) → Chunk 234 (67%) → Chunk 891 (89%) → Encontrado!

Só comparou ~50 chunks em vez de 10.000 (rápido!)

Entendendo Similaridade de Cosseno

Quando comparamos dois embeddings, usamos "similaridade de cosseno":

Vetor A: [0.5, 0.5]    (apontando nordeste)
Vetor B: [0.6, 0.7]    (também apontando nordeste-ish)
Vetor C: [-0.5, 0.5]   (apontando noroeste)

Similaridade de cosseno mede o ÂNGULO entre vetores:

A e B: Ângulo pequeno = ALTA similaridade (0.98)
A e C: Ângulo grande = BAIXA similaridade (0.0)

         B
        /
       /
      / ângulo pequeno
     /
    A────────────
                  \
                   \ ângulo grande
                    \
                     C

Isso funciona independente do "comprimento" dos vetores,
o que é perfeito para comparar embeddings de texto.

📋 Pré-requisitos: O Que Você Precisa Antes de Começar

Antes de poder rodar o MegaRAG, você precisa configurar algumas coisas. Esta seção guia você por cada uma.

Software Necessário

1. Node.js (Runtime JavaScript)

O que é Node.js? Node.js permite que seu computador execute JavaScript fora de um navegador web. Como o MegaRAG é construído com JavaScript/TypeScript, você precisa do Node.js para rodá-lo.

Como instalar Node.js:

Opção A: Baixar do Site (Mais Fácil)
  1. Vá para nodejs.org
  2. Você verá dois botões de download:
    • LTS (Long Term Support) - Escolha este!
    • Current - Tem recursos mais novos mas menos estável
  3. Clique no botão LTS para baixar
  4. Execute o instalador:
    • Windows: Dê duplo clique no arquivo .msi, clique Próximo pelo assistente
    • Mac: Dê duplo clique no arquivo .pkg, siga os prompts
  5. Reinicie seu terminal/prompt de comando
Opção B: Usando nvm (Recomendado para desenvolvedores)

nvm (Node Version Manager) permite trocar facilmente entre versões do Node.js.

Mac/Linux:

# Instalar nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# Reinicie o terminal, depois instale Node.js
nvm install 18
nvm use 18

Windows: Baixe e instale nvm-windows

Verificar se Node.js está instalado:

Abra Terminal (Mac) ou Prompt de Comando (Windows) e execute:

node --version

O que você deve ver:

v18.17.0

(ou qualquer versão 18.x ou superior)

Se você ver um erro:

  • "node is not recognized" - Node.js não está instalado ou não está no seu PATH
  • Tente reiniciar seu terminal
  • Se usar Windows, certifique-se de reiniciar o Prompt de Comando após instalação

2. Git (Controle de Versão)

O que é Git? Git é uma ferramenta que permite baixar código do GitHub e rastrear alterações no seu próprio código.

Como instalar Git:

Windows
  1. Vá para git-scm.com/download/windows
  2. O download deve começar automaticamente
  3. Execute o instalador com configurações padrão (continue clicando Próximo)
Mac

Git vem pré-instalado na maioria dos Macs. Se não:

# Usando Homebrew (se você tiver)
brew install git

# Ou será solicitada instalação do Xcode Command Line Tools
git --version
Linux
# Ubuntu/Debian
sudo apt-get install git

# Fedora
sudo dnf install git

Verificar se Git está instalado:

git --version

O que você deve ver:

git version 2.39.0

(ou qualquer versão 2.x)


Contas Necessárias

3. Conta Supabase (Grátis)

O que é Supabase? Supabase é um "Backend as a Service" que fornece:

  • Um banco PostgreSQL (onde armazenamos todos os dados)
  • Armazenamento de arquivos (onde armazenamos documentos enviados)
  • Geração automática de API
  • Extensão pgvector (para busca semântica)

Por que Supabase?

  • Tier grátis é muito generoso (500MB banco, 1GB armazenamento)
  • Serviço gerenciado (você não precisa configurar servidores)
  • Tem pgvector pré-instalado
  • Dashboard fácil de usar

Como criar uma conta Supabase:

  1. Vá para supabase.com
  2. Clique "Start your project" (canto superior direito)
  3. Clique "Sign up with GitHub" (mais fácil) ou use email
  4. Se usar GitHub:
    • Clique "Authorize Supabase"
    • Pode ser necessário verificar seu email
  5. Você chegará no Dashboard do Supabase
  6. Não crie um projeto ainda - faremos isso nos passos de configuração

O que você deve ver: O Dashboard do Supabase com um botão "New project".


4. Chave API Google AI (Grátis)

O que é a Google AI API? É como acessamos os modelos Gemini AI do Google programaticamente. Gemini é a IA que:

  • Lê e entende seus documentos
  • Cria embeddings (os vetores de 768 números)
  • Gera respostas para suas perguntas

Por que Gemini?

  • Excelente qualidade pelo preço
  • Pode lidar com imagens, vídeo e áudio
  • Tier grátis generoso (15 requisições/minuto, 1 milhão tokens/dia)
  • Fácil de configurar

Como obter uma chave API Google AI:

  1. Vá para aistudio.google.com/apikey
  2. Faça login com sua conta Google (Gmail)
  3. Pode aparecer uma tela de boas-vindas - clique para continuar
  4. Clique "Create API key"
  5. Clique "Create API key in new project" (ou selecione projeto existente)
  6. Copie a chave API imediatamente!
    • Começa com AIza
    • Tem cerca de 40 caracteres
    • Exemplo: AIzaSyC1234567890abcdefghijklmnopqrstuvwx
  7. Salve esta chave em lugar seguro (app de Notas, gerenciador de senhas, etc.)
    • Você não poderá ver novamente no dashboard do Google
    • Se perder, precisará criar uma nova

O que você deve ver: Uma página mostrando sua chave API com botão "Copy".

Notas importantes:

  • Esta chave é secreta - não compartilhe publicamente nem faça commit no GitHub
  • O tier grátis tem limites, mas são generosos para uso pessoal
  • Se atingir limites de taxa, espere um minuto e tente novamente

Checklist de Resumo

Antes de prosseguir, certifique-se de ter:

  • Node.js instalado (execute node --version para verificar)
  • Git instalado (execute git --version para verificar)
  • Conta Supabase criada (você deve ver o dashboard)
  • Chave API Google AI copiada e salva em lugar seguro

🚀 Guia de Configuração Passo a Passo

Agora vamos configurar tudo. Siga estes passos na ordem.

Passo 1: Baixar o Código

Passo 1.1: Abrir Seu Terminal

O que é um terminal? Um terminal (também chamado linha de comando ou prompt de comando) é uma interface baseada em texto para seu computador. Em vez de clicar botões, você digita comandos.

Como abrir o terminal:

  • Mac: Pressione Cmd + Espaço, digite "Terminal", pressione Enter
  • Windows: Pressione Win + R, digite "cmd", pressione Enter (ou busque "Prompt de Comando" ou "PowerShell")
  • Linux: Pressione Ctrl + Alt + T

Você deve ver uma janela com um cursor piscando, algo como:

seu-usuario@seu-computador ~ %

Passo 1.2: Navegar Para Onde Você Quer o Projeto

Quando você baixa código, ele vai para sua pasta atual. Vamos colocar em algum lugar adequado.

Opção A: Usar seu diretório home (mais simples)

# Ir para seu diretório home
cd ~

Opção B: Usar uma pasta específica

# Exemplo: Colocar em uma pasta "Projetos"
cd ~/Projetos

# Se a pasta Projetos não existir, crie primeiro:
mkdir -p ~/Projetos
cd ~/Projetos

Como verificar onde você está:

pwd

Isso imprime seu diretório atual. Você deve ver algo como:

  • Mac: /Users/seunome ou /Users/seunome/Projetos
  • Windows: C:\Users\seunome ou C:\Users\seunome\Projetos

Passo 1.3: Clonar o Repositório

"Clonar" significa baixar uma cópia do código do GitHub.

git clone https://github.com/inematds/MegaRAG.git

O que você deve ver:

Cloning into 'MegaRAG'...
remote: Enumerating objects: 150, done.
remote: Counting objects: 100% (150/150), done.
remote: Compressing objects: 100% (100/100), done.
remote: Total 150 (delta 45), reused 140 (delta 35)
Receiving objects: 100% (150/150), 250.00 KiB | 2.50 MiB/s, done.
Resolving deltas: 100% (45/45), done.

Se você ver um erro:

  • git: command not found - Git não está instalado. Volte aos Pré-requisitos.
  • Repository not found - Verifique erros de digitação na URL
  • Permission denied - Pode ser necessário autenticar no GitHub

Passo 1.4: Entrar na Pasta do Projeto

cd MegaRAG

Agora você está dentro da pasta do projeto. Verifique:

pwd

Deve mostrar: /Users/seunome/MegaRAG ou similar

Passo 1.5: Instalar Dependências

Projetos JavaScript usam "pacotes" (bibliotecas de código pré-escritas) para tarefas comuns. O arquivo package.json lista todos os pacotes que o MegaRAG precisa. O comando npm install baixa todos eles.

npm install

O que você deve ver:

npm warn deprecated some-package@1.0.0: ...
(Alguns avisos são normais, não se preocupe)

added 285 packages, and audited 286 packages in 15s

72 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Se você ver erros:

  • npm: command not found - Node.js não está instalado corretamente
  • EACCES: permission denied - No Mac/Linux, tente: sudo npm install
  • Erros de rede - Verifique sua conexão de internet

O que acabou de acontecer?

  • npm leu package.json para ver quais pacotes precisamos
  • Baixou ~285 pacotes para uma pasta chamada node_modules
  • Esta pasta é grande (~200MB) mas você nunca precisa olhar dentro

Passo 1.6: Verificar a Estrutura do Projeto

Vamos garantir que tudo foi baixado corretamente:

ls -la

O que você deve ver:

drwxr-xr-x   node_modules/
drwxr-xr-x   public/
drwxr-xr-x   src/
-rw-r--r--   .env.example
-rw-r--r--   .gitignore
-rw-r--r--   next.config.mjs
-rw-r--r--   package.json
-rw-r--r--   package-lock.json
-rw-r--r--   README.md
-rw-r--r--   tsconfig.json
...

Se você não vir node_modules, execute npm install novamente.


Passo 2: Criar Seu Projeto Supabase

Passo 2.1: Ir Para o Dashboard do Supabase

  1. Abra seu navegador
  2. Vá para supabase.com
  3. Clique "Dashboard" (canto superior direito) ou faça login

Passo 2.2: Criar um Novo Projeto

  1. Clique o grande botão "New project"
  2. Preencha o formulário:
    • Organization: Selecione sua organização pessoal (ou crie uma)
    • Name: megarag (ou qualquer nome que goste)
    • Database Password: Clique "Generate a password"
    • IMPORTANTE: Copie esta senha e salve em algum lugar! Você não verá novamente.
    • Region: Escolha a mais próxima de você
      • Se você está no Brasil: sa-east-1
      • Se está nos EUA: us-east-1 ou us-west-1
      • Se está na Europa: eu-west-1 ou eu-central-1
    • Pricing Plan: Tier grátis está bom
  3. Clique "Create new project"
  4. Espere 2-3 minutos enquanto o Supabase configura seu banco

O que você deve ver: Uma tela de progresso dizendo "Setting up project..." seguida do Dashboard do Projeto.

Passo 2.3: Obter Suas Credenciais do Supabase

Uma vez que seu projeto está pronto:

  1. Clique no ícone Settings (engrenagem ⚙️) na barra lateral esquerda
  2. Clique API em "Project Settings"
  3. Você verá uma página com suas credenciais

Encontre e copie estes três valores:

Campo Onde encontrar Como parece
Project URL Em "Project URL" https://abcd1234.supabase.co
anon public Em "Project API keys" eyJhbGciOiJIUzI1... (JWT mais curto)
service_role Em "Project API keys" (clique "Reveal") eyJhbGciOiJIUzI1... (JWT mais longo)

IMPORTANTE:

  • Mantenha a chave service_role SECRETA. Ela tem acesso total ao banco.
  • A chave anon é segura para usar no código do navegador (tem permissões limitadas)

Anote ou cole em um app de notas. Você precisará em breve.


Passo 3: Configurar o Banco de Dados

Agora precisamos criar as tabelas e funções que o MegaRAG usa.

Passo 3.1: Abrir o Editor SQL

  1. No Dashboard do Supabase, clique SQL Editor na barra lateral esquerda
  2. Você verá uma janela de query em branco
  3. É aqui que executaremos comandos SQL

Passo 3.2: Executar Cada Comando SQL

Como executar SQL no Supabase:

  1. Copie o código SQL abaixo
  2. Cole no Editor SQL
  3. Clique o botão verde "Run" (ou pressione Cmd/Ctrl + Enter)
  4. Verifique a mensagem de sucesso na parte inferior
  5. Repita para o próximo bloco SQL

Execute estes comandos SQL na ordem:


Comando SQL 1: Habilitar Extensão pgvector

-- ═══════════════════════════════════════════════════════════════════════════════
-- Habilitar extensão pgvector
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- O que isso faz:
-- pgvector é uma extensão PostgreSQL que nos permite armazenar e buscar embeddings
-- (aqueles arrays de 768 números que representam significado). Sem esta extensão,
-- PostgreSQL não saberia o que fazer com dados vetoriais.
--
-- O que acontece:
-- Após executar, PostgreSQL ganha novas capacidades:
-- • Tipo de dado VECTOR(768) - pode armazenar arrays de 768 números de ponto flutuante
-- • Operador <=> - pode calcular distância entre dois vetores
-- • Tipo de índice HNSW - pode criar índices de busca por similaridade rápidos

CREATE EXTENSION IF NOT EXISTS vector;

O que você deve ver:

Success. No rows returned

Comando SQL 2: Criar Tabela de Documentos

-- ═══════════════════════════════════════════════════════════════════════════════
-- Criar tabela documents
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- O que isso faz:
-- Esta tabela armazena metadados sobre cada arquivo enviado. Pense nela como o
-- "catálogo de fichas" que rastreia quais arquivos existem e seu status de processamento.
--
-- O que cada coluna significa:
-- • id: Um identificador único para cada documento (geramos isso)
-- • file_name: O nome original do arquivo como "relatorio_trimestral.pdf"
-- • file_type: A extensão como "pdf", "mp4", "png"
-- • file_size: O tamanho do arquivo em bytes
-- • file_path: Onde o arquivo está armazenado no Supabase Storage
-- • status: Onde estamos no processamento: pending → processing → processed → (ou failed)
-- • chunks_count: Quantos chunks de texto foram criados deste documento
-- • error_message: Se o processamento falhou, o que deu errado
-- • metadata: Campo JSON flexível para dados extras
-- • created_at/updated_at: Quando o registro foi criado/modificado

CREATE TABLE IF NOT EXISTS documents (
    id VARCHAR(255) PRIMARY KEY,
    workspace VARCHAR(255) DEFAULT 'default',
    file_name VARCHAR(1024) NOT NULL,
    file_type VARCHAR(50) NOT NULL,
    file_size BIGINT,
    file_path TEXT,
    status VARCHAR(64) DEFAULT 'pending',
    chunks_count INTEGER DEFAULT 0,
    error_message TEXT,
    metadata JSONB DEFAULT '{}'::jsonb,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Índices tornam queries mais rápidas pré-organizando os dados
-- Pense neles como o índice no final de um livro
CREATE INDEX IF NOT EXISTS idx_documents_status ON documents(status);
CREATE INDEX IF NOT EXISTS idx_documents_file_type ON documents(file_type);
CREATE INDEX IF NOT EXISTS idx_documents_created_at ON documents(created_at);

O que você deve ver:

Success. No rows returned

Comando SQL 3: Criar Tabela de Chunks

-- ═══════════════════════════════════════════════════════════════════════════════
-- Criar tabela chunks
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- O que isso faz:
-- Esta é a tabela MAIS IMPORTANTE. Ela armazena o conteúdo real dos seus
-- documentos, dividido em pedaços pesquisáveis, junto com seus embeddings.
--
-- Por que "chunks"?
-- Documentos podem ser muito longos (100+ páginas). Não podemos pesquisar a coisa
-- toda de uma vez. Em vez disso, dividimos em pedaços menores (~800 palavras cada) e
-- pesquisamos esses. Quando você faz uma pergunta, encontramos os chunks mais
-- relevantes, não documentos inteiros.
--
-- O que cada coluna significa:
-- • id: Identificador único para este chunk
-- • document_id: De qual documento este chunk veio (liga à tabela documents)
-- • chunk_order_index: A ordem deste chunk (1º, 2º, 3º pedaço do doc)
-- • content: O conteúdo de texto real deste chunk
-- • content_vector: O embedding - 768 números representando o significado
-- • tokens: Quantos tokens (aproximadamente palavras) estão neste chunk
-- • chunk_type: Que tipo de conteúdo: text, image, table, video_segment, audio
-- • page_idx: De qual página isso veio (para PDFs)
-- • timestamp_start/end: Intervalo de tempo (para vídeo/áudio)
--
-- A cláusula REFERENCES cria uma "chave estrangeira":
-- • Significa que document_id DEVE existir na tabela documents
-- • ON DELETE CASCADE significa: se deletarmos um documento, deletamos seus chunks também

CREATE TABLE IF NOT EXISTS chunks (
    id VARCHAR(255) PRIMARY KEY,
    workspace VARCHAR(255) DEFAULT 'default',
    document_id VARCHAR(255) REFERENCES documents(id) ON DELETE CASCADE,
    chunk_order_index INTEGER,
    content TEXT NOT NULL,
    content_vector VECTOR(768),
    tokens INTEGER,
    chunk_type VARCHAR(50) DEFAULT 'text',
    page_idx INTEGER,
    timestamp_start FLOAT,
    timestamp_end FLOAT,
    metadata JSONB DEFAULT '{}'::jsonb,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Índice para encontrar rapidamente todos os chunks de um documento
CREATE INDEX IF NOT EXISTS idx_chunks_document_id ON chunks(document_id);
CREATE INDEX IF NOT EXISTS idx_chunks_type ON chunks(chunk_type);

-- Índice HNSW para busca rápida por similaridade vetorial
-- Esta é a mágica que torna a busca semântica rápida
-- Sem ele, teríamos que comparar cada chunk (lento!)
-- Com ele, podemos encontrar chunks similares em milissegundos
--
-- Parâmetros:
-- • vector_cosine_ops: Usa similaridade de cosseno (mede ângulo entre vetores)
-- • m = 16: Número de conexões por nó (maior = mais preciso, mais memória)
-- • ef_construction = 64: Qualidade de construção (maior = melhor índice, construção mais lenta)
CREATE INDEX IF NOT EXISTS idx_chunks_vector ON chunks
USING hnsw (content_vector vector_cosine_ops) WITH (m = 16, ef_construction = 64);

O que você deve ver:

Success. No rows returned

Comando SQL 4: Criar Tabela de Entidades

-- ═══════════════════════════════════════════════════════════════════════════════
-- Criar tabela entities
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- O que isso faz:
-- Esta tabela armazena "entidades" extraídas dos seus documentos. Entidades são
-- coisas notáveis como pessoas, empresas, lugares, conceitos, etc.
--
-- Por que entidades?
-- Entidades permitem busca mais inteligente. Em vez de apenas encontrar texto
-- que corresponde à sua query, podemos entender SOBRE O QUE você está perguntando.
--
-- Exemplo:
-- Documento menciona "Tim Cook" múltiplas vezes em diferentes chunks.
-- Criamos UMA entidade para "Tim Cook" com tipo "PERSON" e descrição
-- como "CEO da Apple Inc., mencionado no contexto de anúncios de produtos."
--
-- O que cada coluna significa:
-- • id: Identificador único
-- • entity_name: O nome como "Tim Cook" ou "Apple Inc."
-- • entity_type: Categoria: PERSON, ORGANIZATION, LOCATION, EVENT, CONCEPT, etc.
-- • description: Contexto sobre esta entidade dos documentos
-- • content_vector: Embedding da descrição (para busca semântica)
-- • source_chunk_ids: Quais chunks mencionam esta entidade (array JSON)

CREATE TABLE IF NOT EXISTS entities (
    id VARCHAR(255) PRIMARY KEY,
    workspace VARCHAR(255) DEFAULT 'default',
    entity_name VARCHAR(512) NOT NULL,
    entity_type VARCHAR(128),
    description TEXT,
    content_vector VECTOR(768),
    source_chunk_ids JSONB DEFAULT '[]'::jsonb,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_entities_name ON entities(entity_name);
CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(entity_type);
CREATE INDEX IF NOT EXISTS idx_entities_vector ON entities
USING hnsw (content_vector vector_cosine_ops) WITH (m = 16, ef_construction = 64);

O que você deve ver:

Success. No rows returned

Comando SQL 5: Criar Tabela de Relações

-- ═══════════════════════════════════════════════════════════════════════════════
-- Criar tabela relations
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- O que isso faz:
-- Esta tabela armazena RELACIONAMENTOS entre entidades. Isso é o que faz
-- do MegaRAG um sistema de "grafo de conhecimento".
--
-- Exemplos de relacionamentos:
-- • "Tim Cook" --[CEO_DE]--> "Apple Inc."
-- • "iPhone 15" --[FABRICADO_POR]--> "Apple Inc."
-- • "WWDC 2024" --[SEDIADO_POR]--> "Apple Inc."
--
-- Por que relacionamentos?
-- Eles permitem queries complexas que seguem conexões:
-- P: "Quem lidera empresas que fazem smartphones?"
-- → Encontrar entidades "smartphone"
-- → Encontrar relacionamentos onde smartphones são alvos
-- → Encontrar entidades fonte com relacionamentos "CEO" ou "lidera"
-- → Retornar essas pessoas
--
-- O que cada coluna significa:
-- • source_entity_id: A entidade onde o relacionamento começa ("Tim Cook")
-- • target_entity_id: A entidade para onde o relacionamento aponta ("Apple Inc.")
-- • relation_type: O tipo de relacionamento ("CEO_DE")
-- • description: Mais contexto sobre este relacionamento
-- • content_vector: Embedding para busca semântica em relacionamentos

CREATE TABLE IF NOT EXISTS relations (
    id VARCHAR(255) PRIMARY KEY,
    workspace VARCHAR(255) DEFAULT 'default',
    source_entity_id VARCHAR(512),
    target_entity_id VARCHAR(512),
    relation_type VARCHAR(256),
    description TEXT,
    content_vector VECTOR(768),
    source_chunk_ids JSONB DEFAULT '[]'::jsonb,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_relations_source ON relations(source_entity_id);
CREATE INDEX IF NOT EXISTS idx_relations_target ON relations(target_entity_id);
CREATE INDEX IF NOT EXISTS idx_relations_type ON relations(relation_type);
CREATE INDEX IF NOT EXISTS idx_relations_vector ON relations
USING hnsw (content_vector vector_cosine_ops) WITH (m = 16, ef_construction = 64);

O que você deve ver:

Success. No rows returned

Comando SQL 6: Criar Tabelas de Chat

-- ═══════════════════════════════════════════════════════════════════════════════
-- Criar tabelas de sessão de chat e mensagens
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- O que isso faz:
-- Estas tabelas armazenam seu histórico de conversas para que você possa ter
-- chats de múltiplos turnos e voltar a conversas anteriores.
--
-- chat_sessions: Uma linha por thread de conversa
-- chat_messages: Uma linha por mensagem (tanto perguntas do usuário quanto respostas da IA)

CREATE TABLE IF NOT EXISTS chat_sessions (
    id VARCHAR(255) PRIMARY KEY,
    workspace VARCHAR(255) DEFAULT 'default',
    title VARCHAR(512) DEFAULT 'Novo Chat',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS chat_messages (
    id VARCHAR(255) PRIMARY KEY,
    session_id VARCHAR(255) REFERENCES chat_sessions(id) ON DELETE CASCADE,
    role VARCHAR(50) NOT NULL,  -- 'user' ou 'assistant'
    content TEXT NOT NULL,
    sources JSONB DEFAULT '[]'::jsonb,  -- Referências de fonte para respostas da IA
    metadata JSONB DEFAULT '{}'::jsonb,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_chat_sessions_updated ON chat_sessions(updated_at);
CREATE INDEX IF NOT EXISTS idx_chat_messages_session ON chat_messages(session_id);

O que você deve ver:

Success. No rows returned

Comando SQL 7: Criar Tabela de Cache LLM

-- ═══════════════════════════════════════════════════════════════════════════════
-- Criar tabela de cache LLM
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- O que isso faz:
-- Faz cache de respostas da IA para evitar chamar a API repetidamente para a mesma pergunta.
-- Se você perguntar "Qual foi a receita do Q3?" duas vezes, retornamos a resposta em cache
-- instantaneamente em vez de pagar por outra chamada de API.
--
-- Entradas de cache expiram após 24 horas por padrão (configurável).

CREATE TABLE IF NOT EXISTS llm_cache (
    id VARCHAR(255) PRIMARY KEY,
    prompt_hash VARCHAR(64) NOT NULL,  -- Hash do prompt completo
    response TEXT NOT NULL,            -- A resposta da IA em cache
    model VARCHAR(128),                -- Qual modelo gerou isso
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    expires_at TIMESTAMP WITH TIME ZONE
);

CREATE INDEX IF NOT EXISTS idx_llm_cache_hash ON llm_cache(prompt_hash);
CREATE INDEX IF NOT EXISTS idx_llm_cache_expires ON llm_cache(expires_at);

O que você deve ver:

Success. No rows returned

Comando SQL 8: Criar Funções de Busca

-- ═══════════════════════════════════════════════════════════════════════════════
-- Criar funções de busca
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- O que fazem:
-- Estas são funções reutilizáveis que executam busca por similaridade. Em vez de
-- escrever queries SQL complexas no nosso código, chamamos estas funções.
--
-- Como funcionam:
-- 1. Recebem um query_embedding (sua pergunta convertida em 768 números)
-- 2. Encontram linhas onde o embedding é similar (acima de match_threshold)
-- 3. Retornam as mais similares (até match_count)
--
-- O operador <=> calcula distância de cosseno:
-- • 0 = vetores idênticos
-- • 2 = vetores opostos
-- Convertemos para similaridade fazendo: 1 - distância
-- Então similaridade de 0.9 significa 90% similar

-- Buscar chunks por similaridade semântica
CREATE OR REPLACE FUNCTION search_chunks(
    query_embedding VECTOR(768),
    match_threshold FLOAT DEFAULT 0.3,
    match_count INT DEFAULT 10
) RETURNS TABLE (
    id VARCHAR,
    document_id VARCHAR,
    content TEXT,
    chunk_type VARCHAR,
    similarity FLOAT
) LANGUAGE plpgsql AS $$
BEGIN
    RETURN QUERY
    SELECT
        c.id,
        c.document_id,
        c.content,
        c.chunk_type,
        (1 - (c.content_vector <=> query_embedding))::FLOAT AS similarity
    FROM chunks c
    WHERE c.content_vector IS NOT NULL
      AND 1 - (c.content_vector <=> query_embedding) > match_threshold
    ORDER BY c.content_vector <=> query_embedding
    LIMIT match_count;
END;
$$;

-- Buscar entidades por similaridade semântica
CREATE OR REPLACE FUNCTION search_entities(
    query_embedding VECTOR(768),
    match_threshold FLOAT DEFAULT 0.3,
    match_count INT DEFAULT 20
) RETURNS TABLE (
    id VARCHAR,
    entity_name VARCHAR,
    entity_type VARCHAR,
    description TEXT,
    similarity FLOAT
) LANGUAGE plpgsql AS $$
BEGIN
    RETURN QUERY
    SELECT
        e.id,
        e.entity_name,
        e.entity_type,
        e.description,
        (1 - (e.content_vector <=> query_embedding))::FLOAT AS similarity
    FROM entities e
    WHERE e.content_vector IS NOT NULL
      AND 1 - (e.content_vector <=> query_embedding) > match_threshold
    ORDER BY e.content_vector <=> query_embedding
    LIMIT match_count;
END;
$$;

-- Buscar relações por similaridade semântica
CREATE OR REPLACE FUNCTION search_relations(
    query_embedding VECTOR(768),
    match_threshold FLOAT DEFAULT 0.3,
    match_count INT DEFAULT 20
) RETURNS TABLE (
    id VARCHAR,
    source_entity_id VARCHAR,
    target_entity_id VARCHAR,
    relation_type VARCHAR,
    description TEXT,
    similarity FLOAT
) LANGUAGE plpgsql AS $$
BEGIN
    RETURN QUERY
    SELECT
        r.id,
        r.source_entity_id,
        r.target_entity_id,
        r.relation_type,
        r.description,
        (1 - (r.content_vector <=> query_embedding))::FLOAT AS similarity
    FROM relations r
    WHERE r.content_vector IS NOT NULL
      AND 1 - (r.content_vector <=> query_embedding) > match_threshold
    ORDER BY r.content_vector <=> query_embedding
    LIMIT match_count;
END;
$$;

O que você deve ver:

Success. No rows returned

Passo 3.3: Verificar se as Tabelas Foram Criadas

Vamos garantir que tudo funcionou. Execute este SQL:

-- Listar todas as tabelas que acabamos de criar
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name;

O que você deve ver:

table_name
-----------
chat_messages
chat_sessions
chunks
documents
entities
llm_cache
relations

Se alguma estiver faltando, volte e execute aquele comando SQL novamente.


Passo 3.4: Criar o Bucket de Armazenamento

O banco armazena texto e metadados. Mas os arquivos reais (PDFs, vídeos, etc.) precisam ir para outro lugar. Supabase Storage é esse lugar.

  1. No Dashboard do Supabase, clique Storage na barra lateral esquerda
  2. Clique o botão "New bucket"
  3. Preencha o formulário:
    • Name: documents (exatamente assim, minúsculo)
    • Public bucket: Deixe OFF (queremos privado)
    • Allowed MIME types: Deixe vazio (permitir todos os tipos)
    • File size limit: 104857600 (isso é 100MB em bytes)
  4. Clique "Create bucket"

O que você deve ver: Um novo bucket chamado "documents" na sua lista de armazenamento.


Passo 4: Configurar Variáveis de Ambiente

Agora precisamos dizer ao MegaRAG como conectar ao Supabase e Gemini.

Passo 4.1: Criar o Arquivo de Ambiente

Volte para seu terminal (certifique-se de estar na pasta megarag):

# Criar .env.local copiando o exemplo
cp .env.example .env.local

O que isso faz: Cria um novo arquivo chamado .env.local que é uma cópia de .env.example. A parte .local diz ao Git para ignorar este arquivo (para você não commitar acidentalmente seus segredos).

Passo 4.2: Editar o Arquivo de Ambiente

Abra .env.local em um editor de texto:

Usando VS Code (recomendado):

code .env.local

Usando nano (editor de terminal):

nano .env.local

No Windows, você pode:

notepad .env.local

Passo 4.3: Preencher Seus Valores

Substitua os valores placeholder pelas suas credenciais reais:

# ═══════════════════════════════════════════════════════════════════════════════
# CONFIGURAÇÃO SUPABASE
# ═══════════════════════════════════════════════════════════════════════════════
#
# Obtenha estes de: Dashboard Supabase → Settings → API
#
# Sua URL do projeto parece: https://abcdefghijkl.supabase.co
# A parte "abcdefghijkl" é o ID único do seu projeto
NEXT_PUBLIC_SUPABASE_URL=https://seu-project-id.supabase.co

# A chave "anon" é segura para expor no código do navegador
# Ela tem permissões limitadas baseadas em regras de Row Level Security
# Encontre em "Project API keys" → "anon public"
NEXT_PUBLIC_SUPABASE_ANON_KEY=sua-chave-anon-aqui

# A chave "service role" é SECRETA - nunca exponha publicamente!
# Ela ignora todas as regras de segurança - use apenas no servidor
# Encontre em "Project API keys" → "service_role" (clique "Reveal")
SUPABASE_SERVICE_ROLE_KEY=sua-chave-service-role-aqui

# ═══════════════════════════════════════════════════════════════════════════════
# CONFIGURAÇÃO GOOGLE AI
# ═══════════════════════════════════════════════════════════════════════════════
#
# Obtenha de: aistudio.google.com/apikey
# Começa com "AIza" e tem cerca de 40 caracteres
GOOGLE_AI_API_KEY=AIzaSySuaChaveApiAqui

Passo 4.4: Verificar Seu Arquivo de Ambiente

Vamos garantir que os valores estão definidos. Execute:

# Isso deve imprimir sua URL do Supabase (não um placeholder)
grep "NEXT_PUBLIC_SUPABASE_URL" .env.local

O que você deve ver:

NEXT_PUBLIC_SUPABASE_URL=https://abcd1234.supabase.co

(Com seu ID de projeto real, não "abcd1234")

Erros comuns:

  • Não inclua aspas ao redor dos valores
  • Não adicione espaços ao redor do sinal =
  • Certifique-se de não haver espaços no final
  • A URL deve começar com https://

Passo 5: Iniciar a Aplicação

Passo 5.1: Executar o Servidor de Desenvolvimento

npm run dev

O que você deve ver:

   ▲ Next.js 14.2.x
   - Local:        http://localhost:3000
   - Environments: .env.local

 ✓ Starting...
 ✓ Ready in 2.3s

Se você ver erros:

  • Port 3000 is in use: Outro app está usando a porta 3000. Feche-o ou rode o MegaRAG em porta diferente: npm run dev -- -p 3001
  • Missing environment variables: Verifique seu arquivo .env.local
  • Module not found: Execute npm install novamente

Passo 5.2: Abrir a Aplicação

  1. Abra seu navegador web (Chrome, Firefox, Safari, Edge)
  2. Vá para: http://localhost:3000

O que você deve ver: A página inicial do MegaRAG com um botão "Get Started".

  1. Clique "Get Started" ou vá para http://localhost:3000/dashboard

O que você deve ver: O Dashboard com:

  • Uma área de upload à direita
  • Uma lista de documentos vazia à esquerda
  • Um link "Chat" na barra lateral

Passo 5.3: Verificar se Tudo Funciona

Vamos testar o fluxo completo:

  1. Faça upload de um arquivo de teste:

    • Baixe qualquer PDF simples ou crie um arquivo de texto
    • Arraste e solte na área de upload
    • Você deve vê-lo aparecer na lista de documentos com status "Processing"
  2. Espere o processamento:

    • O status deve mudar para "Ready" (✓) após 10-60 segundos
    • Se disser "Failed", verifique os logs do Supabase por erros
  3. Teste o chat:

    • Clique "Chat" na barra lateral
    • Digite uma pergunta sobre seu documento
    • Você deve receber uma resposta com citações de fonte

Parabéns! O MegaRAG está rodando! 🎉


📱 Usando a Aplicação

O Dashboard (/dashboard)

Esta é sua base para gerenciar documentos.

Fazendo Upload de Arquivos

Método 1: Arrastar e Soltar

  1. Encontre um arquivo no seu computador
  2. Arraste-o para a área de upload
  3. Solte para fazer upload

Método 2: Clicar para Navegar

  1. Clique na área de upload
  2. Selecione um arquivo no diálogo
  3. Clique "Abrir" para fazer upload

Método 3: Upload em Massa

  1. Selecione múltiplos arquivos (Ctrl/Cmd + clique)
  2. Arraste todos de uma vez
  3. Eles serão processados em paralelo

Entendendo Status de Documento

Status Ícone Significado
Pending Arquivo enviado, aguardando processamento
Processing 🔄 IA está lendo e dividindo o documento
Ready Documento processado e pesquisável
Failed ⚠️ Algo deu errado (passe o mouse para detalhes)

Gerenciando Documentos

Deletar um documento:

  • Passe o mouse sobre um documento
  • Clique no ícone de lixeira (🗑️)
  • Você tem 5 segundos para clicar "Desfazer"

Filtrar por status:

  • Use o dropdown para mostrar apenas documentos Ready, Processing ou Failed

Buscar por nome:

  • Pressione Cmd/Ctrl + K ou clique na barra de busca
  • Digite para filtrar documentos por nome

A Interface de Chat (/dashboard/chat)

Aqui é onde você faz perguntas sobre seus documentos.

Uso Básico

  1. Digite sua pergunta na caixa de entrada
  2. Pressione Enter ou clique Enviar
  3. Espere a IA responder
  4. As fontes aparecerão abaixo da resposta

Modos de Query

Clique no seletor de modo para escolher como o MegaRAG busca:

Modo O Que Faz Melhor Para
Mix (padrão) Usa todos os métodos de busca Perguntas gerais
Naive Só busca chunks de texto Perguntas de palavras-chave simples
Local Busca entidades primeiro "Quem é X?" "O que é Y?"
Global Segue relacionamentos "Como X se relaciona com Y?"
Hybrid Combina Local + Global Perguntas complexas

Sessões de Chat

Iniciar novo chat:

  • Clique "New Chat" na barra lateral

Renomear um chat:

  • Passe o mouse sobre um chat na barra lateral
  • Clique no ícone de lápis (✏️)
  • Digite um novo nome
  • Pressione Enter

Deletar um chat:

  • Passe o mouse sobre um chat
  • Clique no ícone de lixeira (🗑️)

Alternar entre chats:

  • Clique em qualquer chat na barra lateral
  • Seu histórico de conversa é preservado

O Explorador de Dados (/dashboard/explorer)

Mostra o que o MegaRAG "sabe" dos seus documentos.

Abas

Chunks:

  • Mostra todos os pedaços de texto dos seus documentos
  • Clique para expandir e ver o conteúdo completo
  • Mostra de qual documento cada chunk veio

Entities:

  • Mostra todas as entidades extraídas (pessoas, empresas, etc.)
  • Mostra o tipo e descrição
  • Mostra quais documentos mencionam esta entidade

Relations:

  • Mostra relacionamentos entre entidades
  • Formato: Origem → [Tipo de Relação] → Destino
  • Exemplo: "Tim Cook" → [CEO_DE] → "Apple Inc."

🚨 Guia de Solução de Problemas

Problemas Comuns e Soluções

Erros "Cannot find module" ao executar npm run dev

O que isso significa: Alguns pacotes não instalaram corretamente.

Solução:

# Deletar node_modules e reinstalar
rm -rf node_modules
rm package-lock.json
npm install

Erros "Invalid API key" do Gemini

O que isso significa: Sua chave API do Google AI está errada, expirada ou não definida.

Solução:

  1. Vá para aistudio.google.com/apikey
  2. Verifique se sua chave ainda é válida (não deletada)
  3. Se necessário, crie uma nova chave
  4. Atualize GOOGLE_AI_API_KEY em .env.local
  5. Reinicie o servidor dev: Pare com Ctrl+C, depois execute npm run dev novamente

Erros "relation 'documents' does not exist" ou "table does not exist"

O que isso significa: As tabelas do banco não foram criadas.

Solução:

  1. Vá para o Editor SQL do Supabase
  2. Execute todos os comandos SQL do Passo 3 novamente
  3. Certifique-se de que cada um mostra "Success"

Arquivos travados em "Processing" para sempre

O que isso significa: O processamento começou mas não completou. Pode ser:

  • Problemas de chave API
  • Arquivo muito grande
  • Processamento travou

Solução:

  1. Verifique o console do navegador (F12 → Console) por erros
  2. Verifique logs do Supabase (Dashboard → Logs)
  3. Verifique se seu .env.local tem valores corretos
  4. Para arquivos grandes (vídeos), certifique-se de que estão abaixo de 1GB
  5. Tente deletar o documento e reenviar

Erros "CORS" no console do navegador

O que isso significa: Erro de Cross-Origin Resource Sharing. O navegador está bloqueando requisições.

Solução:

  1. Certifique-se de que NEXT_PUBLIC_SUPABASE_URL corresponde exatamente à URL do seu projeto
  2. Inclua https:// no início
  3. Não inclua barra no final

Buscas não retornam resultados

O que isso significa: Ou:

  • Nenhum documento está processado
  • Embeddings não foram gerados
  • A query não corresponde a nenhum conteúdo

Solução:

  1. No Supabase, vá para Table Editor → chunks
  2. Verifique se há linhas com content_vector não nulo
  3. Se vetores são nulos, reprocesse os documentos
  4. Certifique-se de que sua GOOGLE_AI_API_KEY é válida

"429 Too Many Requests" do Gemini

O que isso significa: Você atingiu o limite de taxa (15 requisições/minuto no tier grátis).

Solução:

  • Espere 1 minuto e tente novamente
  • Processe menos documentos de uma vez
  • Faça upgrade para tier pago se precisar mais capacidade

Modo escuro não funciona

O que isso significa: O tema não está sendo aplicado corretamente.

Solução:

  1. Limpe o cache do navegador
  2. Verifique se ThemeProvider envolve seu app em layout.tsx
  3. Tente clicar no alternador de tema múltiplas vezes

Obtendo Ajuda

Se nenhuma dessas soluções funcionar:

  1. Verifique o console por erros:

    • Navegador: Pressione F12, clique "Console"
    • Servidor: Olhe no terminal onde npm run dev está rodando
  2. Verifique logs do Supabase:

    • Dashboard → Logs → Postgres Logs
  3. Abra uma issue no GitHub:


🚀 Deploy em Produção

Opção 1: Vercel (Recomendado)

Vercel é a empresa que faz o Next.js, então o deploy é perfeito.

Passo a Passo:

  1. Envie seu código para o GitHub

    git init
    git add .
    git commit -m "Commit inicial"
    git remote add origin https://github.com/seuusuario/seu-repo.git
    git push -u origin main
  2. Crie conta na Vercel

    • Vá para vercel.com
    • Clique "Sign Up" → "Continue with GitHub"
  3. Importe seu projeto

    • Clique "New Project"
    • Selecione seu repositório
    • Clique "Import"
  4. Configure variáveis de ambiente

    • Clique "Environment Variables"
    • Adicione cada variável do seu .env.local:
      • NEXT_PUBLIC_SUPABASE_URL
      • NEXT_PUBLIC_SUPABASE_ANON_KEY
      • SUPABASE_SERVICE_ROLE_KEY
      • GOOGLE_AI_API_KEY
  5. Deploy

    • Clique "Deploy"
    • Espere 1-2 minutos
    • Você receberá uma URL como https://seu-projeto.vercel.app

Deploy com Um Clique

Ou use este botão:

Deploy with Vercel


Opção 2: Outras Plataformas

MegaRAG funciona em qualquer plataforma que suporta Node.js:

Railway

  1. Vá para railway.app
  2. "New Project" → "Deploy from GitHub"
  3. Adicione variáveis de ambiente
  4. Deploy

Render

  1. Vá para render.com
  2. "New" → "Web Service"
  3. Conecte repo do GitHub
  4. Adicione variáveis de ambiente
  5. Deploy

Self-hosted

# Build para produção
npm run build

# Iniciar servidor de produção
npm start

# Roda na porta 3000 por padrão
# Use um proxy reverso (nginx) para HTTPS

Checklist de Produção

Antes de ir ao ar:

  • Todas as variáveis de ambiente definidas em produção
  • SUPABASE_SERVICE_ROLE_KEY mantida secreta (não em logs)
  • Backup do banco configurado (Supabase faz isso automaticamente)
  • Domínio configurado com HTTPS
  • Testado com documentos reais

📚 Recursos Adicionais

Documentação Relacionada

Recursos Externos

Conceitos de RAG

Tecnologias Usadas

TypeScript & React


Contribuindo

Encontrou um bug? Quer adicionar uma funcionalidade?

  1. Faça fork do repositório
  2. Crie uma branch: git checkout -b minha-funcionalidade
  3. Faça suas alterações
  4. Teste localmente
  5. Envie um Pull Request

Licença

Licença MIT - Use este código como quiser!


Precisa de Ajuda? Abra uma issue no GitHub

Feito com ❤️ por INEMAT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors