Comecei a trabalhar em um recurso de IA para o trabalho porque vi uma oportunidade de contornar uma ferramenta especializada antiga e desajeitada e, claro, toda start-up precisa ser uma start-up de IA . Ao criar o protótipo desse recurso, encontrei alguns problemas estranhamente familiares. Então, olhei em meus diários e encontrei Maggie, a bebê tradutora que eu e um amigo construímos antes da pandemia. Já se passaram quase sete anos e os mesmos problemas que afetaram os testes de IA e a implantação da produção ainda são uma praga absoluta, embora o estado da arte tenha feito progressos significativos. Aqui está uma reflexão sobre minhas notas, pensamentos e código de Maggie para demonstrar os problemas comuns no caminho para a produção de IA. Espero que você ache isso útil.
Maggie é o nome da filha mais nova dos Simpsons do programa de mesmo nome. Maggie é um bebê que ainda não aprendeu a falar. O tio de Maggie, Herb, chega ao fundo do poço após uma má decisão de negócios e vai morar com os Simpsons. Ele milagrosamente constrói um tradutor para bebês depois de se inspirar em sua sobrinha e na frustração da família com sua falta de fala. De maneira semelhante, meu amigo Chris teve a ideia de criar um tradutor para bebês devido ao relacionamento com sua irmã mais nova, que tinha dificuldade para aprender a falar. Por isso, chamamos nosso aplicativo de Maggie.
Chris estava trabalhando em um laboratório para bebês na época e descobriu que havia limitações fisiológicas no espectro de sons que crianças de uma determinada faixa etária podiam emitir. A partir dessa percepção, ele reuniu dados de treinamento e construiu um modelo de classificação para o choro do bebê – um feito impressionante, já que ele era formado em Física e não tinha experiência em Ciência da Computação.
Compartilhamos uma aula – Engineer Service Learning – onde toda a turma trabalhou na certificação LEED para um dos edifícios do campus. Lembro-me dele como o cara despreocupado que andava de longboard para a aula. Nossa primeira interação foi fora da sala de aula, no estacionamento escuro de um supermercado, onde o vi se preparando para andar de bicicleta suja. Ele havia estacionado ao lado do meu carro e conversamos. Então notei um papel amassado ao lado dele, peguei-o, percebi que era dinheiro e disse que ele havia deixado cair o dinheiro. Ele disse que não era dele, mas eu disse-lhe para ficar com ele. Não sabíamos quanto custava; o estacionamento estava muito escuro. $ 1, $ 10 ou $ 100. Eu disse a ele que esperava que custasse US$ 100. Custava US$ 10. Mas essa primeira interação construiu confiança suficiente entre nós que, em poucas semanas, enquanto ambos trabalhávamos no Venture Lab – a incubadora de startups da UC Merced – ele me pediu para construir um aplicativo para implantar seu bebê tradutor. Sem o Venture Lab, nunca teríamos pensado em colaborar. Eu certamente não saí por aí dizendo a colegas aleatórios que desenvolvo aplicativos Android, nem ele saiu por aí se gabando de seu modelo de tradução para bebês. Há uma magia magnética nos terceiros espaços presenciais que você não deve subestimar.
Apesar de construir um modelo funcional. Chris não conseguia descobrir como implantá-lo. Isso foi no início de 2017 e não havia muitos cursos ou guias que demonstrassem isso. Seu mentor no TensorFlow recomendou a implantação no Android, mas aprender o desenvolvimento móvel era uma ponte longe demais. Eu conhecia o Android e havia implantado vários aplicativos na Play Store, mas mesmo para mim isso era um exagero. Então, fiz a coisa mais fácil.
Coloquei o modelo em um servidor e fiz chamadas de API para ele. Executar o modelo em um servidor Flask foi surpreendentemente fácil: importar o TensorFlow, carregar o modelo do disco local (nem pensei em implantar o modelo de uma forma que fosse fácil de versionar até mais tarde) e apontar as solicitações para isto. Mas houve algumas pegadinhas:
Apesar desses problemas, funcionou. Compartilhar o analisador de entrada do modelo e o código do transformador resolveu o primeiro problema. Tratar o modelo como uma caixa preta e zombar dele tornou mais fácil a construção de testes de integração em torno dele. Esses testes garantiriam que não houvesse desalinhamentos inesperados entre o servidor e o modelo – desde que as simulações fossem precisas. Agora, existem interfaces de modelo que podem garantir a correção simulada durante o desenvolvimento. A implantação e o controle de versão para modelos não são um problema que exige soluções inovadoras para a maioria dos casos de uso atualmente.
Por outro lado, os problemas de latência e disponibilidade eventualmente nos levaram a implantar o modelo no aplicativo na borda. Isso teve a vantagem de remover a latência da rede, usar a CPU muito mais rápida do telefone e manter o aplicativo rodando em segundo plano, o que resolveu nosso problema de latência de inicialização e reduziu nossos custos de hospedagem. Mas é claro que surgiram novos problemas.
Passamos muito tempo debatendo onde colocar o modelo. Queríamos a velocidade e a segurança do telefone, mas ansiamos pela segurança e facilidade de implantação do servidor. Inicialmente, colocar o modelo no servidor era atrativo:
No final, decidimos colocar o modelo no aplicativo devido aos dois primeiros pontos – o aplicativo não era atraente se você tivesse que esperar a tradução ou se ocasionalmente ficasse inativo. Alguns segundos de latência parecem uma eternidade quando você tem um recém-nascido chorando nos braços. Mas colocar o modelo no telefone teve seus problemas, como descreverei na próxima seção.
A lição que tirei disso é que você deve otimizar para obter a melhor experiência do usuário, mesmo que a solução não seja escalonável, não proporcione crescimento futuro ou arrisque seu IP. As empresas vivem e morrem pela experiência do usuário, especialmente se forem novas empresas que precisam ganhar confiança e construir uma marca.
Colocar o modelo no telefone trouxe uma montanha de dificuldades técnicas. Alguns deles não existem agora, mas a maioria sim. Estávamos na vanguarda. O TensorFlow para Android mal tinha sido lançado — o lançamento público foi em fevereiro de 2017 e eu estava construindo o aplicativo em março. Mas com perseverança e muita ajuda de Pete Warden do TensorFlow, conseguimos fazer o modelo funcionar no aplicativo.
O primeiro problema foi conseguir o modelo no pacote APK. Na época, o Android tinha um limite de APK de 50 MB e um recurso de extensão que permitia que os aplicativos ficassem maiores baixando componentes após a instalação. No entanto, considerei o recurso de extensão inseguro, pois significava expor o modelo em um servidor. Então, decidimos quantizar o aplicativo — uma técnica que envolve a redução da precisão de todas as entradas e saídas de cada camada.
No nosso caso, convertemos todos os números de ponto flutuante em inteiros, o que reduziu significativamente o tamanho do modelo e o tornou mais rápido, mas também reduziu a precisão. Chris passou por diversas iterações do modelo com diferentes esquemas de quantização e finalmente decidiu pela quantização inteira, apesar da redução na precisão. Foi útil desde que o modelo tivesse um desempenho melhor do que os novos pais. Bônus: resolveu o problema de atualização – baixar centenas de MB de dados em cada atualização de modelo era uma tarefa difícil em conexões de internet limitadas, mas alguns MBs eram gerenciáveis (isso parece bobagem para mim agora, já que as pessoas baixam regularmente GBs de conteúdo de vídeo em seus telefones hoje ).
Depois veio uma longa série de problemas menores. O maior deles foi que as bibliotecas FFT suportadas pelas diferentes versões do Java fornecidas com o Android não produziam o mesmo espectrograma no qual o modelo foi treinado. Treinamos o modelo usando uma biblioteca C++ FFT e ele produziu espectrogramas com diferentes cores e dimensões. Por serem ferramentas secretas, as versões C++ e Java foram escritas de forma opaca e difíceis de modificar. Outra decisão rápida: decidimos treinar novamente o modelo usando espectrogramas Java FFT. Isso significou transformar todos os arquivos de áudio em espectrogramas e depois executar o processo de treinamento, que demorava dias no antigo Macbook do meu amigo. Mas o problema foi resolvido e pude me concentrar em outra coisa durante esse tempo.
Mas o aplicativo continuou congelando e travando. Acontece que carregar a gravação na memória e depois criar o espectrograma na memória foi uma má ideia. O aplicativo estava consumindo muitos recursos do telefone. A solução foi salvar em disco e transmitir. Salvar em disco foi fácil; a parte do streaming foi difícil porque, uma vez que o áudio saísse da memória, qualquer coisa poderia acontecer com ele no disco. Outro programa pode lê-lo e modificá-lo; ele pode ser excluído, pode falhar ao salvar, etc.… Esses casos extremos geralmente não existem na web - você tem um canal isolado com seu usuário, mas não em dispositivos. Garantir que havia espaço suficiente para fazer isso e limpar depois do aplicativo foi um desafio inesperado. Descobri mais tarde que é uma suposição equivocada acreditar que, se o telefone tivesse memória suficiente para instalar seu aplicativo, então teria memória suficiente para executá-lo.
Por último, o próprio dispositivo era um adversário: os telefones Android vêm com uma grande variedade de CPUs, quantidades de memória e, o mais importante, microfones. O problema de CPU e memória pode ser resolvido configurando a versão necessária do Android para a mais recente e esperando o melhor; o pior cenário seria um aplicativo lento – não há como definir os requisitos de recursos diretamente no Android. O verdadeiro problema era levar em conta as várias qualidades dos microfones – o Android permite que você exija microfones nos dispositivos em que seu aplicativo está instalado, mas não o tipo de microfone.
Não tentei resolver esse problema. Eu tinha muitos telefones de teste na época e percebi como as previsões eram piores nos telefones baratos. Decidi que não havia tempo para encontrar uma solução agora – estávamos tentando lançar o mais rápido possível. Às vezes, a melhor solução para um problema é anotá-lo e seguir em frente. Agora percebo que essa questão nos apontou na direção do produto final – Homer, um alto-falante inteligente.
Uma vez superadas (ou evitadas) as dificuldades técnicas, passamos para o problema mais difícil da qualidade da previsão. Como o modelo residia no aplicativo, estávamos cegos para seu desempenho. Se o desempenho foi ruim, a única maneira de sabermos é por meio de comentários na página do aplicativo ou desinstalações; até então, já é tarde demais. Portanto, construir um wrapper de logs, monitoramento, coleta de dados e feedback em torno do modelo foi fundamental.
O modelo utilizou espectrogramas e algumas outras informações para categorizar os sons que o bebê emitia – fome, desconforto, dor, sono e gases, essas eram as traduções. Ele retornou uma lista de todas as categorias possíveis, com cada categoria tendo uma porcentagem representando o quão confiante o modelo estava naquela tradução específica. Todas as porcentagens somam 100 – se a tradução mais precisa chegasse a 90%, então as outras cinco categorias teriam precisões que somam 10%.
A questão que enfrentamos desde o início foi se deveríamos exibir todas as traduções (ordenadas da mais precisa para a menos precisa) ou apenas uma. Optei por mostrar apenas um porque não queria confundir as pessoas com mais traduções e era mais simples construir isso (a preguiça é a base do Agile). No entanto, tivemos problemas com nosso primeiro conjunto de usuários.
Quando o modelo estava certo (acima de 80%), a sugestão funcionou – não recebemos reclamações dos pais. Mas nem sempre foi tão confiante. Quando a precisão da tradução estava abaixo de 80%, era tão boa quanto a do pai ou da adivinhação. Isso vai contra o propósito do aplicativo; deveria oferecer traduções mais precisas do que as tentativas em pânico de um novo pai de acalmar seu filho. E assim foi, não é de surpreender que a segunda ou terceira traduções tenham sido corretas. Descobrimos isso por meio de entrevistas presenciais – entrevistas presenciais não são escalonáveis e demoradas, mas são extremamente densas em informações; se você puder fazer um diariamente, faça. O bebê chorava e o aplicativo mostrava a tradução errada com pouca confiança, mas tentávamos as outras traduções (vimos nos registros) e funcionavam.
Isso foi contra-intuitivo para mim porque pensei no aplicativo como um tradutor; só deveria haver uma maneira de traduzir algo, certo? Errado. O aplicativo era uma ferramenta de exploração para novos pais e responsáveis determinarem o que deveriam tentar primeiro. Devo tentar arrotar meu bebê? Ele está com fome? Quando foi a última vez que ele tirou uma soneca? Todos os pais passam por esta lista de verificação quando o bebê começa a chorar. Nosso aplicativo acelerou essa exploração; foi assim que os pais usaram, e esse foi o feedback que recebemos quando lançamos diversas traduções. Esse não era o recurso matador, mas certamente transformou o aplicativo de um artifício em uma ferramenta de uso diário, um companheiro confiável quando o cônjuge está fora ou os avós estão dormindo.
Com base nesses dados, decidimos rapidamente exibir mais traduções. O truque era descobrir quantos. Exibir todas as traduções – todas as cinco categorias – fazia com que o aplicativo parecesse repetir sempre as mesmas traduções. O que você pensaria se o Google mostrasse os mesmos quatro restaurantes toda vez que você pesquisasse por comida? Decidimos pelas três principais traduções – parte arte e parte dados.
As pessoas tendem ao número três por algum motivo. Os dados mostraram que a confiança do modelo em outras traduções caiu significativamente após a terceira tradução. Se a primeira tradução tivesse uma confiança de 70%, a 2ª teria 20%, a terceira 9% e as restantes abaixo de 1%. Então, abandonamos essas traduções. Havia uma pequena chance de que essas traduções perdidas fossem precisas, mas incluí-las corria o risco de fazer o aplicativo parecer repetitivo. A escolha foi que 1 em cada 100 usuários receberia traduções totalmente erradas ou todos os usuários veriam traduções inúteis e pensariam que o aplicativo estava adivinhando. Foi uma escolha fácil.
É claro que, pensando bem, eu deveria ter testado isso usando um multi-arm bandit – lançar cinco versões diferentes do aplicativo, uma para cada escolha, por exemplo, mostrar uma tradução, mostrar duas, mostrar três, etc., e migrar lentamente as pessoas na versão do aplicativo que obteve melhores resultados. A principal métrica de sucesso seria quantas pessoas clicaram na marca de seleção verde (satisfeitas com a tradução). Mas, numa fase tão inicial, acredito que tomámos a decisão correta e, mais importante ainda, tomámos a decisão da forma correta. Tínhamos a mente aberta, não considerávamos nenhuma decisão concreta (sem egos aqui), verificamos constantemente nossos usuários e os ouvimos, mesmo que não parecesse certo.
Cada interação é uma oportunidade para melhorar e impressionar. Minha preocupação desde o início deste empreendimento era que o modelo tivesse sorte, que haveria um pai ou mãe solteiro que foi informado de que seu bebê estava chorando porque estava com gases e arrotava o bebê até a morte. Improvável, mas nos sentimos responsáveis pelo bem-estar do bebê de cada usuária. Portanto, adiamos o lançamento adicionando um recurso de feedback ao aplicativo.
Após cada tradução, perguntaram a você o quão útil ela era - uma página que não pode ser ignorada. Em seguida, o aplicativo carregou o feedback do usuário, a saída do modelo, o tipo de dispositivo e o espectrograma. Inicialmente, carreguei o arquivo de áudio, mas rapidamente percebi que o microfone capturava muito ruído de fundo. Para privacidade dos nossos usuários, optamos por fazer upload apenas do espectrograma. O que eu não sabia era que era possível reverter um espectrograma e reconstruir o áudio, embora com qualidade inferior e com alguma dificuldade. Este foi o nosso volante.
No entanto, estou pulando os debates e os vários rascunhos que levaram a esta versão final. Decidir quais dados coletar, como medir o sucesso e como definir o sucesso é difícil, mas é um processo iterativo que você pode realizar em pequenos passos e melhorar. O melhor conselho que recebi foi definir como é o sucesso ou, se isso for muito difícil, como é o fracasso (para mim, é muito mais fácil definir o fracasso do que o sucesso - nunca sei o que quero, mas tenho certeza o que quero evitar) e ser específico. A partir dessa resposta, derive as métricas que você pode usar para avaliar seus esforços – se o fracasso for perder usuários antes que o bebê fique velho demais para usar o aplicativo, então meça a vida útil média do aplicativo no telefone do usuário. Mas tenha em mente que essas definições e métricas não são estáticas – elas mudarão. Você só precisa decidir e cumpri-los até que parem de funcionar. Eles deixarão de funcionar quando você parar de aprender com eles ou pelo menos quando for mais difícil aprender com eles. O objetivo é esse, aprender e melhorar, o resto são detalhes.
Na era da IA/ML, o ativo digital mais valioso de uma empresa são os dados que lhe são confiados, não o modelo. O crescimento destes dados – de preferência de forma transparente e ética – é fundamental para o sucesso contínuo. Assim, cada interação do usuário deve ser tratada como um momento de geração de valor, independentemente das taxas de conversão. Conclui-se então que cada interação deve deixar o usuário impressionado e com vontade de retornar. Construímos algo que impressionou e inspirou; tivemos uma grande designer, Teresa Ibarra , que pegou meu rascunho rudimentar e o transformou em um aplicativo que era agradável e agradável de usar. E cada tradução tornou a próxima melhor.
A última coisa que construímos foi Homer. Depois de realizar dezenas de entrevistas pessoais com usuários do aplicativo e ligar para ainda mais pessoas, percebemos que procurar seu telefone, desbloquear a tela, encontrar nosso aplicativo, abri-lo e clicar em traduzir enquanto segura seu filho chorando é difícil e inconveniente. Por que demoramos tanto para perceber isso? Éramos dois rapazes solteiros e sem filhos, na casa dos vinte anos - não me lembro da última vez que segurei um bebê, muito menos acalmei seus choros. Então, decidimos construir uma babá eletrônica usando um alto-falante inteligente. Encomendei um kit do Raspberry Pi e construí um alto-falante Google Home personalizado com um grande botão azul na parte superior.
Chris tinha uma ótima visão de vender o modelo para empresas de babás eletrônicas, mas não estávamos ganhando força com essas empresas, então por que não construir nossa própria babá eletrônica usando um alto-falante inteligente? Depois de construir o Google Home, criei um script bash para executar o tradutor na inicialização. O tradutor usou o SDK do Google Home para traduzir a frase de gatilho 'Ok, Google, traduza'. O tradutor era um script Python que lia o áudio dos microfones, transformava-o em um espectrograma e depois o enviava a um servidor para ser traduzido. Mantive as coisas ágeis e funcionou ! Finalmente tivemos nosso aplicativo matador, mas ele não salvou a empresa.
Ficamos sem financiamento – o prêmio em dinheiro que ganhamos em uma competição. A vida estava rapidamente caindo sobre nós dois. Nós nos formamos na faculdade e ambos voltamos para casa - aceitei um emprego na Bay Area e Chris foi embora para cuidar de sua mãe doente no Texas. A inicialização falhou.
Startups são difíceis e dolorosas. Você não pode fazê-los em meio período. Todos que têm uma participação precisam trabalhar em tempo integral ou precisam sair para abrir espaço para outra pessoa. Ou você terá que diminuir suas ambições, talvez abandoná-las completamente. Agora, existem problemas que podem ser resolvidos de forma lucrativa em regime de meio período – mas será que valem a pena? Eles te excitam?
Se aprendi alguma coisa - além de como é difícil implantar modelos de ML no Android - é que você realmente precisa se preocupar com o problema que está resolvendo. Você precisa encontrar coragem para se comprometer em tempo integral, apesar dos riscos financeiros e do tremendo custo de oportunidade. De jeito nenhum eu desistiria do meu trabalho técnico para trabalhar nisso. Adorei ajudar pais de primeira viagem e pais desesperados; era estimulante aprender e construir a tecnologia, mas como eu poderia explicar ao meu pai por que estava voltando para nosso apertado apartamento na Seção 8 depois de me formar? Como eu poderia recusar um salário de seis dígitos depois de viver tanto tempo da Previdência Social?
E quanto ao capital de risco? Por que você não tentou arrecadar dinheiro? A realidade é que os VCs só atendem o telefone se conhecerem você, a escola que você estudou ou a empresa em que trabalhou. Eles não se importam com o que você construiu – exceto que seja lucrativo, sua inovação é um pequeno detalhe – os VCs investem primeiro nos fundadores e nas equipes e nos produtos por último. Mas a maioria deles não sabe como escolher bons fundadores ou equipes, então deixam que os oficiais de admissão nas escolas de elite ou na FAANG façam isso.