Streamlit×LangChain — WebチャットUIを20行で作る
LangChainでプロンプト、チェーン、メモリ、エージェントと学んできた方にとって、次のステップは「実際に動くWebアプリ」を作ることです。HTMLやJavaScriptを書かずにPythonだけで対話型チャット画面を構築できるフレームワークが Streamlit です。本記事ではStreamlitの基本からLangChainの会話メモリとの組み合わせまで、最小限のコードでAIチャットボットを完成させます。
Streamlitとは
StreamlitはPythonスクリプトだけでWebアプリを構築できるフレームワークで、機械学習・データサイエンス分野で広く使われています。Pythonだけで完結する、コード保存で画面に即座に反映される、状態管理の仕組みがある、の三特徴があり、LangChainと組み合わせればプロンプト組み立て・LLM呼び出し・会話履歴管理・画面表示までPython一貫で記述できます。
チャットUIの最小構成
pip install streamlit langchain langchain-openai
Streamlitはチャット画面専用の部品を用意しています。st.chat_message で発言の枠を、st.chat_input で入力欄を作れます。
import streamlit as st
st.title("シンプルチャット")
user_input = st.chat_input("メッセージを入力してください")
if user_input:
with st.chat_message("user"):
st.write(user_input)
with st.chat_message("assistant"):
st.write("これはダミーの応答です。")
st.chat_message に "user" または "assistant" を渡すと、左右に配置された吹き出しとして表示されます。
セッション状態で会話を保持する
Streamlitはユーザー入力のたびにスクリプト全体を再実行するため、単純な変数に履歴を入れると毎回初期化されます。これを防ぐ仕組みが セッション状態(session state) です。st.session_state は画面の再実行をまたいで値を保持できる辞書型オブジェクトです。
import streamlit as st
st.title("セッション状態の確認")
if "messages" not in st.session_state:
st.session_state.messages = []
user_input = st.chat_input("メッセージを入力")
if user_input:
st.session_state.messages.append({"role": "user", "content": user_input})
st.session_state.messages.append({"role": "assistant", "content": "ダミー応答"})
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.write(msg["content"])
if "messages" not in st.session_state で初回起動時のみ空リストを初期化するのがポイントです。
LangChainの会話メモリと組み合わせる
LLMと会話メモリを組み合わせて本物のAIチャットボットに仕上げます。ChatPromptTemplate と MessagesPlaceholder を使い、文脈を踏まえた応答を生成します。
import streamlit as st
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage
st.title("AIチャットボット")
if "messages" not in st.session_state:
st.session_state.messages = []
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
prompt = ChatPromptTemplate.from_messages([
("system", "あなたは親切で丁寧なAIアシスタントです。日本語で応答してください。"),
MessagesPlaceholder(variable_name="messages"),
("human", "{input}")
])
chain = prompt | llm
user_input = st.chat_input("メッセージを入力してください")
if user_input:
st.session_state.messages.append({"role": "user", "content": user_input})
history = []
for msg in st.session_state.messages:
if msg["role"] == "user":
history.append(HumanMessage(content=msg["content"]))
else:
history.append(AIMessage(content=msg["content"]))
response = chain.invoke({
"messages": history[:-1],
"input": user_input
})
st.session_state.messages.append({"role": "assistant", "content": response.content})
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.write(msg["content"])
コードのポイント
-
プロンプトの3層構造 — システムメッセージ・会話履歴・新しい入力。
MessagesPlaceholderが可変長メッセージリストを挿入する箇所を示し、LLMが文脈を踏まえた応答を生成します。 -
履歴の変換 — セッション状態は辞書リストですが、LangChainに渡す際は
HumanMessageとAIMessageに変換します。 -
二重送信の防止 — 履歴の最後は
"input"として別に渡すためhistory[:-1]で除外します。
まとめ
- StreamlitはPythonのみでWebアプリを構築できる。
st.chat_messageとst.chat_inputでチャット画面を作れる - セッション状態(
st.session_state)で画面再実行をまたいで会話履歴を保持できる - LangChainの
ChatPromptTemplateとMessagesPlaceholderにより文脈を踏まえた応答を生成できる -
chain.streamとst.emptyの組み合わせでストリーミング応答も実現できる
StreamlitとLangChainの組み合わせは、AIアプリのプロトタイプから本番運用まで幅広く活用できる強力な組み合わせです。まずは20行から始めて、自分だけのAIアシスタントを作ってみてください。
読者特典(無料)
本記事のような実装パターンを横断的にまとめたチートシートと、Obsidian・Notionのテンプレート集を無料配布しています。8冊の内容から「何をどのツールでやるか」の判断チャートも含みます。
参考書籍: LangChain x AI実践入門(Kindle・Kindle Unlimited読み放題対象)(葉山悠希 著)