使用Streamlit對話組件,快速構建自己的ChatBot應用(st.chat_messagest.chat_input)

背景說明

隨著ChatGPT等各種LLM工具的出現,各種相關的應用開發也如雨後春筍般冒出。
其中Streamlit就是一個很常用到的套件,它提供了十分簡單的方式,讓開發者可以不需要自己去處理繁複的前後端流程就能架設一個應用。

而最初在Streamlit中其實只有提供一些簡單的單次文字輸入組件,不過對於我們所習慣的對話方式的介面則是比較難實現的。但在最近的一次更新當中,新增的兩個組件:st.chat_messagest.chat_input 即是為此而生的。接下來讓我們快速看一下應該要如何使用吧。

基本概念

st.chat_input: 對話輸入框

對話輸入框類似於一般的st.text_input,我們可以設定一個輸入框內的提示詞,然後將使用者的輸入儲存到左側的變數中。

⚠️ st.chat_input目前只能在Streamlit應用的最外層,不能放在其他的tab、columns、form、sidebar等層級下。

範例:

user_input = st.chat_input("請輸入內容...")
if user_input:
	st.write(f"使用者輸入了:`{user_input}`")

效果:

st.chat_message: 對話紀錄

而對話紀錄則比較像是st.expander,會配合with語句進行使用。

  • 參數需要指定發言者,目前只支援:
    • user
    • assitant

範例:

with st.chat_message("user"):
	st.write("給我一張圖")

with st.chat_message("assistant"):
	st.bar_chart(np.random.randn(30, 3))

效果:

實用技巧

組合輸入輸出

學會輸入框對話紀錄兩個組件後,我們就可以把他們結合起來使用了。

範例:

if user_input := st.chat_input("請輸入內容..."):
	with st.chat_message("user"):
		st.markdown(user_input)
	
	with st.chat_message("assistant"):
		st.markdown(user_input)

其中的:=為海象運算符(因為樣子很像海象XD),用來結合賦值和判斷式。

效果:

印出所有紀錄

在上面的範例中,我們可以發現只會顯示單次的輸入和輸出。若我們希望可以保留所有的對話紀錄,這邊可以搭配st.sesseion_state來紀錄使用。

範例:

# 初始化session
if "messages" not in st.session_state:
	st.session_state.messages = []

# 接收使用者輸入
if user_input := st.chat_input("請輸入內容..."):
	# 將使用者的輸入加入紀錄
	st.session_state.messages.append({"role": "user", "content": user_input})
	
	# 將回應加入紀錄
	st.session_state.messages.append({"role": "assistant", "content": f"Ok, {user_input}"})

# 顯示所有紀錄
for message in st.session_state.messages:
	with st.chat_message(message["role"]):
		st.markdown(message["content"])

效果:

參考資料