7.5 Testando tudo junto
Last updated
Last updated
Vamos simular um ciclo completo nessa já conhecida figura:
Entre no GitLab e crie um novo issue:
Título: Retreinar ignorando acentos
Descrição: O modelo de classificação de produtos parece estar errando quando há acentos. Por exemplo, "senhor dos anéis" é corretamente reconhecido como um livro, mas "senhor dos aneis" é reconhecido como um brinquedo.
Na página do issue, já clique em "Create merge request", junto com um branch. Na nova página do merge request, veja que o título aparece com um prefixo "Draft:". Isso indica que esse merge request é apenas um rascunho, o que é ótimo, pois nem sequer começamos a trabalhar nele. Deixe assim e confirme a criação.
A primeira coisa que faremos, segundo as boas práticas, é reproduzir o problema. Para isso, vamos criar um caso de teste que demonstra a situação que leva ao erro. Mas antes não podemos nos esquecer de trocar para o branch novo.
Agora sim, vamos criar um caso de teste e adicioná-lo aos nossos testes. Modifique o arquivo test_api.py
:
Execute os casos de teste, e veja que de fato o erro acontece:
Agora vamos tentar resolver o problema. Para isso, é interessante retomar o notebook original e tentar ajustar algo por lá. Caso não tenha mais o ambiente, volte até a Seção 2.1.1 e refaça o processo como explicamos lá.
Já vimos que o problema existe, e reproduzimos em um caso de teste. Mas vamos reproduzir o problema aqui também, no notebook, para facilitar nossa vida. No final do notebook, altere:
Estamos simplesmente testando de uma só vez a predição para as duas grafias de "Senhor dos anéis", com e sem acento. O resultado, como já sabíamos, é que a predição muda (com acento é livro, sem acento é brinquedo):
Para retirar os acentos durante o treinamento (o que em teoria resolve o problema), podemos utilizar o pacote Unidecode. Entre outras coisas, ele despreza caracteres que tem acento, substituindo por suas alternativas sem acento.
Altere o notebook nos seguintes locais:
Execute novamente o notebook e veja que agora a predição é a mesma, independentemente do acento:
Se você estiver rodando o notebook modificado na Seção 2.1, ele já terá salvo o modelo no arquivo model.sav
. Caso contrário, faça as modificações novamente:
Após a execução, um novo arquivo model.sav
será salvo, e temos que copiá-lo para a pasta do projeto. Feito isso, execute os testes novamente, e confirme que agora estamos passando em todos eles.
Vamos também testar para ver se o sistema continua funcionando, e se não quebramos algo. O primeiro teste pode ser usando o próprio modo DEBUG do Flask:
Enviando um POST simples, vemos que aparentemente funcionou:
Tudo deu certo, e o melhor é que não quebramos nenhum dos testes que já estavam passando. Ainda podemos testar com o mesmo ambiente que estará rodando em produção, fazendo uso do Docker. Apesar de já termos testado usando Flask, no ambiente final lembre-se que temos ainda outros componentes, como o gunicorn e o nginx. Então faz sentido testar com tudo isso integrado.
Lembrando que alteramos nossa imagem para que a porta seja especificada em uma variável de ambiente, vamos construir a imagem e subir o contêiner especificando a porta como uma variável de ambiente, como o Heroku faria:
No exemplo, sorteamos a porta 9361. Veja como passamos isso para o contêiner por meio do parâmetro --env PORT=9361
. E estamos mapeando isso para a porta 8080 da máquina hospedeira. No Heroku, isso é mapeado para a porta 80.
Teste, acessando no navegador o endereço http://localhost:8080
, e veja que tudo está funcionando.
Então já podemos fazer o envio das mudanças para o GitLab:
Neste momento, nosso pipeline CI/CD já deve ter começado a executar. Vamos lá conferir no GitLab:
Sucesso! Testes e cobertura foram verificados e não causamos nenhum problema!
Veja que os estágios de release não foram executados, pois eles foram configurados para rodar somente no branch main, lembra? Portanto, na verdade o que rodou foi apenas a parte de CI.
Agora é o momento de revisar e aprovar o merge request. Abra-o e veja que ele está marcado como "draft". Clique em "Mark as ready":
Agora clique em "Merge" (lembrando que em um ambiente corporativo provavelmente é outra pessoa que irá fazer isso, verificando as mudanças, conferindo se os pipelines estão passando, etc.). Isso irá disparar o pipeline novamente, e agora ele inclui a parte de CD. Em breve a nova versão estará pronta e implantada no Heroku para testarmos.
Enquanto o pipeline é executado, aproveite para ver o gráfico e conferir a ordem dos commits:
Depois de um tempo, os jobs completam, exceto pelo deploy em produção, pois deixamos este para ser executado manualmente, lembra?
Vamos fazer um último teste. Entre no ambiente de staging e faça mais testes. Neste momento, uma boa ideia é chamar usuários e colocá-los para usar o sistema em sua nova versão, sem ainda mexer na versão oficial:
Assim que estiver satisfeito, basta retornar ao pipeline, executar o deploy em produção, e a versão oficial passará a contar com as melhorias implementadas.
Pare um pouco e respire. Olhe novamente a figura que começou este livro (prometemos que será a última vez):
Andamos por um longo caminho, não? Agora temos um ciclo completo, que agiliza todo processo de implantação e entrega de mudanças, desde os testes até chegar em um servidor na nuvem.
Fizemos aqui exemplos concretos, com tecnologias reais. É claro que existem outras alternativas para tudo o que vimos aqui. Algumas pagas, outras gratuitas. Umas mais simples, outras mais complexas. O importante é entender os conceitos e o princípio, que não mudam.
Também é importante ressaltar que seguimos um caminho simplificado. Não abordamos questões mais complexas, como verificações adicionais, notificações, configurações mais complexas de ambientes.
Também não abordamos a questão do versionamento, desde o código até as imagens no Docker. É uma boa prática nomear corretamente todas as versões, seguindo uma política bem estabelecida e respeitada.
Mas esperamos que você tenha aproveitado o que aprendeu até aqui, e que consiga agora compreender o que está envolvido no conceito de CI/CD.
Porém, ainda há o que aprender. Tudo o que fizemos aqui, de certa forma, não tem muitas especificidades exclusivas do aprendizado de máquina. Então, no fundo, estivemos falando de DevOps, e não de MLOps. É esse o caminho que iremos trilhar a seguir.