Emilyxml commited on
Commit
a72090c
·
verified ·
1 Parent(s): 74af1a5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +18 -51
app.py CHANGED
@@ -24,7 +24,7 @@ scheduler = CommitScheduler(
24
  token=TOKEN
25
  )
26
 
27
- # --- 3. 数据加载逻辑 (保持不变) ---
28
  def load_data():
29
  groups = {}
30
  if not os.path.exists(DATA_FOLDER):
@@ -57,13 +57,8 @@ def load_data():
57
 
58
  ALL_GROUPS, ALL_GROUP_IDS = load_data()
59
 
60
- # --- 4. 保存逻辑 (支持多选保存) ---
61
  def save_user_vote(user_id, group_id, choice_labels, method_names):
62
- """
63
- 保存投票。
64
- choice_labels: 字符串,例如 "Option A; Option B"
65
- method_names: 字符串,例如 "omnigen; sdxl"
66
- """
67
  user_filename = f"user_{user_id}.csv"
68
  user_file_path = LOG_FOLDER / user_filename
69
 
@@ -85,7 +80,7 @@ def save_user_vote(user_id, group_id, choice_labels, method_names):
85
 
86
  print(f"Saved: User {user_id} selected {method_names}")
87
 
88
- # --- 5. 交互逻辑 (多选核心) ---
89
 
90
  def get_current_question_ui(user_state):
91
  """根据当前索引刷新界面"""
@@ -100,8 +95,8 @@ def get_current_question_ui(user_state):
100
  gr.update(visible=False),
101
  gr.update(value="## 🎉 测试结束!\n感谢您的参与,所有结果已保存。", visible=True),
102
  user_state,
103
- [], # 清空文件路径
104
- [] # 清空当前选中的索引
105
  )
106
 
107
  # 2. 获取数据
@@ -111,7 +106,7 @@ def get_current_question_ui(user_state):
111
  # 3. 准备文本
112
  instruction_text = f"### 任务 ({current_idx + 1} / {len(ALL_GROUP_IDS)})\n\n{group_data['instruction']}"
113
 
114
- # 4. 准备图片 (盲测 + 打乱)
115
  original_images = group_data["images"]
116
  shuffled_images = original_images.copy()
117
  random.shuffle(shuffled_images)
@@ -119,7 +114,7 @@ def get_current_question_ui(user_state):
119
  # 构造显示列表
120
  display_list = []
121
  for i, img_path in enumerate(shuffled_images):
122
- label = f"Option {chr(65+i)}" # Option A, Option B...
123
  display_list.append((img_path, label))
124
 
125
  # 动态列数
@@ -128,33 +123,25 @@ def get_current_question_ui(user_state):
128
 
129
  return (
130
  gr.update(value=instruction_text, visible=True),
131
- gr.update(value=display_list, columns=cols, visible=True), # Gallery
132
- gr.update(value="当前未选择任何图片", visible=True), # 状态栏重置
133
- gr.update(visible=True), # 按钮区可见
134
- gr.update(visible=False), # 结束语
135
  user_state,
136
  shuffled_images,
137
- [] # 重置选中的索引列表
138
  )
139
 
140
  def toggle_selection(evt: gr.SelectData, current_indices):
141
- """
142
- 处理图片点击:
143
- 点击一次 -> 选中
144
- 再点一次 -> 取消选中
145
- """
146
  clicked_idx = evt.index
147
 
148
- # 切换状态
149
  if clicked_idx in current_indices:
150
  current_indices.remove(clicked_idx)
151
  else:
152
  current_indices.append(clicked_idx)
153
 
154
- # 排序一下,让显示更好看 (Option A, Option B)
155
  current_indices.sort()
156
 
157
- # 更新状态文本
158
  if not current_indices:
159
  status_text = "当前未选择任何图片"
160
  else:
@@ -164,9 +151,6 @@ def toggle_selection(evt: gr.SelectData, current_indices):
164
  return current_indices, status_text
165
 
166
  def submit_vote(user_state, current_file_paths, current_indices, is_none=False):
167
- """
168
- 提交投票(可能是多选,可能是None)
169
- """
170
  user_id = user_state["user_id"]
171
  current_idx = user_state["index"]
172
 
@@ -175,16 +159,14 @@ def submit_vote(user_state, current_file_paths, current_indices, is_none=False):
175
 
176
  group_id = ALL_GROUP_IDS[current_idx]
177
 
178
- # --- 场景1: 都没有 ---
179
  if is_none:
180
  save_user_vote(user_id, group_id, "Rejected All", "None_Satisfied")
181
  user_state["index"] += 1
182
  return get_current_question_ui(user_state)
183
 
184
- # --- 场景2: 提交多选 ---
185
  if not current_indices:
186
- # 如果用户没选图片就点了提交,弹窗提示或者不做反应
187
- # 这里为了简单,返回原样,并提示
188
  return (
189
  gr.update(), gr.update(),
190
  gr.update(value="❌ 请至少选择一张图片,或者点击“都不满意”"),
@@ -192,16 +174,13 @@ def submit_vote(user_state, current_file_paths, current_indices, is_none=False):
192
  user_state, current_file_paths, current_indices
193
  )
194
 
195
- # 解析所有选中的图片
196
  selected_labels = []
197
  selected_methods = []
198
 
199
  for idx in current_indices:
200
- # 1. 记录 Option X
201
  label = f"Option {chr(65+idx)}"
202
  selected_labels.append(label)
203
 
204
- # 2. 提取方法名
205
  real_path = current_file_paths[idx]
206
  filename = os.path.basename(real_path)
207
  name_no_ext = os.path.splitext(filename)[0]
@@ -209,28 +188,24 @@ def submit_vote(user_state, current_file_paths, current_indices, is_none=False):
209
  method = parts[1] if len(parts) > 1 else name_no_ext
210
  selected_methods.append(method)
211
 
212
- # 用分号连接 (CSV友好)
213
  str_labels = "; ".join(selected_labels)
214
  str_methods = "; ".join(selected_methods)
215
 
216
  save_user_vote(user_id, group_id, str_labels, str_methods)
217
 
218
- # 下一题
219
  user_state["index"] += 1
220
  return get_current_question_ui(user_state)
221
 
222
- # --- 6. 界面构建 ---
223
- with gr.Blocks(title="Multi-Select User Study", theme=gr.themes.Soft()) as demo:
224
 
225
- # 状态变量
226
  state_user = gr.State(lambda: {"user_id": str(uuid.uuid4())[:8], "index": 0})
227
- state_files = gr.State([]) # 存当前图片的真实路径
228
- state_indices = gr.State([]) # 存当前选中的图片索引 [0, 2]
229
 
230
  with gr.Column():
231
  instruction_md = gr.Markdown("Loading...")
232
 
233
- # 图片区
234
  gallery = gr.Gallery(
235
  label="请点击选择图片(可多选)",
236
  allow_preview=True,
@@ -239,40 +214,32 @@ with gr.Blocks(title="Multi-Select User Study", theme=gr.themes.Soft()) as demo:
239
  interactive=True
240
  )
241
 
242
- # 状态显示区(告诉用户选了啥)
243
  status_box = gr.Textbox(value="当前未选择任何图片", label="当前选中状态", interactive=False)
244
 
245
- # 按钮区
246
  with gr.Row():
247
  btn_submit = gr.Button("✅ 提交选择 (Confirm Selection)", variant="primary", scale=2)
248
  btn_none = gr.Button("🚫 都不满意 (None of them)", variant="stop", scale=1)
249
 
250
  end_msg = gr.Markdown(visible=False)
251
 
252
- # --- 事件流 ---
253
-
254
- # 1. 启动加载
255
  demo.load(
256
  fn=get_current_question_ui,
257
  inputs=[state_user],
258
  outputs=[instruction_md, gallery, status_box, btn_submit, end_msg, state_user, state_files, state_indices]
259
  )
260
 
261
- # 2. 点击图片 -> 切换选中状态 (不翻页)
262
  gallery.select(
263
  fn=toggle_selection,
264
  inputs=[state_indices],
265
  outputs=[state_indices, status_box]
266
  )
267
 
268
- # 3. 点击提交 -> 保存并下一页
269
  btn_submit.click(
270
  fn=lambda s, f, i: submit_vote(s, f, i, is_none=False),
271
  inputs=[state_user, state_files, state_indices],
272
  outputs=[instruction_md, gallery, status_box, btn_submit, end_msg, state_user, state_files, state_indices]
273
  )
274
 
275
- # 4. 点击都不满意 -> 保存并下一页
276
  btn_none.click(
277
  fn=lambda s, f, i: submit_vote(s, f, i, is_none=True),
278
  inputs=[state_user, state_files, state_indices],
 
24
  token=TOKEN
25
  )
26
 
27
+ # --- 3. 数据加载逻辑 ---
28
  def load_data():
29
  groups = {}
30
  if not os.path.exists(DATA_FOLDER):
 
57
 
58
  ALL_GROUPS, ALL_GROUP_IDS = load_data()
59
 
60
+ # --- 4. 保存逻辑 ---
61
  def save_user_vote(user_id, group_id, choice_labels, method_names):
 
 
 
 
 
62
  user_filename = f"user_{user_id}.csv"
63
  user_file_path = LOG_FOLDER / user_filename
64
 
 
80
 
81
  print(f"Saved: User {user_id} selected {method_names}")
82
 
83
+ # --- 5. 交互逻辑 ---
84
 
85
  def get_current_question_ui(user_state):
86
  """根据当前索引刷新界面"""
 
95
  gr.update(visible=False),
96
  gr.update(value="## 🎉 测试结束!\n感谢您的参与,所有结果已保存。", visible=True),
97
  user_state,
98
+ [],
99
+ []
100
  )
101
 
102
  # 2. 获取数据
 
106
  # 3. 准备文本
107
  instruction_text = f"### 任务 ({current_idx + 1} / {len(ALL_GROUP_IDS)})\n\n{group_data['instruction']}"
108
 
109
+ # 4. 准备图片
110
  original_images = group_data["images"]
111
  shuffled_images = original_images.copy()
112
  random.shuffle(shuffled_images)
 
114
  # 构造显示列表
115
  display_list = []
116
  for i, img_path in enumerate(shuffled_images):
117
+ label = f"Option {chr(65+i)}"
118
  display_list.append((img_path, label))
119
 
120
  # 动态列数
 
123
 
124
  return (
125
  gr.update(value=instruction_text, visible=True),
126
+ gr.update(value=display_list, columns=cols, visible=True),
127
+ gr.update(value="当前未选择任何图片", visible=True),
128
+ gr.update(visible=True),
129
+ gr.update(visible=False),
130
  user_state,
131
  shuffled_images,
132
+ []
133
  )
134
 
135
  def toggle_selection(evt: gr.SelectData, current_indices):
 
 
 
 
 
136
  clicked_idx = evt.index
137
 
 
138
  if clicked_idx in current_indices:
139
  current_indices.remove(clicked_idx)
140
  else:
141
  current_indices.append(clicked_idx)
142
 
 
143
  current_indices.sort()
144
 
 
145
  if not current_indices:
146
  status_text = "当前未选择任何图片"
147
  else:
 
151
  return current_indices, status_text
152
 
153
  def submit_vote(user_state, current_file_paths, current_indices, is_none=False):
 
 
 
154
  user_id = user_state["user_id"]
155
  current_idx = user_state["index"]
156
 
 
159
 
160
  group_id = ALL_GROUP_IDS[current_idx]
161
 
162
+ # 场景1: 都没有
163
  if is_none:
164
  save_user_vote(user_id, group_id, "Rejected All", "None_Satisfied")
165
  user_state["index"] += 1
166
  return get_current_question_ui(user_state)
167
 
168
+ # 场景2: 提交多选
169
  if not current_indices:
 
 
170
  return (
171
  gr.update(), gr.update(),
172
  gr.update(value="❌ 请至少选择一张图片,或者点击“都不满意”"),
 
174
  user_state, current_file_paths, current_indices
175
  )
176
 
 
177
  selected_labels = []
178
  selected_methods = []
179
 
180
  for idx in current_indices:
 
181
  label = f"Option {chr(65+idx)}"
182
  selected_labels.append(label)
183
 
 
184
  real_path = current_file_paths[idx]
185
  filename = os.path.basename(real_path)
186
  name_no_ext = os.path.splitext(filename)[0]
 
188
  method = parts[1] if len(parts) > 1 else name_no_ext
189
  selected_methods.append(method)
190
 
 
191
  str_labels = "; ".join(selected_labels)
192
  str_methods = "; ".join(selected_methods)
193
 
194
  save_user_vote(user_id, group_id, str_labels, str_methods)
195
 
 
196
  user_state["index"] += 1
197
  return get_current_question_ui(user_state)
198
 
199
+ # --- 6. 界面构建 (已移除 theme 参数) ---
200
+ with gr.Blocks(title="Multi-Select User Study") as demo:
201
 
 
202
  state_user = gr.State(lambda: {"user_id": str(uuid.uuid4())[:8], "index": 0})
203
+ state_files = gr.State([])
204
+ state_indices = gr.State([])
205
 
206
  with gr.Column():
207
  instruction_md = gr.Markdown("Loading...")
208
 
 
209
  gallery = gr.Gallery(
210
  label="请点击选择图片(可多选)",
211
  allow_preview=True,
 
214
  interactive=True
215
  )
216
 
 
217
  status_box = gr.Textbox(value="当前未选择任何图片", label="当前选中状态", interactive=False)
218
 
 
219
  with gr.Row():
220
  btn_submit = gr.Button("✅ 提交选择 (Confirm Selection)", variant="primary", scale=2)
221
  btn_none = gr.Button("🚫 都不满意 (None of them)", variant="stop", scale=1)
222
 
223
  end_msg = gr.Markdown(visible=False)
224
 
 
 
 
225
  demo.load(
226
  fn=get_current_question_ui,
227
  inputs=[state_user],
228
  outputs=[instruction_md, gallery, status_box, btn_submit, end_msg, state_user, state_files, state_indices]
229
  )
230
 
 
231
  gallery.select(
232
  fn=toggle_selection,
233
  inputs=[state_indices],
234
  outputs=[state_indices, status_box]
235
  )
236
 
 
237
  btn_submit.click(
238
  fn=lambda s, f, i: submit_vote(s, f, i, is_none=False),
239
  inputs=[state_user, state_files, state_indices],
240
  outputs=[instruction_md, gallery, status_box, btn_submit, end_msg, state_user, state_files, state_indices]
241
  )
242
 
 
243
  btn_none.click(
244
  fn=lambda s, f, i: submit_vote(s, f, i, is_none=True),
245
  inputs=[state_user, state_files, state_indices],