Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -45,13 +45,12 @@ def load_prompt(level):
|
|
| 45 |
def chat_process(message, display_history, full_logs, prompt_level):
|
| 46 |
"""
|
| 47 |
チャット処理を行う関数
|
| 48 |
-
|
| 49 |
-
full_logs: 全保存用の履歴 (CSV保存用)
|
| 50 |
"""
|
| 51 |
if display_history is None: display_history = []
|
| 52 |
if full_logs is None: full_logs = []
|
| 53 |
|
| 54 |
-
# 1. ユーザーメッセージの
|
| 55 |
current_time_user = datetime.datetime.now(JST).strftime("%Y-%m-%d %H:%M:%S")
|
| 56 |
user_msg_data = {
|
| 57 |
"role": "user",
|
|
@@ -59,16 +58,15 @@ def chat_process(message, display_history, full_logs, prompt_level):
|
|
| 59 |
"timestamp": current_time_user
|
| 60 |
}
|
| 61 |
|
| 62 |
-
#
|
| 63 |
-
display_history
|
| 64 |
-
full_logs
|
| 65 |
|
| 66 |
-
# APIリクエスト用のメッセージ作成
|
| 67 |
system_prompt = load_prompt(prompt_level)
|
| 68 |
messages_for_api = [{"role": "system", "content": system_prompt}]
|
| 69 |
|
| 70 |
-
for msg in
|
| 71 |
-
# roleとcontentだけ抽出してAPIに渡す
|
| 72 |
messages_for_api.append({"role": msg["role"], "content": msg["content"]})
|
| 73 |
|
| 74 |
ai_response = ""
|
|
@@ -92,7 +90,7 @@ def chat_process(message, display_history, full_logs, prompt_level):
|
|
| 92 |
print(error_msg, file=sys.stderr)
|
| 93 |
ai_response = f"システムエラーが発生しました: {e}"
|
| 94 |
|
| 95 |
-
# 2. AIメッセージの
|
| 96 |
current_time_ai = datetime.datetime.now(JST).strftime("%Y-%m-%d %H:%M:%S")
|
| 97 |
ai_msg_data = {
|
| 98 |
"role": "assistant",
|
|
@@ -100,21 +98,19 @@ def chat_process(message, display_history, full_logs, prompt_level):
|
|
| 100 |
"timestamp": current_time_ai
|
| 101 |
}
|
| 102 |
|
| 103 |
-
|
| 104 |
-
|
|
|
|
| 105 |
|
| 106 |
-
# 入力欄
|
| 107 |
-
return "",
|
| 108 |
|
| 109 |
def change_difficulty_logic(new_level, full_logs):
|
| 110 |
"""
|
| 111 |
難易度変更時の処理
|
| 112 |
-
- 画面用履歴(display_history)はリセットして新しい通知を入れる
|
| 113 |
-
- 全保存用履歴(full_logs)は維持して通知を追記する
|
| 114 |
"""
|
| 115 |
if full_logs is None: full_logs = []
|
| 116 |
|
| 117 |
-
# 通知メッセージ作成
|
| 118 |
notification_msg = (
|
| 119 |
f"**[システム通知]**\n"
|
| 120 |
f"難易度を **{new_level}** に変更しました。\n"
|
|
@@ -128,13 +124,14 @@ def change_difficulty_logic(new_level, full_logs):
|
|
| 128 |
"timestamp": current_time
|
| 129 |
}
|
| 130 |
|
| 131 |
-
# 新しい画面用履歴(これまでの会話は消える)
|
| 132 |
new_display_history = [msg_data]
|
| 133 |
|
| 134 |
-
# 全保存用履歴には追記する(
|
| 135 |
-
full_logs
|
| 136 |
|
| 137 |
-
|
|
|
|
| 138 |
|
| 139 |
def export_csv_logic(user_id, user_name, full_logs):
|
| 140 |
print(f"Exporting CSV for UserID: {user_id}, Name: '{user_name}'")
|
|
@@ -173,10 +170,10 @@ def export_csv_logic(user_id, user_name, full_logs):
|
|
| 173 |
|
| 174 |
# --- UI Definition ---
|
| 175 |
with gr.Blocks() as demo:
|
| 176 |
-
# ステート
|
| 177 |
user_id_state = gr.State(generate_user_id)
|
| 178 |
-
display_history_state = gr.State([]) # 画面
|
| 179 |
-
full_logs_state = gr.State([]) #
|
| 180 |
prompt_level_state = gr.State("Beginner")
|
| 181 |
|
| 182 |
gr.Markdown("# Multi-Level AI Chatbot")
|
|
@@ -200,50 +197,38 @@ with gr.Blocks() as demo:
|
|
| 200 |
interactive=True
|
| 201 |
)
|
| 202 |
|
| 203 |
-
#
|
| 204 |
chatbot = gr.Chatbot(type="messages", height=500)
|
|
|
|
|
|
|
| 205 |
msg_input = gr.Textbox(
|
| 206 |
placeholder="メッセージを入力してください... (Enterで送信)",
|
| 207 |
label="Chat Input",
|
| 208 |
lines=1
|
| 209 |
)
|
| 210 |
-
# 送信ボタン(非表示にしてEnter送信だけでも良いが、あると便利)
|
| 211 |
send_btn = gr.Button("送信", variant="primary")
|
| 212 |
|
| 213 |
-
# --- Event Handling ---
|
| 214 |
|
| 215 |
# 1. メッセージ送信時の処理
|
| 216 |
-
#
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
inputs=[display_history_state],
|
| 224 |
-
outputs=[chatbot]
|
| 225 |
-
)
|
| 226 |
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
inputs=[msg_input, display_history_state, full_logs_state, prompt_level_state],
|
| 230 |
-
outputs=[msg_input, chatbot, full_logs_state]
|
| 231 |
-
).then(
|
| 232 |
-
fn=lambda x: x,
|
| 233 |
-
inputs=[display_history_state],
|
| 234 |
-
outputs=[chatbot]
|
| 235 |
-
)
|
| 236 |
|
| 237 |
# 2. 難易度変更時の処理
|
|
|
|
|
|
|
| 238 |
level_radio.change(
|
| 239 |
fn=change_difficulty_logic,
|
| 240 |
inputs=[level_radio, full_logs_state],
|
| 241 |
-
outputs=[chatbot, full_logs_state, prompt_level_state]
|
| 242 |
-
).then(
|
| 243 |
-
# 画面履歴Stateも更新しておく
|
| 244 |
-
fn=lambda history: history,
|
| 245 |
-
inputs=[chatbot],
|
| 246 |
-
outputs=[display_history_state]
|
| 247 |
)
|
| 248 |
|
| 249 |
# 3. CSV保存処理
|
|
|
|
| 45 |
def chat_process(message, display_history, full_logs, prompt_level):
|
| 46 |
"""
|
| 47 |
チャット処理を行う関数
|
| 48 |
+
Stateの更新漏れを防ぐため、リストは + 演算子で新しく生成して返す
|
|
|
|
| 49 |
"""
|
| 50 |
if display_history is None: display_history = []
|
| 51 |
if full_logs is None: full_logs = []
|
| 52 |
|
| 53 |
+
# 1. ユーザーメッセージの作成
|
| 54 |
current_time_user = datetime.datetime.now(JST).strftime("%Y-%m-%d %H:%M:%S")
|
| 55 |
user_msg_data = {
|
| 56 |
"role": "user",
|
|
|
|
| 58 |
"timestamp": current_time_user
|
| 59 |
}
|
| 60 |
|
| 61 |
+
# 【修正】appendではなく新しいリストを作成して結合 (State更新を確実にするため)
|
| 62 |
+
temp_display = display_history + [user_msg_data]
|
| 63 |
+
temp_logs = full_logs + [user_msg_data]
|
| 64 |
|
| 65 |
+
# APIリクエスト用のメッセージ作成
|
| 66 |
system_prompt = load_prompt(prompt_level)
|
| 67 |
messages_for_api = [{"role": "system", "content": system_prompt}]
|
| 68 |
|
| 69 |
+
for msg in temp_display:
|
|
|
|
| 70 |
messages_for_api.append({"role": msg["role"], "content": msg["content"]})
|
| 71 |
|
| 72 |
ai_response = ""
|
|
|
|
| 90 |
print(error_msg, file=sys.stderr)
|
| 91 |
ai_response = f"システムエラーが発生しました: {e}"
|
| 92 |
|
| 93 |
+
# 2. AIメッセージの作成
|
| 94 |
current_time_ai = datetime.datetime.now(JST).strftime("%Y-%m-%d %H:%M:%S")
|
| 95 |
ai_msg_data = {
|
| 96 |
"role": "assistant",
|
|
|
|
| 98 |
"timestamp": current_time_ai
|
| 99 |
}
|
| 100 |
|
| 101 |
+
# 【修正】最終的な新しいリストを作成
|
| 102 |
+
new_display = temp_display + [ai_msg_data]
|
| 103 |
+
new_logs = temp_logs + [ai_msg_data]
|
| 104 |
|
| 105 |
+
# 戻り値: (入力欄クリア, Chatbot表示更新, 画面用State更新, 保存用State更新)
|
| 106 |
+
return "", new_display, new_display, new_logs
|
| 107 |
|
| 108 |
def change_difficulty_logic(new_level, full_logs):
|
| 109 |
"""
|
| 110 |
難易度変更時の処理
|
|
|
|
|
|
|
| 111 |
"""
|
| 112 |
if full_logs is None: full_logs = []
|
| 113 |
|
|
|
|
| 114 |
notification_msg = (
|
| 115 |
f"**[システム通知]**\n"
|
| 116 |
f"難易度を **{new_level}** に変更しました。\n"
|
|
|
|
| 124 |
"timestamp": current_time
|
| 125 |
}
|
| 126 |
|
| 127 |
+
# 新しい画面用履歴(これまでの会話は消え、通知だけ入る)
|
| 128 |
new_display_history = [msg_data]
|
| 129 |
|
| 130 |
+
# 【修正】全保存用履歴には追記する(新しいリストを作成)
|
| 131 |
+
new_full_logs = full_logs + [msg_data]
|
| 132 |
|
| 133 |
+
# 戻り値: (Chatbot表示更新, 画面用State更新, 保存用State更新, 難易度State更新)
|
| 134 |
+
return new_display_history, new_display_history, new_full_logs, new_level
|
| 135 |
|
| 136 |
def export_csv_logic(user_id, user_name, full_logs):
|
| 137 |
print(f"Exporting CSV for UserID: {user_id}, Name: '{user_name}'")
|
|
|
|
| 170 |
|
| 171 |
# --- UI Definition ---
|
| 172 |
with gr.Blocks() as demo:
|
| 173 |
+
# ステート定義
|
| 174 |
user_id_state = gr.State(generate_user_id)
|
| 175 |
+
display_history_state = gr.State([]) # 画面用
|
| 176 |
+
full_logs_state = gr.State([]) # 保存用
|
| 177 |
prompt_level_state = gr.State("Beginner")
|
| 178 |
|
| 179 |
gr.Markdown("# Multi-Level AI Chatbot")
|
|
|
|
| 197 |
interactive=True
|
| 198 |
)
|
| 199 |
|
| 200 |
+
# Chatbotコンポーネント
|
| 201 |
chatbot = gr.Chatbot(type="messages", height=500)
|
| 202 |
+
|
| 203 |
+
# 入力エリア
|
| 204 |
msg_input = gr.Textbox(
|
| 205 |
placeholder="メッセージを入力してください... (Enterで送信)",
|
| 206 |
label="Chat Input",
|
| 207 |
lines=1
|
| 208 |
)
|
|
|
|
| 209 |
send_btn = gr.Button("送信", variant="primary")
|
| 210 |
|
| 211 |
+
# --- Event Handling (ここが重要) ---
|
| 212 |
|
| 213 |
# 1. メッセージ送信時の処理
|
| 214 |
+
# 入力: [メッセージ, 画面履歴, 保存履歴, 難易度]
|
| 215 |
+
# 出力: [入力欄, チャットボット, 画面履歴State, 保存履歴State] ← 全て更新する
|
| 216 |
+
chat_event_args = {
|
| 217 |
+
"fn": chat_process,
|
| 218 |
+
"inputs": [msg_input, display_history_state, full_logs_state, prompt_level_state],
|
| 219 |
+
"outputs": [msg_input, chatbot, display_history_state, full_logs_state]
|
| 220 |
+
}
|
|
|
|
|
|
|
|
|
|
| 221 |
|
| 222 |
+
msg_input.submit(**chat_event_args)
|
| 223 |
+
send_btn.click(**chat_event_args)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
|
| 225 |
# 2. 難易度変更時の処理
|
| 226 |
+
# 入力: [難易度, 保存履歴]
|
| 227 |
+
# 出力: [チャットボット, 画面履歴State, 保存履歴State, 難易度State] ← 全て更新する
|
| 228 |
level_radio.change(
|
| 229 |
fn=change_difficulty_logic,
|
| 230 |
inputs=[level_radio, full_logs_state],
|
| 231 |
+
outputs=[chatbot, display_history_state, full_logs_state, prompt_level_state]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
)
|
| 233 |
|
| 234 |
# 3. CSV保存処理
|