- Streamlit 是打造自訂 AI 聊天機器人介面的快速工具,但若要超越內建聊天元件,還需要更多彈性。
- Botpress Chat API 提供聊天機器人的邏輯、檢索與工作流程,並透過自訂 Python 客戶端對外開放。
- Streamlit 應用程式負責管理對話、串流回應,並整合動態使用者會話。
就我所知,Streamlit 是目前最快能打造可自訂網頁應用程式的方式。如果你想要建立 AI 聊天機器人並部署在自己的前端,我想不到比這更好的選擇了。
唯一的限制是聊天元件庫。它們主要針對 OpenAI 的 API 和 Python 客戶端設計。
這其實很棒——只要幾行程式碼就能與頂尖技術互動,真的很方便。
但這還不是全部。
如果你想要對你的機器人有更多控制權怎麼辦?例如,你可能需要一個多步驟的工作流程,或是檢索增強生成(RAG)。這些額外的功能通常意味著要整合各種有不同相依性的函式庫。
還是其實不需要這麼做?
這篇教學會帶你打造一個以 Streamlit 為主機的聊天機器人客戶端。我會展示一個能快速迭代且高度自訂的聊天機器人介面。接著,你會學到如何用自製的 OpenAI 風格 Python 客戶端整合這個聊天機器人。
如果你正在做原型,依賴與技術細節不該成為你的阻礙。
而且,為了快速原型開發,如果你想跳過教學直接動手玩,程式碼已經放在 GitHub。
直接開炸 💣
步驟一:建立聊天機器人邏輯
不論是用來自動化工作流程,還是預約訂位聊天機器人,這裡的應用真的無限大。
如果你需要靈感,建議你多看看GenAI 聊天機器人的各種應用案例。為了簡單起見,我會用我那應該已經小有名氣的侍酒師 Winona 當例子。
我們這個聰明又貼心的小機器人只要幾個步驟就能完成。我會簡單帶過,但你也可以參考其他更詳細又超實用的教學。
1. 設定指令
在 Studio 介面左側邊欄,點選首頁。

你應該會看到指令區塊在正中央。點進去就能新增或修改純文字指令。

這能為機器人設定指引、個性與行為界線。用簡單的語言,就能有效引導機器人表現出你想要的行為。讓它聽起來更像真人,還有——
2. 建立流程
這裡就是機器人個性的核心:存取特定資訊、嚴謹的步驟流程、執行程式碼等等。
別小看簡單的力量。一個自動節點就能媲美推理代理的功能。我就有一個連接到我的知識庫(KB)。

3. 新增知識庫
如果說指令決定氛圍,知識庫就是冷冰冰的事實。以我為例,知識庫內容來自Wine Reviews 資料集,裡面有酒款、描述和價格。我會把它當作我們機器人的酒品庫存。
我會點選左側面板的資料表,然後在頁面左上角按新增資料表,並取個有意義的名字。

點選右上角的垂直省略號(⋮),然後選匯入。

把你的 .csv 檔拖進彈窗,然後依照畫面指示操作。
要讓機器人能存取這個資料表,請到左側邊欄的知識庫。

點一下綠色的資料表圖示,選擇對應來源,再按新增資料表。

確認你的流程有存取知識庫的權限就可以了。

步驟二:加入 Chat API 整合
機器人和本地端客戶端的連接點就是 Chat API。要把它加進機器人,我會捲動到通訊管道,然後點… 更多。

你可以瀏覽各種整合選項。我們要找的是Chat。我還花了一點時間才找到。

點選整合,然後在彈窗中按安裝整合。

安裝完成後,你會在 webhook URL 的最後看到Chat API ID。這等等會用到。
步驟三:撰寫 Python 客戶端
Chat API 提供多個端點,能對使用者、對話和訊息進行CRUD 操作。如前所述,我會把這些包成一個可以取代 OpenAI 客戶端的 Python 客戶端。
1. 加入你的憑證
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,
}
你可以把 Chat API ID 加到 .env 檔——這有助於除錯,但不是必要步驟。我們會在建立 Streamlit 應用時處理 API ID 和使用者金鑰。
我會把BASE_URI 和 HEADERS 放在獨立的 constants.py 檔案,讓程式碼更整齊。
# constants.py
BASE_URI = "https://chat.botpress.cloud"
HEADERS = {
"accept": "application/json",
"Content-Type": "application/json",
}
2. 建立請求方法
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")如前所述,這些方法幾乎都對應 API 的端點。我只是把它們包進一個類別。
3. 建立 SSE 監聽器
這就是所有小技巧的精華。為了監聽對話更新並串接到 Streamlit 前端,客戶端需要一個方法來監聽並傳回來自機器人的伺服器推送事件。
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"]}這個函式會接收 conversation_id(應用程式內會自動取得),並即時傳回收到的資料。
步驟四:建立 Streamlit 應用程式
一切就緒後,該來打造聊天機器人了。這裡我會參考 Streamlit 的LLM 聊天應用程式教學,並加上一些進階功能。
1. 調整範本程式碼
理論上,你只要對 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}
)
這裡我們會讀取秘密變數。請建立 .streamlit/secrets.toml 檔,並把變數放進去:
CHAT_API_ID = ”YOUR_API_ID”
USER_KEY = ”YOUR_USER_KEY”主要的處理都在這裡:
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}
)
這裡客戶端會連接聊天元件,負責傳送和接收訊息。
這樣雖然可行,但還是有幾個缺點:
- 你必須另外建立新對話。
- 舊訊息和新訊息格式不同,因為缺少角色標記(user 或 assistant)。
- 你沒辦法切換對話。
2. 動態建立對話
從頭開始時,我會自動建立新對話或開啟最近的一個:
# 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"]
請注意,我已經修改秘密金鑰,能儲存多個使用者。你需要修改.streamlit/secrets.toml 檔來反映這個設定:
[[users]]
key = "your_user_key"你可以重複這段設定,將使用者儲存為資料表陣列。
3. 讓使用者建立並切換對話
如標題所示,這會在頂部建立一個下拉選單和按鈕,讓你選擇要用的對話。
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. 為過去訊息指派正確角色
我們會透過為每則舊訊息指派 user 或 assistant 角色,來解決前述格式問題:
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})這樣就能讓程式碼符合 Streamlit 預期的結構。
5. 加入訊息傳遞邏輯
這部分和之前大致相同,只是調整成新的結構。
# 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. 建立使用者
邏輯都準備好了,但你還需要建立一個使用者才能執行應用程式。我選擇另外處理這步,模擬註冊服務的流程。幸好我也寫了一個腳本:
# 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)
只要你有 Chat API ID,就能執行:
python create_user.py –name YOUR_NAME –id SOME_USER_ID –chat_api_id YOUR_CHAT_API_ID
這會幫你建立使用者並加到 secrets 檔案裡。
步驟五:執行應用程式
當你的邏輯建構完成且使用者已建立後,就是時候來實際運行這個應用程式了。請安裝相關依賴,然後執行:
streamlit run app.py
就這麼簡單,你就能看到我們的機器人完整呈現。

今天就來運行一個 Streamlit 聊天機器人
如果你正在用 Streamlit 做原型設計,你會知道自訂化不該犧牲便利性。聊天機器人的目的是解決問題——不是製造更多問題。
Botpress 提供視覺化拖拉式建構器、數十種官方整合,以及易於存取的 API 端點。這樣你就能在多種通訊管道上建構、反覆調整並部署。
立即開始打造。免費使用。
常見問題
為什麼我會選擇 Streamlit 而不是其他前端框架來打造聊天機器人?
如果你想用 Python 快速打造互動式應用程式,又不想花時間在前端技術上,Streamlit 是很好的選擇。它能用最少的程式碼處理聊天元件和狀態管理,讓你快速做出原型。
Streamlit 聊天機器人適合用於正式環境,還是只適合做原型?
Streamlit 聊天機器人很適合做原型或內部工具,但如果要做大量流量或需要進階樣式的公開應用,可能還需要加上反向代理、安全強化,甚至選擇更穩定的前端框架來因應規模。
用 Streamlit 建立的聊天機器人在外觀和風格上可以自訂到什麼程度?
Streamlit 可以調整基本樣式,例如顏色、字型和版面配置,但彈性比傳統網頁框架低;如果要完全自訂設計,需嵌入自訂 HTML/CSS 或 JavaScript,這雖然可行,但比直接用 Streamlit 的內建元件來得複雜。
我可以把 Streamlit 聊天機器人整合到現有網站嗎?還是只能獨立運作?
Streamlit 聊天機器人通常是獨立網頁應用程式,有自己的網址,但你也可以透過 iframe 嵌入到現有網站。不過這樣需要特別處理樣式和安全性,才能讓使用者有無縫的體驗。
將 Streamlit 聊天機器人部署給公眾使用需要多少費用?
如果在本地或 Streamlit Community Cloud 上部署小型應用,Streamlit 聊天機器人可以免費使用;但若要大規模公開使用,根據流量和運作時間需求,在 Heroku、AWS 或 DigitalOcean 等雲端平台,每月費用大約落在 5~50 美元之間。





.webp)
