💬

StreamlitでChatGPTアプリを作成しよう!

2023/08/11に公開

2023年9月2日追記
アプリの公開をしました!streamlitとgithubで公開しています。
ぜひチェックしてみてください。リンクは一番下に置いています。


StreamlitでChatGPTアプリが作れちゃうんです。
しかもstreaming機能ありで結構本家に近いですよ!

Streamlitとは?

Streamlitは、PythonでWebアプリケーションを素早く作成するためのオープンソースライブラリです。データ分析、可視化、機械学習モデルのデモなどに特に適しており、コーディングの専門知識がなくても使いやすいツールです。
https://streamlit.io/

ChatGPTとは?

ChatGPTについてはご存じですよね?ChatGPTはOpenAIによって開発された自然言語処理のモデルで、人間のような文章の生成が可能です。テキスト生成、質問応答、文章要約など、多岐にわたる応用があります。

必要なライブラリのインストール

pip install streamlit
pip install openai

早速実装してみましょう!

以下のリンクを参考にしています。
https://docs.streamlit.io/knowledge-base/tutorials/build-conversational-apps

import openai
import streamlit as st

# タイトルを設定
st.title("ChatGPT by Streamlit")

# OpenAIのAPIキーを設定
openai.api_key = 'your-api-key-here'

# セッション内で使用するモデルが指定されていない場合のデフォルト値
if "openai_model" not in st.session_state:
    st.session_state["openai_model"] = "gpt-3.5-turbo"

# セッション内のメッセージが指定されていない場合のデフォルト値
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)

    with st.chat_message("assistant"):
        message_placeholder = st.empty() # 一時的なプレースホルダーを作成
        full_response = ""
        # ChatGPTからのストリーミング応答を処理
        for response in openai.ChatCompletion.create(
            model=st.session_state["openai_model"],
            messages=[
                {"role": m["role"], "content": m["content"]}
                for m in st.session_state.messages
            ],
            stream=True,
        ):
            full_response += response.choices[0].delta.get("content", "")
            message_placeholder.markdown(full_response + "▌") # レスポンスの途中結果を表示
        message_placeholder.markdown(full_response) # 最終レスポンスを表示
    st.session_state.messages.append({"role": "assistant", "content": full_response}) # 応答をメッセージに追加

Streamlitを使用してアプリを起動するには、ターミナルで以下のコマンドを実行します。

streamlit run XXX.py

 

キーとなる部分は説明しますね!

openai.api_key = "OPENAI_API_KEY"

OpenAIのAPI keyはご自身のを記載してください。
API keyの取得方法は他の方の記事を参考にしてください。

st.session_state["openai_model"] = "gpt-3.5-turbo"

chat modelの指定を出来ます。
gpt-4は2023年8月時点ではAPIを使用して支払い履歴のある方のみ使用可能になるようです。

for response in openai.ChatCompletion.create(
    model=st.session_state["openai_model"],
    messages=[
	{"role": m["role"], "content": m["content"]}
	for m in st.session_state.messages
    ],
    stream=True,
):

ChatGPT APIと会話を実行する部分になります。
ここではparameterを設定する事も出来ます!temperatureなんかはよくいじったりしますよね!

stream=True

上記が肝です。streaming機能をonとすることでまるでAIがその場で会話を考えながら生成しているように見えるんですね!
 
因みにChatGPT APIと会話する際のメッセージの中身はざっくりと下記のようになっています。

messages=[
{"role": "system", "content": "システムプロンプト"},
{"role": "user", "content": "ユーザープロンプト"},
{"role": "assistant", "content": "応答"}
]

このままでは公式のコードをそのまま持ってきただけなので折角なので少し手を加えましょう!
会話履歴を消去するボタンを作成してみます。

import openai
import streamlit as st

st.title("ChatGPT by Streamlit") # タイトルの設定

openai.api_key = 'your-api-key-here' # OpenAIのAPIキーを設定

# セッション内で使用するモデルが指定されていない場合のデフォルト値
if "openai_model" not in st.session_state:
    st.session_state["openai_model"] = "gpt-3.5-turbo"

# セッション内のメッセージが指定されていない場合のデフォルト値
if "messages" not in st.session_state:
    st.session_state.messages = []

# セッション内でチャット履歴をクリアするかどうかの状態変数
if "Clear" not in st.session_state:
    st.session_state.Clear = False

# 以前のメッセージを表示
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)

    with st.chat_message("assistant"):
        message_placeholder = st.empty() # 一時的なプレースホルダーを作成
        full_response = ""
        # ChatGPTからのストリーミング応答を処理
        for response in openai.ChatCompletion.create(
            model=st.session_state["openai_model"],
            messages=[
                {"role": m["role"], "content": m["content"]}
                for m in st.session_state.messages
            ],
            stream=True,
        ):
            full_response += response.choices[0].delta.get("content", "")
            message_placeholder.markdown(full_response + "▌") # レスポンスの途中結果を表示
        message_placeholder.markdown(full_response) # 最終レスポンスを表示
    st.session_state.messages.append({"role": "assistant", "content": full_response})
    st.session_state.Clear = True # チャット履歴のクリアボタンを有効にする

# チャット履歴をクリアするボタンが押されたら、メッセージをリセット
if st.session_state.Clear:
    if st.button('clear chat history'):
        st.session_state.messages = [] # メッセージのリセット
        full_response = ""
        st.session_state.Clear = False # クリア状態をリセット
        st.experimental_rerun() # 画面を更新

詳しい説明は省きますが、自分はこのコードで実行出来ました!
 
この他にもChatGPTアプリだったら色々機能を付け加えたいですよね!
テンプレートの選択、モデルの選択、システムプロンプトの設定、パラメータの設定等…皆さんはどんな機能を付けたいと思いましたか!?ぜひコメントで教えてください!

アプリの公開

今回のアプリをstreamlit shareで公開しています!ぜひ使ってみてください。
左のスライドバーにOpenAIのAPI Keyを設定してください。
https://app-app-qdhfimujklvewyuzbjtddj.streamlit.app/

また、これまで作成したアプリはgithubでも公開しています!ぜひチェックしてみてください。
https://github.com/tsuzukia21/streamlit-app

Discussion