DocumentaçãoPara quem hospeda
Inteligência artificial
Como ligar um provedor de IA no OpENEM, o que usa IA (comentário de questão e classificação de assunto) e como limitar o custo com cotas.
A IA é opcional. Sem nenhum provedor configurado, o app funciona normalmente e só os recursos desta página ficam indisponíveis. As chamadas são pagas pela chave de quem hospeda a instância, por isso vale ler a parte de cotas antes de ligar.
O que usa IA
Comentário de questão sob demanda
As provas oficiais chegam sem comentário. Depois de responder, o aluno vê o botão Ver comentário. Na primeira vez que alguém pede, a API (POST /api/v1/questions/:id/explanation) gera o comentário, grava no banco e o devolve; os alunos seguintes recebem o texto gravado, sem nova chamada. O app avisa que o comentário foi gerado por IA e pode conter erros, e o prompt manda a IA nunca contradizer o gabarito oficial.
Sem provedor, o botão responde que a questão ainda não tem comentário. Esse recurso usa AI_PROVIDER e AI_EXPLANATION_MODEL, gasta a cota AI_EXPLANATION_DAILY_LIMIT e tem um limite próprio de 10 pedidos por minuto por aluno.
Classificação de assunto
O import entrega as questões oficiais só com a área. Revisão espaçada, mapa de calor e recomendação trabalham por assunto, então a questão sem assunto fica de fora deles. A classificação por palavra-chave, que roda sem IA no bootstrap, resolve parte do banco; o script de IA cuida do resto. Ele não roda pelo app: quem hospeda executa pelo terminal.
docker compose exec backend node dist-scripts/prisma/classify-questions.js --limit=50 --dry-run
docker compose exec backend node dist-scripts/prisma/classify-questions.js
Opções: --dry-run mostra as decisões sem gravar, --limit e --area restringem o lote, e --min-confidence (padrão 0.6) define a confiança mínima para gravar o assunto. O script usa AI_PROVIDER e AI_CLASSIFY_MODEL. Ele percorre milhares de questões, então prefira um modelo barato. Como AI_CLASSIFY_MODEL não passa pelo compose, informe-o na própria chamada:
docker compose exec -e AI_CLASSIFY_MODEL=<modelo barato do seu provedor> backend node dist-scripts/prisma/classify-questions.js
O script não passa pelas cotas por aluno.
Provedores
| Provedor | Ligado por | Modelo padrão |
|---|---|---|
anthropic | ANTHROPIC_API_KEY | ANTHROPIC_MODEL, senão claude-opus-4-8 |
openai | OPENAI_API_KEY | OPENAI_MODEL, senão gpt-4o |
gemini | GEMINI_API_KEY (ou GOOGLE_API_KEY) | GEMINI_MODEL, senão gemini-2.5-flash |
openai-compatible | OPENAI_BASE_URL | OPENAI_MODEL, senão llama3.1 |
O provedor openai-compatible atende servidores que imitam a API da OpenAI, como Ollama, Groq, OpenRouter, LM Studio e vLLM. A chave é opcional, porque servidores locais não pedem autenticação. Como nem todo servidor aceita schema estrito de JSON, nesse modo a API pede só um objeto JSON e descreve o formato no prompt.
Como o provedor é escolhido
- O comentário de questão e a classificação usam
AI_PROVIDER. - Sem variável, vale o primeiro provedor configurado nesta ordem:
anthropic,openai,gemini,openai-compatible.
Um provedor escolhido por variável mas sem chave não cai em outro: o recurso fica indisponível.
No Docker Compose
Coloque a chave e o modelo no .env da raiz:
ANTHROPIC_API_KEY=<sua chave>
ANTHROPIC_MODEL=claude-opus-4-8
AI_DAILY_LIMIT=500
- Defina sempre o modelo do provedor (
ANTHROPIC_MODEL,OPENAI_MODELouGEMINI_MODEL). Sem ele no.env, o compose repassa a variável vazia e o backend usa o modelo vazio em vez do padrão. - O compose repassa
AI_PROVIDER, as chaves, os modelos,OPENAI_BASE_URLe as cotas.AI_EXPLANATION_MODEL,AI_CLASSIFY_MODELeGOOGLE_API_KEYnão chegam ao container; use umdocker-compose.override.yml, como em Variáveis de ambiente. - Dentro do container,
localhosté o próprio container. UmOPENAI_BASE_URLapontando parahttp://localhost:11434/v1não alcança um Ollama rodando no host.
Depois de mudar o .env, recrie o backend com docker compose up -d.
Cotas e custo
O rate limiting não segura custo: o cadastro é livre, e cada conta nova teria o próprio limite. Por isso as chamadas pagas passam por uma cota por aluno, guardada no banco (tabela AiUsage), numa janela móvel de 24 horas, e por um teto global opcional.
| Variável | Padrão | Conta |
|---|---|---|
AI_EXPLANATION_DAILY_LIMIT | 30 | comentários gerados por aluno |
AI_DAILY_LIMIT | 0 (sem teto) | todas as chamadas de todos os alunos |
0desliga o limite correspondente.- Quem passa do limite recebe HTTP 429.
- A cota é reservada antes da chamada ao provedor: uma chamada que falha também conta.
- Abrir um comentário já gravado não gasta cota. Se dois alunos pedem o mesmo comentário ao mesmo tempo, a API faz uma chamada só (também entre instâncias, com uma trava no Redis), mas o pedido conta na cota de cada um.