Guia para Code Review — 4 PRs em 2 repositórios.
Abra cada PR, entenda o contexto e revise.
O i-Diário é usado por milhares de professores em todo o Brasil. A IA vem para automatizar tarefas repetitivas, economizar tempo e melhorar a qualidade dos registros educacionais.
As funcionalidades de IA não vão para a comunidade open source agora.
Elas vivem exclusivamente no engine i-diario-plus, que é proprietário da Portabilis.
O i-diario-portabilis recebe apenas
pontos de extensão vazios — partials com um comentário e nada mais —
e esse código é replicado para o repositório open source i-diario.
Este é o padrão central. O app principal cria partials vazias como "slots" que o engine preenche com conteúdo real.
O engine usa prepend_view_path para que suas views tenham prioridade sobre as do app principal.
Quando o Rails procura shared/_plugin_widget, verifica primeiro o path do engine.
Se encontra lá, usa aquela versão. Caso contrário, usa a partial vazia do app principal.
Apenas 5 linhas de código. Nenhuma lógica de IA. Apenas "slots" vazios para o engine preencher.
As partials usam nomes como _plugin_widget e _plugin_scripts
em vez de _ai_chat_widget. Isso é intencional:
não acopla o ponto de extensão a uma funcionalidade específica (IA) e permite
que qualquer plugin/engine use esses slots no futuro.
4 arquivos · +5 linhas · Risco extremamente baixo
A base de tudo: model de configuração, CRUD admin, provider de LLM, sistema de prompts e migrations. Deve ser mergeada primeiro.
Acessível apenas para administradores, no menu Administrativo > Configurações de IA. Permite ligar/desligar cada feature de IA independentemente.
chat_enabled
Boolean (toggle)
Desativado
descriptive_ai_enabled
Boolean (toggle)
Desativado
descriptive_ai_prompt
Texto livre
Template padrão
As features de IA vêm desabilitadas por padrão. O administrador precisa explicitamente ativar cada uma. Sem chave de API do OpenAI configurada nos secrets, nada funciona.
O sistema usa um Factory Pattern para desacoplar a implementação do provider de LLM. Hoje usa OpenAI, mas a arquitetura permite adicionar Claude, Gemini ou outros facilmente.
Os prompts são templates ERB armazenados em app/prompts/, renderizados pelo PromptRenderer.
Isso separa o conteúdo do prompt da lógica de código.
| Tabela | Campos Principais | Propósito |
|---|---|---|
ai_configurations |
chat_enabled, descriptive_ai_enabled, descriptive_ai_prompt |
Singleton com feature flags e prompts customizáveis |
22 arquivos · +623 linhas · As PRs #347 e #348 dependem desta
O professor registra frequência por texto ou voz, usando linguagem natural. A feature mais complexa, com orchestrator, context builder e integração nativa com o i-Diário.
Em vez de marcar cada aluno individualmente em uma tabela, o professor diz algo como:
A IA recebe o nome do professor, turmas, lista de alunos com IDs, datas e o histórico da conversa. Tudo isso no system prompt.
A IA faz fuzzy matching de nomes (ex: "a Ana" vira "Ana Silva"), infere datas (ex: "hoje"), e seleciona turma automaticamente quando o professor tem só uma.
Nenhum registro é feito sem confirmação explícita do professor. A IA apresenta um resumo e espera o "sim" antes de persistir no banco.
Usa os mesmos services existentes do i-Diário (DailyFrequenciesCreator)
para gravar a frequência, respeitando calendário e deadlines.
Texto ou áudio pelo widget de chat no canto da tela. Vai para ChatController#create_message.
Se for áudio, o WhisperTranscriber converte para texto via API OpenAI Whisper (whisper-1, pt-BR).
ContextBuilder monta o system prompt com: nome do professor, turmas, lista de alunos com IDs, data atual, e sessão anterior.
OpenaiProvider envia para GPT-4o mini com response_format JSON. O modelo retorna uma ação estruturada.
O Orchestrator analisa a ação retornada:
register_attendance (mostrar resumo e pedir confirmação),
ask_clarification (pedir mais info),
ou general_response (conversa livre).
Professor confirma → AttendanceRegistrar usa DailyFrequenciesCreator do i-Diário para persistir a frequência. Valida calendário, deadline e dia letivo.
| Tabela | Campos Principais | Propósito |
|---|---|---|
chat_sessions |
user_id, teacher_id, entity_id, conversation_state, pending_action |
Sessão de chat por professor, com estado da conversa e ação pendente (JSONB) |
chat_messages |
chat_session_id, role, content, audio, metadata |
Histórico de mensagens (user/assistant/system) com suporte a áudio |
Máximo de 10 mensagens por minuto por sessão. Protege contra uso excessivo da API.
Limite de 10 MB por arquivo de áudio (base64). Previne uploads gigantescos.
O LLM recebe apenas as últimas 10 mensagens da conversa, evitando excesso de tokens.
O registrador valida: não é data futura, está no calendário escolar, dentro do prazo de lançamento, e é dia letivo.
23 arquivos · +3.176 linhas · A feature mais complexa
O professor dita a nota do aluno por voz. A IA transcreve e formata em linguagem formal educacional, seguindo as normas do MEC.
Na tela de avaliações descritivas, o professor pode ditar a nota do aluno por voz.
Usa a API OpenAI Whisper (modelo whisper-1) para converter áudio em texto, com suporte nativo a português brasileiro.
O texto transcrito passa por um segundo processamento que o transforma em linguagem formal, pedagogicamente adequada para boletins escolares.
Se a formatação falhar, o professor recebe a transcrição bruta. Nunca perde o que ditou.
O administrador pode personalizar o prompt de formatação via painel de configurações, sem alterar código.
Na tela de edição de avaliações descritivas, o botão de gravação aparece ao lado do campo de texto do aluno.
JavaScript captura áudio pelo navegador, converte para WAV (8kHz), e envia como base64 para o backend.
WhisperTranscriber recebe o áudio e retorna texto em português.
NoteFormatter envia a transcrição + contexto (aluno, turma, disciplina) para o GPT-4o mini, que reescreve em linguagem formal educacional.
O texto formatado é inserido no campo SummerNote do aluno. O professor revisa, edita se quiser, e salva.
9 arquivos · +1.346 linhas · Feature independente do Chat
Decisões arquiteturais que garantem a segurança e privacidade dos dados educacionais.
Cada entidade (rede escolar) tem seu próprio banco de dados no i-Diário.
Os arquivos de áudio são armazenados em diretórios separados por entity_id:
development/entity-{id}/chat_audio/{session_id}/.
As sessões de chat incluem entity_id como chave estrangeira obrigatória.
As chaves da API OpenAI são armazenadas em Rails.application.secrets,
nunca hardcoded no código. Sem a chave configurada, as features simplesmente
não funcionam — sem erros visíveis para o usuário.
Chat: Apenas professores com registro ativo podem usar.
O controller verifica require_teacher em todas as ações.
Configurações: Apenas administradores podem acessar.
O decorator verifica admin? para as features de IA.
Assistente de Voz: Apenas professores com acesso a
tela de avaliações descritivas.
O model AiConfiguration usa a gem audited,
registrando todas as mudanças de configuração com quem, quando e o que mudou.
Erros de API são reportados ao Honeybadger para monitoramento
em tempo real. Todas as mensagens do chat ficam persistidas no banco para
auditoria posterior.
O WhisperTranscriber cria arquivos temporários durante a transcrição.
Esses arquivos são sempre removidos no bloco ensure,
mesmo em caso de erro. Nenhum dado de áudio temporário permanece no servidor.
Análise jurídica em andamento sobre conformidade com a Lei Geral de Proteção de Dados para uso de IA em contexto educacional.
As features de IA utilizam provedores externos (OpenAI, Anthropic, Groq) para duas funcionalidades: speech-to-text (transcrição de áudio) e LLM (processamento de linguagem natural). Os dados processados incluem informações sobre frequência de alunos e avaliações descritivas em contexto educacional público (redes municipais e estaduais).
Os provedores de IA (OpenAI, Anthropic, Groq) processam dados em servidores fora do Brasil. A LGPD permite transferência internacional quando há garantias adequadas:
O i-Diário gerencia dados de alunos da educação básica, incluindo crianças e adolescentes. A LGPD exige que o tratamento desses dados seja realizado no melhor interesse do menor e com consentimento específico dos responsáveis.
Dados sobre crianças em contexto educacional podem ser considerados sensíveis. A análise jurídica está avaliando:
A ANPD pode exigir um Relatório de Impacto à Proteção de Dados Pessoais (RIPD) quando há tratamento de dados sensíveis ou de menores. O relatório deve conter:
Todos os provedores considerados possuem DPAs e políticas de dados empresariais:
Whisper (transcrição) + GPT-4o mini (LLM). DPA disponível. Dados da API não usados para treino.
Alternativa de alta performance para LLM. DPA disponível. Processamento em hardware dedicado.
Claude como alternativa de LLM. DPA disponível. Foco em segurança de IA.
Independente da base legal escolhida, os titulares (ou responsáveis, no caso de menores) precisam ser informados sobre o uso de IA. Pontos em análise:
Respostas para as dúvidas mais comuns sobre IA no i-Diário.
O trabalho original era uma única PR monolítica com 56 arquivos e +5.150 linhas.
Dividimos em 4 PRs para facilitar o review:
PR #4894 (App Principal) — Apenas 5 linhas, pontos de extensão vazios. Review rápido.
PR #346 (Infra) — Toda a base compartilhada: config, providers, prompts, migrations. Merge primeiro.
PR #347 (Chat) — Feature completa do chat de frequência. Pode ser revisada independente da #348.
PR #348 (Voz) — Feature completa do assistente de voz. Pode ser revisada independente da #347.
Cada PR é autocontida e pode ser entendida sem ler as outras.
A única dependência é que #347 e #348 precisam da #346 mergeada primeiro.
Não neste momento. Toda a lógica de IA vive no engine
i-diario-plus, que é um repositório privado da Portabilis e nunca
vai para o open source. O i-diario-portabilis recebe apenas pontos
de extensão vazios (que depois vão para o i-diario open source).
Sem o engine instalado, a experiência do i-Diário é exatamente a mesma de antes.
Os preços atuais da OpenAI (fev/2026):
| Serviço | Preço | Equivalente |
|---|---|---|
GPT-4o mini (input) |
US$ 0,15 / 1M tokens | ~2.500 páginas por US$ 0,15 |
GPT-4o mini (output) |
US$ 0,60 / 1M tokens | 16x mais barato que o GPT-4o |
Whisper (transcrição) |
US$ 0,006 / minuto | US$ 0,36 por hora de áudio |
Na prática: Uma mensagem de chat (prompt + resposta) custa frações de centavo. Uma transcrição de 30 segundos de áudio custa US$ 0,003. O rate limiting (10 msgs/min por sessão) ajuda a controlar uso. A chave de API é configurada pelo administrador do sistema.
Fonte: openai.com/api/pricing
Sim! A arquitetura já foi pensada para isso. O ProviderFactory
aceita diferentes providers no hash PROVIDERS. Para adicionar um novo,
basta criar uma classe que herda de BaseProvider e implementar
chat_completion. O provider ativo é definido pelo secret
LLM_PROVIDER.
O sistema tem fallback em vários níveis:
Chat: Retorna uma mensagem amigável de erro ao professor. O Honeybadger é
notificado. A sessão permanece intacta para retentativa.
Assistente de Voz: Se a formatação falhar, o professor recebe a
transcrição bruta. Se a transcrição também falhar, recebe erro com explicação.
Em nenhum caso dados são perdidos.
O ContextBuilder consulta o banco do i-Diário em tempo real.
Ele busca todas as turmas de frequência geral do professor, e para cada turma
lista os alunos ativamente matriculados na data corrente. Essas informações
(com nomes e IDs) são injetadas no system prompt, permitindo que a IA
identifique alunos por nome, apelido ou parte do nome.
O schema já suporta o canal whatsapp na tabela chat_sessions,
mas a implementação atual é apenas via web.
A infraestrutura está pronta para expandir para WhatsApp no futuro.
Não. A PR #4894 adiciona apenas partials com um comentário ERB —
renderizam literalmente nada. As PRs #346, #347 e #348 ficam no engine i-diario-plus,
que só é carregado quando instalado. Sem o engine, essas linhas de código são invisíveis e inofensivas.
O risco é extremamente baixo.