
Tanto quanto sei, o Streamlit é a forma mais rápida de lançar uma aplicação Web personalizável. Se está à procura de construir um agente de IA e implementá-lo no seu próprio front-end, não consigo pensar numa opção melhor.
O único obstáculo é a biblioteca de elementos de chat. Eles são muito especificamente ajustados à API do OpenAIe ao cliente Python
O que é ótimo - algumas linhas de código para interagir com alguma da mais prestigiada tecnologia disponível é, bem... ótimo.
Mas não é tudo.
E se quiser ter mais controlo sobre o seu bot? Por exemplo, pode querer um fluxo de trabalho de várias etapas ou geração aumentada por recuperação (RAG). Essas camadas adicionais de funcionalidade geralmente significam a organização de bibliotecas com todos os tipos de dependências.
Ou será que não?
Neste tutorial, vou construir um cliente de chatbot hospedado no Streamlit. Mostrarei uma interface para iteração rápida e chatbots altamente personalizáveis. Em seguida, você aprenderá como integrar o chatbot usando um cliente Python personalizado OpenAI.
Se estiver a criar protótipos, as dependências e os aspectos técnicos não o devem impedir.
E, no espírito da prototipagem rápida, se quiser saltar o tutorial e começar a mexer, o código está no GitHub.
Bombas à distância 💣
Etapa 1: criar a lógica do Chatbot
Quer se trate de automatização do fluxo de trabalho ou de um chatbot de marcação de consultas, o mundo é realmente a sua ostra.
Aconselho-o a explorar a variedade de casos de utilização dos chatbots GenAI se estiver à procura de inspiração. Por uma questão de simplicidade, vou voltar a falar-vos da minha esperançosamente agora famosa sommelier, Winona.
O nosso pequeno bot sofisticado e útil pode ser alcançado em apenas alguns passos. Vou ser breve, mas há muitos tutoriais extensos e muito úteis que podem ser consultados.
1. Dar-lhe instruções
No estúdio, navegaremos para Início na barra lateral esquerda.

Deverá ver a secção Instruções no centro da página. Clique nela para adicionar ou modificar as instruções em texto simples.

Isto dá ao nosso bot diretivas, personalidade e guardrails. Usando linguagem simples, pode orientar o seu bot de forma bastante eficaz para o comportamento desejado. Faça-o parecer mais humano, e
2. Construir o fluxo
É aqui que residem os aspetos essenciais da personalidade do bot: acesso a informações específicas, passos rígidos, execução de código, etc.
Não subestime o poder da simplicidade. Um único nó autónomo rivaliza com a funcionalidade dos agentes de raciocínio. Eu tenho um ligado à minha Base de Dados de Conhecimento (KB).

3. Adicionar a base de conhecimentos
Se as instruções são sobre vibrações, a KB é sobre factos concretos. No meu caso, os factos em questão são os vinhos no conjunto de dados Wine Reviews, uma lista de vinhos, descrições e preços. Vou tratar isto como um inventário de vinhos de facto para o nosso bot Sommelier-ize.
Clico em Tables (Tabelas ) no painel esquerdo e carrego em New Table (Nova tabela) no canto superior esquerdo da página e dou-lhe um nome descritivo.

Clique nas elipses verticais (⋮) no canto superior direito e prima Importar.

Arraste o seu .csv para o modal que aparece e siga os passos no ecrã.
Para tornar a tabela acessível ao seu bot, navegue até Bases de Conhecimento na barra lateral esquerda.

Clique no pequeno ícone de tabela verde e selecione a fonte relevante. Clique em Adicionar tabelas.

Certifique-se de que o seu fluxo tem acesso à base de dados de conhecimento e está pronto para começar.

Etapa 2: adicionar a integração da API Chat
O ponto de contacto entre o bot e o nosso cliente local é a API Chat . Para adicionar isso ao nosso bot, vou até Communication Channels (Canais de comunicação) e carrego em ... Mais.

Se quiser, pode consultar as integrações. Estamos atrás de Chat. Tive de percorrer um pouco para o encontrar.

Clique na integração e prima Instalar integração no modal que aparece.

Depois de instalado, você verá a ID da APIChat no final do URL webhook . Você precisará dela mais tarde.
Passo 3: Escrever o cliente Python
A API Chat expõe uma série de endpoints para realizar operações em usuários, conversas e mensagens. Como prometido, eu vou envolver isso em um cliente Python que pode substituir um cliente OpenAI .
1. Adicione as suas credenciais
class BotpressClient:
def __init__(self, api_id=None, user_key=None):
self.api_id = api_id or os.getenv("CHAT_API_ID")
self.user_key = user_key or os.getenv("USER_KEY")
self.base_url = f"{BASE_URI}/{self.api_id}"
self.headers = {
**HEADERS,
"x-user-key": self.user_key,
}
Pode adicionar o seu ID da API Chat a um ficheiro .env - ajuda na depuração, mas não é estritamente necessário. Lidaremos com a ID da API e a chave de usuário quando criarmos o aplicativo Streamlit.
Eu mantenho BASE_URI
e CABEÇALHOS
numa constants.py
ficheiro, para a desarrumação.
# constants.py
BASE_URI = "https://chat.botpress.cloud"
HEADERS = {
"accept": "application/json",
"Content-Type": "application/json",
}
2. Criar os métodos Request
def _request(self, method, path, json=None):
url = f"{self.base_url}{path}"
try:
response = requests.request(method, url, headers=self.headers, json=json)
response.raise_for_status()
return response.json()
except requests.HTTPError:
return response.status_code, response.text
# --- Core API Methods ---
def get_user(self):
return self._request("GET", "/users/me")
def create_user(self, name, id):
user_data = {"name": name, "id": id}
return self._request("POST", "/users", json=user_data)
def set_user_key(self, key):
self.user_key = key
self.headers["x-user-key"] = key
def create_and_set_user(self, name, id):
new_user = self.create_user(name, id)
self.set_user_key(new_user["key"])
def create_conversation(self):
return self._request("POST", "/conversations", json={"body": {}})
def list_conversations(self):
return self._request("GET", "/conversations")
def get_conversation(self, conversation_id):
return self._request("GET", f"/conversations/{conversation_id}")
def create_message(self, message, conversation_id):
payload = {
"payload": {"type": "text", "text": message},
"conversationId": conversation_id,
}
return self._request("POST", "/messages", json=payload)
def list_messages(self, conversation_id):
return self._request("GET", f"/conversations/{conversation_id}/messages")
Como mencionado, quase todos estes mapeiam para um ponto final na API. Estou apenas a envolvê-los numa classe.
3. Criar um ouvinte SSE
Esta é a extensão do hackerismo. Para ouvir as actualizações da conversa e fazer um loop num front-end Streamlit, o cliente precisa de um método para ouvir - e produzir - eventos enviados pelo servidor do nosso bot.
def listen_conversation(self, conversation_id):
url = f"{self.base_url}/conversations/{conversation_id}/listen"
for event in sseclient.SSEClient(url, headers=self.headers):
print(event.data)
if event.data == "ping":
continue
data = json.loads(event.data)["data"]
yield {"id": data["id"], "text": data["payload"]["text"]}
Esta função recebe o conversation_id (que será acedido programaticamente dentro da aplicação) e produz os dados de entrada à medida que estes acontecem.
Passo 4: Criar a aplicação Streamlit
Com os nossos patos em fila, é altura de construir o chatbot. Note-se que estou a seguir o guia do Streamlit para criar uma aplicação de chat LLM -com algumas funcionalidades adicionais.
1. Adaptar o código padrão
Em teoria, é possível pôr a aplicação a funcionar com alterações mínimas ao boilerplate no exemplo do Streamlit.
# app.py
from client import BotpressClient
import streamlit as st
from constants import CONVERSATION_ID
st.title("Botpress Front-end for Streamlit")
client = BotpressClient(
api_id=st.secrets["CHAT_API_ID"], user_key=st.secrets["USER_KEY"]
)
if "messages" not in st.session_state:
messages = client.list_messages(CONVERSATION_ID)
next_token = messages["meta"]["nextToken"]
st.session_state.messages = messages["messages"][::-1]
for message in st.session_state.messages:
with st.chat_message(message["userId"]):
st.markdown(message["payload"]["text"])
if prompt := st.chat_input("*wine*-d it up"):
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
client.create_message(prompt, conversation_id=CONVERSATION_ID)
with st.chat_message("assistant"):
response_box = st.empty()
last_rendered = ""
for message in client.listen_conversation(CONVERSATION_ID):
message_id = message["id"]
message_text = message["text"]
if message_id != last_rendered:
last_rendered = message_id
response_box.markdown(message_text)
st.session_state.messages.append(
{"role": "assistant", "content": message_text}
)
Estamos a ler variáveis secretas aqui. Portanto, crie um arquivo .streamlit/secrets.toml e coloque suas variáveis dentro dele:
CHAT_API_ID = "SEU_API_ID"
USER_KEY = "SUA_CHAVE_DE_UTILIZADOR"
O trabalho pesado está a ser feito dentro:
with st.chat_message("assistant"):
response_box = st.empty()
last_rendered = ""
for message in client.listen_conversation(CONVERSATION_ID):
message_id = message["id"]
message_text = message["text"]
if message_id != last_rendered:
last_rendered = message_id
response_box.markdown(message_text)
st.session_state.messages.append(
{"role": "assistant", "content": message_text}
)
em que o cliente se agarra aos elementos de conversação para entregar e receber mensagens.
Isto funciona, mas não é o ideal por algumas razões:
- Tem de ter criado uma nova conversa separadamente.
- As mensagens antigas serão formatadas de forma diferente das novas, uma vez que não têm a designação de função (utilizador ou assistente).
- Não é possível alternar as conversas.
2. Criar conversas de forma dinâmica
Começando do zero, crio automaticamente uma nova conversa ou abro a mais recente:
# app.py
from client import BotpressClient
import streamlit as st
st.title("Botpress Front-end for Streamlit")
client = BotpressClient(
api_id=st.secrets["CHAT_API_ID"], user_key=st.secrets["users"][0]["key"]
)
# user info
user = client.get_user()
user_id = user["user"]["id"]
conversations = client.list_conversations()["conversations"]
conversation_ids = [conv["id"] for conv in conversations]
# conversation
def create_conversation():
res = client.create_conversation()
print(f"Created new conversation: {res}")
conversation_id = res["conversation"]["id"]
st.session_state.active_conversation = conversation_id
st.session_state.messages = []
st.rerun()
if not conversations:
create_conversation()
if "active_conversation" not in st.session_state:
st.session_state["active_conversation"] = conversations[0]["id"]
Note que modifiquei as chaves secretas para poder armazenar vários utilizadores. Você vai querer modificar seu .streamlit/secrets.toml
para refletir isso:
[[utilizadores]]
chave = "sua_chave_de_utilizador"
Pode repetir este bloco as vezes que quiser, armazenando os utilizadores como uma matriz de tabelas.
3. Permitir que os utilizadores criem e alternem entre conversas
Tal como o título indica, isto cria um menu pendente na parte superior com um botão que lhe permite escolher a sua conversa.
col1, col2 = st.columns([5, 1])
with col1:
conversation_id = st.selectbox(
"Select Conversation",
options=[conv["id"] for conv in conversations],
index=conversation_ids.index(st.session_state.active_conversation),
)
with col2:
st.markdown("<div style='height: 1.9em'></div>", unsafe_allow_html=True)
if st.button("➕"):
create_conversation()
selected_conversation = client.get_conversation(conversation_id)
4. Atribuir a função correta às mensagens anteriores
Resolveremos o problema de formatação acima, atribuindo a função de utilizador ou assistente a cada uma das mensagens anteriores:
if (
"messages" not in st.session_state
or st.session_state.get("active_conversation") != conversation_id
):
st.session_state.active_conversation = conversation_id
st.session_state.messages = []
messages = client.list_messages(conversation_id)
next_token = messages["meta"].get("nextToken")
for message in messages["messages"][::-1]:
role = "user" if message["userId"] == user_id else "assistant"
text = message["payload"]["text"]
st.session_state.messages.append({"role": role, "content": text})
Isto faz com que o nosso código esteja em conformidade com a estrutura que o Streamlit espera.
5. Adicionar a lógica de envio de mensagens
É mais ou menos a mesma coisa que antes, adaptada à nova estrutura.
# display chat history
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
if prompt := st.chat_input("*wine*-d it up"):
st.session_state.messages.append({"role": "user", "content": prompt})
client.create_message(prompt, conversation_id=conversation_id)
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
stream = client.listen_conversation(conversation_id=conversation_id)
response = st.write_stream(stream)
st.session_state.messages.append({"role": "assistant", "content": response})
5. Criar um utilizador
A lógica está pronta, mas é necessário criar um utilizador para executar a aplicação. Optei por adicionar isto separadamente para simular a experiência de subscrição de um serviço. Felizmente para si, também escrevi um script:
# create_user.py
import argparse
from pathlib import Path
from client import *
from constants import *
secrets_path = Path(".streamlit") / "secrets.toml"
template = """[[users]]
key="{}"
"""
client = BotpressClient()
def create_user(name, id, add_to_secrets=True):
res = client.create_user(name, id)
if not add_to_secrets:
return res
secrets_path.touch(exist_ok=True)
with open(secrets_path, "a") as f:
f.write(template.format(res["user"]["id"], res["key"]))
return res
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Create a Botpress user and optionally store secrets."
)
parser.add_argument("--name", required=True, help="Display name of the user.")
parser.add_argument(
"--id", required=True, help="User ID. If omitted, one is generated by the API."
)
parser.add_argument("--chat_api_id", help="ID for the Botpress Chat API integration. Taken from `.env` file if not provided.")
parser.add_argument(
"--no-secrets",
action="store_true",
help="Do not append to .streamlit/secrets.toml.",
)
args = parser.parse_args()
print(f"Creating user: {args.name} (ID: {args.id or 'auto-generated'})")
result = create_user(name=args.name, id=args.id, add_to_secrets=not args.no_secrets)
print("✅ User created:")
print(result)
Desde que tenha o seu ID da API Chat , pode executar:
python criar_utilizador.py -nome SEU_NOME -id ALGUM_ID_DO_UTILIZADOR -id_api_do_chat SEU_ID_API_DO_CHAT
Isto irá tratar da criação do utilizador e adicioná-lo ao seu ficheiro de segredos.
Passo 5: Executar a aplicação
Com a sua lógica construída e o seu utilizador criado, está na altura de dar uma volta com esta aplicação. Instale as dependências e execute:
streamlit run app.py
E, sem mais nem menos, verá o nosso bot em toda a sua glória.

Execute um chatbot Streamlit hoje mesmo
Se está a criar protótipos com o Streamlit, sabe que a personalização não deve ser feita à custa da conveniência. Os chatbots existem para resolver problemas - não para os criar.
Botpress vem com um construtor visual de arrastar e soltar, dezenas de integrações oficiais e pontos de extremidade de API acessíveis. Dessa forma, é possível criar, iterar e implantar em vários canais de comunicação.
Comece a construir hoje. É grátis.