Palavras chaves: Streamlit, deployment, modelo em produção, GitHub, Heroku, projeto no ar
Material produzido para a Tera
Depois de gastar horas e horas no desenvolvimento de seu projeto de Ciência de Dados, você provavelmente deve ter se deparado com mais um obstáculo: como mostrar o valor do seu trabalho e fazer com que seu projeto possa ser utilizado por qualquer pessoa, independente de seu conhecimento técnico de programação?
Este artigo vai ensinar na prática como utilizar o básico do Streamlit, GitHub e Heroku para criar uma interface interativa de seu projeto e disponibilizá-lo na internet.
Conceitos Iniciais
É tão importante assim colocar o projeto no ar? Parece ser mais fácil simplesmente compartilhar o resultado final.
De fato, enviar um slide ou um relatório pode ser feito em alguns cliques. Contudo, é importante ressaltar que nem sempre as pessoas sabem o que querem. Quantas vezes você já se deparou em uma situação onde foi necessário executar seu modelo inúmeras vezes a fim de atender as expectativas?
Ao oferecer uma solução que seja acessível e de fácil entendimento, o usuário ganha autonomia para explorar suas possibilidades e tirar suas próprias conclusões. Isso é valioso porque, ao invés de simplesmente oferecer um resultado estático, a solução colocada no ar pode ser customizada pelo usuário de acordo com sua preferência.
Transformar o projeto em uma solução intuitiva e simples é uma habilidade importante para pessoas que trabalham com Ciência de Dados. É com essa proposta que o Streamlit vem ganhando popularidade no cenário atual.
O que é o Streamlit?
O Streamlit é uma biblioteca de código aberto do Python que foi criada especificamente para o desenvolvimento de aplicativos web baseados em modelos de Machine Learning. A biblioteca permite criar elementos gráficos interativos em poucas linhas de código.
Uma das vantagens da ferramenta é que ela dispensa o domínio técnico de Front-End, ou seja, é possível criar aplicativos web mesmo sem saber HTML, CSS ou JavaScript.
O site oficial do Streamlit contém casos reais de aplicativos web, como o Udacity Self-driving Car Image Browser e Uber Pickups in New York City.
OK, como começar?
Como todas as outras bibliotecas: primeiro instalando e depois entendendo como utilizar suas funcionalidades.
pip install streamlit
streamlit hello
Estruturas básicas
Dentre as diversas funcionalidades do Streamlit, é possível apontar uma série de elementos básicos que podem ser usados na maioria das aplicações web: a barra lateral, textos, tabelas, objetos interativos, gráficos e imagens.
Para facilitar o entendimento sobre essas estruturas básicas, é recomendado que você faça a leitura abaixo acompanhando este link, que contém exemplos dessas estruturas na interface do Streamlit.
Barra lateral
Talvez a estrutura mais comum de qualquer projeto em Streamlit, a barra lateral serve como um menu e concentra os elementos principais que são relevantes em qualquer momento da solução, seja no início, meio ou fim.
Nos exemplo, a barra lateral encontra-se logo à esquerda e contém uma caixa de seleção da categoria. Esse recurso é criada pelo comando streamlit.sidebar
e, normalmente, é combinado com outras estruturas. Em nosso caso, o código utilizado foi st.sidebar.selectbox('Escolha a espécie a ser visualizada')
Textos
Os textos podem ser diferenciados por tamanho da fonte e formatação:
import streamlit as st#Diferentes tamanhos de texto
st.title('Isso é um título')
st.header('Isso é um cabeçalho')
st.subheader('Isso é um subcabeçalho')
st.text('Isso é um texto normal')#formatação
st.markdown('Texto em **negrito** ou _itálico_')#Utilização para guardar html
st.markdown('[Isso é um texto com html](https://docs.streamlit.io/en/stable/api.html#display-text)',False)
Tabelas
É possível apresentar dados em tabelas interativas ou em tabelas estáticas. Apesar da tabela interativa permitir a ordenação de colunas, a tabela fixa carrega uma layout mais harmônico.
import pandas as pd
import numpy as np#gerando um dataframe aleatório
df = pd.DataFrame(
np.random.randn(15,10),
columns=('col_%d' % i for i in range(10))
)#tabelas interativas
st.dataframe(df)#tabelas fixas
st.table(df)
Objetos interativos
Essa categoria representa um dos principais motivos pelo qual o Streamlit é considerado uma ferramenta altamente versátil. Os objetos interativos são os meios de interação entre a solução e os usuários, servido para definir desde os parâmetros específicos de modelos, as variáveis a compor o modelo ou mesmo as janelas temporais utilizadas nas amostras.
Dentre as diversas funcionalidades, é possível implementar desde botões,…
#Botão
if st.button('Gerar número aleatório'):
st.write(randint(0, 1000000))
else:
st.write('Clique no botão acima')#Radio
chute = st.radio(
"por que essa função se chama radio?",
('Opção 1: porque o rádio é um osso muito bonito',
'Opção 2: é uma homenagem à Marie Curie',
'Opção 3: as opções lembram botões de rádio')
)if chute == 'as opções lembram botões de rádio':
st.write('Correto!')
else:
st.write("Incorreto, tente novamente.")
…barras de arraste, …
#Barra de arraste
bar = st.slider('Isso é um slider',
min_value=0,
max_value=10,
value=5,
step=1)st.write("você selecionou: ",bar)
…caixas de seleção e…
#caixa de multiseleção
#obs.: utilizando o dataframe criado anteriormente
cx_mult = st.multiselect(
'Selecione as colunas abaixos',
df.columns
)st.dataframe(df[cx_mult])
…a possibilidade do usuário inserir seus próprios dados.
#input de números
input_num = st.number_input(
'Escreva um número entre 0 e 10',
min_value = 0,
max_value = 10,
value = 0,
step = 1
)st.write('O número inputado foi: ', input_num)
#input de texto
input_txt = st.text_input(
'Escreva uma palavra com até 5 letras',
value = 'juiz',
max_chars = 5
)st.write('A palavra inputada foi: ', input_txt)
Gráficos
E o que seriam de soluções de Ciência de Dados sem gráficos?
#vamos aproveitar o dataframe criado anteriormente
df2 = pd.DataFrame(df, columns=['col_0','col_1','col_2'])#exemplo de gráfico
st.area_chart(df2)
Adicionalmente aos gráficos da própria biblioteca, o Streamlit também permite a integração com a biblioteca Plotly. A única diferença é a necessidade da inclusão de uma estrutura específica, o st.plotly_chart()
. O exemplo utiliza o código abaixo:
#dataset de iris do sklearn
df = px.data.iris()#lista de possíveis especies
lista_especie = ('setosa','versicolor','virginica')#caixa de seleção à esquerda
var_especie = st.sidebar.selectbox(
'Escolha a espécie a ser visualizada',
lista_especie
)#dicionários de cores a serem visualizadas no gráficos
dict_flor={
lista_especie[0]:'blue',
lista_especie[1]:'red',
lista_especie[2]:'green'
}#gráfico 3D gerado a partir do plotly
fig = go.Figure(
data=go.Scatter3d(
x=df['sepal_length'],
y=df['sepal_width'],
z=df['petal_width'],
mode='markers',
marker=dict(
size=4,
color=np.where(
df['species'] == var_especie,
dict_flor[var_especie],
'lightgray'
)
)
)
)
st.plotly_chart(fig)
Mídias
Por fim, fotos, vídeos ou áudios podem ser instrumentos eficientes de se comunicar um conceito complexo. Segue um exemplo de como incluir uma imagem no Streamlit:
from PIL import Imagefoto = Image.open('foto.png')st.image(foto,
caption='Logo do Streamlit',
use_column_width=False)
Legal, mas essa foto está desalinhada. Não há como centralizar essas estruturas?
Essa limitação do Streamlit persistiu por muito tempo, porém, felizmente, os desenvolvedores ouviram as sugestões da comunidade e estão buscando auma solução definitiva nesse exato momento (literalmente, pois recebi essa atualização pela newletter do Streamlit a alguns dias atrás).
Uma solução desenvolvida foi o st.beta_columns()
. Essa funcionalidade divide a interface da página em colunas. Para centralizar uma imagem, portanto, basta dividir nossa interface em três colunas e utilizar a do meio.
#criando 3 colunas
col1, col2, col3 = st.beta_columns(3)foto = Image.open('foto.png')#inserindo na coluna 2
col2.image(foto, use_column_width=True)
Disclaimer: no momento de produção deste material, a estrutura acima encontra-se em fase beta. Recomenda-se a verificação na documentação oficial da biblioteca antes de sua utilização.
Bônus
Já deu para perceber que o Streamlit carrega uma vasta coletânea de estruturas. E por esse mesmo motivo, é comum se confundir em relação a sintaxe.
Pensando nisso, foi criada uma estrutura coringa (os próprios desenvolvedores se referem a ela como swiss-army knife): ost.write()
.
#precisa escrever o texto? Beleza
st.write('hola!')#quer mostrar a tabela? Não tem problema
st.write(df)#aguenta gráficos? Tranquilo
st.write(plotlyfigure)#e muito mais...
Executando o Streamlit
Acabei de montar meu código com as estruturas do Streamlit. E agora?
Após salvar seu arquivo com a extensão .py (por exemplo: app.py), é necessário executar o mesmo com o Streamlit via terminal de comando.
Abra seu terminal e localize a pasta raiz de seu script. Se for necessário, veja esse tutorial sobre comandos básicos no terminal.
streamlit run app.py
Uma aba de seu navegador deve ter sido aberto com o aplicativo web. Caso contrário, basta acessar a URL disponibilizada no terminal.
Colocando no ar
Uma vez o script rodou, o próximo passo é colocá-lo no ar. Para isso utilizaremos o GitHub e o Heroku. Também será necessário criar três arquivos complementares: o “setup.sh”, o “requirements.txt” e o “Procfile” (sem extensão).
Definições iniciais (glossário)
- GitHub: plataforma colaborativa que oferece controle de versão. Será utilizado para armazenarmos os arquivos em nuvem.
- Heroku: serviço de implementação e administração de aplicativos web. Será utilizado para o deploy (i.e. “colocar no ar”).
Passo-a-passo
Passo 1: crie o documento setup.sh contendo o código abaixo de configuração das portas de conexão do Streamlit.
mkdir -p ~/.streamlit/echo "\
[server]\n\
port = $PORT\n\
enableCORS = false\n\
headless = true\n\
\n\
" > ~/.streamlit/config.toml
Passo 2: crie o documento Procfile (sem extensão) contendo o código abaixo a ser instruído ao aplicativo web durante a implementação:
web: sh setup.sh && streamlit run app.py
Passo 3: crie o documento requirements.txt contendo as bibliotecas e versões utilizadas no projeto. É possível fazê-lo manualmente ou pelo terminal:
pip install pipreqs#localize a pasta raiz
pipreqs --force .
A pasta raiz do projeto deverá conter, além dos arquivos necessários ao projeto, o script e os três arquivos: Procfile, requirements.txt e setup.sh.
Passo 4: crie um novo repositório no GitHub e carregue com todos os arquivos.
Embora o GitHub aceite arquivos com até 100MB, a funcionalidade de ‘arrasta-e-solta’ disponibilizada para o navegador funciona apenas para arquivos com menos de 25MB. Portanto, arquivos acima de 25MB deverão ser carregados no GitHub via terminal.
Passo 5: crie um novo aplicativo no Heroku, selecione o GitHub como método de implementação e atribua o repositório previamente no GitHub
Passo 6: escolhe seu método de implementação e, finalmente, deploy.
Passo 7: verifique se a implementação foi bem sucedida.
Parabéns! Você está oficialmente capacitado a implementar suas soluções na internet e permitir seu acesso a milhares de usuários ao redor do mundo.
Conclusão
Este artigo abordou uma maneira de permitir que notebooks sejam transformados em soluções acessíveis. Utilizando-se do framework do Streamlit para aplicações web, é possível criar uma interface de seu projeto em questões de horas.
E, repare, durante o processo não foi preciso escrever uma linha sequer de HTML ou JavaScript. Sem qualquer conhecimento de Front-End, criamos uma solução web altamente interativa e prática.
Os arquivos utilizados para a produção deste artigo encontram-se neste link.
FAQ
Meu Streamlit resultou em erro quando eu o executei localmente.
O Streamlit indica em qual linha do código ele “engasgou”. No exemplo, o problema ocorreu na linha 104.
Basta revisar o código, salvar o arquivo e atualizar o navegador (Ctrl+R ou F5, por padrão).
A implementação não deu certo. Essa imagem de erro apareceu no navegador.
É necessário verificar se o problema está no script ou no conjunto de arquivos complementares (i.e. setup.sh, requirements.txt e Procfile).
A sugestão é avaliar os arquivos complementares primeiro, e caso o problema persistir, avaliar o script.
Para resolver problemas no script, é necessário avaliar os logs da implementação. Existem duas maneiras de se fazer isso: via logs disponíveis no próprio site do Heroku ou via terminal com o Heroku CLI. Para usar o Heroku CLI:
pip install herokuheroku logs --tail --app (substituir essa observação, incluindo o parênteses, pelo nome do aplicativo)
Exemplo: heroku logs --tail --app app-artigo-streamlit