- Streamlit to szybki sposób na budowanie własnych interfejsów czatbotów AI, ale wymaga większej elastyczności niż oferują wbudowane komponenty czatu.
- Botpress Chat API odpowiada za logikę czatbota, wyszukiwanie i przepływy, udostępniane przez niestandardowego klienta Pythona.
- Aplikacja Streamlit zarządza rozmowami, przesyła odpowiedzi strumieniowo i integruje się z dynamicznymi sesjami użytkowników.
O ile mi wiadomo, Streamlit to najszybszy sposób na uruchomienie konfigurowalnej aplikacji webowej. Jeśli chcesz zbudować AI chatbota i wdrożyć go na własnym froncie, nie znam lepszej opcji.
Jedynym ograniczeniem jest biblioteka elementów czatu. Są one dość mocno dostosowane do API OpenAI i klienta Pythona.
To świetne – kilka linijek kodu, by korzystać z jednej z najbardziej prestiżowych technologii dostępnych na rynku, to naprawdę spora zaleta.
Ale to nie wszystko.
A co jeśli chcesz mieć większą kontrolę nad swoim botem? Na przykład możesz potrzebować wieloetapowego procesu lub generowania wspomaganego wyszukiwaniem (RAG). Te dodatkowe funkcje zwykle oznaczają konieczność łączenia różnych bibliotek z wieloma zależnościami.
A może jednak nie?
W tym poradniku zbuduję klienta chatbota hostowanego na Streamlit. Pokażę ci interfejs do szybkiego iterowania i pełnej personalizacji chatbotów. Następnie nauczysz się integrować chatbota za pomocą własnego klienta Pythona w stylu OpenAI.
Jeśli prototypujesz, zależności i technikalia nie powinny cię ograniczać.
A jeśli chcesz pominąć poradnik i od razu zacząć eksperymentować, kod znajdziesz na GitHubie.
Do dzieła 💣
Krok 1: Zbuduj logikę chatbota
Niezależnie od tego, czy chodzi o automatyzację procesów, czy chatbota do rezerwacji wizyt – masz tu pełną dowolność.
Zachęcam do zapoznania się z szerokim zakresem zastosowań chatbotów GenAI, jeśli szukasz inspiracji. Dla uproszczenia, wrócę do mojego – mam nadzieję już słynnego – sommeliera Winony.
Nasz zaawansowany, pomocny bot może powstać w kilku prostych krokach. Będę zwięzły – możesz znaleźć dłuższe, bardzo pomocne poradniki na ten temat.
1. Nadaj instrukcje
W studio przejdziemy do Home w lewym pasku bocznym.

Powinieneś zobaczyć sekcję Instructions na środku ekranu. Kliknij ją, aby dodać lub zmodyfikować instrukcje w formie tekstowej.

To nadaje naszemu botowi wytyczne, osobowość i ograniczenia. Używając prostego języka, możesz skutecznie ukierunkować bota na pożądane zachowanie. Spraw, by brzmiał bardziej naturalnie i
2. Zbuduj przepływ
Tu znajduje się sedno osobowości bota: dostęp do konkretnych informacji, sztywne kroki, wykonywanie kodu itp.
Nie lekceważ siły prostoty. Jeden autonomiczny węzeł może dorównać funkcjonalności agentów rozumujących. Ja mam taki podłączony do mojej Bazy Wiedzy (KB).

3. Dodaj bazę wiedzy
Jeśli instrukcje to klimat, KB to twarde fakty. W moim przypadku są to dane o winach z Wine Reviews dataset – lista win, opisów i cen. Potraktuję to jako domyślną bazę win dla naszego bota-sommeliera.
Klikam Tables w lewym panelu, wybieram New Table w lewym górnym rogu strony i nadaję jej opisową nazwę.

Kliknij pionowe wielokropki (⋮) w prawym górnym rogu i wybierz Import.

Przeciągnij plik .csv do pojawiającego się okna i postępuj zgodnie z instrukcjami na ekranie.
Aby tabela była dostępna dla bota, przejdź do Knowledge Bases w lewym pasku bocznym.

Kliknij zieloną ikonę tabeli i wybierz odpowiednie źródło. Następnie kliknij Add tables.

Upewnij się, że twój flow ma dostęp do Bazy Wiedzy – i gotowe.

Krok 2: Dodaj integrację z Chat API
Punktem styku między botem a lokalnym klientem jest Chat API. Aby dodać je do bota, przewiń do Kanałów Komunikacji i kliknij … More.

Możesz przejrzeć dostępne integracje. Szukamy Chat. Musiałem trochę przewinąć, żeby ją znaleźć.

Kliknij integrację i wybierz Install Integration w pojawiającym się oknie.

Po instalacji zobaczysz Chat API ID na końcu adresu webhooka. Będzie ci potrzebny później.
Krok 3: Napisz klienta w Pythonie
Chat API udostępnia kilka endpointów do operacji CRUD na użytkownikach, rozmowach i wiadomościach. Zgodnie z obietnicą, opakuję je w klienta Pythona, który może zastąpić klienta OpenAI.
1. Dodaj swoje dane dostępowe
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,
}
Możesz dodać Chat API ID do pliku .env – ułatwia to debugowanie, ale nie jest konieczne. Zajmiemy się API ID i kluczem użytkownika podczas budowy aplikacji Streamlit.
Trzymam BASE_URI i HEADERS w osobnym pliku constants.py, żeby nie robić bałaganu.
# constants.py
BASE_URI = "https://chat.botpress.cloud"
HEADERS = {
"accept": "application/json",
"Content-Type": "application/json",
}
2. Utwórz metody żądań
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")Jak wspomniałem, prawie wszystkie odpowiadają endpointom API. Po prostu opakowuję je w klasę.
3. Utwórz nasłuchiwacz SSE
To cała „magia”. Aby nasłuchiwać aktualizacji rozmowy i przekazywać je do frontu Streamlit, klient potrzebuje metody do odbierania i przekazywania zdarzeń wysyłanych przez serwer od naszego bota.
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"]}Ta funkcja przyjmuje conversation_id (które będzie pobierane programowo w aplikacji) i przekazuje dane na bieżąco.
Krok 4: Stwórz aplikację Streamlit
Gdy wszystko gotowe, czas zbudować chatbota. Korzystam z przewodnika Streamlit o budowaniu aplikacji czatu LLM – z kilkoma dodatkami.
1. Dostosuj kod bazowy
Teoretycznie aplikacja zadziała przy minimalnych zmianach w kodzie bazowym z przykładu 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}
)
Odczytujemy tu zmienne tajne. Utwórz plik .streamlit/secrets.toml i umieść tam swoje zmienne:
CHAT_API_ID = ”YOUR_API_ID”
USER_KEY = ”YOUR_USER_KEY”Najważniejsze rzeczy dzieją się w:
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}
)
gdzie klient łączy się z elementami czatu, by wysyłać i odbierać wiadomości.
To działa, ale nie jest idealne z kilku powodów:
- Musisz osobno utworzyć nową rozmowę.
- Stare wiadomości będą inaczej formatowane niż nowe, bo nie mają przypisanej roli (user lub assistant).
- Nie możesz przełączać rozmów.
2. Twórz rozmowy dynamicznie
Od zera – automatycznie utworzę nową rozmowę lub otworzę najnowszą:
# 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"]
Zwróć uwagę, że zmodyfikowałem klucze tajne, by móc przechowywać wielu użytkowników. Zmień swój plik .streamlit/secrets.toml odpowiednio:
[[users]]
key = "your_user_key"Możesz powtarzać ten blok dowolnie, przechowując użytkowników jako tablicę tabel.
3. Pozwól użytkownikom tworzyć i przełączać rozmowy
Jak w nagłówku – to tworzy rozwijane menu na górze z przyciskiem do wyboru rozmowy.
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. Przypisz odpowiednią rolę do wcześniejszych wiadomości
Rozwiążemy problem formatowania, przypisując rolę user lub assistant do każdej wcześniejszej wiadomości:
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})To dostosowuje nasz kod do struktury oczekiwanej przez Streamlit.
5. Dodaj logikę wysyłania wiadomości
To praktycznie to samo co wcześniej, tylko dostosowane do nowej struktury.
# 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. Utwórz użytkownika
Logika jest gotowa, ale musisz utworzyć użytkownika, by uruchomić aplikację. Ja dodałem to osobno, by zasymulować proces rejestracji. Mam dla ciebie gotowy skrypt:
# 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)
Mając Chat API ID, możesz uruchomić:
python create_user.py –name TWOJE_IMIĘ –id JAKIEŚ_USER_ID –chat_api_id TWÓJ_CHAT_API_ID
To utworzy użytkownika i doda go do pliku secrets.
Krok 5: Uruchom aplikację
Gdy Twoja logika jest już gotowa, a użytkownik utworzony, czas przetestować aplikację. Zainstaluj wymagane zależności i uruchom:
streamlit run app.py
I właśnie tak zobaczysz naszego bota w pełnej okazałości.

Uruchom chatbota w Streamlit już dziś
Jeśli tworzysz prototypy w Streamlit, wiesz, że możliwość dostosowania nie powinna odbywać się kosztem wygody. Chatboty mają rozwiązywać problemy – nie je tworzyć.
Botpress oferuje wizualny kreator typu przeciągnij i upuść, dziesiątki oficjalnych integracji oraz dostępne punkty końcowe API. Dzięki temu możesz budować, testować i wdrażać na wielu kanałach komunikacji.
Zacznij budować już dziś. To nic nie kosztuje.
Najczęstsze pytania
Dlaczego miałbym wybrać Streamlit zamiast innych frameworków front-endowych do budowy chatbota?
Warto wybrać Streamlit do budowy chatbota, jeśli zależy Ci na szybkim, opartym na Pythonie rozwiązaniu, które pozwala szybko prototypować interaktywne aplikacje bez konieczności znajomości front-endu, ponieważ Streamlit sam obsługuje elementy interfejsu, takie jak komponenty czatu i zarządzanie stanem, przy minimalnej ilości kodu.
Czy chatbot oparty na Streamlit nadaje się do zastosowań produkcyjnych, czy tylko do prototypów?
Chatbot w Streamlit świetnie sprawdzi się w prototypach i narzędziach wewnętrznych, ale do aplikacji produkcyjnych dostępnych publicznie, z dużym ruchem lub zaawansowanym wyglądem, możesz potrzebować dodatkowych warstw, takich jak reverse proxy, wzmocnienie bezpieczeństwa i być może bardziej rozbudowanego frameworka front-endowego, aby obsłużyć skalę.
Jak bardzo można dostosować wygląd i styl chatbota stworzonego w Streamlit?
Streamlit pozwala zmieniać podstawowe elementy wyglądu, takie jak kolory, czcionki i układ, ale jest mniej elastyczny niż tradycyjne frameworki webowe; aby uzyskać naprawdę indywidualny design, trzeba osadzić własny kod HTML/CSS lub JavaScript, co jest możliwe, ale bardziej skomplikowane niż korzystanie z wbudowanych widżetów Streamlit.
Czy mogę zintegrować chatbota Streamlit z istniejącą stroną internetową, czy musi działać samodzielnie?
Chatbot w Streamlit zwykle działa jako samodzielna aplikacja webowa pod własnym adresem URL, ale można go osadzić na istniejącej stronie przez iframe – wymaga to jednak zadbania o wygląd i bezpieczeństwo, by zapewnić użytkownikom spójne doświadczenie.
Ile kosztuje wdrożenie chatbota Streamlit do publicznego użytku?
Wdrożenie chatbota Streamlit może być bezpłatne, jeśli jest hostowany lokalnie lub na Streamlit Community Cloud dla mniejszych aplikacji, ale w przypadku publicznego użytku na większą skalę koszty wahają się od około 5 do 50 USD miesięcznie na platformach chmurowych, takich jak Heroku, AWS czy DigitalOcean, w zależności od ruchu i wymagań dotyczących dostępności.





.webp)
