Upload app.py
Browse files
app.py
CHANGED
|
@@ -11,11 +11,17 @@ import re
|
|
| 11 |
load_dotenv()
|
| 12 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
| 13 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
|
|
|
|
|
|
| 14 |
if not GEMINI_API_KEY or not GROQ_API_KEY:
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
genai.configure(api_key=GEMINI_API_KEY)
|
| 18 |
-
gemini_model = genai.GenerativeModel('gemini-
|
| 19 |
groq_client = Groq(api_key=GROQ_API_KEY)
|
| 20 |
|
| 21 |
print("日本語感情分析モデルをロード中...")
|
|
@@ -43,7 +49,7 @@ DEFAULT_SCENE_PARAMS = {
|
|
| 43 |
"constraints": ["会話を「別に。」のような一言で終わらせない", "必ず相手の発言を拾ってリアクションを返す"]
|
| 44 |
}
|
| 45 |
|
| 46 |
-
# --- 2.
|
| 47 |
|
| 48 |
def detect_scene_change(history, message):
|
| 49 |
history_text = "\n".join([f"ユーザー: {u}\n麻理: {m}" for u, m in history[-4:]])
|
|
@@ -121,7 +127,7 @@ def generate_dialogue_with_gemini(history, message, affection, stage_name, scene
|
|
| 121 |
try:
|
| 122 |
generation_config = genai.types.GenerationConfig(max_output_tokens=200, temperature=0.95)
|
| 123 |
response = gemini_model.generate_content(system_prompt, generation_config=generation_config)
|
| 124 |
-
return response.text
|
| 125 |
except Exception as e:
|
| 126 |
print(f"応答生成エラー(Gemini): {e}")
|
| 127 |
return "(ごめんなさい、ちょっと考えがまとまらない……)"
|
|
@@ -142,7 +148,7 @@ def update_affection(message, affection):
|
|
| 142 |
return affection
|
| 143 |
return affection
|
| 144 |
|
| 145 |
-
# --- メイン応答処理 ---
|
| 146 |
|
| 147 |
def respond(message, chat_history, affection, history, scene_params):
|
| 148 |
new_affection = update_affection(message, affection)
|
|
@@ -151,40 +157,30 @@ def respond(message, chat_history, affection, history, scene_params):
|
|
| 151 |
|
| 152 |
final_scene_params = scene_params
|
| 153 |
|
| 154 |
-
if new_scene_name:
|
|
|
|
| 155 |
new_params_base = generate_scene_instruction_with_groq(new_affection, stage_name, new_scene_name, message)
|
| 156 |
if new_params_base:
|
| 157 |
final_scene_params = {**DEFAULT_SCENE_PARAMS, **new_params_base}
|
| 158 |
instruction = final_scene_params.get("initial_dialogue_instruction")
|
| 159 |
bot_message = generate_dialogue_with_gemini(history, message, new_affection, stage_name, final_scene_params, instruction=instruction)
|
| 160 |
-
else:
|
|
|
|
| 161 |
bot_message = generate_dialogue_with_gemini(history, message, new_affection, stage_name, final_scene_params)
|
| 162 |
else:
|
| 163 |
bot_message = generate_dialogue_with_gemini(history, message, new_affection, stage_name, final_scene_params)
|
| 164 |
|
| 165 |
new_history = history + [(message, bot_message)]
|
| 166 |
chat_history.append((message, bot_message))
|
|
|
|
| 167 |
theme_name = final_scene_params.get("theme", "default")
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
console.log("背景画像を設定: {background_url}");
|
| 176 |
-
chat.style.backgroundImage = "url('{background_url}')";
|
| 177 |
-
chat.style.backgroundSize = "cover";
|
| 178 |
-
chat.style.backgroundPosition = "center";
|
| 179 |
-
chat.style.transition = "background-image 1s ease-in-out";
|
| 180 |
-
}}
|
| 181 |
-
}}, 100);
|
| 182 |
-
</script>
|
| 183 |
-
"""
|
| 184 |
-
|
| 185 |
-
return "", chat_history, new_affection, stage_name, new_affection, new_history, final_scene_params, js_script
|
| 186 |
-
|
| 187 |
-
# --- Gradio UI ---
|
| 188 |
|
| 189 |
with gr.Blocks(css="style.css", theme=gr.themes.Soft(primary_hue="rose", secondary_hue="pink")) as demo:
|
| 190 |
scene_state = gr.State(DEFAULT_SCENE_PARAMS)
|
|
@@ -194,19 +190,36 @@ with gr.Blocks(css="style.css", theme=gr.themes.Soft(primary_hue="rose", seconda
|
|
| 194 |
gr.Markdown("# 麻理チャット")
|
| 195 |
with gr.Row():
|
| 196 |
with gr.Column(scale=2):
|
| 197 |
-
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
with gr.Column(scale=1):
|
| 200 |
-
stage_display = gr.Textbox(label="現在の関係ステージ", interactive=False)
|
| 201 |
affection_gauge = gr.Slider(minimum=0, maximum=100, label="麻理の好感度", value=30, interactive=False)
|
| 202 |
-
js_injector = gr.HTML(elem_classes="hidden")
|
| 203 |
|
|
|
|
| 204 |
msg_input.submit(
|
| 205 |
respond,
|
| 206 |
[msg_input, chatbot, affection_state, history_state, scene_state],
|
| 207 |
-
[msg_input, chatbot, affection_gauge, stage_display, affection_state, history_state, scene_state,
|
| 208 |
)
|
|
|
|
|
|
|
| 209 |
|
| 210 |
if __name__ == "__main__":
|
| 211 |
-
demo.launch()
|
| 212 |
-
|
|
|
|
| 11 |
load_dotenv()
|
| 12 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
| 13 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
| 14 |
+
|
| 15 |
+
# Hugging Face SpacesのSecretsに設定されているかチェック
|
| 16 |
if not GEMINI_API_KEY or not GROQ_API_KEY:
|
| 17 |
+
# ローカルでの実行のために、環境変数が設定されていない場合はダミー値を設定
|
| 18 |
+
print("警告: APIキーがSecretsに設定されていません。")
|
| 19 |
+
# 実行を止めないようにダミーを設定(デプロイ時はSecrets設定が必須)
|
| 20 |
+
GEMINI_API_KEY = "your_gemini_api_key_here"
|
| 21 |
+
GROQ_API_KEY = "your_groq_api_key_here"
|
| 22 |
|
| 23 |
genai.configure(api_key=GEMINI_API_KEY)
|
| 24 |
+
gemini_model = genai.GenerativeModel('gemini-1.5-flash')
|
| 25 |
groq_client = Groq(api_key=GROQ_API_KEY)
|
| 26 |
|
| 27 |
print("日本語感情分析モデルをロード中...")
|
|
|
|
| 49 |
"constraints": ["会話を「別に。」のような一言で終わらせない", "必ず相手の発言を拾ってリアクションを返す"]
|
| 50 |
}
|
| 51 |
|
| 52 |
+
# --- 2. 機能定義 ---
|
| 53 |
|
| 54 |
def detect_scene_change(history, message):
|
| 55 |
history_text = "\n".join([f"ユーザー: {u}\n麻理: {m}" for u, m in history[-4:]])
|
|
|
|
| 127 |
try:
|
| 128 |
generation_config = genai.types.GenerationConfig(max_output_tokens=200, temperature=0.95)
|
| 129 |
response = gemini_model.generate_content(system_prompt, generation_config=generation_config)
|
| 130 |
+
return response.text.strip()
|
| 131 |
except Exception as e:
|
| 132 |
print(f"応答生成エラー(Gemini): {e}")
|
| 133 |
return "(ごめんなさい、ちょっと考えがまとまらない……)"
|
|
|
|
| 148 |
return affection
|
| 149 |
return affection
|
| 150 |
|
| 151 |
+
# --- 3. メイン応答処理 ---
|
| 152 |
|
| 153 |
def respond(message, chat_history, affection, history, scene_params):
|
| 154 |
new_affection = update_affection(message, affection)
|
|
|
|
| 157 |
|
| 158 |
final_scene_params = scene_params
|
| 159 |
|
| 160 |
+
if new_scene_name and new_scene_name in THEME_URLS:
|
| 161 |
+
print(f"シーンチェンジを検出: {new_scene_name}")
|
| 162 |
new_params_base = generate_scene_instruction_with_groq(new_affection, stage_name, new_scene_name, message)
|
| 163 |
if new_params_base:
|
| 164 |
final_scene_params = {**DEFAULT_SCENE_PARAMS, **new_params_base}
|
| 165 |
instruction = final_scene_params.get("initial_dialogue_instruction")
|
| 166 |
bot_message = generate_dialogue_with_gemini(history, message, new_affection, stage_name, final_scene_params, instruction=instruction)
|
| 167 |
+
else: # Groqが失敗した場合のフォールバック
|
| 168 |
+
final_scene_params["theme"] = new_scene_name
|
| 169 |
bot_message = generate_dialogue_with_gemini(history, message, new_affection, stage_name, final_scene_params)
|
| 170 |
else:
|
| 171 |
bot_message = generate_dialogue_with_gemini(history, message, new_affection, stage_name, final_scene_params)
|
| 172 |
|
| 173 |
new_history = history + [(message, bot_message)]
|
| 174 |
chat_history.append((message, bot_message))
|
| 175 |
+
|
| 176 |
theme_name = final_scene_params.get("theme", "default")
|
| 177 |
+
|
| 178 |
+
# 背景レイヤーのHTMLコンテンツをクラス名付きで生成
|
| 179 |
+
background_html = f'<div class="chat-background {theme_name}"></div>'
|
| 180 |
+
|
| 181 |
+
return "", chat_history, new_affection, stage_name, new_affection, new_history, final_scene_params, background_html
|
| 182 |
+
|
| 183 |
+
# --- 4. Gradio UI ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
|
| 185 |
with gr.Blocks(css="style.css", theme=gr.themes.Soft(primary_hue="rose", secondary_hue="pink")) as demo:
|
| 186 |
scene_state = gr.State(DEFAULT_SCENE_PARAMS)
|
|
|
|
| 190 |
gr.Markdown("# 麻理チャット")
|
| 191 |
with gr.Row():
|
| 192 |
with gr.Column(scale=2):
|
| 193 |
+
# チャットボットと背景を重ねるためのコンテナ
|
| 194 |
+
with gr.Column(elem_id="chat_container"):
|
| 195 |
+
# 背景レイヤー
|
| 196 |
+
background_display = gr.HTML(
|
| 197 |
+
f'<div class="chat-background {DEFAULT_SCENE_PARAMS["theme"]}"></div>',
|
| 198 |
+
elem_id="background_container"
|
| 199 |
+
)
|
| 200 |
+
# チャットボット
|
| 201 |
+
chatbot = gr.Chatbot(
|
| 202 |
+
label="麻理との会話", bubble_full_width=False, elem_id="chat_area", show_label=False
|
| 203 |
+
)
|
| 204 |
+
|
| 205 |
+
msg_input = gr.Textbox(
|
| 206 |
+
label="あなたのメッセージ",
|
| 207 |
+
placeholder="「水族館はどう?」と聞いた後、「いいね、行こう!」のように返してみてください",
|
| 208 |
+
scale=5,
|
| 209 |
+
show_label=False
|
| 210 |
+
)
|
| 211 |
with gr.Column(scale=1):
|
| 212 |
+
stage_display = gr.Textbox(label="現在の関係ステージ", interactive=False, value=get_relationship_stage(30))
|
| 213 |
affection_gauge = gr.Slider(minimum=0, maximum=100, label="麻理の好感度", value=30, interactive=False)
|
|
|
|
| 214 |
|
| 215 |
+
# 応答関数とUIコンポーネントの接続を更新
|
| 216 |
msg_input.submit(
|
| 217 |
respond,
|
| 218 |
[msg_input, chatbot, affection_state, history_state, scene_state],
|
| 219 |
+
[msg_input, chatbot, affection_gauge, stage_display, affection_state, history_state, scene_state, background_display]
|
| 220 |
)
|
| 221 |
+
# ページロード時に初期ステージを表示
|
| 222 |
+
demo.load(lambda affection: get_relationship_stage(affection), affection_state, stage_display)
|
| 223 |
|
| 224 |
if __name__ == "__main__":
|
| 225 |
+
demo.launch()
|
|
|