← Voltar a studyAI — Documentação do Projeto

⚙️ Decisões Técnicas

studyAI — Documentação do Projeto

Apresentação

Decisões Tecnológicas — studyAI

Registo das decisões tecnológicas com rationale e alternativas consideradas.


Índice

  1. Resumo
  2. Frontend
  3. Backend
  4. Base de dados
  5. Vector DB
  6. Storage
  7. Auth
  8. LLM e Embeddings
  9. Orquestração
  10. Cache e filas
  11. Observabilidade
  12. Estrutura do repositório

Resumo

ÁreaDecisãoAlternativas
FrontendNext.js (App Router)React + Vite, Remix
BackendFastAPIDjango, Flask, Node
DBPostgreSQLMySQL, SQLite
Vector DBpgvectorQdrant, Chroma, Pinecone
StorageS3-compatible (MinIO/R2)Local filesystem
AuthAuth própria (JWT + refresh tokens)Supabase Auth, Auth0
LLMOpenAIAnthropic, LiteLLM (multi)
Embeddingstext-embedding-3-smallCohere, Voyage
OrchestrationLangGraphLangChain only, AutoGen
CacheRedisMemcached
ObservabilidadeLangSmithLangfuse, OpenTelemetry
RepoMonorepo2 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_tokens para 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.