【ListeningMindガイド編集部からのご案内】
無料トライアルのご案内
「ブランドは消費者にどう思われているのか?」
「消費者は何に困り、何を求めているのか?」
ListeningMindは、
消費者の思考を明らかにするツールです。
>>ターゲット層のペルソナを調べてみる(無料トライアル有り)
【ListeningMindガイド編集部からのご案内】
無料トライアルのご案内
「ブランドは消費者にどう思われているのか?」
「消費者は何に困り、何を求めているのか?」
ListeningMindは、
消費者の思考を明らかにするツールです。
>>ターゲット層のペルソナを調べてみる(無料トライアル有り)
これまでの連載で、「AIとやり取りする裏側の仕組み(PythonやAPI)」と「Streamlitで画面を作る方法」を学びました。今回はついに、これらを合体させて「画面から入力した文字をGeminiに送り、結果を受け取る」という、AIアプリの心臓部を作ります。
さらに、AIアプリで非常によく使われる「AIの回答を元に、さらに次の指示を出す」という連続処理(プロンプトチェーン)を実装します。この実装を通じて、Streamlitを使いこなす上で避けては通れない「セッションステート(一時記憶)」という超重要概念を初心者向けに解説します。
まずは、画面などは一旦忘れて「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チャットアプリが完成します。
⚠️ 重要:APIキーは絶対にコードに直接書かないでください。
APIキーは「厨房への合鍵」です。コードに書いたままGitHubなどに公開すると、第三者に悪用されて意図しない課金が発生する危険があります。
安全な管理方法として、プロジェクトフォルダに .env ファイルを作り、そこにキーを書きます。
text#.env ファイルの中身
GOOGLE_API_KEY=あなたの実際のキー
Pythonコードでは python-dotenv ライブラリを使って読み込みます:
pythonfrom dotenv import load_dotenv
import os
load_dotenv()
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
また、.env ファイルは .gitignore に追加してバージョン管理から除外することが必須です。
さて、ここからが本題の「連続処理(プロンプトチェーン)」です。
今回は、「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 が「まだ空っぽ」という初期状態にリセット(記憶喪失)されてしまうのです。
これは欠陥ではなく、Streamlitの意図的な設計です。「画面の状態が変わるたびに全体を描き直す」ことで、複雑なフロントエンドの制御を不要にし、Pythonだけで動くシンプルさを実現しています。HTMLで言えば「ページをリロードして最新状態にする」のと同じ発想です。このクセさえ理解してしまえば、むしろ動きが予測しやすくなります。
st.session_state(一時記憶の金庫)の魔法この記憶喪失を防ぐための救世主が、st.session_state(セッションステート)です。
これは、Streamlitが用意してくれている「再起動しても中身が消えない、一時記憶の金庫」です。ユーザーがブラウザを開いている間だけ、安全にデータを守り続けてくれます。
使い方はとても簡単です。普通の変数の代わりに、st.session_state. の後ろに好きな名前をつけてデータを保存するだけです。
python# 金庫の中に「step1_result」という名前でデータを保管する
st.session_state.step1_result = "Geminiが作った見出し"
これを使って、先ほどの連続処理を「絶対に記憶喪失にならないコード」に書き換えてみましょう。
st.session_state と Gemini API を組み合わせて、「見出し作成 → 本文執筆」という連続処理パイプラインのコードを完成させます。
これが、今回作成するアプリの最も重要な骨組みになります。
if "step1_result" not in st.session_state: という行は「金庫にまだその枠がなければ作る」という条件分岐です。これが必要な理由は、ページを初めて開いたときは金庫が空の状態だからです。初期化なしに st.session_state.step1_result を参照しようとすると、「そんな枠はない」というエラーが発生します。この「最初だけ枠を作る」パターンはsession_stateを使う際の定型文として覚えておきましょう。
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)
if st.button("Step2:本文を作る"):
# ★追加:Step1が済んでいない場合は警告を出す
if st.session_state.step1_result is None:
st.warning("先にStep1で見出しを作成してください。")
else:
prompt2 = f"以下の見出しを元に..."
# --- Step2: 本文の生成 ---
if st.button("Step2:本文を作る"):
# ★ポイント:金庫の中からStep1の結果を取り出して、次の指示に混ぜる
# :Step1が済んでいない場合は警告を出す
if st.session_state.step1_result is None:
st.warning("先にStep1で見出しを作成してください。")
else:
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つの重要ポイントを学びました。
この「セッションステート」を理解できたあなたは、もうStreamlit初心者ではありません。複雑なAIツールも自由に設計できる基礎が身につきました!
次回は、今回ローカル(自分のパソコン)で作ったこのアプリを、Streamlit Community Cloudを使って世界中に公開(デプロイ)する方法を解説します。

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