- StreamlitはカスタムAIチャットボットUIを素早く作る方法ですが、組み込みチャットコンポーネント以上の柔軟性が必要です。
- Botpress Chat APIはチャットボットのロジック、検索、ワークフローを提供し、カスタムPythonクライアントから利用できます。
- Streamlitアプリは会話を管理し、レスポンスをストリーミングし、動的なユーザーセッションと統合します。
私の知る限り、Streamlitはカスタマイズ可能なWebアプリを素早く立ち上げる最速の方法です。もし自分のフロントエンドでAIチャットボットを作成して公開したいなら、これ以上の選択肢は思いつきません。
唯一の難点はチャット要素のライブラリです。これらはOpenAIのAPIとPythonクライアント向けに特化されています。
それは素晴らしいことです。数行のコードで最先端の技術に触れられるのは、本当に素晴らしいです。
でも、それだけではありません。
ボットをもっと細かく制御したい場合はどうすればよいでしょうか?たとえば、複数ステップのワークフローや、検索拡張生成(RAG)を利用したい場合などです。こうした機能を追加しようとすると、通常はさまざまな依存関係を持つライブラリを組み合わせる必要があります。
本当にそうでしょうか?
このチュートリアルでは、Streamlit上で動くチャットボットクライアントを作成します。素早く試行できて高いカスタマイズ性を持つチャットボット用インターフェースを紹介し、その後、OpenAI風のカスタムPythonクライアントでチャットボットを統合する方法を解説します。
プロトタイピング中は、依存関係や技術的な細かいことにとらわれる必要はありません。
素早いプロトタイピングの精神で、チュートリアルを飛ばしてすぐ試したい方は、GitHubにコードがあります。
それでは始めましょう 💣
ステップ1:チャットボットのロジックを作成する
ワークフロー自動化でも予約受付チャットボットでも、ここでできることは無限大です。
インスピレーションを探しているなら、GenAIチャットボットの活用例をぜひご覧ください。今回はシンプルに、私の自慢のソムリエWinonaを例にします。
この洗練された便利なボットは、ほんの数ステップで作れます。ここでは簡単に説明しますが、詳しくて役立つチュートリアルもたくさんあります。
1. 指示を与える
スタジオで、左サイドバーのHomeに移動します。

画面中央にInstructionsセクションが表示されているはずです。クリックして、指示文を追加または編集しましょう。

これでボットに指示や性格、ガードレールを与えます。自然な言葉で書くことで、ボットの振る舞いを効果的にコントロールできます。より人間らしい応答にしたり、
2. フローを作成する
ここがボットの個性の中核です。特定情報へのアクセス、厳密なステップ実行、コード実行などができます。
シンプルさの力を侮ってはいけません。単一の自律ノードでも推論エージェントに匹敵する機能を持ちます。私はこれをナレッジベース(KB)に接続しています。

3. ナレッジベースを追加する
指示が雰囲気を決めるものだとすれば、KBは事実を扱います。私の場合、Wine Reviewsデータセットにあるワインのリスト、説明、価格が事実です。これをボットのワイン在庫として扱います。
左パネルのTablesをクリックし、ページ左上のNew Tableを押して、分かりやすい名前を付けます。

右上の縦三点リーダー(⋮)をクリックし、Import.を選択します。

表示されたモーダルに.csvファイルをドラッグし、画面の指示に従ってください。
テーブルをボットから利用できるようにするには、左サイドバーのKnowledge Basesに移動します。

緑色のテーブルアイコンをクリックし、該当するソースを選択します。Add tablesをクリックしてください。

フローがナレッジベースにアクセスできることを確認すれば準備完了です。

ステップ2:Chat API連携を追加する
ボットとローカルクライアントの接点がChat APIです。これをボットに追加するには、Communication Channelsまでスクロールし、… Moreをクリックします。

統合一覧を見てみても良いでしょう。今回はChatを探します。少しスクロールする必要がありました。

統合をクリックし、表示されたモーダルでInstall Integrationを押します。

インストールが完了すると、Webhook URLの末尾にChat API IDが表示されます。後で使うので控えておきましょう。
ステップ3: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,
}
.envファイルにChat API IDを追加しても構いません。デバッグに便利ですが、必須ではありません。API IDとユーザーキーはStreamlitアプリ作成時に扱います。
私は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を受け取り(アプリ内でプログラム的に取得)、発生したデータを逐次出力します。
ステップ4: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}
)
ここでクライアントがチャット要素に接続し、メッセージの送受信を行います。
この方法でも動きますが、いくつか問題があります:
- 新しい会話を別途作成しておく必要があります。
- 古いメッセージは新しいものとフォーマットが異なり、役割(ユーザーかアシスタントか)がありません。
- 会話の切り替えができません。
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. 過去のメッセージに正しい役割を割り当てる
上記のフォーマット問題は、過去の各メッセージにユーザーまたはアシスタントの役割を割り当てることで解決します:
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
これでユーザーが作成され、シークレットファイルに追加されます。
ステップ5:アプリケーションを実行する
ロジックを構築し、ユーザーを作成したら、いよいよこのアプリケーションを実際に動かしてみましょう。依存関係をインストールし、次のコマンドを実行します:
streamlit run app.py
これだけで、ボットがしっかり動作している様子が確認できます。

今日から Streamlit チャットボットを動かしてみましょう
Streamlit でプロトタイプを作成している場合、カスタマイズ性が利便性を損なうべきではありません。チャットボットは問題を解決するためのものであり、新たな問題を生み出すものではありません。
Botpress にはビジュアルなドラッグ&ドロップビルダー、公式インテグレーションが多数、そして使いやすい API エンドポイントが備わっています。これにより、さまざまなコミュニケーションチャネルで構築・反復・デプロイが可能です。
今すぐ構築を始めましょう。無料です。
よくある質問
チャットボットを作る際、他のフロントエンドフレームワークではなく Streamlit を選ぶ理由は?
フロントエンドの専門知識がなくても、チャットコンポーネントや状態管理などの UI 要素を最小限のコードで扱えるため、素早くインタラクティブなアプリをプロトタイプしたい場合は、Python ベースの Streamlit が最適です。
Streamlitのチャットボットは本番環境でも使えますか、それともプロトタイプ向けですか?
Streamlit チャットボットはプロトタイプや社内ツールには最適ですが、外部公開や高トラフィック、より高度なデザインが必要な場合は、リバースプロキシやセキュリティ強化、より堅牢なフロントエンドフレームワークの導入など追加の対応が必要になることがあります。
Streamlitで作成したチャットボットの見た目やデザインはどの程度カスタマイズできますか?
Streamlit では色やフォント、レイアウトなど基本的なスタイル調整は可能ですが、従来の Web フレームワークほど柔軟ではありません。完全にカスタムなデザインにしたい場合は、HTML/CSS や JavaScript を埋め込む必要があり、Streamlit の標準ウィジェットだけを使うよりも複雑になります。
Streamlitチャットボットは既存のウェブサイトに組み込めますか、それとも単体で動作させる必要がありますか?
Streamlit チャットボットは通常、独立したウェブアプリとして専用の URL で動作しますが、iframe を使って既存のウェブサイトに埋め込むことも可能です。ただし、その場合はスタイルやセキュリティ面での調整が必要となり、ユーザーにとって違和感のない体験を提供する工夫が求められます。
Streamlitチャットボットを一般公開用にデプロイする場合、費用はどれくらいかかりますか?
Streamlitチャットボットのデプロイは、ローカルやStreamlit Community Cloudで小規模なアプリとしてホストする場合は無料で行えます。ただし、一般公開や大規模運用の場合は、Heroku、AWS、DigitalOceanなどのクラウドプラットフォームでは、トラフィックや稼働時間の要件によって月額約5ドル〜50ドル程度の費用がかかります。





.webp)
