【Streamlit】生成AIチャットアプリを構築しよう

Streamlit
この記事は約16分で読めます。

こんにちは、JS2IIUです。
Streamlitは、Pythonでインタラクティブなウェブアプリケーションを簡単に作成できるフレームワークです。データサイエンスや機械学習の分野で人気ですが、Chat elementsとst.session_stateを活用することで、ChatGPTのような本格的なチャットアプリも開発できます。

この記事では、st.chat_message()st.chat_input()、そしてst.session_stateを使い、さらには生成AIのChatGPTも活用し、チャットアプリを構築する方法をステップバイステップで解説します。今回もよろしくお願いします。

Chat elementsの紹介

st.chat_message()

st.chat_message() は、チャットのメッセージを表示する関数です。

  • シグネチャ:st.chat_message(name, *, avatar=None)
  • name:メッセージの送信者名。
  • avatar:送信者のアバター画像のURL。

サンプルプログラム:

Python
import streamlit as st

# ユーザーからのメッセージ
with st.chat_message("user", avatar="https://www.gravatar.com/avatar/HASH"):
    st.write('Hello, this is JS2IIU.🖐️')

# アシスタントからのメッセージ
with st.chat_message("assistant"):
    st.write('Hi, how are you?')

st.chat_input()

st.chat_input() は、チャットの入力欄を表示する関数です。

  • シグネチャ:st.chat_input(placeholder="Your message", *, key=None, max_chars=None, disabled=False, on_submit=None, args=None, kwargs=None)
  • placeholder:入力欄に表示するプレースホルダーテキスト。
  • key:ウィジェットの識別子。
  • max_chars:入力可能な最大文字数。
  • disabled:入力欄を無効にするかどうか。
  • on_submit:送信ボタンがクリックされたときに実行するコールバック関数。

サンプルプログラム:

Python
import streamlit as st

user_input = st.chat_input("Enter your message here...")
if user_input:
  st.write(f"You said: {user_input}")

st.session_stateの説明

st.session_stateは、Streamlitアプリケーション内で変数の値をセッション全体にわたって保持するための仕組みです。これにより、ユーザーの入力やアプリケーションの状態を維持することができます。

  • st.session_stateは辞書のように扱えます。
  • 初期値を設定しない場合、キーに対応する値は存在しません。
  • セッションがアクティブな間は、st.session_stateに保存された値は保持されます。

サンプルプログラム:

Python
import streamlit as st

if "count" not in st.session_state:
    st.session_state.count = 0

st.button("Increment", on_click=lambda: st.session_state.update({"count": st.session_state.count + 1}))
st.write(st.session_state.count)

このプログラムでは、ボタンをクリックするたびにst.session_state.countの値が1ずつ増加し、その値が表示されます。

サンプルプログラム

以下のサンプルプログラムは、StreamlitでChatGPT風のチャットアプリを実現するものです。

Python
import streamlit as st

# セッションステートを初期化
if "messages" not in st.session_state:
    st.session_state.messages = []

# メッセージ履歴を表示
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

# ユーザーからの入力を受け取る
if prompt := st.chat_input("What is up?"):
    # ユーザーのメッセージを履歴に追加
    st.session_state.messages.append({"role": "user", "content": prompt})
    # チャットメッセージとして表示
    with st.chat_message("user"):
        st.markdown(prompt)

    # AIからの応答を生成 (ここでは例としてユーザーの入力をそのまま返す)
    response = f"Echo: {prompt}"

    # AIのメッセージを履歴に追加
    st.session_state.messages.append({"role": "assistant", "content": response})
    # チャットメッセージとして表示
    with st.chat_message("assistant"):
        st.markdown(response)

サンプルプログラムの解説

  1. セッションステートの初期化: st.session_state を使用して、チャットのメッセージ履歴を messages というキーで保存します。
  2. メッセージ履歴の表示: st.session_state.messages に保存されたメッセージをループ処理し、 st.chat_message() を使用して表示します。
  3. ユーザーからの入力を受け取る: st.chat_input() を使用してユーザーからの入力を受け取ります。
  4. ユーザーのメッセージを履歴に追加: ユーザーが入力したメッセージを st.session_state.messages に追加します。
  5. AIからの応答を生成: ここでは例として、ユーザーの入力をそのまま返すシンプルな処理をしています。実際のアプリケーションでは、OpenAI APIなどを利用してAIの応答を生成します。
  6. AIのメッセージを履歴に追加: 生成されたAIの応答を st.session_state.messages に追加します。

ChatGPTの実装

上のサンプルでは、AIからの返事が返ってくるところを省略していました。OpenAIのAPIを使ってgpt-4oと会話できるようにしていきます。

OpenAIへの登録、API Keyの取得

コードを実行するにはOpenAIのAPI KEYが必要です。入手するためにはOpenAIに登録して、KEYを生成するところまでいくつかステップがあります。詳しく解説している良記事がたくさんあります。いくつか挙げておきますので、これらを参照して、API KEYを取得して下さい。APIの使用に対しては従量制で費用が発生しますのでご注意ください。

openaiのインストール

PythonからOpenAIのAPIを使うためのパッケージをインストールします。

Bash
pip install openai

インストールが成功するとこのような表示が出ます。

Plaintext
Successfully installed distro-1.9.0 httpcore-1.0.7 httpx-0.28.1 jiter-0.8.2 openai-1.59.3 tqdm-4.67.1

サンプルコード

サンプルコードを示します。

5行目のapikey=のところにはOpenAIで入手したAPI KEYを入れて下さい。実際のキーはsk-から始まる長い文字列です。以下のようにAPI KEYがダブルクォーテーションで囲まれた形にして下さい。

Python
api_key="sk-proj-abcdefg-******"

OpenAIの生成AIモデルはgpt-4o-miniを使っています。用途とコストのバランスで色々と選べます。この記事は2025年1月時点のものです。今後次々と新しい、より良いモデルが出てくると思いますので、こちらのページを見てどのようなモデルが使えるかを確認してみて下さい。Models – OpenAI API

Just a moment...
Python
import streamlit as st
from openai import OpenAI

# OpenAIクライアントを生成
client = OpenAI(api_key="YOUR API KEY HERE")  # ここにあなたのAPIキーを入力してください

# セッションステートを初期化
if "messages" not in st.session_state:
    st.session_state.messages = []

# メッセージ履歴を表示
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

# ユーザーからの入力を受け取る
if prompt := st.chat_input("What is up?"):
    # ユーザーのメッセージを履歴に追加
    st.session_state.messages.append({"role": "user", "content": prompt})
    # チャットメッセージとして表示
    with st.chat_message("user"):
        st.markdown(prompt)

    # OpenAI APIを使ってAIからの応答を生成
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            *st.session_state.messages,
        ]
    )
    response_content = response.choices[0].message.content

    # AIのメッセージを履歴に追加
    st.session_state.messages.append({"role": "assistant", "content": response_content})
    # チャットメッセージとして表示
    with st.chat_message("assistant"):
        st.markdown(response_content)

動作確認の様子

実際に動作させてみた様子を動画でみていきます。最初は英語で問いかけてみました。

日本語でも同様に動作しています。

サンプルコードの解説

ステップバイステップで解説していきましょう。

1. 必要なライブラリをインポート

Python
import streamlit as st
from openai import OpenAI
  • streamlit : ユーザーインターフェースを構築するためのライブラリです。
  • openai : OpenAIのAPIにアクセスするためのライブラリです。

2. OpenAIクライアントを生成

Python
client = OpenAI(api_key="YOUR API KEY HERE")  # ここにあなたのAPIキーを入力してください
  • OpenAI(api_key="YOUR API KEY HERE") でOpenAIのAPIにアクセスするためのクライアントオブジェクトを生成します。
  • YOUR API KEY HERE の部分を、ご自身のOpenAI APIキーに置き換えてください。

3. セッションステートを初期化

Python
if "messages" not in st.session_state:
    st.session_state.messages = []
  • st.session_state は、Streamlitが提供するセッション状態管理機能です。
  • このコードでは、messages というキーでチャットのメッセージ履歴をリストとして保存します。
  • if "messages" not in st.session_state: で、セッション状態に messages が存在しない場合(つまり、アプリが初めて起動された場合)に、空のリスト []st.session_state.messages に代入して初期化しています。

4. メッセージ履歴を表示

Python
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])
  • st.session_state.messages に保存されているメッセージ履歴を for ループで一つずつ取り出します。
  • 各メッセージについて、st.chat_message(message["role"]) を使ってチャットメッセージを表示します。
    • message["role"] は、メッセージの送信者が “user” か “assistant” かを示します。
  • st.markdown(message["content"]) で、メッセージの内容をMarkdown形式で表示します。

5. ユーザーからの入力を受け取る

Python
if prompt := st.chat_input("What is up?"):
    # ユーザーのメッセージを履歴に追加
    # ...
  • st.chat_input("What is up?") で、”What is up?” というプレースホルダーテキストを持つチャット入力欄を表示します。
  • ユーザーが入力して送信ボタンを押すと、入力されたテキストが prompt に代入されます。
  • if prompt := ... は、prompt に値が入力された場合にのみ、以降の処理を実行することを意味します。

6. ユーザーのメッセージを履歴に追加

Python
    st.session_state.messages.append({"role": "user", "content": prompt})
  • ユーザーが入力した prompt を、{"role": "user", "content": prompt} という辞書形式で st.session_state.messages に追加します。
  • これにより、メッセージ履歴にユーザーの入力が保存されます。

7. ユーザーのメッセージを表示

Python
    with st.chat_message("user"):
        st.markdown(prompt)
  • st.chat_message("user") を使って、ユーザーのメッセージをチャット画面に表示します。

8. OpenAI APIを使ってAIからの応答を生成

Python
    response = client.chat.completions.create(
        model="gpt-4o-mini", 
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            *st.session_state.messages,
        ]
    )
    response_content = response.choices[0].message.content
  • client.chat.completions.create(...) で、OpenAIのAPIを呼び出してAIからの応答を生成します。
    • model="gpt-4o-mini" : 使用する言語モデルをGPT-4o-miniに指定します。
    • messages=[...] : AIに渡すメッセージのリストを指定します。
      • {"role": "system", "content": "You are a helpful assistant."} は、AIの役割を「役に立つアシスタント」として設定します。
      • *st.session_state.messages で、これまでのメッセージ履歴をすべてAIに渡します。これにより、AIは過去の会話の流れを踏まえて応答を生成できます。
  • response.choices[0].message.content で、APIのレスポンスからAIが生成したテキストを取り出します。

9. AIのメッセージを履歴に追加

Python
    st.session_state.messages.append({"role": "assistant", "content": response_content})
  • AIが生成した response_content を、{"role": "assistant", "content": response_content} という辞書形式で st.session_state.messages に追加します。

10. AIのメッセージを表示

Python
    with st.chat_message("assistant"):
        st.markdown(response_content)
  • st.chat_message("assistant") を使って、AIのメッセージをチャット画面に表示します。

これで、ユーザーが入力したメッセージに対して、GPT-4が応答を生成し、チャット形式で表示されるアプリケーションが完成します。

さらに改良したい方

ChatGPTのWEBサイトのように、パラパラと徐々に文字が表示されて、あたかも喋っているかのように見せるUIが特徴的ですよね。今回のサンプルは生成AIの回答がばっと一気に表示されました。パラパラと表示させるにはストリーミングという方法を使います。そのやり方についてはこちらの記事を参照して下さい。

参考

最後に、書籍のPRです。

最新のOpenAIのチャットAPIの使い方もしっかりと解説されている良書です。2024年11月初版発行、「LangChainとLangGraphによるRAG・AIエージェント[実践]入門」西見、吉田、大嶋著。

最後まで読んでいただきありがとうございました。73

コメント

タイトルとURLをコピーしました