
Voor zover ik weet is Streamlit de snelste manier om een aanpasbare web-app van de grond te krijgen. Als je een AI-agent wilt bouwen en deze wilt implementeren op je eigen front-end, dan kan ik geen betere optie bedenken.
Het enige nadeel is de chatelementen-bibliotheek. Ze zijn vrij specifiek afgestemd op OpenAI's API en Python-client.
En dat is geweldig: een paar regels code om te communiceren met de meest prestigieuze technologie die er is, is... geweldig.
Maar het is niet alles.
Wat als u meer controle wilt over uw bot? U wilt bijvoorbeeld een workflow met meerdere stappen, of retrieval-augmented generation (RAG). Deze extra lagen van functionaliteit betekenen meestal dat u bibliotheken met allerlei afhankelijkheden moet samenvoegen.
Of toch niet?
In deze tutorial bouw ik een Streamlit gehoste chatbot client. Ik laat je een interface zien voor snelleiteratie en zeer aanpasbare chatbots. Daarna leer je hoe je de chatbot kunt integreren met behulp van een op maat gemaakte OpenAI Python client.
Als je prototypes maakt, moeten afhankelijkheden en technische problemen je niet tegenhouden.
En, in de geest van snel prototypen, als je de tutorial wilt overslaan en wilt beginnen met sleutelen, de code staat op GitHub.
Bommen los 💣
Stap 1: Bouw de chatbotlogica
Of het nu gaat om workflowautomatisering of een chatbot voor het maken van afspraken, de wereld ligt voor je open.
Ik dring er bij je op aan om de vele use cases voor GenAI-chatbots te verkennen als je op zoek bent naar inspiratie. Om het eenvoudig te houden, kom ik terug met mijn hopelijk nu beroemde sommelier Winona.
Onze geavanceerde, behulpzame kleine bot kan in slechts een paar stappen worden gemaakt. Ik zal het kort houden, maar er zijn veel uitgebreide, zeer nuttige tutorials die je kunt doorbladeren.
1. Geef het instructies
In de studio navigeren we naar Home in de linker zijbalk.

Je zou de sectie Instructies vooraan en in het midden moeten zien. Klik erop om de instructies in platte tekst toe te voegen of te wijzigen.

Dit geeft onze bot richtlijnen, persoonlijkheid en vangrails. Met gewone taal kun je je bot behoorlijk effectief sturen in de richting van het gewenste gedrag. Laat het menselijker klinken en
2. Bouw de stroom
Dit is waar de moeren en bouten van de persoonlijkheid van de bot leven: toegang tot specifieke informatie, rigide stappen-voor-stap, het uitvoeren van code, enz.
Onderschat de kracht van eenvoud niet. Een enkel autonoom knooppunt evenaart de functionaliteit van redenerende agenten. Ik heb er een aangesloten op mijn kennisbank (KB).

3. De kennisbank toevoegen
Als de instructies over vibes gaan, gaat de KB over koude, harde feiten. In mijn geval zijn de feiten de wijnen in de Wine Reviews dataset, een lijst met wijnen, beschrijvingen en prijzen. Ik behandel dit als een de-facto wijninventaris voor onze bot om te Sommelier-iseren.
Ik klik op Tabellen in het linkerpaneel en klik op Nieuwe tabel linksboven op de pagina en geef de tabel een beschrijvende naam.

Klik op de verticale ellips (⋮) rechtsboven en klik op Importeren.

Sleep je .csv naar het venster dat verschijnt en volg de stappen op het scherm.
Om de tabel toegankelijk te maken voor uw bot, navigeert u naar Kennisbanken in uw linker zijbalk.

Klik op het kleine groene tabelpictogram en selecteer de relevante bron. Klik op Tabellen toevoegen.

Zorg ervoor dat je flow toegang heeft tot de Knowledge Base en je kunt aan de slag.

Stap 2: De Chat API-integratie toevoegen
Het contactpunt tussen de bot en onze lokale client is de Chat API. Om die aan onze bot toe te voegen, scroll ik naar Communicatiekanalen en druk op ... Meer.

Bekijk de integraties als je wilt. We zijn op zoek naar Chat. Ik moest een beetje scrollen om het te vinden.

Klik op de integratie en klik op Integratie installeren in het venster dat verschijnt.

Eenmaal geïnstalleerd zie je de Chat API ID aan het einde van de webhook URL. Die heb je later nodig.
Stap 3: De Python-client schrijven
De Chat API stelt een aantal eindpunten bloot om ruwe bewerkingen uit te voeren op gebruikers, conversaties en berichten. Zoals beloofd, zal ik deze in een Python client verpakken die een OpenAI client kan vervangen.
1. Uw referenties toevoegen
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,
}
Je bent vrij om je Chat API ID toe te voegen aan een .env bestand-het helpt bij het debuggen, maar het is niet strikt noodzakelijk. We zullen de API ID en gebruikerssleutel behandelen wanneer we de Streamlit app bouwen.
Ik blijf BASIS_URI
en KOPPEN
in een aparte constanten.py
bestand, voor rommel.
# constants.py
BASE_URI = "https://chat.botpress.cloud"
HEADERS = {
"accept": "application/json",
"Content-Type": "application/json",
}
2. Maak de Request-methodes
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")
Zoals gezegd, bijna al deze gegevens verwijzen naar een eindpunt in de API. Ik verpak ze gewoon in een klasse.
3. Een SSE-luisteraar maken
Dit is de omvang van de hackery. Om te luisteren naar gespreksupdates en door te lussen naar een Streamlit front-end, heeft de client een methode nodig om te luisteren naar door de server verstuurde gebeurtenissen van onze bot en deze op te halen.
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"]}
Deze functie neemt de conversation_id (die programmatisch binnen de app zal worden benaderd) en levert inkomende gegevens op wanneer dit gebeurt.
Stap 4: Maak de Streamlit App
Nu we alles op een rijtje hebben, is het tijd om de chatbot te bouwen. Merk op dat ik Streamlit's gids voor het bouwen van een LLM chat-appvolg ,met enkele toegevoegde functies.
1. Pas de boilerplate code aan
In theorie kun je de app werkend krijgen met minimale wijzigingen aan de boilerplate in het Streamlit voorbeeld.
# 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}
)
We lezen hier geheime variabelen. Dus maak een .streamlit/secrets.toml bestand en plaats je variabelen daarin:
CHAT_API_ID = "UW_API_ID".
USER_KEY = "UW_GEBRUIKERSSLEUTEL
Het zware werk gebeurt binnen:
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}
)
waarbij de client zich vastklampt aan de chat-elementen om berichten af te leveren en te ontvangen.
Dit werkt, maar is om een paar redenen niet ideaal:
- Je moet apart een nieuw gesprek hebben aangemaakt.
- Oude berichten worden anders opgemaakt dan nieuwe, omdat ze niet de rolaanduiding (gebruiker of assistent) hebben.
- Je kunt niet schakelen tussen gesprekken.
2. Dynamisch gesprekken aanmaken
Als ik opnieuw begin, maak ik automatisch een nieuw gesprek aan of open ik het meest recente gesprek:
# 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"]
Merk op dat ik de geheime sleutels heb aangepast om meerdere gebruikers te kunnen opslaan. Je zult je .streamlit/geheimen.toml
bestand om dat weer te geven:
[[gebruikers]]
sleutel = "jouw_gebruiker_sleutel
Je kunt dit blok zo vaak herhalen als je wilt, waarbij je gebruikers opslaat als een array van tabellen.
3. Laat gebruikers conversaties aanmaken en wisselen tussen conversaties
Zoals de titel al zegt, wordt er bovenaan een dropdown gemaakt met een knop waarmee je je gesprek kunt kiezen.
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. De juiste rol toewijzen voor berichten uit het verleden
We lossen het opmaakprobleem van hierboven op door de rol van gebruiker of assistent toe te wijzen aan elk van de berichten uit het verleden:
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})
Dit conformeert onze code aan de structuur die Streamlit verwacht.
5. De berichtenlogica toevoegen
Dit is min of meer hetzelfde als voorheen, aangepast voor de nieuwe structuur.
# 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. Maak een gebruiker
De logica is klaar, maar je moet nog een gebruiker aanmaken om de app uit te voeren. Ik heb ervoor gekozen om dit apart toe te voegen om de ervaring van het aanmelden voor een service te simuleren. Gelukkig voor jou heb ik ook een script geschreven:
# 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)
Als je je Chat API ID hebt, kun je het uitvoeren:
python create_user.py -name YOUR_NAME -id SOME_USER_ID -chat_api_id YOUR_CHAT_API_ID
Dit zal de gebruiker aanmaken en toevoegen aan je secrets bestand.
Stap 5: De toepassing uitvoeren
Nu je logica is gebouwd en je gebruiker is aangemaakt, is het tijd om deze applicatie uit te proberen. Installeer de afhankelijkheden en start:
streamlit run app.py
En zo zie je onze bot in al zijn glorie.

Voer vandaag nog een Streamlit chatbot uit
Als je prototypes maakt met Streamlit, weet je dat aanpasbaarheid niet ten koste mag gaan van gebruiksgemak. Chatbots zijn er om problemen op te lossen, niet om ze te creëren.
Botpress wordt geleverd met een visuele drag-and-drop builder, tientallen officiële integraties en toegankelijke API endpoints. Op deze manier kun je bouwen, itereren en implementeren via vele communicatiekanalen.
Begin vandaag nog met bouwen. Het is gratis.