Deploy de Modelos na ViaHub — Parte 2
Neste artigo vamos detalhar do processo de padronização da implantação de modelos no ambiente produtivo, caso você ainda não tenha lido a contextualização, acesse o artigo aqui
Introdução
Para padronizar o processo de implantação produtiva de Modelos de ML evitar o crescimento demasiado de formas artesanais de deploy, criamos dois grandes pilares centrais na nossa padronização, as esteiras de CI/CD como a frente de MLOps e os padrões de Repositório.
Vamos discutir sobre estes dois assuntos neste artigo, começando pelas Esteiras de CI/CD, com os padrões de repositório na sequência
Esteiras de CI/CD + Gitflow
Nesta seção do artigo, vamos explicar como é a dinâmica desde o desenvolvimento de um código de modelo de ML até ele chegar no ambiente produtivo.
Do código de desenvolvimento ao código produtivo
Adotamos o Git flow aqui, para o desenvolvimento do modelo, ou de um ajuste ou uma nova função no código, o cientista cria uma nova branch a partir da versão mais recente da branch main, trabalhando em branches com prefixo feature/*, onde o nome que preencherá o asterisco é de livre escolha do cientista.
A branch main é utilizada apenas para armazenar o código produtivo, mantendo todo o histórico do código produtivo do modelo nesta branch.
Para que o código seja entregue a branch main, um processo de revisão acontece, onde um engenheiro de machine learning e um cientista de dados fazem a revisão do código e aprovam, todo esse processo é feito via Pull Request dentro do próprio Github.
Nota: Caso algum ajuste seja necessário, o cientista responsável volta para a branch feature/* de desenvolvimento e faz o ajuste, validando a nova execução já possível re-solicitar a revisão do Pull Request
Após a aprovação do Pull Request, temos a nova execução da esteira de CI, permitindo que o Merge seja feito e o código desenvolvido já testado e revisado seja integrado na branch produtiva, neste caso, a main.
Uma curiosidade é: no ambiente produtivo utilizamos scripts python ao invés de python notebooks, pois acreditamos na sinergia dos scripts com IDEs locais e na nuvem, com o uso de linters e testes integrados nativos, além de poderem ser gerados facilmente depois do desenvolvimento em notebooks python.
Continuos Integration (CI)
Na esteira de CI, que roda no Github Actions, temos a execução dos seguintes passos a cada commit em qualquer branch:
- Executa todos os testes disponíveis na pasta /tests
- Executa o SonarCloud Scan
Na esteira de CD, que roda no Github Actions, temos a execução dos seguintes passos ao fazer a operação merge na branch main:
- Converte os arquivos do repositório em artefato (pasta zipada)
- Faz upload dos artefatos no nosso Data Lake
- Para execução periódica do modelo, publica a trigger e pipeline no Azure Data Factory
- Copia os scripts python para
Após fazer o agendamento da execução para a periodicidade desejada, o modelo, ou nova versão do modelo, já estará implantada em ambiente produtivo!
Sobre um ponto-chave referente ao artefato de código: Considerando que todo o código é organizado em funções e módulos, torna-se obrigatório importar algum outro script python por meio do script principal, para realizar tal tarefa, convertemos todo o código em um artefato que pode ser utilizado na computação do ambiente produtivo sem maiores esforços.
Após fazer o agendamento da execução para a periodicidade desejada, o modelo, ou nova versão do modelo, já estará implantada em ambiente produtivo!
Inspiração
Como inspiração do processo de CI/CD, utilizamos as grandes referências geradas pelo Google, o primeiro artigo publicado pela Google Cloud [1], com os níveis de maturidade dos processos de CI/CD, e o artigo do Sculley [2], traduzindo toda problemática que já vínhamos observamos.
Padrões de Código e Repositório
Nesta seção do artigo, vamos explicar como são nossos padrões de repositório, sendo estes os garantidores que o processo de implantação em ambiente produtivo possa ocorrer da melhor forma
A estrutura do repositório
Para garantir padronização no código, uma estrutura de repositório padrão é copiada para cada novo modelo a ser desenvolvido. Abaixo temos a representação da estrutura do repositório em formato de árvore de arquivos.
arq-ref-ml-batch/
┣ .github/
┃ ┣ workflows/ # Github Actions Workflows Folder
┃ ┃ ┣ .gitkeep
┃ ┃ ┣ cd_dev.yml # CD Workflow for Development
┃ ┃ ┣ cd_prod.yml # CD Workflow for Production
┃ ┃ ┗ ci.yml # CI Workflow
┃ ┗ PULL_REQUEST_TEMPLATE.md
┃
┣ notebooks/ # Data Scientist can make its sandbox here
┃ ┗ .gitkeep
┃
┣ pipelines/ # Folder containing JSON files of
┃ ┣ pipeline.json # Azure Data Factory service
┃ ┣ pipeline_stg.json # (all used for triggering the ML Model
┃ ┗ trigger.json # periodically)
┃
┣ src/ # Source code folder
┃ ┣ contrib/ # Stores custom code for production
┃ ┃ ┣ __init__.py
┃ ┃ ┗ utils.py # Store all Data Scientist utility functions
┃ ┣ data_preparation/
┃ ┃ ┣ __init__.py
┃ ┃ ┗ etl.py # ETL for ML Data Preparation
┃ ┣ ml/
┃ ┃ ┣ __init__.py
┃ ┃ ┣ predictor.py # Model Prediction script
┃ ┃ ┗ trainer.py # Model Training script
┃ ┣ __init__.py
┃ ┣ config.py # Python script reading /config_env.yaml
┃ ┗ main.py # Entry point of ML Model code
┃
┣ tests/ # Test folder for CI process
┃ ┣ e2e/
┃ ┃ ┗ test_e2e.py
┃ ┣ structure/ # Test code structure (accordingly to pattern)
┃ ┃ ┣ test_config.py
┃ ┃ ┣ test_dirs_and_files.py
┃ ┃ ┣ test_predictor.py
┃ ┃ ┣ test_src_main.py
┃ ┃ ┗ test_trainer.py
┃ ┣ __init__.py
┃ ┣ config_test.yaml
┃ ┗ test_main.py # Entry point of test code
┃
┣ .env.example
┣ .gitignore
┣ .pylintrc
┣ Dockerfile
┣ Makefile # Used for running tests on CI
┣ README.md #
┣ config_dev.yaml # Keeps all constants for Development step
┣ config_prod.yaml # Keeps all constants for Production step
┣ install_requirements.sh # Installs requirements.txt and other dependencies
┣ pip.conf #
┣ requirements.txt # List of python dependencies (production)
┣ requirements_dev.txt
┣ setup.py # Builds the code as artefact (wheel file)
┣ sonar-project.properties
┗ tox.ini
Vamos falar das pastas e arquivos que o cientista de dados vai utilizar durante seu desenvolvimento.
- A pasta notebooks pode ser utilizada para desenvolver livremente o que cientista precisar, sendo um dos primeiros lugares que o código do cientista vai aparecer;
- O arquivo src/main.py é o ponto de entrada do modelo, é responsável por orquestrar a execução de todos os passos necessários para o modelo fazer a escoragem, inclusive executar o ETL quando aplicável. Deve conter a importação de métodos já existentes em outros script, realizando a chamada destes métodos na ordem necessária;
- O arquivo src/ml/predictor.py tem a responsabilidade de carregar o modelo, carregar as variáveis/features, fazer a escoragem e então salvar os resultados;
- O arquivo src/ml/trainer.py contém todo o código treinar o modelo, tendo a responsabilidade de carregar os dados de treinamento, produzir toda esteira de treino, fazer o treinamento do modelo e salvar o modelo treinado no mlflow;
- O arquivo src/data_preparation/etl.py é responsável por fazer a chamada do ETL que gera as tabelas/dados de treino e escoragem do modelo, não é necessariamente o único código que gera o ETL, mas é o responsável por orquestrar esse processo;
- Os arquivos config_dev.yaml e config_prod.yaml são utilizados para armazenar as constantes utilizados no modelo, assim como nomes de tabelas de entrada e saída
- O arquivo src/ml/config.py contém todo o código para identificar o ambiente de execução, se é produtivo ou desenvolvimento, e então ler as constantes disponíveis no arquivo de configuração YAML respectivo;
Uma curiosidade: Utilizamos scripts python por maior aderência ao ambiente produtivo e normalização de código, bem como permitir o uso de linters e IDEs locais e em nuvem, sendo híbrido tanto tem desenvolvimento quanto em produção.
Inspiração
Para a estrutura de repositório, nos inspiramos na arquitetura híbrida batch/API que o serviço Azure Machine Learning utiliza para organizar seus arquivos, matendo o script main.py como ponto de entrada único.
Acredito que já deu para entender que aqui na ViaHub agente tem paixão por alta performance, autonomia e participação não é? Esses são alguns dos pilares da ViaHub, a nossa área de tecnologia! Se você gostou e tem interesse de estar em um time assim, basta se inscrever no nosso portal de vagas em https://viahub.gupy.io/. Conheça também mais sobre a ViaHub e a cultura tech que temos em https://www.viahub.com.br/ !
Referências
[1] Cloud Architecture Center. MLOps: Continuous delivery and automation pipelines in machine learning
[2] Sculley, D. et al. “Hidden Technical Debt in Machine Learning Systems.” NIPS (2015).