{"id":51202279,"url":"https://github.com/brufelix/publicnotice-ai","last_synced_at":"2026-06-28T01:03:53.595Z","repository":{"id":355472388,"uuid":"1226748973","full_name":"brufelix/publicnotice-ai","owner":"brufelix","description":"Assistente de IA para PDFs com RAG: faça perguntas em linguagem natural e receba respostas com citações ao trecho exato do documento.","archived":false,"fork":false,"pushed_at":"2026-06-22T15:16:35.000Z","size":251,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T16:06:08.614Z","etag":null,"topics":["chatbot","docker","fastapi","nextjs","ollama","pdf","pgvector","rag"],"latest_commit_sha":null,"homepage":"https://publicnotice-ai.vercel.app","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brufelix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-01T19:39:11.000Z","updated_at":"2026-06-22T15:18:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/brufelix/publicnotice-ai","commit_stats":null,"previous_names":["brufelix/publicnotice-ai"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/brufelix/publicnotice-ai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brufelix%2Fpublicnotice-ai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brufelix%2Fpublicnotice-ai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brufelix%2Fpublicnotice-ai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brufelix%2Fpublicnotice-ai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brufelix","download_url":"https://codeload.github.com/brufelix/publicnotice-ai/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brufelix%2Fpublicnotice-ai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34873666,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chatbot","docker","fastapi","nextjs","ollama","pdf","pgvector","rag"],"created_at":"2026-06-28T01:03:49.469Z","updated_at":"2026-06-28T01:03:53.582Z","avatar_url":"https://github.com/brufelix.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📜 publicnotice-ai\n\n\u003e Assistente de IA para **editais de concursos públicos brasileiros**. Faça perguntas em linguagem natural e receba respostas com **citações ao trecho exato do PDF**.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\n---\n\n## ✨ O que faz\n\nUm sistema **RAG (Retrieval-Augmented Generation)** completo:\n\n1. **Upload** de um edital em PDF (concurso público, vestibular, licitação)\n2. O sistema **indexa** o documento (parse → chunking → embeddings → pgvector)\n3. Você **conversa** com o edital em linguagem natural\n4. Cada resposta vem com **citações clicáveis** apontando a página de origem\n\n\u003e **Roda 100% local** com Ollama (privacidade total) ou em **produção** com Groq/Gemini/OpenAI — graças à arquitetura hexagonal, é só trocar uma variável de ambiente.\n\n---\n\n## 🏗️ Arquitetura\n\n```\n┌─────────────────┐       ┌─────────────────┐       ┌──────────────────┐\n│  Next.js (Web)  │ ───►  │  FastAPI (API)  │ ───►  │ Postgres+pgvector│\n│  Vercel         │       │  Railway        │       │ Railway          │\n└─────────────────┘       └────────┬────────┘       └──────────────────┘\n                                   │\n                                   ▼\n                          ┌─────────────────┐\n                          │  Ollama (dev)   │\n                          │  Groq (prod)    │\n                          └─────────────────┘\n```\n\nVer [`docs/architecture.md`](docs/architecture.md) para diagrama detalhado e fluxo do RAG.\n\n### Princípios\n\n- **Hexagonal / Ports \u0026 Adapters** — LLM, embeddings, vector store e parser são `Protocol`s trocáveis\n- **Camadas:** `api → services → domain` (domain puro, sem I/O)\n- **Evals como first-class:** [`tests/evals/`](apps/api/tests/evals) mede qualidade do RAG (RAGAS)\n- **12-factor app** — config via `.env`, logs estruturados em stdout\n- **ADRs** documentando cada decisão técnica em [`docs/adr/`](docs/adr/)\n\n---\n\n## 🧰 Stack\n\n### Backend (`apps/api/`)\n- **Python 3.12** + **FastAPI** + **uv**\n- **SQLAlchemy 2.0 async** + **Alembic** + **pgvector**\n- **PyMuPDF** (parsing) + **structlog** (logs)\n- **pytest** + **testcontainers** + **RAGAS** (evals)\n- **ruff** + **mypy**\n\n### Frontend (`apps/web/`)\n- **Next.js 15** (App Router) + **React 19** + **TypeScript**\n- **Tailwind v4** + **shadcn/ui**\n- **TanStack Query** + **Vercel AI SDK** (streaming)\n- **Biome** (lint + format)\n\n### Infra\n- **Docker Compose** (dev local: Postgres+pgvector + Ollama + API + Web)\n- **Railway** (API + DB) + **Vercel** (Web) em produção\n\n---\n\n## 🚀 Como rodar localmente\n\n### Pré-requisitos\n- Docker + Docker Compose\n- ~6 GB de RAM livre (pro Ollama)\n\n### Setup\n```bash\n# 1. Clone e entre no diretório\ngit clone https://github.com/brunodias/publicnotice-ai.git\ncd publicnotice-ai\n\n# 2. Copie variáveis de ambiente\ncp .env.example .env\n\n# 3. Suba tudo (API, Web, Postgres, Ollama)\nmake up\n\n# 4. Baixe os modelos do Ollama (~2 GB, primeira vez só)\nmake pull-models\n\n# 5. Rode migrations e ingere PDFs de exemplo\nmake bootstrap\n\n# 6. Abra o app\nopen http://localhost:3000\n```\n\n### Atalhos do Makefile\n| Comando | O que faz |\n|---|---|\n| `make up` | Sobe todos os serviços (docker compose up -d) |\n| `make down` | Derruba tudo |\n| `make logs` | Mostra logs agregados |\n| `make pull-models` | Baixa `llama3.2:3b` e `nomic-embed-text` |\n| `make bootstrap` | Migrations + seed de PDFs de exemplo |\n| `make seed` | Re-ingere PDFs de `data/sample/` |\n| `make test` | Roda testes da API |\n| `make lint` | Lint + format check |\n\n---\n\n## 📁 Estrutura\n\n```\npublicnotice-ai/\n├── apps/\n│   ├── api/        # Backend Python (FastAPI)\n│   └── web/        # Frontend Next.js\n├── data/sample/    # PDFs de editais reais (seed)\n├── docs/\n│   ├── architecture.md\n│   └── adr/        # Architecture Decision Records\n├── infra/docker/   # Dockerfiles\n└── scripts/        # bootstrap.sh, pull-ollama-models.sh\n```\n\nDetalhes em [`docs/architecture.md`](docs/architecture.md).\n\n---\n\n## 🌐 Deploy\n\n| Serviço | Plataforma | Root dir |\n|---|---|---|\n| API | Railway | `apps/api` |\n| Postgres + pgvector | Railway (template) | — |\n| Web | Vercel | `apps/web` |\n\n### Vercel (frontend)\n\n1. [vercel.com/new](https://vercel.com/new) → importar o repositório `publicnotice-ai`\n2. **Root Directory:** `apps/web`\n3. **Framework Preset:** Next.js (detectado automaticamente)\n4. Variável de ambiente:\n   - `NEXT_PUBLIC_API_URL` = URL da API no Railway (ex.: `https://seu-projeto.up.railway.app`)\n5. Deploy\n\nVia CLI (a partir de `apps/web`):\n\n```bash\ncp .env.example .env.local   # ajustar NEXT_PUBLIC_API_URL\nnpx vercel                   # preview\nnpx vercel --prod            # produção\n```\n\nVer [`docs/adr/0005-deployment-strategy.md`](docs/adr/0005-deployment-strategy.md) (em breve).\n\n---\n\n## 📄 Licença\n\n[MIT](LICENSE) © Bruno Dias\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrufelix%2Fpublicnotice-ai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrufelix%2Fpublicnotice-ai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrufelix%2Fpublicnotice-ai/lists"}