Lilli98 commited on
Commit
60d8a4a
·
verified ·
1 Parent(s): 586db6e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -60
app.py CHANGED
@@ -1,5 +1,5 @@
1
  # app.py
2
- # @title 啤酒游戏最终整合版 (Streamlit 交互应用 + Hugging Face 日志上传)
3
 
4
  # -----------------------------------------------------------------------------
5
  # 1. 导入必要的库
@@ -19,6 +19,12 @@ from pathlib import Path
19
  from datetime import datetime
20
  from huggingface_hub import HfApi, upload_file
21
 
 
 
 
 
 
 
22
  # -----------------------------------------------------------------------------
23
  # 2. 配置游戏核心参数和API密钥
24
  # -----------------------------------------------------------------------------
@@ -50,12 +56,14 @@ try:
50
  else:
51
  hf_api = None
52
  except Exception as e:
53
- st.error(f"启动时读取Secrets出错: {e}")
54
- st.info("请确保在Streamlit的Secrets中设置了 OPENAI_API_KEY。可选设置 HF_TOKEN 和 HF_REPO_ID 用于上传日志。")
55
  client = None
56
  HF_TOKEN = None
57
  HF_REPO_ID = None
58
  hf_api = None
 
 
59
 
60
 
61
  # -----------------------------------------------------------------------------
@@ -311,61 +319,65 @@ def save_logs_and_upload(state: dict):
311
  # -----------------------------------------------------------------------------
312
  # 4. Streamlit UI 界面
313
  # -----------------------------------------------------------------------------
314
- st.set_page_config(page_title="啤酒游戏-人机协作版", layout="wide")
315
  st.title("🍺 啤酒游戏:人机协作挑战")
316
- st.markdown("你将扮演供应链中的一个角色,与另外三个由大语言模型(LLM)驱动的AI代理合作。")
317
-
318
- # --- 游戏设置和初始化 ---
319
- if 'game_state' not in st.session_state or not st.session_state.game_state.get('game_running', False):
320
- st.header("🎮 开始新游戏")
321
- col1, col2 = st.columns(2)
322
- with col1:
323
- llm_personality = st.selectbox("AI '性格'", ('human_like', 'perfect_rational'), format_func=lambda x: x.replace('_', ' ').title())
324
- with col2:
325
- info_sharing = st.selectbox("信息共享", ('local', 'full'), format_func=lambda x: x.title())
326
- if st.button("🚀 开始游戏", type="primary"):
327
- init_game_state(llm_personality, info_sharing)
328
- st.rerun()
329
-
330
- # --- 游戏主界面 ---
331
- elif 'game_state' in st.session_state and st.session_state.game_state.get('game_running'):
332
- state = st.session_state.game_state
333
- week, human_role, echelons = state['week'], state['human_role'], state['echelons']
334
- st.header(f"第 {week} 周 / 共 {WEEKS} 周")
335
- st.subheader(f"你的角色: **{human_role}** | AI模式: **{state['llm_personality'].replace('_', ' ')}** | 信息: **{state['info_sharing']}**")
336
- cols = st.columns(4)
337
- for i, name in enumerate(["Retailer", "Wholesaler", "Distributor", "Factory"]):
338
- with cols[i]:
339
- e, title_icon = echelons[name], "👤" if name == human_role else "🤖"
340
- st.markdown(f"### {title_icon} {name} {'(你)' if name == human_role else '(AI)'}")
341
- st.metric("库存", e['inventory']); st.metric("缺货/积压", e['backlog'])
342
- st.write(f"本周收到订单: **{e['incoming_order']}**")
343
- st.write(f"下周到货: **{list(e['incoming_shipments'])[0] if e['incoming_shipments'] else 0}**")
344
- st.markdown("---")
345
- st.header("你的决策")
346
- human_echelon_state = echelons[human_role]
347
- prompt_sugg = get_llm_prompt(human_echelon_state, week, state['llm_personality'], state['info_sharing'], echelons)
348
- ai_suggestion, _ = get_llm_order_decision(prompt_sugg, f"{human_role} (Suggestion)", week, state['llm_personality'])
349
- st.info(f"💡 AI建议你 ({human_role}) 本周向上游订购 **{ai_suggestion}** 单位。")
350
- with st.form(key="order_form"):
351
- final_order = st.number_input("请输入你的最终订单数量:", min_value=0, step=1, value=ai_suggestion)
352
- if st.form_submit_button(label="✅ 提交订单并进入下一周"):
353
- step_game(int(final_order)); st.rerun()
354
- st.sidebar.header("游戏信息")
355
- st.sidebar.markdown(f"**游戏ID**: `{state['participant_id']}`")
356
- st.sidebar.markdown(f"**当前周**: {week-1} (已完成)")
357
- if st.sidebar.button("🔄 重置游戏"):
358
- del st.session_state.game_state; st.rerun()
359
-
360
- # --- 游戏结束界面 ---
361
- if 'game_state' in st.session_state and not st.session_state.game_state.get('game_running', False) and st.session_state.game_state['week'] > WEEKS:
362
- st.header("🎉 游戏结束!")
363
- state = st.session_state.game_state
364
- logs_df = pd.json_normalize(state['logs'])
365
- title = f"Beer Game (Human: {state['human_role']})\n(AI: {state['llm_personality'].replace('_', ' ').title()} | Info: {state['info_sharing'].title()})"
366
- fig = plot_results(logs_df, title)
367
- st.pyplot(fig)
368
- # 保存并上传日志
369
- save_logs_and_upload(state)
370
- if st.button("✨ 开始一局新游戏"):
371
- del st.session_state.game_state; st.rerun()
 
 
 
 
 
 
1
  # app.py
2
+ # @title 啤酒游戏最终整合版 (Streamlit 交互应用 + Hugging Face 日志上传) - 已修复版本
3
 
4
  # -----------------------------------------------------------------------------
5
  # 1. 导入必要的库
 
19
  from datetime import datetime
20
  from huggingface_hub import HfApi, upload_file
21
 
22
+ # -----------------------------------------------------------------------------
23
+ # 0. 页面配置 (必须是第一个Streamlit命令)
24
+ # -----------------------------------------------------------------------------
25
+ st.set_page_config(page_title="啤酒游戏-人机协作版", layout="wide")
26
+
27
+
28
  # -----------------------------------------------------------------------------
29
  # 2. 配置游戏核心参数和API密钥
30
  # -----------------------------------------------------------------------------
 
56
  else:
57
  hf_api = None
58
  except Exception as e:
59
+ # 将错误信息显示在主页面,而不是在加载配置时就调用st.error
60
+ st.session_state.initialization_error = f"启动时读取Secrets出错: {e}. 请确保在Streamlit的Secrets中设置了 OPENAI_API_KEY。可选设置 HF_TOKEN 和 HF_REPO_ID 用于上传日志。"
61
  client = None
62
  HF_TOKEN = None
63
  HF_REPO_ID = None
64
  hf_api = None
65
+ else:
66
+ st.session_state.initialization_error = None
67
 
68
 
69
  # -----------------------------------------------------------------------------
 
319
  # -----------------------------------------------------------------------------
320
  # 4. Streamlit UI 界面
321
  # -----------------------------------------------------------------------------
 
322
  st.title("🍺 啤酒游戏:人机协作挑战")
323
+
324
+ # 检查初始化时是否有错误
325
+ if st.session_state.get('initialization_error'):
326
+ st.error(st.session_state.initialization_error)
327
+ else:
328
+ st.markdown("你将扮演供应链中的一个角色,与另外三个由大语言模型(LLM)驱动的AI代理合作。")
329
+
330
+ # --- 游戏设置和初始化 ---
331
+ if 'game_state' not in st.session_state or not st.session_state.game_state.get('game_running', False):
332
+ st.header("🎮 开始新游戏")
333
+ col1, col2 = st.columns(2)
334
+ with col1:
335
+ llm_personality = st.selectbox("AI '性格'", ('human_like', 'perfect_rational'), format_func=lambda x: x.replace('_', ' ').title())
336
+ with col2:
337
+ info_sharing = st.selectbox("信息共享", ('local', 'full'), format_func=lambda x: x.title())
338
+ if st.button("🚀 开始游戏", type="primary", disabled=(client is None)):
339
+ init_game_state(llm_personality, info_sharing)
340
+ st.rerun()
341
+
342
+ # --- 游戏主界面 ---
343
+ elif 'game_state' in st.session_state and st.session_state.game_state.get('game_running'):
344
+ state = st.session_state.game_state
345
+ week, human_role, echelons = state['week'], state['human_role'], state['echelons']
346
+ st.header(f" {week} / {WEEKS} ")
347
+ st.subheader(f"你的角色: **{human_role}** | AI模式: **{state['llm_personality'].replace('_', ' ')}** | 信息: **{state['info_sharing']}**")
348
+ cols = st.columns(4)
349
+ for i, name in enumerate(["Retailer", "Wholesaler", "Distributor", "Factory"]):
350
+ with cols[i]:
351
+ e, title_icon = echelons[name], "👤" if name == human_role else "🤖"
352
+ st.markdown(f"### {title_icon} {name} {'(你)' if name == human_role else '(AI)'}")
353
+ st.metric("库存", e['inventory']); st.metric("缺货/积压", e['backlog'])
354
+ st.write(f"本周收到订单: **{e['incoming_order']}**")
355
+ st.write(f"下周到货: **{list(e['incoming_shipments'])[0] if e['incoming_shipments'] else 0}**")
356
+ st.markdown("---")
357
+ st.header("你的决策")
358
+ human_echelon_state = echelons[human_role]
359
+ prompt_sugg = get_llm_prompt(human_echelon_state, week, state['llm_personality'], state['info_sharing'], echelons)
360
+ ai_suggestion, _ = get_llm_order_decision(prompt_sugg, f"{human_role} (Suggestion)", week, state['llm_personality'])
361
+ st.info(f"💡 AI建议你 ({human_role}) 本周向上游订购 **{ai_suggestion}** 单位。")
362
+ with st.form(key="order_form"):
363
+ final_order = st.number_input("请输入你的最终订单数量:", min_value=0, step=1, value=ai_suggestion)
364
+ if st.form_submit_button(label=" 提交订单并进入下一周"):
365
+ step_game(int(final_order)); st.rerun()
366
+ st.sidebar.header("游戏信息")
367
+ st.sidebar.markdown(f"**游戏ID**: `{state['participant_id']}`")
368
+ st.sidebar.markdown(f"**当前周**: {week-1} (已完成)")
369
+ if st.sidebar.button("🔄 重置游戏"):
370
+ del st.session_state.game_state; st.rerun()
371
+
372
+ # --- 游戏结束界面 ---
373
+ if 'game_state' in st.session_state and not st.session_state.game_state.get('game_running', False) and st.session_state.game_state['week'] > WEEKS:
374
+ st.header("🎉 游戏结束!")
375
+ state = st.session_state.game_state
376
+ logs_df = pd.json_normalize(state['logs'])
377
+ title = f"Beer Game (Human: {state['human_role']})\n(AI: {state['llm_personality'].replace('_', ' ').title()} | Info: {state['info_sharing'].title()})"
378
+ fig = plot_results(logs_df, title)
379
+ st.pyplot(fig)
380
+ # 保存并上传日志
381
+ save_logs_and_upload(state)
382
+ if st.button("✨ 开始一局新游戏"):
383
+ del st.session_state.game_state; st.rerun()