Deploy de Modelos na ViaHub — Parte 2

Iago Modesto Brandão
casasbahiatech
Published in
7 min readMay 15, 2023
Photo by Hugh McCann on Unsplash

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.

Figura X — Início do código de desenvolvimento

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

Figura X — Fluxo de desenvolvimento e abertura 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.

Figura X — Fluxo de desenvolvimento e entrega do código para branch produtiva

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
Figura X — Fluxo de desenvolvimento e abertura do Pull Request

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/ !

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).

--

--

Iago Modesto Brandão
casasbahiatech

Passionate by tech and all possibilities, come with us to learn more and develop the next step of the world?