
AIアプリ開発入門 第3回|Geminiと繋いで連続処理(チェーン)を作ろう!〜Streamlitの一時記憶の魔法〜
これまでの連載で、「AIとやり取りする裏側の仕組み(PythonやAPI)」と「Streamlitで画面を作る方法」を学びました。今回はついに、これらを合体させて「画面から入力した文字をGeminiに送り、結果を受け取る」という、AIアプリの心臓部を作ります。
さらに、AIアプリで非常によく使われる「AIの回答を元に、さらに次の指示を出す」という連続処理(プロンプトチェーン)を実装します。この実装を通じて、Streamlitを使いこなす上で避けては通れない「セッションステート(一時記憶)」という超重要概念を初心者向けに解説します。
1. Gemini APIを呼び出す基本のコード
まずは、画面などは一旦忘れて「PythonからGeminiにお願いをする」だけの最もシンプルなコードを見てみましょう。前回の記事で、ライブラリは「優秀な通訳」だと説明しました。その通訳を呼び出すためのコードは以下のようになります。
pythonimport google.generativeai as genai
# 1. APIキーを設定(Geminiの厨房へ入るためのパスパスポート)
genai.configure(api_key="あなたのAPIキー")
# 2. 使うAIモデルを選択(最新の高速モデル flash を指定)
model = genai.GenerativeModel('gemini-1.5-flash')
# 3. お願い(プロンプト)を送信して、結果を受け取る
response = model.generate_content("SEOについて教えて")
# 4. 結果のテキストを表示する
print(response.text)
この4つのステップだけで、AIの回答を受け取ることができます。 非常にシンプルですよね。
これをそのまま前回の st.button("送信") を押した時の処理に組み込めば、立派なAIチャットアプリが完成します。
2. Streamlit最大の壁「記憶喪失」問題
さて、ここからが本題の「連続処理(プロンプトチェーン)」です。
今回は、「Step1でブログ記事の見出しを生成し、Step2でその見出しを元に本文を生成する」という2段階の処理を作りたいとします。
通常、Pythonのプログラムなら以下のように書けば済みそうに思えます。
python# 失敗するコードのイメージ
step1_result = "まだ空っぽ"
if st.button("Step1: 見出しを作る"):
step1_result = model.generate_content("ブログの見出しを作って").text
if st.button("Step2: 本文を作る"):
# Step1の結果を使って、本文を書かせる
final_result = model.generate_content(f"これをもとに本文を書いて:{step1_result}").text
しかし、Streamlitでこれを実行すると大失敗します。なぜなら、Streamlitには「画面上のボタンが押されたり、入力が切り替わったりするたびに、プログラム全体を上から下まで一番最初から読み直す(再起動する)」という非常に特殊なクセがあるからです。
つまり、ユーザーが「Step2」のボタンを押した瞬間、プログラムが1行目から再実行されるため、せっかくStep1で作った step1_result が「まだ空っぽ」という初期状態にリセット(記憶喪失)されてしまうのです。
3. 解決策:st.session_state(一時記憶の金庫)の魔法
この記憶喪失を防ぐための救世主が、st.session_state(セッションステート)です。
これは、Streamlitが用意してくれている「再起動しても中身が消えない、一時記憶の金庫」です。ユーザーがブラウザを開いている間だけ、安全にデータを守り続けてくれます。
使い方はとても簡単です。普通の変数の代わりに、st.session_state. の後ろに好きな名前をつけてデータを保存するだけです。
python# 金庫の中に「step1_result」という名前でデータを保管する
st.session_state.step1_result = "Geminiが作った見出し"
これを使って、先ほどの連続処理を「絶対に記憶喪失にならないコード」に書き換えてみましょう。
4. プロンプトチェーン(連続処理)を完成させる
st.session_state と Gemini API を組み合わせて、「見出し作成 → 本文執筆」という連続処理パイプラインのコードを完成させます。
これが、今回作成するアプリの最も重要な骨組みになります。
pythonimport streamlit as st
import google.generativeai as genai
st.title("ブログ記事の自動生成ツール")
# --- 事前準備:金庫の初期化 ---
# 金庫にまだ「step1_result」という枠がなければ、空っぽの枠を作っておく
if "step1_result" not in st.session_state:
st.session_state.step1_result = None
# APIの設定
genai.configure(api_key="あなたのAPIキー")
model = genai.GenerativeModel('gemini-1.5-flash')
# ユーザー入力
theme = st.text_input("記事のテーマを入力してください")
# --- Step1: 見出しの生成 ---
if st.button("Step1:見出しを作る"):
# Geminiに依頼
prompt1 = f"「{theme}」というテーマで見出しを3つ作って。"
response1 = model.generate_content(prompt1)
# ★ポイント:生成結果を「金庫」に大切に保管する
st.session_state.step1_result = response1.text
st.success("見出しが完成しました!")
# 画面に金庫の中身(Step1の結果)を表示する
if st.session_state.step1_result:
st.write("【現在の見出し】")
st.info(st.session_state.step1_result)
# --- Step2: 本文の生成 ---
if st.button("Step2:本文を作る"):
# ★ポイント:金庫の中からStep1の結果を取り出して、次の指示に混ぜる
prompt2 = f"以下の見出しを元に、ブログの本文を書いてください。\n\n{st.session_state.step1_result}"
response2 = model.generate_content(prompt2)
st.write("【完成した本文】")
st.success(response2.text)
このコードなら、Step2のボタンを押して画面が再起動しても、「金庫(session_state)の中にStep1の結果が安全に保管されている」ため、Geminiに正しくデータを渡すことができます。
今回のまとめ
今回は以下の3つの重要ポイントを学びました。
- Gemini APIの基本:数行のコードで「通訳(ライブラリ)」を介してAIと通信できる。
- Streamlitの再実行モデル:ボタンを押すたびにプログラムが上から下へ再実行され、普通の変数はリセットされる。
- st.session_stateの魔法:再実行されてもデータを消さずに保持するための「一時記憶の金庫」を使うことで、Step1→Step2という連携(プロンプトチェーン)が可能になる。
この「セッションステート」を理解できたあなたは、もうStreamlit初心者ではありません。複雑なAIツールも自由に設計できる基礎が身につきました!
次回は、今回ローカル(自分のパソコン)で作ったこのアプリを、Streamlit Community Cloudを使って世界中に公開(デプロイ)する方法を解説します。

初心者向けの参考リソース
Gemini APIの基本を知りたい方へ
- GeminiをPythonで使うための完全ガイド(Qiita)
- Gemini API のクイックスタート(Google公式)
Streamlitの「状態保持(session_state)」を深く理解したい方へ
- Streamlit Session State: スタートガイド(Kanaries Docs)
- Streamlitでセッション管理をしたい:st.session_state(Zenn)
- Streamlitの再実行を止めたい?session_stateの解説(Qiita)
注意事項
本記事の内容は執筆時点の情報をもとに作成しています。
Python、Streamlit、Gemini API、GitHub、Streamlit Cloud、Supabase、Vercel、Cloudflare、Google Cloud などの仕様、料金、UI、提供条件は予告なく変更される場合があります。
記事内のコード、設定例、画面構成は学習用・検証用のサンプルです。
実際の運用環境に導入する場合は、公式ドキュメントを確認したうえで、ご自身の責任で検証・調整してください。
APIキー、認証情報、個人情報、業務データなどの機密情報は、記事中のサンプル通りであっても公開リポジトリや公開画面にそのまま掲載しないでください。
外部サービス利用時の課金、障害、セキュリティ事故、データ消失などについて、当サイトは責任を負いません。

