Artigo

Apps de IA com Streamlit: do Script ao App Web em Minutos

Apps de IA com Streamlit: do Script ao App Web em Minutos
Tempo de leitura9 minutos

Streamlit é a forma mais rápida de transformar um script de IA em um app web que qualquer pessoa pode usar. Sem HTML, sem JavaScript, sem framework de frontend: você escreve Python e ganha uma interface interativa. Neste guia mostro como construir um app de IA completo, com cache de modelos, estado de sessão e deploy.

Vou construir um app que recebe um texto, chama um LLM e exibe o resultado — o ponto de partida para chatbots, dashboards e ferramentas internas.

Por que Streamlit para projetos de IA

  • Velocidade: um app funcional em dezenas de linhas.
  • Python puro: sem aprender frontend.
  • Integração natural: funciona direto com pandas, PyTorch, LLMs.
  • Deploy simples: hospedagem gratuita e integração com GitHub.

Instalando e rodando

python -m venv .venv && source .venv/bin/activate
pip install streamlit openai
streamlit run app.py

O primeiro app

Streamlit reexecuta o script a cada interação. Entender isso é fundamental para usar cache corretamente.

import streamlit as st

st.title("Meu app de IA")
texto = st.text_area("Digite um texto:")
if st.button("Processar") and texto:
    st.write(f"Voce digitou {len(texto)} caracteres.")

Widgets essenciais

modelo = st.selectbox("Modelo", ["gpt-4o-mini", "gpt-4o"])
temperatura = st.slider("Temperatura", 0.0, 1.0, 0.2)
topico = st.radio("Formato", ["Resumo", "Titulos", "Perguntas"])
arquivo = st.file_uploader("Envie um .txt")

Com poucos widgets você cobre a maioria dos casos de uso internos.

Cache: o segredo da performance

Carregar um modelo ou chamar uma API a cada reexecução é caro. Use @st.cache_resource para recursos e @st.cache_data para dados.

import streamlit as st
from openai import OpenAI

@st.cache_resource
def get_client():
    return OpenAI()

@st.cache_data(ttl=600)
def resumir(texto: str) -> str:
    client = get_client()
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": f"Resuma: {texto}"}],
    )
    return resp.choices[0].message.content

cache_resource mantém o objeto vivo entre execuções; cache_data guarda resultados por um tempo. Juntos, evitam recomputar tudo a cada clique.

Estado de sessão

Como o script roda de novo a cada interação, variáveis normais se perdem. O session_state mantém o histórico da conversa:

if "mensagens" not in st.session_state:
    st.session_state.mensagens = []

for m in st.session_state.mensagens:
    st.chat_message(m["role"]).write(m["content"])

if prompt := st.chat_input("Pergunte algo"):
    st.session_state.mensagens.append({"role": "user", "content": prompt})
    resposta = chamar_llm(st.session_state.mensagens)
    st.session_state.mensagens.append({"role": "assistant", "content": resposta})
    st.rerun()

Streaming de resposta

Para chat, streaming melhora muito a experiência:

with st.chat_message("assistant"):
    placeholder = st.empty()
    acumulado = ""
    for pedaco in stream_resposta(prompt):
        acumulado += pedaco
        placeholder.markdown(acumulado)

Layout e organização

col1, col2 = st.columns(2)
with col1:
    st.metric("Chamadas hoje", 128)
with col2:
    st.metric("Latencia media", "1.2s")

with st.sidebar:
    st.header("Configuracoes")
    modelo = st.selectbox("Modelo", ["gpt-4o-mini", "gpt-4o"])

Protegendo o app

Se o app for interno, exija uma senha simples ou autenticação. Nunca deixe chaves no código.

senha = st.text_input("Senha", type="password")
if senha != st.secrets["APP_SENHA"]:
    st.stop()

Deploy

O caminho mais rápido é o Streamlit Community Cloud, ligado ao seu repositório. Alternativas: container próprio ou uma VPS.

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8501
CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]

Autenticação com login real

Apps internos costumam precisar de login. Uma abordagem simples é validar credenciais e guardar o usuário na sessão. O importante é nunca confiar apenas no frontend: valide a sessão também no backend que chama a IA.

import streamlit as st

if "usuario" not in st.session_state:
    st.session_state.usuario = None

if not st.session_state.usuario:
    with st.form("login"):
        u = st.text_input("Usuario")
        s = st.text_input("Senha", type="password")
        if st.form_submit_button("Entrar"):
            if validar(u, s):
                st.session_state.usuario = u
                st.rerun()
            else:
                st.error("Credenciais invalidas")
    st.stop()

Testando o app

Streamlit tem uma API de teste que permite rodar o app programaticamente e verificar o comportamento, sem abrir navegador.

from streamlit.testing.v1 import AppTest

def test_app_carrega():
    at = AppTest.from_file("app.py").run()
    assert not at.exception
    assert at.title[0].value == "Meu app de IA"

Performance e limites de custo

Todo clique reexecuta o script. Sem cache, isso significa chamadas repetidas ao LLM e custo alto. Três medidas resolvem a maior parte: cachear o cliente e o modelo, cachear resultados por entrada e limitar o tamanho do texto aceito.

texto = st.text_area("Texto", max_chars=4000)

Erros comuns

  • Recarregar o modelo a cada interação (faltou cache).
  • Guardar estado em variáveis normais em vez de session_state.
  • Expor chaves de API no código.
  • Não limitar o tamanho da entrada, elevando o custo de tokens.
  • Ignorar streaming em interfaces de chat.
  • Confiar só no frontend para autenticação.

Conectando a um backend de IA

O app Streamlit não deve falar direto com o provedor em produção. Prefira uma API própria, que centraliza autenticação, limites e logs.

import requests

API = "https://api.seuapp.com"

def chamar_backend(texto: str, token: str) -> str:
    r = requests.post(
        f"{API}/api/resumir",
        json={"texto": texto},
        headers={"Authorization": f"Bearer {token}"},
        timeout=60,
    )
    r.raise_for_status()
    return r.json()["resumo"]

Assim, a chave do provedor de IA nunca fica no frontend e você controla o consumo por usuário.

Gráficos e dashboards

Streamlit é excelente para visualização. Combinado com pandas, você monta dashboards de dados de IA em poucas linhas.

import pandas as pd
import streamlit as st

df = pd.DataFrame({"dia": ["seg", "ter", "qua"], "chamadas": [120, 200, 180]})
st.bar_chart(df.set_index("dia"))
st.line_chart(df.set_index("dia"))

Uploads e processamento de arquivos

arquivo = st.file_uploader("Envie um PDF", type=["pdf"])
if arquivo:
    texto = extrair_texto(arquivo)
    st.text_area("Conteudo extraido", texto, height=200)
    if st.button("Resumir"):
        st.write(resumir(texto))

Boas práticas de UX

  • Mostre um spinner durante operações longas (st.spinner).
  • Use st.progress para tarefas em etapas.
  • Trate erros com st.error em vez de deixar quebrar.
  • Organize controles na barra lateral.
  • Persista configurações no session_state.

Streamlit como MVP de validação

Antes de construir um frontend completo, valide a ideia com Streamlit. Se as pessoas usarem, aí sim vale investir em Next.js. Isso evita semanas de trabalho em algo que ninguém quer.

# contador simples de uso para medir interesse
if "usos" not in st.session_state:
    st.session_state.usos = 0
st.session_state.usos += 1
st.caption(f"Interacoes nesta sessao: {st.session_state.usos}")

Quando migrar para um frontend próprio

  • Quando você precisa de SEO e páginas públicas.
  • Quando a interface exige design muito específico.
  • Quando o app tem muitos usuários simultâneos.
  • Quando precisa de fluxo de pagamento integrado.

Enquanto nada disso for verdade, Streamlit economiza tempo valioso.

Otimizando o carregamento de dados

Dados grandes devem ser carregados uma vez e guardados em cache. Carregar um CSV de milhões de linhas a cada interação é o caminho mais rápido para um app lento.

@st.cache_data
def carregar_dados(caminho: str):
    import pandas as pd
    return pd.read_csv(caminho)

df = carregar_dados("dados.csv")

Conclusão e próximos passos

Streamlit é uma ferramenta de produtividade: comece pelo MVP, valide com usuários reais e só então decida se vale um frontend dedicado. O tempo que você economiza aqui é o que financia a próxima ideia.

Multipáginas em Streamlit

Apps crescem. Streamlit suporta múltiplas páginas simplesmente colocando arquivos na pasta pages/. Cada arquivo vira uma entrada no menu lateral.

app.py            # pagina inicial
pages/
  1_Dashboard.py
  2_Chat.py
  3_Configuracoes.py
# navegacao programatica
st.page_link("pages/2_Chat.py", label="Ir para o chat")

Internacionalização simples

Para atender mais de um idioma, um dicionário de traduções resolve sem complicação.

IDIOMAS = {
    "pt": {"titulo": "Meu app de IA", "botao": "Processar"},
    "en": {"titulo": "My AI app", "botao": "Process"},
}
idioma = st.sidebar.selectbox("Idioma", ["pt", "en"])
T = IDIOMAS[idioma]
st.title(T["titulo"])

Integrando com banco de dados

Apps de IA frequentemente precisam consultar dados. Streamlit conecta direto ao banco, com cache para não repetir consultas.

import sqlalchemy as sa
import streamlit as st

@st.cache_resource
def engine():
    return sa.create_engine(st.secrets["DATABASE_URL"])

@st.cache_data(ttl=300)
def buscar_clientes():
    with engine().connect() as conn:
        return conn.execute(sa.text("SELECT nome, cidade FROM clientes")).fetchall()

st.dataframe(buscar_clientes())

Exportando resultados

import pandas as pd

df = pd.DataFrame(buscar_clientes(), columns=["nome", "cidade"])
st.download_button(
    "Baixar CSV",
    df.to_csv(index=False).encode("utf-8"),
    file_name="clientes.csv",
    mime="text/csv",
)

Dicas de layout responsivo

Streamlit se adapta sozinho, mas algumas escolhas ajudam em telas pequenas: use st.columns com moderação, prefira a barra lateral para controles e evite tabelas muito largas.

aba1, aba2, aba3 = st.tabs(["Chat", "Dados", "Config"])
with aba1:
    st.write("Area de chat")
with aba2:
    st.write("Area de dados")

Conclusão geral

Streamlit é ideal para colocar IA na mão de pessoas rápido. Domine cache, sessão e streaming, organize em páginas quando crescer, e migre para um frontend dedicado apenas quando houver motivo real. Você ganha velocidade sem sacrificar qualidade.

Resumo

Streamlit elimina a barreira entre um script de IA e um produto usável. Domine três coisas — cache, estado de sessão e streaming — e você consegue construir desde ferramentas internas até MVPs para validar ideias. O resto é criatividade na interface.

Anterior e próximo

Leituras recentes

Temas parecidos para continuar navegando no blog.

Conteúdo criado para leitura limpa, boa hierarquia visual e navegação clara.