- Streamlit ist eine schnelle Möglichkeit, individuelle KI-Chatbot-Benutzeroberflächen zu erstellen, benötigt aber mehr Flexibilität als die eingebauten Chat-Komponenten bieten.
- Die Botpress Chat API steuert die Chatbot-Logik, das Retrieval und die Workflows und wird über einen eigenen Python-Client bereitgestellt.
- Die Streamlit-App verwaltet Konversationen, streamt Antworten und integriert sich in dynamische Benutzersitzungen.
Soweit ich weiß, ist Streamlit der schnellste Weg, um eine anpassbare Web-App auf die Beine zu stellen. Wenn Sie einen KI-Chatbot erstellen und auf Ihrem eigenen Frontend bereitstellen möchten, fällt mir keine bessere Option ein.
Die einzige Einschränkung ist die Chat-Elemente-Bibliothek. Sie ist ziemlich speziell auf die OpenAI-API und den Python-Client abgestimmt.
Das ist auch gut so – mit nur wenigen Codezeilen können Sie mit einer der fortschrittlichsten Technologien arbeiten. Das ist wirklich großartig.
Aber das ist nicht alles.
Was ist, wenn Sie mehr Kontrolle über Ihren Bot haben möchten? Zum Beispiel könnten Sie einen mehrstufigen Workflow oder Retrieval-Augmented Generation (RAG) benötigen. Diese zusätzlichen Funktionsebenen bedeuten normalerweise, dass Sie verschiedene Bibliotheken mit zahlreichen Abhängigkeiten zusammenführen müssen.
Oder etwa nicht?
In diesem Tutorial werde ich einen Streamlit-basierten Chatbot-Client erstellen. Ich zeige Ihnen eine Oberfläche für schnelle Iterationen und hochgradig anpassbare Chatbots. Anschließend erfahren Sie, wie Sie den Chatbot mit einem eigenen, im OpenAI-Stil gehaltenen Python-Client integrieren.
Wenn Sie prototypisieren, sollten Sie sich nicht von Abhängigkeiten und technischen Details aufhalten lassen.
Und im Sinne des schnellen Prototypings: Wenn Sie das Tutorial überspringen und direkt loslegen möchten, finden Sie den Code auf GitHub.
Los geht’s 💣
Schritt 1: Die Chatbot-Logik erstellen
Ob für Workflow-Automatisierung oder einen Terminbuchungs-Chatbot – hier sind Ihnen keine Grenzen gesetzt.
Ich empfehle Ihnen, die Vielzahl an Einsatzmöglichkeiten für GenAI-Chatbots zu erkunden, wenn Sie Inspiration suchen. Zur Vereinfachung verwende ich wieder meinen hoffentlich inzwischen berühmten Sommelier Winona.
Unser raffinierter, hilfreicher kleiner Bot ist in nur wenigen Schritten einsatzbereit. Ich fasse mich kurz, aber es gibt viele ausführliche, sehr hilfreiche Tutorials, die Sie sich anschauen können.
1. Anweisungen geben
Im Studio navigieren wir in der linken Seitenleiste zu Home.

Sie sollten den Bereich Instructions zentral sehen. Klicken Sie darauf, um die Anweisungen als Klartext hinzuzufügen oder zu bearbeiten.

Damit geben wir unserem Bot Vorgaben, Persönlichkeit und Leitplanken. Mit klarer Sprache können Sie das Verhalten Ihres Bots gezielt steuern. Lassen Sie ihn menschlicher klingen und
2. Den Flow bauen
Hier steckt das Herzstück der Bot-Persönlichkeit: Zugriff auf bestimmte Informationen, feste Schrittfolgen, Code-Ausführung usw.
Unterschätzen Sie nicht die Kraft der Einfachheit. Ein einzelner autonomer Knoten kann mit den Fähigkeiten von Reasoning Agents mithalten. Ich habe einen mit meiner Knowledge Base (KB) verbunden.

3. Die Knowledge Base hinzufügen
Wenn die Anweisungen für die Stimmung sorgen, liefert die KB die harten Fakten. In meinem Fall sind das die Weine aus dem Wine Reviews-Datensatz – eine Liste mit Weinen, Beschreibungen und Preisen. Ich nutze das als Wein-Inventar für unseren Sommelier-Bot.
Ich klicke im linken Panel auf Tables und dann oben links auf New Table und gebe der Tabelle einen aussagekräftigen Namen.

Klicken Sie oben rechts auf die vertikale Ellipse (⋮) und wählen Sie Import.

Ziehen Sie Ihre .csv-Datei in das angezeigte Modal und folgen Sie den Anweisungen auf dem Bildschirm.
Damit Ihr Bot auf die Tabelle zugreifen kann, gehen Sie in der linken Seitenleiste zu Knowledge Bases.

Klicken Sie auf das kleine grüne Tabellen-Symbol und wählen Sie die passende Quelle aus. Klicken Sie auf Add tables.

Stellen Sie sicher, dass Ihr Flow Zugriff auf die Knowledge Base hat – dann kann es losgehen.

Schritt 2: Die Chat API integrieren
Die Schnittstelle zwischen Bot und lokalem Client ist die Chat API. Um sie zu Ihrem Bot hinzuzufügen, scrollen Sie zu Kommunikationskanäle und klicken auf … More.

Schauen Sie sich die Integrationen ruhig an. Wir suchen Chat. Ich musste etwas scrollen, um es zu finden.

Klicken Sie auf die Integration und dann im angezeigten Modal auf Install Integration.

Nach der Installation sehen Sie die Chat API ID am Ende der Webhook-URL. Die brauchen Sie später.
Schritt 3: Den Python-Client schreiben
Die Chat API stellt verschiedene Endpunkte bereit, um CRUD-Operationen für Nutzer, Konversationen und Nachrichten durchzuführen. Wie versprochen, fasse ich diese in einem Python-Client zusammen, der einen OpenAI-Client ersetzen kann.
1. Zugangsdaten hinzufügen
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,
}
Sie können Ihre Chat API ID in einer .env-Datei speichern – das hilft beim Debugging, ist aber nicht zwingend nötig. Mit API ID und User Key beschäftigen wir uns beim Bau der Streamlit-App.
Ich halte BASE_URI und HEADERS in einer separaten constants.py-Datei, damit es übersichtlich bleibt.
# constants.py
BASE_URI = "https://chat.botpress.cloud"
HEADERS = {
"accept": "application/json",
"Content-Type": "application/json",
}
2. Die Request-Methoden erstellen
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")Wie erwähnt, entspricht fast jede Methode einem Endpunkt der API. Ich fasse sie nur in einer Klasse zusammen.
3. Einen SSE-Listener erstellen
Das ist der eigentliche Trick: Damit der Client auf Konversations-Updates reagieren und mit dem Streamlit-Frontend kommunizieren kann, braucht er eine Methode, um Server-Sent Events vom Bot zu empfangen und weiterzugeben.
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"]}Diese Funktion nimmt die conversation_id (die innerhalb der App programmatisch abgerufen wird) und gibt eingehende Daten in Echtzeit weiter.
Schritt 4: Die Streamlit-App erstellen
Nachdem alles vorbereitet ist, bauen wir den Chatbot. Ich orientiere mich dabei an Streamlits Anleitung zum Erstellen einer LLM-Chat-App – mit ein paar zusätzlichen Funktionen.
1. Boilerplate-Code anpassen
Theoretisch funktioniert die App mit nur wenigen Änderungen am Beispiel-Code von 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}
)
Hier werden geheime Variablen eingelesen. Legen Sie also eine .streamlit/secrets.toml-Datei an und tragen Sie Ihre Variablen ein:
CHAT_API_ID = ”YOUR_API_ID”
USER_KEY = ”YOUR_USER_KEY”Die eigentliche Logik steckt in:
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}
)
Hier verbindet sich der Client mit den Chat-Elementen, um Nachrichten zu senden und zu empfangen.
Das funktioniert, ist aber aus mehreren Gründen nicht optimal:
- Sie müssen eine neue Konversation separat anlegen.
- Alte Nachrichten werden anders formatiert als neue, weil ihnen die Rollenbezeichnung (user oder assistant) fehlt.
- Sie können nicht zwischen Konversationen wechseln.
2. Konversationen dynamisch erstellen
Von Grund auf erstelle ich automatisch eine neue Konversation oder öffne die zuletzt verwendete:
# 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"]
Beachten Sie, dass ich die geheimen Schlüssel angepasst habe, um mehrere Nutzer speichern zu können. Passen Sie Ihre .streamlit/secrets.toml-Datei entsprechend an:
[[users]]
key = "your_user_key"Sie können diesen Block beliebig oft wiederholen und Nutzer als Array von Tabellen speichern.
3. Nutzer können Konversationen erstellen und zwischen ihnen wechseln
Wie die Überschrift sagt, wird damit oben ein Dropdown mit einem Button erzeugt, mit dem Sie Ihre Konversation auswählen können.
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. Die richtige Rolle für alte Nachrichten zuweisen
Das Formatierungsproblem von oben lösen wir, indem wir jeder alten Nachricht die Rolle user oder assistant zuweisen:
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})Damit entspricht unser Code der Struktur, die Streamlit erwartet.
5. Die Nachrichtenlogik hinzufügen
Das ist im Wesentlichen wie zuvor, nur an die neue Struktur angepasst.
# 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. Einen Nutzer anlegen
Die Logik steht, aber Sie müssen noch einen Nutzer anlegen, um die App zu starten. Ich habe das separat gelöst, um das Anmelden bei einem Dienst zu simulieren. Zum Glück habe ich dafür auch ein Skript geschrieben:
# 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)
Wenn Sie Ihre Chat API ID haben, können Sie Folgendes ausführen:
python create_user.py –name YOUR_NAME –id SOME_USER_ID –chat_api_id YOUR_CHAT_API_ID
Damit wird der Nutzer erstellt und in Ihre secrets-Datei eingetragen.
Schritt 5: Die Anwendung starten
Nachdem Sie Ihre Logik erstellt und Ihren Benutzer angelegt haben, ist es Zeit, die Anwendung auszuprobieren. Installieren Sie die Abhängigkeiten und führen Sie Folgendes aus:
streamlit run app.py
Und schon sehen Sie unseren Bot in voller Pracht.

Starten Sie noch heute einen Streamlit-Chatbot
Wenn Sie mit Streamlit Prototypen erstellen, wissen Sie, dass Anpassbarkeit nicht auf Kosten der Benutzerfreundlichkeit gehen sollte. Chatbots sollen Probleme lösen – nicht verursachen.
Botpress bietet einen visuellen Drag-and-Drop-Builder, zahlreiche offizielle Integrationen und zugängliche API-Endpunkte. So können Sie auf vielen Kommunikationskanälen entwickeln, testen und bereitstellen.
Jetzt loslegen. Kostenlos.
FAQs
Warum sollte ich Streamlit anderen Frontend-Frameworks für den Bau eines Chatbots vorziehen?
Sie würden Streamlit wählen, wenn Sie eine schnelle, Python-basierte Lösung suchen, mit der Sie interaktive Apps ohne Frontend-Kenntnisse schnell prototypisieren können, da Streamlit UI-Elemente wie Chat-Komponenten und Zustandsverwaltung mit minimalem Code übernimmt.
Ist ein Streamlit-Chatbot für den produktiven Einsatz geeignet oder nur für Prototypen?
Ein Streamlit-Chatbot eignet sich hervorragend für Prototypen und interne Tools. Für öffentlich zugängliche Produktivanwendungen mit viel Traffic oder erweitertem Styling benötigen Sie jedoch eventuell zusätzliche Ebenen wie Reverse Proxies, Sicherheitsmaßnahmen und möglicherweise ein robusteres Frontend-Framework, um die Skalierung zu gewährleisten.
Wie anpassbar ist das Erscheinungsbild eines mit Streamlit erstellten Chatbots?
Mit Streamlit können Sie grundlegende Stile wie Farben, Schriftarten und Layout anpassen, aber es ist weniger flexibel als klassische Web-Frameworks. Für wirklich individuelle Designs müssten Sie eigenes HTML/CSS oder JavaScript einbinden, was möglich ist, aber im Vergleich zu den eingebauten Widgets von Streamlit zusätzlichen Aufwand bedeutet.
Kann ich einen Streamlit-Chatbot in eine bestehende Website integrieren oder muss er eigenständig laufen?
Ein Streamlit-Chatbot läuft in der Regel als eigenständige Webanwendung unter einer eigenen URL. Sie können ihn aber per iframe in eine bestehende Website einbetten – dabei müssen Sie jedoch Styling- und Sicherheitsaspekte berücksichtigen, um ein nahtloses Nutzererlebnis zu gewährleisten.
Wie viel kostet es, einen Streamlit-Chatbot öffentlich bereitzustellen?
Die Bereitstellung eines Streamlit-Chatbots kann kostenlos sein, wenn er lokal oder für kleinere Anwendungen auf der Streamlit Community Cloud gehostet wird. Für den öffentlichen Einsatz in größerem Umfang liegen die Kosten jedoch je nach Traffic und Anforderungen an die Verfügbarkeit bei etwa 5–50 USD pro Monat auf Cloud-Plattformen wie Heroku, AWS oder DigitalOcean.





.webp)
