Apresentação
Decisões Tecnológicas — studyAI
Registo das decisões tecnológicas com rationale e alternativas consideradas.
Índice
- Resumo
- Frontend
- Backend
- Base de dados
- Vector DB
- Storage
- Auth
- LLM e Embeddings
- Orquestração
- Cache e filas
- Observabilidade
- Estrutura do repositório
Resumo
| Área | Decisão | Alternativas |
|---|---|---|
| Frontend | Next.js (App Router) | React + Vite, Remix |
| Backend | FastAPI | Django, Flask, Node |
| DB | PostgreSQL | MySQL, SQLite |
| Vector DB | pgvector | Qdrant, Chroma, Pinecone |
| Storage | S3-compatible (MinIO/R2) | Local filesystem |
| Auth | Auth própria (JWT + refresh tokens) | Supabase Auth, Auth0 |
| LLM | OpenAI | Anthropic, LiteLLM (multi) |
| Embeddings | text-embedding-3-small | Cohere, Voyage |
| Orchestration | LangGraph | LangChain only, AutoGen |
| Cache | Redis | Memcached |
| Observabilidade | LangSmith | Langfuse, OpenTelemetry |
| Repo | Monorepo | 2 repos separados |
Frontend
Next.js (App Router)
Decisão: Next.js com App Router.
Rationale:
- SSR/SSG opcional para páginas públicas (landing, pricing)
- API routes para BFF se necessário
- Ecossistema maduro, boa DX
- Suporte a streaming (respostas do chat)
Alternativas:
- React + Vite: Mais leve, mas sem SSR built-in. Adequado se for SPA pura.
- Remix: Boa alternativa, menos adoção.
Backend
FastAPI
Decisão: FastAPI.
Rationale:
- Async nativo (importante para LLM calls, I/O)
- OpenAPI automático
- Validação com Pydantic
- Performance
- Ecossistema Python para ML/LLM (LangChain, etc.)
Alternativas:
- Django: Mais pesado, sync por default. Bom para CRUD pesado.
- Flask: Menos estrutura, mais manual.
- Node (Express/Fastify): Ecossistema JS, mas LangGraph/LangChain são Python-first.
Base de dados
PostgreSQL
Decisão: PostgreSQL.
Rationale:
- ACID, robusto
- JSONB para campos flexíveis
- pgvector como extensão (vector search no mesmo DB)
- Suporte a full-text search se necessário
Alternativas:
- MySQL: Menos features para JSON/vectors.
- SQLite: Adequado para dev/prototipo, não para produção multi-user.
Vector DB
pgvector
Decisão: pgvector (extensão do PostgreSQL).
Rationale:
- Um sistema menos para manter
- Transações ACID com dados relacionais
- Suficiente para escala inicial/média
- Custo menor (sem serviço dedicado)
Alternativas:
- Qdrant: Melhor para escala muito grande, filtros complexos.
- Chroma: Simples, bom para dev. Menos robusto para produção.
- Pinecone: Managed, pago. Para escala enterprise.
Revisão: Migrar para Qdrant ou Pinecone se pgvector se tornar gargalo (ex: >1M chunks).
Storage
S3-compatible (MinIO dev, R2/S3 prod)
Decisão: API S3-compatible.
Rationale:
- MinIO para dev local (self-hosted)
- R2 ou S3 para produção
- Mesmo código para ambos
- Suporta presigned URLs para upload direto do frontend (futuro)
Alternativas:
- Local filesystem: Simples para dev, não escala, não distribui.
- Supabase Storage: Alternativa se migrar para Supabase Auth no futuro.
Auth
Auth própria no backend (JWT + refresh tokens)
Decisão: Auth própria implementada no backend FastAPI. JWT para access tokens, refresh tokens em DB.
Rationale:
- Docs (API_SPEC, DATA_MODEL) já desenhados para auth própria
- Controlo total: password hash (bcrypt), reset, validação
- Sem dependência externa para MVP
- JWT stateless, escala bem
- Refresh tokens em tabela
refresh_tokenspara revogação e sessões longas
Implementação (MVP):
- Access token: JWT, 15 min, assinado com secret
- Refresh token: 7 dias, guardado em
refresh_tokens(user_id, token_hash, expires_at) - Endpoints: POST /auth/register, /auth/login, /auth/refresh, GET /auth/me
- Password: bcrypt (ou argon2) para hash
Alternativas (pós-MVP):
- Supabase Auth: OAuth (Google, GitHub), magic links — menos código, mas exige migração de users e API
- Auth0: Managed, pago. Muito completo.
LLM e Embeddings
OpenAI
Decisão: OpenAI como provider principal (GPT-4o-mini, gpt-4o).
Rationale:
- API estável, boa documentação
- LangChain/LangGraph têm integração nativa
- Modelos fortes para português
Embeddings: text-embedding-3-small (ou 3-large se precisar mais qualidade).
Alternativas:
- LiteLLM: Abstração multi-provider (OpenAI, Anthropic, local). Útil para fallback ou custo.
- Anthropic: Claude, boa alternativa.
- Local (Ollama, etc.): Para dev sem custo; qualidade inferior.
Revisão: Introduzir LiteLLM se quiseres fallback ou modelos locais para dev.
Orquestração
LangGraph
Decisão: LangGraph para orquestração de agentes.
Rationale:
- State machines explícitas
- Conditional edges, loops
- Checkpointing (persistir estado)
- Integração com LangChain
Alternativas:
- LangChain only: Menos estrutura para fluxos complexos.
- AutoGen/CrewAI: Outros frameworks multi-agent. LangGraph mais flexível.
- Custom: Possível, mas reinventar a roda.
Cache e filas
Redis
Decisão: Redis para cache, rate limiting, sessões e filas.
Rationale:
- Um serviço para múltiplos usos
- Redis Streams ou List para filas simples
- Rate limiting com sliding window
- Cache de respostas (opcional)
Alternativas:
- Celery + Redis: Para jobs assíncronos (ingestão, geração longa).
- BullMQ: Se backend fosse Node.
- RabbitMQ: Mais robusto para filas, mais complexo.
Observabilidade
LangSmith
Decisão: LangSmith como ferramenta principal de tracing para LLM e agentes.
Rationale:
- Integração nativa com LangChain e LangGraph (traces automáticos)
- Visualização de runs, spans, token usage e custo
- Datasets e evaluations para groundedness, relevância
- Debug de prompts e estado entre nós do grafo
Configuração: LANGCHAIN_TRACING_V2=true, LANGCHAIN_API_KEY, LANGCHAIN_PROJECT.
Alternativas:
- Langfuse: Open-source, self-hosted, cost tracking. Boa alternativa se quiseres controlo total.
- OpenTelemetry: Padrão aberto, export para Jaeger/Datadog. Requer mais instrumentação manual.
- Datadog/Sentry: APM genérico; menos focado em LLM/agents.
Estrutura do repositório
Monorepo
Decisão: Monorepo com api/ e web/.
Rationale:
- Um clone, um PR para mudanças que afetam ambos
- Partilha de tipos (ex: schemas API) via pacote interno
- CI único
- Deploy pode ser separado (dois Dockerfiles)
Estrutura:
studyAI/
├── api/ # FastAPI
├── web/ # Next.js
├── shared/ # Tipos, constantes (opcional)
├── docs/
└── docker-compose.yml
Alternativa: Dois repos (studyAI-api, studyAI-web). Mais isolamento, mais overhead de coordenação.
Zona de prática
Sem perguntas. Clica em Editar para adicionar.