- Streamlit là cách nhanh chóng để xây dựng giao diện chatbot AI tùy chỉnh, nhưng cần linh hoạt hơn ngoài các thành phần chat có sẵn.
- Botpress Chat API cung cấp logic, truy xuất và quy trình cho chatbot, được truy cập qua một client Python tùy chỉnh.
- Ứng dụng Streamlit quản lý hội thoại, truyền tải phản hồi và tích hợp với các phiên người dùng động.
Theo tôi biết, Streamlit là cách nhanh nhất để khởi tạo một web-app có thể tùy chỉnh. Nếu bạn muốn xây dựng chatbot AI và triển khai nó trên giao diện riêng, tôi không nghĩ có lựa chọn nào tốt hơn.
Điểm hạn chế duy nhất là thư viện các thành phần chat. Chúng được thiết kế khá riêng cho API và client Python của OpenAI
Điều này cũng tuyệt vời – chỉ vài dòng mã để tương tác với một trong những công nghệ hàng đầu hiện nay là điều rất đáng giá.
Nhưng như vậy vẫn chưa đủ.
Nếu bạn muốn kiểm soát bot của mình nhiều hơn thì sao? Ví dụ, bạn có thể muốn một quy trình làm việc nhiều bước, hoặc tạo nội dung tăng cường truy xuất (RAG). Những lớp chức năng bổ sung này thường đồng nghĩa với việc phải kết hợp nhiều thư viện với đủ loại phụ thuộc.
Hay sao?
Trong hướng dẫn này, tôi sẽ xây dựng một client chatbot chạy trên Streamlit. Tôi sẽ giới thiệu một giao diện cho chatbot dễ thử nghiệm và cực kỳ linh hoạt. Sau đó, bạn sẽ học cách tích hợp chatbot bằng một client Python tự xây dựng theo kiểu OpenAI.
Nếu bạn đang thử nghiệm, đừng để các phụ thuộc và vấn đề kỹ thuật cản trở bạn.
Và đúng tinh thần thử nghiệm nhanh, nếu bạn muốn bỏ qua hướng dẫn và bắt đầu ngay, mã nguồn có trên GitHub.
Bắt đầu thôi 💣
Bước 1: Xây dựng logic cho Chatbot
Dù là tự động hóa quy trình hay chatbot đặt lịch hẹn, bạn có thể sáng tạo tùy ý ở đây.
Tôi khuyến khích bạn khám phá thêm các trường hợp sử dụng chatbot GenAI nếu cần ý tưởng. Để đơn giản, tôi sẽ tiếp tục với cô trợ lý sommelier nổi tiếng của mình, Winona.
Bot nhỏ thông minh, hữu ích này chỉ cần vài bước để hoàn thiện. Tôi sẽ trình bày ngắn gọn, nhưng bạn có thể xem thêm các hướng dẫn chi tiết, cực kỳ hữu ích.
1. Thêm hướng dẫn cho bot
Trong studio, chúng ta sẽ vào Trang chủ ở thanh bên trái.

Bạn sẽ thấy phần Hướng dẫn ngay chính giữa. Nhấn vào đó để thêm hoặc chỉnh sửa hướng dẫn bằng văn bản.

Phần này giúp bot có chỉ dẫn, cá tính và giới hạn. Chỉ cần ngôn ngữ tự nhiên, bạn có thể điều chỉnh bot theo ý muốn. Hãy làm cho nó thân thiện hơn và
2. Xây dựng Flow
Đây là nơi thể hiện cá tính của bot: truy cập thông tin cụ thể, các bước tuần tự, thực thi mã, v.v.
Đừng đánh giá thấp sức mạnh của sự đơn giản. Một node tự động duy nhất có thể sánh ngang chức năng với các agent suy luận. Tôi đã kết nối một node với Knowledge Base (KB) của mình.

3. Thêm Knowledge Base
Nếu hướng dẫn là về cảm xúc, thì KB là về dữ kiện. Trong trường hợp này, dữ kiện là các loại rượu trong bộ dữ liệu Wine Reviews, gồm danh sách rượu, mô tả và giá. Tôi sẽ dùng nó như kho rượu cho bot sommelier.
Tôi sẽ nhấn vào Tables ở thanh bên trái và chọn New Table ở góc trên bên trái, rồi đặt tên mô tả.

Nhấn vào dấu ba chấm dọc (⋮) ở góc trên bên phải, rồi chọn Import.

Kéo file .csv vào cửa sổ hiện ra và làm theo hướng dẫn trên màn hình.
Để bot truy cập được bảng này, vào Knowledge Bases ở thanh bên trái.

Nhấn vào biểu tượng bảng màu xanh nhỏ và chọn nguồn phù hợp. Nhấn Add tables.

Đảm bảo flow của bạn đã truy cập được Knowledge Base là xong.

Bước 2: Thêm tích hợp Chat API
Điểm kết nối giữa bot và client cục bộ là Chat API. Để thêm vào bot, tôi sẽ cuộn xuống phần Communication Channels và nhấn … More.

Bạn có thể xem qua các tích hợp nếu muốn. Chúng ta cần Chat. Tôi phải cuộn xuống một chút mới thấy.

Nhấn vào tích hợp và chọn Install Integration trong cửa sổ hiện ra.

Sau khi cài đặt, bạn sẽ thấy Chat API ID ở cuối URL webhook. Bạn sẽ cần nó sau.
Bước 3: Viết client Python
Chat API cung cấp nhiều endpoint để thao tác CRUD với người dùng, hội thoại và tin nhắn. Như đã hứa, tôi sẽ gói chúng vào một client Python có thể thay thế client OpenAI.
1. Thêm thông tin xác thực
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,
}
Bạn có thể thêm Chat API ID vào file .env – điều này giúp dễ debug, nhưng không bắt buộc. Chúng ta sẽ xử lý API ID và user key khi xây dựng app Streamlit.
Tôi để BASE_URI và HEADERS trong file constants.py riêng để gọn gàng.
# constants.py
BASE_URI = "https://chat.botpress.cloud"
HEADERS = {
"accept": "application/json",
"Content-Type": "application/json",
}
2. Tạo các phương thức 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")Như đã nói, hầu hết các phương thức này đều tương ứng với một endpoint trong API. Tôi chỉ đóng gói chúng vào một class.
3. Tạo Listener SSE
Đây là phần cần tùy chỉnh. Để lắng nghe cập nhật hội thoại và truyền vào giao diện Streamlit, client cần một phương thức để lắng nghe và trả về server-sent events từ 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"]}Hàm này nhận conversation_id (sẽ được truy cập tự động trong app) và trả về dữ liệu mới khi có.
Bước 4: Tạo ứng dụng Streamlit
Khi đã chuẩn bị xong, giờ là lúc xây dựng chatbot. Lưu ý tôi làm theo hướng dẫn của Streamlit về xây dựng ứng dụng chat LLM – có bổ sung thêm tính năng.
1. Điều chỉnh mã mẫu
Về lý thuyết, bạn có thể chạy app với rất ít thay đổi so với mã mẫu của 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}
)
Ở đây, chúng ta đọc các biến bí mật. Hãy tạo file .streamlit/secrets.toml và đặt biến vào đó:
CHAT_API_ID = ”YOUR_API_ID”
USER_KEY = ”YOUR_USER_KEY”Phần xử lý chính nằm ở:
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}
)
nơi client kết nối với các thành phần chat để gửi và nhận tin nhắn.
Cách này hoạt động, nhưng chưa tối ưu vì một số lý do:
- Bạn phải tạo hội thoại mới riêng biệt.
- Tin nhắn cũ sẽ có định dạng khác tin nhắn mới, vì thiếu thông tin vai trò (user hoặc assistant).
- Bạn không thể chuyển đổi giữa các hội thoại.
2. Tạo hội thoại động
Bắt đầu lại từ đầu, tôi sẽ tự động tạo hội thoại mới hoặc mở hội thoại gần nhất:
# 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"]
Lưu ý tôi đã sửa khóa bí mật để lưu được nhiều người dùng. Bạn nên chỉnh file .streamlit/secrets.toml cho phù hợp:
[[users]]
key = "your_user_key"Bạn có thể lặp lại đoạn này bao nhiêu tùy thích, lưu người dùng dưới dạng mảng bảng.
3. Cho phép người dùng tạo và chuyển đổi hội thoại
Đúng như tiêu đề, phần này tạo một menu thả xuống ở đầu với nút cho phép chọn hội thoại.
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. Gán đúng vai trò cho tin nhắn cũ
Chúng ta sẽ giải quyết vấn đề định dạng ở trên bằng cách gán vai trò user hoặc assistant cho từng tin nhắn cũ:
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})Như vậy mã sẽ đúng với cấu trúc mà Streamlit yêu cầu.
5. Thêm logic gửi tin nhắn
Phần này gần giống trước, chỉ điều chỉnh cho phù hợp cấu trúc mới.
# 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. Tạo người dùng
Logic đã sẵn sàng, nhưng bạn cần tạo người dùng để chạy app. Tôi chọn làm riêng bước này để mô phỏng trải nghiệm đăng ký dịch vụ. May mắn là tôi cũng đã viết sẵn 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)
Chỉ cần có Chat API ID, bạn chạy lệnh:
python create_user.py –name YOUR_NAME –id SOME_USER_ID –chat_api_id YOUR_CHAT_API_ID
Lệnh này sẽ tạo người dùng và thêm vào file secrets của bạn.
Bước 5: Chạy ứng dụng
Sau khi bạn đã xây dựng logic và tạo người dùng, giờ là lúc thử nghiệm ứng dụng này. Cài đặt các thư viện cần thiết và chạy lệnh:
streamlit run app.py
Và chỉ như vậy thôi, bạn sẽ thấy bot của chúng tôi hiện ra đầy đủ.

Chạy chatbot Streamlit ngay hôm nay
Nếu bạn đang tạo mẫu với Streamlit, bạn biết rằng khả năng tùy chỉnh không nên đánh đổi sự tiện lợi. Chatbot được tạo ra để giải quyết vấn đề – không phải gây thêm rắc rối.
Botpress cung cấp trình xây dựng trực quan kéo-thả, hàng chục tích hợp chính thức và các điểm cuối API dễ sử dụng. Nhờ đó, bạn có thể xây dựng, thử nghiệm và triển khai trên nhiều kênh giao tiếp khác nhau.
Bắt đầu xây dựng ngay hôm nay. Miễn phí.
Câu hỏi thường gặp
Tại sao tôi nên chọn Streamlit thay vì các framework giao diện khác để xây dựng chatbot?
Bạn nên chọn Streamlit để xây dựng chatbot nếu muốn một giải pháp nhanh chóng dựa trên Python, cho phép bạn tạo mẫu ứng dụng tương tác nhanh mà không cần chuyên môn về giao diện, vì Streamlit xử lý các thành phần giao diện như khung chat và quản lý trạng thái chỉ với ít mã.
Chatbot Streamlit có phù hợp để sử dụng trong môi trường sản xuất hay chỉ dành cho các bản mẫu thử nghiệm?
Chatbot Streamlit rất phù hợp cho tạo mẫu và công cụ nội bộ, nhưng với các ứng dụng sản xuất hướng đến người dùng với lưu lượng lớn hoặc yêu cầu giao diện nâng cao, bạn có thể cần thêm các lớp như reverse proxy, tăng cường bảo mật và có thể một framework giao diện mạnh mẽ hơn để đáp ứng quy mô.
Mức độ tùy chỉnh giao diện và trải nghiệm của chatbot xây dựng bằng Streamlit như thế nào?
Streamlit cho phép bạn điều chỉnh các yếu tố cơ bản như màu sắc, phông chữ và bố cục, nhưng ít linh hoạt hơn các framework web truyền thống; để có thiết kế thực sự tùy chỉnh, bạn cần nhúng HTML/CSS hoặc JavaScript riêng, việc này có thể thực hiện nhưng sẽ phức tạp hơn so với sử dụng các widget tích hợp sẵn của Streamlit.
Tôi có thể tích hợp chatbot Streamlit vào một trang web hiện có không, hay bắt buộc phải chạy độc lập?
Chatbot Streamlit thường chạy như một ứng dụng web độc lập với URL riêng, nhưng bạn có thể nhúng nó vào website hiện có qua iframe, tuy nhiên cần xử lý vấn đề về giao diện và bảo mật để đảm bảo trải nghiệm liền mạch cho người dùng.
Chi phí triển khai chatbot Streamlit để sử dụng công khai là bao nhiêu?
Triển khai chatbot Streamlit có thể miễn phí nếu lưu trữ cục bộ hoặc trên Streamlit Community Cloud cho các ứng dụng nhỏ, nhưng nếu sử dụng công khai với quy mô lớn, chi phí dao động khoảng 5–50 USD mỗi tháng trên các nền tảng đám mây như Heroku, AWS hoặc DigitalOcean, tùy thuộc vào lưu lượng truy cập và yêu cầu thời gian hoạt động.





.webp)
