タイトル画像
琴葉茜

前回危うくそのままWebアプリを公開しそうになったけど、まずはなんで公開しちゃいけないか説明しておくね

琴葉葵

お願いします!

琴葉茜

今のコードには、葵専用のAPIキーが直接書き込んであるでしょ?
これをそのまま公開すると、世界中の誰でも「葵の代わりに、葵の枠を使って」AIが使い放題になっちゃうんだ

琴葉葵

そうか、家の玄関に鍵を挿しっぱなしで出かけるようなものだもんね

琴葉茜

そういうこと!だから、APIキーは直接コードに書き込むんじゃなくて、「環境変数」っていう見えない箱に入れておくのが基本なんよ

琴葉葵

環境変数?

琴葉茜

簡単に言うと、パソコンの中にこっそり隠しておける「自分専用のメモ帳」みたいなものかな

琴葉茜

とはいえ、今回は無料枠で利用にしてるのもあって、利用上限の面でも自分のAPIキーを利用して公開するのはあまり現実的ではないから、今回はユーザーにAPIキーを発行してもらって利用する形式にしようと思うよ

琴葉葵

なるほど!それなら安心だね!

琴葉茜

ということで、まずはAPIキーを入力する画面を作るよ!

琴葉茜

まずはAPIキーを入力してもらう場所をサイドバーに作成しようか

# st.title()の上に追加

with st.sidebar:
    st.title("⚙️ 設定")
    api_key = st.text_input("Gemini API Keyを入力", type="password")
琴葉葵

おー!急にサイドバーが現れた!!

琴葉茜

あとは、api_keyが関数に渡されるようにすればいいだけだよ!

# generate_response関数にapi_keyを渡すように変更
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)
琴葉茜

この時、ついでに「GEMINI_API_KEY」は消しておこうね!

GEMINI_API_KEY = "AIZa~" # この部分を削除(コメントアウトはダメ)
琴葉葵

これでプログラムの中にはAPIキーが書かれてないから安心だね!

琴葉茜

あとは、関数を呼び出す箇所もapi_keyを渡すように変更しつつ、api_keyが空欄の時や関数がエラーを返した時はエラーメッセージを出すようにしよう!

# ボタンが押された時の処理
if st.button("技の設定を作る"):
    if not api_key:
        st.error("左のサイドバーにAPIキーを入力してください!")
    elif not skill_name:
        st.warning("技の名前を入力してください。")
    else:
        try:
        # ここにAIを呼び出す処理を書く
            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']}")
        except Exception as e:
            st.error(f"エラーが発生したよ。APIキーが正しいか確認してね!\n{e}")
琴葉葵

これで一通り問題なく動くようになったね!

琴葉茜

そうだね!ひとまずこれで完成だけど、ついでに「技の設定」をブラウザに保存する機能を追加してみようか

琴葉葵

おおー!それもあると良さそう!!

この時点での全体のプログラム

from google import genai
import json
import streamlit as st

# 技の名前を渡すと、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)

with st.sidebar:
    st.title("⚙️ 設定")
    api_key = st.text_input("Gemini API Keyを入力", type="password")

# 画面のタイトル
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:
        # ここにAIを呼び出す処理を書く
            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']}")
        except Exception as e:
            st.error(f"エラーが発生したよ。APIキーが正しいか確認してね!\n{e}")