Skip to content

Detecção do Processo de Escrita

Transforme os registros de teclas do Potato em sinalizações auditáveis para respostas de texto livre coladas, transcritas ou geradas por máquina, com limiares que dá para ler e sobrescrever.

A detecção do processo de escrita lê a dinâmica de digitação capturada pelo Registro de Teclas e produz sinalizações nomeadas com os indícios anexados, para que você veja quais valores de atributo dispararam cada uma e descarte as que achar erradas.

Exige o Potato 2.7.2 ou posterior e só roda onde o registro de teclas já está ligado. Como keystroke_logging.enabled é false por padrão, um projeto que nunca optou por ativar não tem sobre o que detectar.

Aviso: as sinalizações são indício para revisão humana. Não são prova de má conduta e nunca devem ser ligadas a rejeição automática, retenção de pagamento ou banimento de participantes. Alguém que digita rápido e com fluência produzindo um primeiro rascunho limpo de fato se parece com transcrição. Um anotador no celular de fato se parece com alguém colando. As regras abaixo foram feitas para minimizar essas colisões, e as colisões continuam acontecendo. A seção de falsos positivos faz parte do recurso, não é ressalva.

Três níveis

NívelO que éPrecisa de dados rotulados?Padrão
1. RegrasSeis sinalizações nomeadas com limiares explícitos e indícios visíveisNãoLigado
2. CalibraçãoLimiares reajustados aos anotadores do seu próprio projetoNãoDesligado
3. SupervisionadoUm classificador que você treina com seus próprios rótulosSimDesligado

Nenhum modelo pré-treinado é distribuído com o Potato. Não há corpus rotulado no repositório, então quaisquer coeficientes que distribuíssemos chegariam com um número de validação que teríamos inventado. Em vez disso você recebe seis regras que dá para ler e contestar. Se você tiver rótulos de verdade, o nível 3 é o caminho que reproduz as acurácias da literatura.

Nível 1: as regras

Toda sinalização devolve os valores de atributo que a dispararam, para que você possa defender ou descartar cada uma individualmente.

paste_dominant

Severidade: suspect. Dispara quando pasted_fraction >= 0.5, ou seja, metade ou mais do texto final chegou por colagem.

Suprimida quando todas as colagens foram classificadas como self (reorganizar o próprio rascunho) ou instance_text (citar a passagem em anotação).

silent_insertion

Severidade: suspect. Dispara quando external_insert_ratio >= 0.3, ou seja, quase um terço dos caracteres inseridos apareceu sem tecla correspondente.

É o sinal isolado de maior valor. Colagem, autopreenchimento, ditado e injeção programática aparecem todos aqui, mesmo quando o próprio evento de colagem é suprimido pela página. É uma operacionalização direta da «contagem de teclas anomalamente baixa para o tamanho da resposta» de Asher et al.

Suprimida em teclados virtuais (virtual_keyboard) e durante composição por IME, onde keydown não é emitido de forma confiável e toda inserção pareceria silenciosa. A regra usa a proporção ciente da origem, então citação legítima não conta.

transcription_rhythm

Severidade: review. Dispara quando as três condições valem ao mesmo tempo:

  • iki_log_cv <= 0.06, um ritmo de digitação metronômico
  • revision_ratio <= 0.02, praticamente nenhuma exclusão
  • menos de 0,5 pausas de 2 segundos ou mais a cada 100 caracteres

Conjuntiva de propósito. Qualquer uma sozinha tem uma leitura inocente. Juntas, formam a assinatura da cópia digitada que Crossley et al. descrevem: linear, orientada a rajadas, de baixa variância.

Ignorada por completo em respostas com menos de 80 caracteres ou 40 teclas, onde não há ritmo a falar.

offscreen_composition

Severidade: suspect. Dispara quando uma inserção grande de origem externa (80 caracteres ou mais) vem logo depois de 10 segundos ou mais fora da página. É o padrão «mudou para o ChatGPT, voltou, colou».

Suprimida quando a origem da inserção foi a passagem ou o próprio texto do anotador, já que sair e depois citar a passagem é comportamento comum.

implausible_speed

Severidade: review. Dispara acima de 900 caracteres por minuto (por volta de 180 wpm) de forma sustentada ao longo de uma resposta inteira.

synthetic_input

Severidade: suspect. Dispara em qualquer evento com isTrusted === false, com o navegador informando que a entrada foi gerada por script e não por uma pessoa. Automação de navegador, scripts injetados e parte da tecnologia assistiva produzem isso.

Níveis de veredito

NívelSignificado
okNenhuma sinalização disparou
reviewPelo menos uma sinalização de severidade review
suspectPelo menos uma sinalização de severidade suspect

Sobrescrevendo limiares

yaml
keystroke_logging:
  detection:
    thresholds:
      paste_dominant.pasted_fraction: 0.4
      silent_insertion.ratio: 0.25
      transcription_rhythm.iki_log_cv: 0.05
      transcription_rhythm.revision_ratio: 0.02
      transcription_rhythm.pause_2s_per_100_chars: 0.5
      offscreen_composition.blur_ms: 15000
      offscreen_composition.insert_chars: 100
      implausible_speed.chars_per_min: 1000

Os limiares são avaliados no servidor e nunca enviados ao navegador. Publicá-los diria a um anotador exatamente com que lentidão colar para ficar abaixo da sinalização.

Nível 2: calibração do projeto

Os atributos de teclas variam bastante conforme a tarefa de escrita (Conijn et al. 2019), e limiares fixos sobre uma quantidade de distribuição mista são enviesados (Roeser et al. 2021). Um corte que funciona para uma justificativa de uma frase está errado para uma redação de cinco parágrafos.

A calibração fixa cada limiar em um percentil de cauda das sessões do seu próprio projeto.

bash
# Inspect the fit without saving it
python -m potato.typing_detect calibrate config.yaml --dry-run
 
# Save it
python -m potato.typing_detect calibrate config.yaml
yaml
keystroke_logging:
  detection:
    calibrate: true    # use the saved fit

A calibração exige pelo menos 30 sessões utilizáveis (80 caracteres ou mais, fora de dispositivo móvel). Abaixo disso ela devolve insufficient_data e os padrões continuam valendo.

Aviso: um corte por percentil é uma definição relativa de valor atípico. Por construção ele sinaliza por volta de tail_fraction (5% por padrão) das sessões mesmo numa população em que ninguém faz nada de errado. Ele diz onde olhar primeiro. Não é indício. Os limiares calibrados ainda ficam limitados a até 3× os padrões embutidos, para que uma população homogênea não consiga arrastar um corte até a própria mediana e passar a sinalizar anotadores honestos.

Um thresholds: explícito sempre vence um valor calibrado, que sempre vence o padrão embutido.

Nível 3: classificador supervisionado

Se você tiver sessões rotuladas, treine um modelo de verdade:

python
from potato import typing_store
from potato.typing_detect import fit_supervised
 
rows = typing_store.feature_matrix(task_dir, project)
labels = [...]   # 1 = non-composed, 0 = composed
 
result = fit_supervised(rows, labels, model="random_forest")
print(result["cv_accuracy_mean"], result["feature_importances"])

Exige o scikit-learn, que é importado sob demanda e não é uma dependência do Potato.

Obtendo rótulos sem um estudo externo

A fase de treinamento do Potato pode gerá-los para você. Peça aos anotadores que copiem uma passagem fornecida como tarefa de aquecimento. As sessões de cópia são exemplares genuínos de transcrição e as respostas normais são exemplares redigidos, o que dá um conjunto rotulado de dentro do seu próprio projeto, na sua tarefa, com os seus anotadores. Isso espelha como Crossley et al. construíram o corpus deles, e o exemplo de calibração monta tudo de ponta a ponta.

Falsos positivos

O modo de falha deste recurso é acusar um anotador honesto. Estes são os casos que legitimamente se parecem com os padrões acima.

SituaçãoRegra com que se pareceComo o Potato trata
Citar a passagem em anotaçãopaste_dominant, silent_insertion, offscreen_compositionSuprimida via paste_source: instance_text
Mover o próprio rascunhoA mesmaSuprimida via paste_source: self
Digitar em celular ou tabletsilent_insertionSuprimida via virtual_keyboard
Entrada não latina por IMEsilent_insertionSuprimida via composition_events
Quem digita rápido e com fluência, rascunho limpotranscription_rhythm, implausible_speedRegras conjuntivas; review e não suspect; calibração
Respostas muito curtastranscription_rhythmIgnorada abaixo de 80 caracteres / 40 teclas
Ditado ou fala para textosilent_insertionNão tratado. Vai sinalizar. Exclua esses anotadores ou aumente o limiar.
Leitores de tela e parte da tecnologia assistivasynthetic_inputNão tratado por completo. Algumas ferramentas produzem eventos não confiáveis.
Autocorreção no celularsilent_insertionEm parte. insertReplacementText conta como externo.
Extensões de navegador, como ferramentas de gramáticasilent_insertion, synthetic_inputNão tratado. Vai sinalizar.

Os quatro últimos são limitações reais, não descuidos. Se o seu grupo de participantes inclui quem usa ditado, quem usa tecnologia assistiva ou quem usa extensões de escrita, ou tire essas regras dos seus critérios de revisão, ou trate toda sinalização como motivo para perguntar ao anotador, não para agir.

Acessibilidade

synthetic_input se apoia em isTrusted, que algumas tecnologias assistivas também disparam. Sinalizar um anotador com deficiência por usar as ferramentas de que precisa para trabalhar é um resultado inaceitável.

Essa regra não tem limiar, então não existe valor que você possa definir para torná-la inalcançável. Se o seu estudo está aberto a quem usa tecnologia assistiva, ou deixe synthetic_input de fora dos critérios de revisão que você escrever, ou desligue a detecção por completo e analise você mesmo os atributos exportados:

yaml
keystroke_logging:
  enabled: true
  detection:
    enabled: false

Regras baseadas em limiar podem ser tornadas inalcançáveis com um corte absurdo, por exemplo implausible_speed.chars_per_min: 1000000.

Intervenção em tempo real

yaml
keystroke_logging:
  detection:
    on_external_insert: flag   # allow | warn | block | flag
ValorComportamento
allowNão faz nada além de registrar
warnAviso não bloqueante em colagem externa, mas não em citações próprias ou da passagem
blockImpede colar e soltar nos campos instrumentados
flagPadrão. Registra em silêncio; você decide depois

block é um instrumento tosco. Ele bloqueia também as citações legítimas, e quem estiver decidido pode redigitar. Usar flag e revisar depois costuma ser melhor.

Painel administrativo

O painel Processo de Escrita, na aba Comportamental do Painel Administrativo, mostra medianas por anotador, taxas de colagem, taxas de inserção silenciosa e cada sessão sinalizada com seus indícios.

Ele reporta o writing_process_risk, a parcela das sessões de um usuário que dispararam cada sinalização, ponderada em favor dos sinais com a explicação inocente menos provável. É um auxílio de ordenação, mantido de propósito separado do suspicion_score já existente, para que nenhum dos dois números mude em silêncio o que o outro significa.

Base de pesquisa

Cada citação abaixo foi verificada contra o registro do Crossref ou do DataCite.

Crossley, Tian, Choi, Holmes e Morris (2024) coletaram 500 redações argumentativas, pediram a outros trabalhadores que as transcrevessem e separaram escrita autêntica de transcrição com 99% de acurácia usando uma random forest (96-98% para outros modelos). As famílias de atributos deles são o que o Potato captura: tempos de pausa antes de frases e palavras, contagens de inserção e exclusão, relações produto-processo, rajadas, revisão e variância do processo. O achado deles é o alvo de projeto. A escrita autêntica mostra pausas mais longas, mais inserções e exclusões, e variância maior; a transcrição é linear e orientada a rajadas.

Deane, Zhang, Hao e Li e, separadamente, Zhang, Feng, He, Li e Zhu confirmam de forma independente a separação entre cópia digitada e escrita natural, os segundos com um modelo de aprendizado profundo. Asher, Gold, Chen e Carvalho são o caso específico de crowdsourcing: uma ferramenta de teclas no Prolific sinalizando participantes que colam nos campos de resposta ou cuja contagem de teclas é anomalamente baixa para o tamanho da resposta.

Para as medidas de processo subjacentes, veja Leijten e Van Waes (Inputlog) para as medidas padrão de registro, Chenoweth e Hayes para o conceito de rajada, Conijn, Roeser e van Zaanen para a dependência de tarefa dos atributos de teclas, e Roeser, De Maeyer, Leijten e Van Waes para por que limiares fixos de pausa são enviesados.

Referências

  1. Crossley, S., Tian, Y., Choi, J. S., Holmes, L., & Morris, W. (2024). Plagiarism Detection Using Keystroke Logs. EDM 2024 (Short Papers). doi:10.5281/zenodo.12729864
  2. Deane, P., Zhang, M., Hao, J., & Li, C. Using Keystroke Dynamics to Detect Nonoriginal Text. Journal of Educational Measurement, 63(1). doi:10.1111/jedm.12431
  3. Asher, M. W., Gold, G., Chen, E., & Carvalho, P. F. (2026). Chatbots Are Undermining Crowdsourced Research in the Behavioral Sciences: Detecting Artificial Intelligence-Assisted Cheating With a Keystroke-Based Tool. Advances in Methods and Practices in Psychological Science, 9(1). doi:10.1177/25152459261424723
  4. Zhang, M., Feng, L., He, X., Li, C., & Zhu, M. (2026). Disentangling copy typing and natural writing behaviors using keystroke logs and deep learning model. Assessing Writing. doi:10.1016/j.asw.2026.101070
  5. Leijten, M., & Van Waes, L. (2013). Keystroke Logging in Writing Research: Using Inputlog to Analyze and Visualize Writing Processes. Written Communication, 30(3), 358-392. doi:10.1177/0741088313491692
  6. Chenoweth, N. A., & Hayes, J. R. (2001). Fluency in Writing: Generating Text in L1 and L2. Written Communication, 18(1), 80-98. doi:10.1177/0741088301018001004
  7. Conijn, R., Roeser, J., & van Zaanen, M. (2019). Understanding the keystroke log: the effect of writing task on keystroke features. Reading and Writing, 32(9), 2353-2374. doi:10.1007/s11145-019-09953-8
  8. Roeser, J., De Maeyer, S., Leijten, M., & Van Waes, L. (2021). Modelling typing disfluencies as finite mixture process. Reading and Writing. doi:10.1007/s11145-021-10203-z
  9. Lee, M., Liang, P., & Yang, Q. (2022). CoAuthor: Designing a Human-AI Collaborative Writing Dataset for Exploring Language Model Capabilities. CHI 2022. doi:10.1145/3491102.3502030

Leitura Complementar

Para detalhes de implementação, consulte a documentação de origem.