Appendice E — Uso de IA na Avaliação de Estudantes: o Projeto vpl-ai-feedback

Este apêndice descreve o vpl-ai-feedback, sistema de código aberto desenvolvido para apoiar a correção de submissões de código enviadas ao VPL (Moodle) por meio de feedback gerado por Inteligência Artificial (IA). Diferentemente de um corretor automático tradicional — que apenas compara saídas com casos de teste —, o vpl-ai-feedback envia o código do estudante, junto com a rubrica da questão, a um modelo de linguagem (LLM), que devolve uma análise qualitativa por critério, no estilo de um feedback socrático: o estudante recebe comentários que apontam o que foi feito corretamente, o que pode ser melhorado e por quê, tanto em atividades formativas (exercícios de prática) quanto em atividades avaliativas (simulados) do VPL.

Esse mecanismo de feedback socrático em atividades VPL foi proposto por Zampirolli et al. (2026). O estudo descreve a integração de IA ao processo de avaliação de exercícios de programação parametrizados no VPL/Moodle, utilizando um conjunto de sete LLMs adotados para analisar o código dos estudantes e gerar feedback automatizado a cada solicitação de correção, com resultados preliminares indicando percepção positiva dos estudantes quanto à geração de ideias, clareza das explicações e autonomia de aprendizagem.

O restante deste apêndice detalha a implementação prática dessas ideias no projeto vpl-ai-feedback — cujo código está disponível em https://github.com/fzampirolli/vpl-ai-feedback — e descreve especificamente seu uso nas três turmas de PDI-VC entre maio e agosto de 2026.

AvvisoAtenção: IA não substitui o julgamento docente

O uso de IA para avaliar estudantes não é recomendável como fonte única de nota, pois modelos de linguagem podem alucinar — isto é, produzir avaliações, critérios ou justificativas plausíveis, porém incorretas, mesmo diante de um código correto ou incorreto. Um LLM pode atribuir nota alta a um código com erro sutil, ou nota baixa a um código correto mas escrito de forma incomum, simplesmente porque a explicação gerada “parece” coerente. A IA deve ser usada apenas como um complemento à avaliação, nunca como substituta do professor. O Apêndice A e o Apêndice B descrevem os mecanismos de correção objetiva (casos de teste) que continuam sendo a base da nota oficial; este apêndice trata exclusivamente do uso da IA como camada adicional de feedback qualitativo.

E.1 Contexto de uso

O vpl-ai-feedback foi utilizado em três turmas da disciplina PDI-VC, ministradas entre maio e agosto de 2026, totalizando aproximadamente uma centena de estudantes. O feedback por IA foi empregado de três formas complementares:

  1. Feedback contínuo em atividades formativas — exercícios de prática enviados ao VPL ao longo do curso, nos quais o estudante podia reenviar o código quantas vezes desejasse. A cada submissão, recebia um feedback qualitativo gerado por IA, além da correção objetiva realizada pelo VPL, descrita em Zampirolli et al. (2026).

  2. Feedback complementar em simulados (atividades avaliativas bônus) — quatro simulados realizados ao longo do quadrimestre, previstos no plano de ensino como atividades bônus, cada um valendo até 5% da nota final. Aplicados aproximadamente 30 minutos antes do término das aulas práticas quinzenais em laboratório, os simulados utilizavam o vpl-ai-feedback para gerar uma rubrica individual de avaliação, enviada por e-mail juntamente com um resumo comparativo entre a nota atribuída pelo Moodle/VPL e a avaliação produzida pela IA.

  3. Feedback complementar nas Provas 1 e 2 (avaliações oficiais) — as duas provas formais do quadrimestre, cada uma valendo uma parcela maior da nota final da disciplina, também passaram a utilizar o vpl-ai-feedback após sua aplicação. Diferentemente dos simulados (bônus), aqui a nota oficial já é definida pela correção objetiva do VPL e/ou avaliação manual do professor antes da divulgação; a rubrica gerada pela IA é enviada ao estudante apenas posteriormente, como material de apoio para revisão do próprio desempenho — reforçando, também nas avaliações de maior peso, a separação entre nota oficial e feedback complementar detalhada na Seção D.7.

Uma pesquisa de opinião, respondida por 102 estudantes antes da adoção do sistema, indicou elevada aceitação da proposta. Apenas 2 estudantes atribuíram nota 1 (rejeição) e 7 atribuíram nota 2 ao interesse em receber feedback automático de código por IA. Outros 19 declararam-se indiferentes (nota 3), enquanto a maioria — 38 e 37 estudantes — atribuiu notas 4 e 5 (alta aprovação), respectivamente, totalizando os 102 respondentes. Esse resultado motivou a adoção do sistema como complemento ao processo formativo, e não como substituto da correção humana.

ImportanteA nota oficial nunca foi a nota da IA

É fundamental destacar que, conforme definido no plano de ensino, a nota utilizada tanto para o cálculo do bônus de cada simulado quanto para a nota oficial das Provas 1 e 2 foi sempre a nota atribuída pelo VPL (baseada nos casos de teste) e/ou pela avaliação manual do professor — e não a nota sugerida pela IA. A rubrica gerada pelo vpl-ai-feedback foi enviada ao estudante apenas como material de apoio ao aprendizado — nunca como critério de atribuição de nota, seja em atividades bônus ou em avaliações oficiais. Essa separação entre nota oficial (VPL/professor) e feedback complementar (IA) é o princípio central deste apêndice e foi retomada na Seção D.8.

E.2 Arquitetura do projeto

O vpl-ai-feedback é um script Python assíncrono organizado da seguinte forma:

.
├── config.yaml              ← configuração (credenciais, provedor, pesos) — NUNCA versionado
├── config.yaml.example      ← template público de configuração
├── main.py                  ← script principal (async), orquestra todo o processo
├── run.sh                   ← wrapper de execução (bash run.sh config.yaml)
├── gerar_relatorio.py       ← converte o consolidado *_ALL.txt em CSV
├── enviar_email.py          ← envia as rubricas por e-mail a cada estudante
├── providers/                ← clientes das APIs de LLM
│   ├── __init__.py          ← fábrica de clientes (Factory)
│   ├── base.py               ← lógica de retry, backoff e fallback entre modelos
│   ├── groq.py
│   ├── deepseek.py
│   └── gemini.py
├── core/                      ← lógica de negócio
│   ├── grader.py              ← identifica arquivos por questão, monta o prompt, chama a LLM
│   └── utils.py
└── <pasta_da_turma>/          ← submissões baixadas do Moodle VPL
    ├── Nome estudante - login/
    │   ├── <timestamp>/                 ← última submissão do estudante
    │   │   ├── Q1.py                    ← padrão para provas com múltiplas questões
    │   │   ├── Q2.py
    │   │   └── rubrica.txt              ← gerado pela LLM (somente se avaliação válida)
    │   └── <timestamp>.ceg/
    │       └── execution.txt            ← nota/objetiva atribuída pelo VPL
    └── ...

O sistema aceita três provedores de LLM — Groq, DeepSeek e Gemini — configuráveis em config.yaml por meio da chave llm.provider. Cada provedor pode ter múltiplos modelos cadastrados; a cada chamada, a lista é embaralhada, distribuindo a carga entre os estudantes processados em paralelo e reduzindo a chance de erros de limite de requisições (HTTP 429). Quando um modelo falha, o sistema tenta até três vezes antes de passar ao próximo da lista, respeitando o tempo de espera sugerido pelo provedor. Erros de autenticação (401) ou de saldo insuficiente (402) interrompem imediatamente a tentativa naquele provedor.

Um aspecto importante do projeto diz respeito à privacidade dos dados. Nome, e-mail, login, RA e CPF do estudante nunca são enviados à API do LLM. São transmitidos para processamento apenas: o nome do arquivo contendo o código-fonte; o próprio código (com os comentários removidos); o prompt da rubrica — que não contém dados pessoais —; e, quando disponíveis no execution.txt gerado pelo VPL, o enunciado oficial da questão sorteada para aquele estudante e o resultado bruto dos casos de teste executados (entrada, saída produzida pelo código e saída esperada). Esses dois últimos itens, embora extraídos de um arquivo específico de cada estudante, também não contêm identificação pessoal — apenas o texto da questão e os valores de entrada/saída dos testes automáticos —, e são usados como evidência objetiva para reduzir o risco de a IA identificar incorretamente o tipo de questão ou avaliar a lógica do código apenas por leitura estática (Seção D.3).

Ainda assim, é importante reconhecer que os três provedores atualmente suportados — Groq, DeepSeek e Gemini — são serviços comerciais operados por empresas estrangeiras, cujos modelos são executados em infraestrutura fora do país e sujeitos a políticas de uso, disponibilidade e custo que fogem ao controle da instituição de ensino. Essa dependência de provedores externos traz riscos que vão além da correção de código pontual: mudanças de preço, descontinuação de modelos, indisponibilidade temporária do serviço, alterações unilaterais nos termos de uso e, em casos mais sensíveis, restrições geopolíticas de acesso podem comprometer a continuidade de um sistema de avaliação que passe a depender estruturalmente dessas APIs. Por isso, é estratégico que Instituições de Ensino Superior (IES) como a UFABC invistam no desenvolvimento e na hospedagem de provedores próprios de IA — por exemplo, modelos abertos (open-weight) executados em infraestrutura local ou em nuvem soberana —, reduzindo a dependência de serviços externos, especialmente de outros países, e ampliando o controle institucional sobre custos, disponibilidade, privacidade dos dados de estudantes e continuidade pedagógica de longo prazo. O desenho do vpl-ai-feedback já favorece esse caminho: a arquitetura de providers/ foi construída como uma fábrica (factory) extensível, na qual um novo provedor — inclusive um modelo hospedado localmente pela própria instituição, com interface compatível — pode ser adicionado com baixo esforço de integração.

E.3 O prompt universal e a rubrica em duas etapas

Cada tipo de prova é descrito em um arquivo de prompt (por exemplo, Simulado4.txt), referenciado em grading.prompt_file no config.yaml. Esse arquivo instrui a LLM a realizar a avaliação em duas etapas:

  1. Identificação da questão — a LLM determina o tipo específico de operação sorteado para aquele estudante (útil quando há questões paramétricas sorteadas e embaralhadas por estudante, como descrito no Apêndice A);
  2. Aplicação da rubrica correspondente — a LLM avalia o código segundo critérios pontuados, cada um com uma faixa máxima de pontos, retornando ao final uma nota no formato NOTA FINAL: X/PESO.

Em provas parametrizadas, o arquivo de prompt costuma conter várias rubricas paralelas, uma para cada tipo de questão possível, delimitadas por marcadores como [START_RUBRICA_TIPO_A] / [END_RUBRICA_TIPO_A]. A LLM identifica primeiro qual tipo foi sorteado para aquele estudante e aplica apenas a rubrica correspondente, ignorando as demais — o que evita que critérios de um tipo diferente contaminem a nota.

Quando a prova possui mais de uma questão por atividade VPL, os arquivos de código devem seguir o padrão Q1.*, Q2.* etc. — um arquivo por questão, com extensão livre conforme a linguagem escolhida pelo estudante —, e cada questão tem peso configurável individualmente em grading.weights no config.yaml. Quando a prova tem uma única questão e não foi gerada pelo MCTest, o sistema aceita qualquer nome de arquivo com extensão suportada, desde que seja o único arquivo de código presente na pasta de submissão.

No caso do Simulado 4 (tópico Operadores Morfológicos), por exemplo, um dos tipos possíveis definia três critérios, com peso total de 100 pontos para aquela questão:

Critério Descrição Pontuação máxima
1 — Entrada de dados Leitura de H, W e da matriz binária (mm.readImg) 25 pts
2 — Processamento morfológico Abertura + Fechamento (mm.sebox()), mm.measure, ordenação por bbox[0]/bbox[1] e reatribuição de IDs 50 pts
3 — Saída e formatação Exibição da imagem limpa (mm.drawImg) e tabela de medidas formatada 25 pts

O prompt exige ainda um formato de resposta obrigatório (largura de linha, ordem das seções, marcação NOTA FINAL:), o que torna a extração automática da nota e a montagem do relatório consolidado mais confiáveis — embora, como discutido na Seção D.8, isso não elimine o risco de erro semântico na avaliação do conteúdo.

E.4 Duas camadas adicionais de evidência

Para reduzir o risco de a LLM alucinar o tipo de questão ou a corretude do código — o risco central discutido na Seção D.7 —, o vpl-ai-feedback passou a fornecer à IA duas fontes de evidência objetiva, extraídas automaticamente do próprio execution.txt gerado pelo VPL, além do código-fonte:

  • Enunciado oficial da questão. Como as questões costumam ser sorteadas e embaralhadas por estudante no MCTest (Apêndice A), o execution.txt de cada estudante já traz, no campo “Descrição resumida da questão”, o texto exato da questão que caiu para ele. O sistema extrai esse trecho automaticamente e o envia à LLM como evidência primária para identificar o tipo/variação da questão — mais confiável do que inferir apenas pela leitura estática do código, especialmente em submissões incompletas ou ambíguas entre dois tipos próximos (por exemplo, erosão “plana” versus “com pesos”). Quando o código entregue diverge do que o enunciado pede, o sistema não ignora o enunciado nem “corrige” a leitura silenciosamente: mantém a identificação pelo enunciado, reduz a confiança da avaliação para “Baixa” e explicita a divergência no feedback enviado ao estudante.
  • Resultado real da execução no VPL. Quando disponível, o sistema também envia à LLM os casos de teste efetivamente executados sobre aquele código — entrada, saída produzida e saída esperada —, como evidência objetiva de corretude, a ser usada para confirmar ou refutar a leitura da lógica antes de pontuar os critérios de processamento e de saída, em vez de a IA depender apenas de simular mentalmente o código (o que é especialmente falho em laços com min/max, deslocamento de índice ou cálculo de limiar de Otsu, onde erros sutis passam despercebidos numa leitura estática).

Além disso, a LLM é instruída a declarar explicitamente seu nível de confiança (Alta, Média ou Baixa) na identificação de cada tipo de questão, com justificativa quando a confiança não for Alta. Esse valor é extraído automaticamente e alimenta uma coluna Revisar_Manualmente no relatório CSV consolidado (Seção D.4), permitindo ao professor priorizar exatamente os casos em que a própria IA reconhece maior incerteza — em vez de tratar todas as avaliações de uma turma como igualmente confiáveis.

E.5 Fluxo de execução

A execução típica, feita por bash run.sh config.yaml, segue os passos:

  1. Carrega config.yaml e localiza a pasta de submissões (paths.student_base_dir);
  2. Para cada estudante, identifica a última submissão (pasta com o timestamp mais recente);
  3. Extrai a nota objetiva do Moodle a partir de *.ceg/execution.txt;
  4. Para cada questão da prova, localiza o arquivo de código (Q1.*, Q2.*, ou o único arquivo, no caso de prova que não foi gerada pelo MCTest), monta o prompt (código + rubrica) e envia a um modelo sorteado da lista configurada;
  5. Processa todos os estudantes em paralelo, com controle de concorrência;
  6. Gera, por estudante, o arquivo rubrica.txt — somente se a IA retornar ao menos uma avaliação válida para as questões que possuem código; caso contrário, o arquivo não é salvo, forçando nova tentativa na próxima execução;
  7. Consolida todos os rubrica.txt em um único *_ALL.txt e gera um relatório *_relatorio.csv, comparando nota do Moodle, nota da IA e a diferença entre ambas, por questão e no total.
Situação rubrica.txt é salvo?
Todas as questões com código avaliadas com sucesso ✅ Sim
IA falhou em ao menos uma questão com código ❌ Não — reprocessa na próxima execução
estudante sem nenhum arquivo de código enviado ❌ Não
Tipo de questão identificado como DESCONHECIDO ❌ Não

E.6 Exemplo ilustrativo: rubrica de uma prova com três questões

NotaSobre a origem deste exemplo

O trecho a seguir não reproduz o código de nenhum estudante específico. Trata-se de um exemplo reconstruído pelo autor, que reproduz um padrão de erro observado repetidamente ao longo das turmas de PDI-VC — a confusão entre uma função morfológica 2D (mm.ero/mm.ero0) e uma operação 1D sobre sinais — sem citar ou identificar qualquer submissão real. Essa opção evita qualquer risco de violação do direito autoral do estudante sobre seu próprio código-fonte, ainda que anonimizado, já que a titularidade da obra permanece do autor original mesmo quando nome e login são removidos.

O trecho a seguir ilustra a saída gerada pelo vpl-ai-feedback para um estudante de uma prova com três questões (Q1, Q2, Q3), usando o modelo deepseek-chat. O resumo comparativo aparece no topo do arquivo, seguido do enunciado oficial de cada questão, do código submetido e da avaliação por critério.

┌─────────────────────────────────────────────────────────────────────┐
│ RESUMO — IA (deepseek-chat)  x  MOODLE                              │
├─────────────────────────────────────────────────────────────────────┤
│ Peso total : 100 pts                                                │
│ ─────────────────────────────────────────────────────────────────── │
│ Q1 (IA) :  3.3 / 33 pts                                             │
│ Q2 (IA) :  6.7 / 33 pts                                             │
│ Q3 (IA) : 33.3 / 34 pts                                             │
│ ─────────────────────────────────────────────────────────────────── │
│ Moodle : (Q1=33 + Q2=0 + Q3=34) = 67 pts                            │
│ IA     : 43.3 / 100 pts                                             │
│ ─────────────────────────────────────────────────────────────────── │
│ Diferença (IA - Moodle): -23.7 pts                                  │
│ ─────────────────────────────────────────────────────────────────── │
│ Q1: tipo identificado = B  | confiança = Baixa (código não          │
│   corresponde ao enunciado da questão) ⚠️ REVISAR                   │
│ Q2: tipo identificado = A  | confiança = Alta (enunciado oficial    │
│   confirma o tipo e a variação)                                     │
│ Q3: tipo identificado = C1 | confiança = Alta (enunciado oficial    │
│   confirma erosão 2D com OpenCV integrada)                          │
└─────────────────────────────────────────────────────────────────────┘

Q1 — código não corresponde ao enunciado (confiança baixa): o enunciado oficial da questão, extraído do execution.txt, pedia uma erosão morfológica 1D sobre um sinal (leitura de N, M, o sinal e o elemento estruturante B, seguida do mínimo dos vizinhos ativos). O código submetido, no entanto, lê apenas dois inteiros e invoca mm.ero0 — uma função de erosão 2D para imagens, não relacionada à operação pedida.

Tipo identificado: TIPO B (Erosão 1D — plana)
Confiança: Baixa — código não corresponde ao enunciado da questão (usa
mm.ero0, função de erosão 2D, em vez de implementar erosão 1D plana
sobre um sinal)

Critério 1 - [3.33/10.00 pts]:
- O código lê dois inteiros em uma única linha (que corresponderiam a
  N e M), mas não lê o sinal nem o elemento estruturante B como vetores
  1D. Em vez disso, trata ambos como imagens via mm.readImg, o que não
  corresponde à leitura esperada de um sinal 1D e de B em linhas
  separadas.

Critério 2 - [0.00/16.67 pts]:
- A operação aplicada é mm.ero0(img, element), erosão 2D para imagens,
  não a erosão 1D de sinais pedida no enunciado. A lógica de mínimo dos
  vizinhos ativos com bordas por recorte não está implementada.

Critério 3 - [0.00/6.67 pts]:
- A saída é uma imagem 2D via mm.drawImg, não o sinal 1D resultante em
  uma única linha com valores inteiros separados por espaço, como
  exigido.

NOTA FINAL: 3.33/33.33

Comentários para o estudante: O código apresentado não corresponde ao que o
enunciado pede. A questão sorteada solicita uma erosão morfológica 1D
sobre um sinal unidimensional; o código usa uma função de erosão 2D
para imagens. Releia atentamente o enunciado sorteado antes de escolher
a implementação.

Q2 — erro de sintaxe impede a execução (confiança alta, nota baixa por falha real): aqui a IA identificou corretamente o tipo (limiarização com Otsu), com apoio do enunciado oficial, mas o código continha um erro de indentação que impedia a execução — evidenciado tanto pela leitura estática quanto pela ausência de saída válida nos testes do VPL.

Tipo identificado: TIPO A (Limiarização — T manual + Otsu)
Confiança: Alta — enunciado oficial confirma o tipo e a variação

Critério 1 - [6.67/10.00 pts]:
- Lê corretamente os três parâmetros L, C e T em linhas separadas e a
  imagem de entrada. Porém, a definição de uma função auxiliar de
  limiarização está indentada incorretamente dentro do escopo global,
  causando um erro de indentação que impede a execução completa do
  programa.

Critério 2 - [0.00/16.67 pts]:
- A binarização com limiar fixo T está corretamente estruturada, mas o
  cálculo do limiar de Otsu depende da função auxiliar malformada, que
  referencia uma variável fora de escopo. O erro de indentação impede
  qualquer processamento.

Critério 3 - [0.00/6.67 pts]:
- Devido ao erro de indentação, nenhuma saída é produzida.

NOTA FINAL: 6.67/33.33

Comentários para o estudante: A estrutura geral está correta (leitura de L,
C, T e da imagem), mas há um erro de indentação que impede a execução.
Revise a sintaxe Python antes de submeter e teste localmente o código
antes do envio ao VPL.

Q3 — divergência de função, mas equivalência funcional confirmada por evidência real (confiança alta, nota justa): o enunciado pedia explicitamente o uso de mm.ero (versão integrada ao OpenCV), mas o código usa mm.ero0 (versão plana implementada manualmente). Como o execution.txt mostrava os 10 casos de teste do VPL passando integralmente, a IA não penalizou a divergência de função — reconheceu a equivalência funcional demonstrada pelos testes reais, mas ainda assim registrou a observação no feedback.

Tipo identificado: TIPO C1 (Erosão 2D — plana sem pesos)
Confiança: Alta — enunciado oficial confirma erosão 2D com OpenCV
integrada (mm.ero), e o código implementa erosão plana via mm.ero0

Critério 1 - [10.00/10.00 pts]:
- Lê corretamente altura, largura, a matriz da imagem e as dimensões e
  valores do elemento estruturante B.

Critério 2 - [16.67/16.67 pts]:
- O enunciado pedia o uso de mm.ero (OpenCV integrada), mas o código
  usa mm.ero0 (plana sem pesos). Apesar da divergência de função, a
  operação foi implementada corretamente com o elemento estruturante
  lido: os 10 testes executados no VPL passaram integralmente (10/10),
  confirmando equivalência funcional para os casos testados.

Critério 3 - [6.67/6.67 pts]:
- Imprime a imagem resultante no formato correto; os testes confirmaram
  a saída correta.

NOTA FINAL: 33.34/33.33

Comentários para o estudante: O código está correto e funcional, com todos
os 10 testes passando. Observação: o enunciado pedia explicitamente
mm.ero (versão OpenCV), mas você usou mm.ero0 (versão plana). Embora os
resultados tenham sido equivalentes nos testes, siga exatamente a
função solicitada no enunciado em provas futuras.

Note que, nesse caso composto, a IA atribuiu 23,7 pontos a menos do que a nota objetiva do VPL, puxada principalmente pela Q1. A diferença agregada por si só já seria um sinal para investigação (Seção D.7), mas o próprio sistema entrega ao professor a causa provável de cada questão: a coluna Revisar_Manualmente do CSV é marcada “SIM” sempre que ao menos uma questão do estudante recebe confiança baixa, com o motivo específico registrado na coluna de confiança correspondente — reduzindo o tempo que o professor precisa gastar para localizar, entre uma centena de estudantes, os poucos casos que realmente merecem atenção manual antes da atribuição da nota oficial. O caso da Q3, por sua vez, ilustra o cuidado inverso: a divergência entre enunciado e código não resultou em penalização indevida, porque a evidência real de execução confirmou a equivalência funcional — exatamente o comportamento que a Seção D.3 descreve para essas duas camadas de evidência.

E.7 Envio do feedback por e-mail

Após a geração das rubricas, o script enviar_email.py envia a cada estudante um e-mail com o rubrica.txt em anexo. O corpo do e-mail é definido em config.yaml, em templates.corpo, e é interpolado com {nome_pasta} e {login}:

email:
  smtp_server: smtp.ufabc.edu.br
  smtp_port: 587
  from_address: professor@ufabc.edu.br
  password: "SUA_SENHA_AQUI"     # nunca versionar credenciais reais
  use_tls: true

templates:
  assunto: "Rubricas e Correções geradas por LLM - Simulado - {login}@aluno.ufabc.edu.br"
  corpo: |
    Prezado(a) {nome_pasta},
    ...
ImportanteSegurança de credenciais

O config.yaml contém segredos reais (senha de SMTP, chaves de API). Ele deve constar do .gitignore do projeto e jamais ser publicado, compartilhado ou versionado — inclusive em anexos de e-mail, capturas de tela ou repositórios públicos.

Um exemplo real de e-mail enviado a um estudante (dados anonimizados, com nome e login substituídos por um caso fictício) é reproduzido a seguir, para ilustrar o tom didático e as ressalvas explicitadas ao estudante:

ImportanteExemplo de mensagem individual (anonimizada)

Prezado(a) [Nome do Estudante] - [login],

A sua nota do Simulado 4 está disponível no Moodle.

Envio abaixo as competências avaliadas e uma correção detalhada do seu código, gerada automaticamente por Inteligência Artificial (IA).

No anexo “rubrica.txt” está o retorno completo da IA (recomendo baixar e abrir com um editor de texto ou bloco de notas).

Ressalto que essa correção gerada por IA PODE conter imprecisões ou erros, mas serve como um excelente apoio ao seu processo de aprendizagem na disciplina.

Uma sugestão pedagógica é submeter os seus códigos (contidos neste arquivo), juntamente com a RUBRICA abaixo, a outros modelos de LLM para comparação. Isso pode ajudar a identificar possíveis divergências, além de oferecer diferentes perspectivas sobre o seu código e sobre os critérios de avaliação.

Caso tenha dúvidas ou note alguma inconsistência gritante na correção apresentada no Moodle, estou à disposição para esclarecimentos.

Atenciosamente,

Prof. Francisco Zampirolli

PS.: Explicando o processo: a última versão do seu código salva no Moodle foi anexada ao prompt e enviada para um dos LLMs escolhidos de forma integrada ao nosso sistema de avaliação (modelos = (“deepseek-chat”)). O processo é repetido até que seja obtida uma resposta com nota válida (entre 0 e 100).

Três elementos didáticos merecem destaque nesse texto: (i) o alerta explícito de que a correção pode conter erros; (ii) o convite para que o próprio estudante contraste a avaliação com outros LLMs, transformando a IA em ferramenta de estudo ativo em vez de veredito passivo; e (iii) a explicação transparente do processo automatizado, incluindo o(s) modelo(s) usado(s) e a política de reprocessamento até obter uma nota válida.

E.8 Riscos, limites éticos e responsabilidade docente

ImportanteO professor não pode simplesmente adotar a nota da IA

Este é o ponto central deste apêndice: em nenhuma hipótese a nota sugerida pela IA deve ser atribuída automaticamente ao estudante como nota oficial. Modelos de linguagem podem alucinar — atribuir pontos a critérios não atendidos, “inventar” que uma função foi chamada corretamente quando não foi, ou penalizar um código correto por má interpretação da rubrica. A nota final de qualquer atividade avaliativa deve sempre resultar de avaliação manual do professor (ou da correção objetiva por casos de teste, como no VPL/MCTest), com a IA cumprindo, no máximo, o papel de primeira leitura ou de material de apoio ao estudante, nunca de instância decisória.

Alguns cuidados práticos adotados no uso do vpl-ai-feedback, e recomendados a qualquer professor que deseje adaptar o sistema:

  • Separação clara entre nota oficial e feedback de IA. No caso relatado, a nota do bônus dos simulados sempre veio do VPL, nunca da IA (Seção D.1). A rubrica de IA foi comunicada ao estudante como material de apoio, com aviso explícito de que pode conter erros.
  • Transparência com o estudante. O e-mail enviado (Seção D.6) explicita que a avaliação foi gerada por IA, informa o(s) modelo(s) utilizados e convida o estudante a comparar com outros LLMs — reduzindo a assimetria de informação e incentivando o pensamento crítico sobre a própria correção recebida.
  • Reprocessamento em vez de cache inválido. O sistema só grava rubrica.txt quando obtém avaliação válida (Seção D.4); isso evita que uma resposta malformada, incompleta ou visivelmente inconsistente da IA seja apresentada ao estudante como se fosse definitiva.
  • Monitoramento das divergências. O relatório CSV consolidado (coluna Diferenca = Total_IA - Total_Moodle) permite ao professor identificar rapidamente os casos em que IA e correção objetiva mais discordam — como no exemplo da Seção D.5 (+20 pontos) —, priorizando esses casos para revisão manual.
  • Canal aberto para contestação. O e-mail final oferece explicitamente ao estudante a possibilidade de reportar inconsistências, mantendo o professor como autoridade final sobre a nota.
  • Dados pessoais fora do prompt. Como descrito na Seção D.2, nome, e-mail, login, RA e CPF nunca são enviados à API do LLM, reduzindo riscos de privacidade no uso de provedores externos de IA.

E.9 Considerações finais

O vpl-ai-feedback mostra como a IA pode enriquecer o ciclo de feedback em disciplinas de programação com alto volume de submissões, oferecendo a cada estudante uma leitura qualitativa e individualizada do próprio código — algo inviável de se fazer manualmente para uma centena de estudantes, em múltiplas questões e provas ao longo do quadrimestre. A pesquisa de opinião citada na Seção D.1 sugere que esse tipo de retorno é bem recebido pelos estudantes. Ainda assim, o uso responsável do sistema depende de um princípio inegociável, reiterado ao longo deste apêndice: a IA complementa, mas não substitui, a avaliação do professor, e a nota oficial de qualquer atividade avaliativa deve continuar sendo definida por correção objetiva (VPL/MCTest, Apêndices A e B) e/ou julgamento humano — nunca pela nota bruta devolvida por um modelo de linguagem.