O computador mais limitado que a maioria das pessoas alguma vez vai usar é aquele em que está a ler isto. Não é o telemóvel. É o separador.
Um separador do navegador não tem instalador, não tem placa gráfica com que contar, dispõe de umas centenas de megabytes de memória antes de a coisa dar para o torto, e tem à frente um utilizador cuja paciência para uma barra de progresso se mede em segundos. É o pior sítio da informática moderna para pôr uma rede neuronal. Nós pusemos lá a nossa de propósito.
Porque é que o modelo tem de estar no separador
Anonimização enquanto serviço é uma contradição. Para a usar, carrega o documento confidencial para a empresa que promete protegê-lo. Não reduziu a sua exposição. Mudou-a de sítio, e acrescentou um fornecedor.
É por isso que a nossa deteção corre dentro do seu navegador: a leitura do PDF, o reconhecimento de carateres nas páginas digitalizadas e o modelo que percebe que Margarida Rodrigues é uma pessoa e que 1249-300 Lisboa é uma morada, em sete línguas, sem que ninguém lhe diga qual. O que obriga o modelo a caber num separador. A primeira versão não cabia.
O imposto do alfabeto
O nosso detetor nasce de um BERT multilingue afinado para encontrar nomes, organizações e lugares. Bom modelo. Só que carrega também um vocabulário de 119 547 tokens para 104 línguas.
Nós oferecemos sete: inglês, francês, alemão, espanhol, italiano, neerlandês e português. Todas em alfabeto latino.
A 768 dimensões, essa tabela de vocabulário ocupa cerca de 92 MB de um ficheiro de 178,5 MB — mais de metade do modelo, e à volta de 97 % de tudo o que descarrega quem chega pela primeira vez. Lá dentro: devanágari, cirílico, hangul, tailandês, arménio, hebraico, árabe, kana e treze mil ideogramas. Descarregado por todos os utilizadores. Usado por nenhum.
Chamemos-lhe o imposto do alfabeto. Cada visitante paga para transportar 104 línguas a fim de ler uma. E aqui vem a parte de que temos menos orgulho: a ferramenta que resolve isto já estava escrita, já tínhamos provado que não degradava nada — e deixámo-la como um comando opcional que ninguém executava. Um passo de compilação facultativo é um passo de compilação que não acontece em lado nenhum.
Apagar linhas, não comprimir fotografias
A resposta habitual é a destilação: treinar um pequeno modelo aluno para imitar um grande modelo professor. Funciona, e troca exatidão por tamanho — troca que não se faz à socapa numa ferramenta cujo único ofício é não deixar escapar nada. Por isso não a fizemos.
O que fizemos parece-se mais com apagar linhas inúteis de uma folha de cálculo. Não se toca num único peso do codificador: as doze camadas que fazem o verdadeiro trabalho de compreensão são copiadas tal e qual. A tabela de vocabulário é quantizada por tensor, pelo que uma linha mantida guarda o seu valor exato, estejam ou não as vizinhas lá. E o tokenizador fica sempre com o fragmento mais longo disponível: retirar apenas fragmentos inalcançáveis em escrita latina deixa o texto latino segmentado exatamente da mesma maneira.
Resultado: de 119 547 tokens para 68 875. De 178,5 MB para 139,6 MB, cerca de 100 MB na rede. E a afirmação não é «quase idêntico». Passámos os dois modelos por 77 documentos reais nas sete línguas: zero diferenças na segmentação do texto, zero diferenças em 2 219 entidades detetadas, e uma diferença máxima à saída do modelo de 0,0000000000. Não é um modelo mais pequeno que se sai mais ou menos igual. É o mesmo modelo, sem o lastro.
Lá chegar custou-nos uma péssima semana. Os identificadores de token aparecem em três sítios do ficheiro do tokenizador; atualizámos dois. Todos os testes passavam, o texto era segmentado de forma idêntica, e o modelo devolvia caladinho respostas diferentes em sessenta documentos. A regra que ficou: comparar a saída bruta do modelo, nunca a lista de entidades. Duas listas de entidades podem concordar por sorte.
Duas tentativas de ir mais longe
O vocabulário ainda é um terço do que resta, boa parte dele escrita latina para línguas que não oferecemos. Pareciam estar ali mais 30 a 40 megabytes. Não é um compromisso. É um precipício.
Guardar 58 000 dos 68 875 tokens latinos — 84 % deles — poupava 8 MB e custava 13 % de todas as deteções. Depois veio o ensaio que fechou a discussão: uma lista apenas com os tokens que os nossos documentos de teste realmente usam — 22 800 guardados, 46 000 deitados fora — produziu uma segmentação idêntica ao bit e 100 % de concordância. Um vocabulário pequeno não custa nada, portanto. É o token que falta que custa tudo. Não há curva nenhuma onde afinar, e voltar a segmentar bate com mais força nas palavras raras — que é exatamente o que são os nomes próprios.
Um número decidiu. Os carateres latinos das línguas para as quais não vendemos — o turco ğ ı, o vietnamita ư ạ ế, o romeno ă ț, o checo ř ů, o húngaro ő, o nórdico ø — dão 4 200 fragmentos. 3,2 MB. É o alfabeto de todos os nomes estrangeiros de um contrato europeu: dados pessoais no estado puro, nos documentos com mais probabilidade de os conter, por três megabytes. Se a nossa deteção falha no seu nome porque o seu nome é turco, construímos o produto errado.
Segunda tentativa: DistilBERT — seis camadas em vez de doze, cerca de 70 MB na rede contra os nossos 100. Depois medimo-lo contra 137 entidades verificadas à mão. A deteção caía de 77,2 % para 73,5 % — pouco o suficiente para nos convencermos a nós próprios. Mas a média esconde a forma: o alemão perdia 13 pontos, o inglês 9, o espanhol 22. E os dois modelos só concordavam em 76 % do que encontravam. Não detetava menos entidades. Detetava um conjunto diferente, de tamanho parecido. Com «menos» trabalha-se. Com «diferente» não.
Minuscule
O modelo que distribuímos chama-se Minuscule. A minúscula carolíngia foi a escrita normalizada em todo o império de Carlos Magno no século VIII — uma escrita latina limpa, deliberadamente estreita, e é por isso que um copista de Aquisgrano conseguia ler um manuscrito copiado em Tours. Muitas línguas, um alfabeto, nada a mais. E, já agora, é pequenina.
68 875 tokens. 139,6 MB em disco, cerca de 100 MB transferidos uma única vez e depois guardados em cache para sempre. Nem um peso do codificador alterado em relação ao modelo de que deriva. Traz consigo a sua própria ficha de fabrico — modelo de origem, definições, tamanhos de vocabulário, impressão digital dos seus próprios pesos — porque um modelo incapaz de dizer de onde vem não tem nada que fazer ao pé daquilo que está a tentar proteger. Está publicado no Hugging Face — pesos, tokenizador e ficha de fabrico — para que os números acima seja o leitor a confirmá-los em vez de acreditar em nós.
O que se compra com cem megabytes
Neste preciso momento, algures, um assistente jurídico está a colar o contrato de um cliente numa janela de conversa. Uma enfermeira carrega uma carta de alta. Um técnico de serviço social larga o processo de uma família num site de tradução gratuito. Não são pessoas imprudentes. Estão atrasadas. A via aprovada exige um pedido, uma revisão de segurança e duas semanas, e o prazo é quinta-feira.
A única versão de «protegido» que alguma vez ganha é a que já está aberta. Sem instalação, sem direitos de administrador, sem autorização, sem reunião. Ou seja, um separador do navegador. Ou seja, um modelo que caiba num separador do navegador. E é por isso que houve gente adulta a passar uma semana a discutir 3,2 megabytes de diacríticos turcos.
Trabalho ingrato, invisível por construção. Mas acaba com uma pessoa à frente de um portátil, num escritório que o leitor nunca vai ver, a entregar o trabalho a horas — e o nome do cliente nunca saiu da sala. Cem megabytes, uma vez. A partir daí, são seus.
Perguntas frequentes
Retirar vocabulário a um modelo reduz a sua precisão?
Não, quando o vocabulário retirado é inalcançável nas línguas que oferece. Não se altera nenhum peso do codificador e cada linha mantida é copiada bit a bit, pelo que para texto em alfabeto latino o resultado é numericamente idêntico ao original: medimos zero diferenças em 2 219 entidades ao longo de 77 documentos. Cortar vocabulário que o modelo consegue alcançar é outra coisa completamente diferente, e aí a degradação é abrupta.
Porque não usar simplesmente um modelo mais pequeno?
Tentámos. Um DistilBERT de seis camadas da mesma família ocupa cerca de 70 MB na rede contra os nossos 100, mas obteve 73,5 % contra 77,2 % no nosso conjunto verificado, e a média escondia 22 pontos perdidos em espanhol e 13 em alemão. Além disso, só concordava com o modelo que distribuímos em 76 % do que encontrava: um conjunto de entidades diferente, não menor. A nossa comparação com o Microsoft Presidio explica como medimos isto.
Um modelo deste tamanho consegue mesmo correr num separador do navegador?
Sim, com duas ressalvas. A descarga acontece uma única vez e fica depois em cache no seu dispositivo, e o modelo tem ainda assim de ser compilado numa sessão a cada arranque — daí a barra de carregamento na primeira utilização. Tudo o resto é local: nenhuma página do seu documento é enviada. Porque construímos o nosso próprio motor de deteção cobre o resto da cadeia.
Que línguas cobre e o que acontece às restantes?
Inglês, francês, alemão, espanhol, italiano, neerlandês e português, mais qualquer outra língua em alfabeto latino cujos carateres tenham sobrevivido no vocabulário: turco, vietnamita, romeno, checo, húngaro e nórdico foram mantidos de propósito, porque os nomes estrangeiros aparecem a toda a hora em contratos europeus. Uma língua numa escrita removida, como o japonês, precisa do seu próprio pacote em vez de um único modelo que engorda a cada língua acrescentada.