前回でだいたい動くようになって使ってみたけど、ページを更新すると今までの技の情報が消えちゃうのってちょっともったいないよね
確かにそうだね
じゃあ今回はページを更新しても技の履歴が残るようにしてみようか
おおー!そんな事ができるんだね!!
ブラウザには「ローカルストレージ」っていう情報を保存する機能があるんよ
ほうほう
そういえば、たまにサイトによっては入力情報が残ってることがあるよね
そうそう
まぁ入力情報を保持する機能は「ローカルストレージ」以外にもあるんだけどね
じゃあ早速お願いします!
まずはstreamlitでローカルストレージを扱えるライブラリ「streamlit_javascript」をインストールしよう
pip install streamlit-javascript
インストールが終わったら「streamlit_javascript」をインポートして、まずはローカルストレージのデータを読み込む処理を追加しよう
history_json = st_javascript("localStorage.getItem('skill_history');")
なんか、JavaScriptのプログラムを直接動かす感じになるんだね
ちなみに、ローカルストレージは「JSON」形式になっていて、今回はキーを「skill_history」にしてるよ
んで、次はその読み込んだデータを表示する方法だけど、これはサイドバーに表示するようにしようか
with st.sidebar:
st.title("⚙️ 設定")
api_key = st.text_input("Gemini API Keyを入力", type="password")
# サイドバーに履歴を表示する
st.markdown("---")
st.subheader("📜 生成履歴")
if history_json and history_json != "null":
try:
history_data = json.loads(history_json)
# 新しい順に表示
for h in reversed(history_data):
st.markdown(f"**{h['name']}** ({h['element']})")
st.caption(f"威力: {h['power']} / MP: {h['mp_cost']}")
except Exception:
st.caption("履歴の解析に失敗しました")
おっけー!
まだローカルストレージに情報はないけど、とりあえず「生成履歴」って表示されたよ!
じゃあ次は、技を生成したときにローカルストレージに保存するようにしよう
response = generate_response(skill_name, api_key)
st.write(f"技名: {skill_name}")
st.write(f"属性: {response['element']}")
st.write(f"威力: {response['power']}")
st.write(f"消費MP: {response['mp_cost']}")
# ここから下を追加する
current_history = []
if history_json and history_json != "null":
try:
current_history = json.loads(history_json) # 読み込んだデータを変換
except:
current_history = []
if len(current_history) >= 10: # 追加する前に10個以上だったら一番古いデータを消す
current_history.pop(0)
current_history.append(response) # 追加
st_javascript(f"localStorage.setItem('skill_history', '{json.dumps(current_history)}');") # 保存
この時、読み込んだデータの後ろに追加する形にしていて、データを保持しすぎないように10個以上になったら古いデータを消すようにしてるよ
おおー!
技を生成した時点ではまだ何も増えてないけど、ページを再読み込みしたら表示された!
ひとまずはこれで完成!!
他にも、キー名を変えることでAPIキーを保持出来るようにしたりできるから、色々と試してみてね!
生成AIを使ったら、AIと会話してクリアを目指すゲームとか診断とかも作れそうだよね!
上手く使いこなせば、まだまだ新しいゲームの形を生み出せるかもだから、いっぱいアイデアを形にしていこうね!
全体のプログラム
from google import genai
import json
import streamlit as st
from streamlit_javascript import st_javascript
# 技の名前を渡すと、AIがJSON形式で技の設定を返してくれる関数
def generate_response(skill_name, api_key):
# AIの設定
client = genai.Client(api_key=api_key)
prompt = f"""
RPGのゲームマスターとして、技名「{skill_name}」の設定を作ってください。
以下のJSONフォーマットで出力してください。
{{
"name": "{skill_name}",
"element": "属性(火、水、風、雷、光、闇から選択)",
"power": "威力(10〜999の数値)",
"mp_cost": "消費MP(5〜100の数値)"
}}
"""
response = client.models.generate_content(
model='gemini-2.5-flash',
contents=prompt,
config={'response_mime_type': 'application/json'}
)
return json.loads(response.text)
# 1. 起動時にローカルストレージから履歴を読み込む
history_json = st_javascript("localStorage.getItem('skill_history');")
with st.sidebar:
st.title("⚙️ 設定")
api_key = st.text_input("Gemini API Keyを入力", type="password")
# 2. サイドバーに履歴を表示する
st.markdown("---")
st.subheader("📜 生成履歴")
if history_json and history_json != "null":
try:
history_data = json.loads(history_json)
# 新しい順に表示
for h in reversed(history_data):
st.markdown(f"**{h['name']}** ({h['element']})")
st.caption(f"威力: {h['power']} / MP: {h['mp_cost']}")
except Exception:
st.caption("履歴の解析に失敗しました")
# 画面のタイトル
st.title("AIで技の設定を作ろう")
# ユーザーが技名を入力する欄
skill_name = st.text_input("技の名前を入力してください")
# ボタンが押された時の処理
if st.button("技の設定を作る"):
if not api_key:
st.error("左のサイドバーにAPIキーを入力してください!")
elif not skill_name:
st.warning("技の名前を入力してください。")
else:
try:
response = generate_response(skill_name, api_key)
st.write(f"技名: {skill_name}")
st.write(f"属性: {response['element']}")
st.write(f"威力: {response['power']}")
st.write(f"消費MP: {response['mp_cost']}")
# 3. 生成した技を履歴に追加して保存する
current_history = []
if history_json and history_json != "null":
try:
current_history = json.loads(history_json)
except:
current_history = []
if len(current_history) >= 10:
current_history.pop(0)
current_history.append(response)
st_javascript(f"localStorage.setItem('skill_history', '{json.dumps(current_history)}');")
except Exception as e:
st.error(f"エラーが発生したよ。APIキーが正しいか確認してね!\n{e}")
