Emilyxml commited on
Commit
f544cf4
·
verified ·
1 Parent(s): 1cd259c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -86
app.py CHANGED
@@ -5,8 +5,8 @@ import uuid
5
  import csv
6
  from datetime import datetime
7
  from pathlib import Path
8
- from PIL import Image # 引入 PIL 用于处理图片
9
- from huggingface_hub import CommitScheduler, snapshot_download
10
 
11
  # --- 1. 配置区域 ---
12
  DATASET_REPO_ID = "Emilyxml/moveit"
@@ -15,6 +15,9 @@ LOG_FOLDER = Path("logs")
15
  LOG_FOLDER.mkdir(parents=True, exist_ok=True)
16
  TOKEN = os.environ.get("HF_TOKEN")
17
 
 
 
 
18
  # --- 2. 自动下载数据 ---
19
  if not os.path.exists(DATA_FOLDER) or not os.listdir(DATA_FOLDER):
20
  try:
@@ -30,17 +33,10 @@ if not os.path.exists(DATA_FOLDER) or not os.listdir(DATA_FOLDER):
30
  except Exception as e:
31
  print(f"⚠️ 下载失败: {e}")
32
 
33
- # --- 3. 启动同步调度器 ---
34
- scheduler = CommitScheduler(
35
- repo_id=DATASET_REPO_ID,
36
- repo_type="dataset",
37
- folder_path=LOG_FOLDER,
38
- path_in_repo="logs",
39
- every=1,
40
- token=TOKEN
41
- )
42
 
43
- # --- 4. 数据加载 ---
44
  def load_data():
45
  groups = {}
46
  if not os.path.exists(DATA_FOLDER):
@@ -79,52 +75,38 @@ def load_data():
79
 
80
  ALL_GROUPS, ALL_GROUP_IDS = load_data()
81
 
82
- # --- NEW: 图片优化函数 (提速关键) ---
83
  def optimize_image(image_path, max_width=800):
84
- """
85
- 读取图片并调整大小,减少传输时间。
86
- max_width: 限制最大宽度为 800px (足够人眼评估)
87
- """
88
- if not image_path:
89
- return None
90
  try:
91
  img = Image.open(image_path)
92
- # 如果图片太大,就缩小
93
  if img.width > max_width:
94
  ratio = max_width / img.width
95
  new_height = int(img.height * ratio)
96
  img = img.resize((max_width, new_height), Image.LANCZOS)
97
  return img
98
  except Exception as e:
99
- print(f"Error loading image {image_path}: {e}")
100
  return None
101
 
102
- # --- 5. 核心逻辑 ---
103
 
104
  def get_next_question(user_state):
105
- """准备下一题的数据"""
106
  idx = user_state["index"]
107
 
108
  if idx >= len(ALL_GROUP_IDS):
109
  return (
110
- gr.update(visible=False),
111
- gr.update(visible=False),
112
- gr.update(visible=False),
113
- gr.update(visible=False),
114
- gr.update(visible=False),
115
- gr.update(visible=False),
116
  gr.update(value="## 🎉 测试结束!感谢您的参与。", visible=True),
117
- user_state,
118
- []
119
  )
120
 
121
  group_id = ALL_GROUP_IDS[idx]
122
  group_data = ALL_GROUPS[group_id]
123
 
124
- # 1. 优化原图 (返回 PIL 对象而不是路径)
125
  origin_img = optimize_image(group_data["origin"], max_width=600)
126
 
127
- # 2. 优化候选图
128
  candidates = group_data["candidates"].copy()
129
  random.shuffle(candidates)
130
 
@@ -134,10 +116,7 @@ def get_next_question(user_state):
134
 
135
  for i, path in enumerate(candidates):
136
  label = f"Option {chr(65+i)}"
137
-
138
- # 优化每张候选图
139
  optimized_img = optimize_image(path, max_width=600)
140
-
141
  gallery_items.append((optimized_img, label))
142
  choices.append(label)
143
  candidates_info.append({"label": label, "path": path})
@@ -149,11 +128,8 @@ def get_next_question(user_state):
149
  gr.update(value=gallery_items, visible=True),
150
  gr.update(choices=choices, value=[], visible=True),
151
  gr.update(value=instruction, visible=True),
152
- gr.update(visible=True),
153
- gr.update(visible=True),
154
- gr.update(visible=False),
155
- user_state,
156
- candidates_info
157
  )
158
 
159
  def save_and_next(user_state, candidates_info, selected_options, is_none=False):
@@ -166,7 +142,6 @@ def save_and_next(user_state, candidates_info, selected_options, is_none=False):
166
  else:
167
  if not selected_options:
168
  raise gr.Error("请至少勾选一个选项,或点击“都不满意”")
169
-
170
  choice_str = "; ".join(selected_options)
171
  selected_methods = []
172
  for opt in selected_options:
@@ -181,27 +156,43 @@ def save_and_next(user_state, candidates_info, selected_options, is_none=False):
181
  break
182
  method_str = "; ".join(selected_methods)
183
 
184
- user_file = LOG_FOLDER / f"user_{user_state['user_id']}.csv"
185
- with scheduler.lock:
186
- exists = user_file.exists()
187
- with open(user_file, "a", newline="", encoding="utf-8") as f:
188
- writer = csv.writer(f)
189
- if not exists:
190
- writer.writerow(["user_id", "timestamp", "group_id", "choices", "methods"])
191
- writer.writerow([
192
- user_state["user_id"],
193
- datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
194
- group_id,
195
- choice_str,
196
- method_str
197
- ])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  user_state["index"] += 1
200
  return get_next_question(user_state)
201
 
202
- # --- 6. 界面构建 ---
203
  with gr.Blocks(title="User Study") as demo:
204
-
205
  state_user = gr.State(lambda: {"user_id": str(uuid.uuid4())[:8], "index": 0})
206
  state_candidates_info = gr.State([])
207
 
@@ -210,26 +201,15 @@ with gr.Blocks(title="User Study") as demo:
210
 
211
  with gr.Row():
212
  with gr.Column(scale=1):
213
- # 将 format 设置为 jpeg 进一步减小体积
214
  img_origin = gr.Image(label="Reference (参考原图)", interactive=False, height=400, format="jpeg")
215
 
216
  with gr.Column(scale=2):
217
  gallery_candidates = gr.Gallery(
218
  label="Candidates (候选结果)",
219
- columns=[2],
220
- height="auto",
221
- object_fit="contain",
222
- interactive=False,
223
- format="jpeg" # 强制输出 JPEG 格式
224
  )
225
-
226
  gr.Markdown("👇 **请在下方勾选您认为最好的结果(可多选):**")
227
-
228
- checkbox_options = gr.CheckboxGroup(
229
- choices=[],
230
- label="您的选择",
231
- info="对应上方图片的标签 (Option A, B...)"
232
- )
233
 
234
  with gr.Row():
235
  btn_submit = gr.Button("🚀 提交 (Submit)", variant="primary")
@@ -237,23 +217,11 @@ with gr.Blocks(title="User Study") as demo:
237
 
238
  md_end = gr.Markdown(visible=False)
239
 
240
- demo.load(
241
- fn=get_next_question,
242
- inputs=[state_user],
243
- outputs=[img_origin, gallery_candidates, checkbox_options, md_instruction, btn_submit, btn_none, md_end, state_user, state_candidates_info]
244
- )
245
 
246
- btn_submit.click(
247
- fn=lambda s, c, o: save_and_next(s, c, o, is_none=False),
248
- inputs=[state_user, state_candidates_info, checkbox_options],
249
- outputs=[img_origin, gallery_candidates, checkbox_options, md_instruction, btn_submit, btn_none, md_end, state_user, state_candidates_info]
250
- )
251
 
252
- btn_none.click(
253
- fn=lambda s, c, o: save_and_next(s, c, o, is_none=True),
254
- inputs=[state_user, state_candidates_info, checkbox_options],
255
- outputs=[img_origin, gallery_candidates, checkbox_options, md_instruction, btn_submit, btn_none, md_end, state_user, state_candidates_info]
256
- )
257
 
258
  if __name__ == "__main__":
259
  demo.launch()
 
5
  import csv
6
  from datetime import datetime
7
  from pathlib import Path
8
+ from PIL import Image
9
+ from huggingface_hub import snapshot_download, HfApi # 引入 HfApi 用于直接上传
10
 
11
  # --- 1. 配置区域 ---
12
  DATASET_REPO_ID = "Emilyxml/moveit"
 
15
  LOG_FOLDER.mkdir(parents=True, exist_ok=True)
16
  TOKEN = os.environ.get("HF_TOKEN")
17
 
18
+ # 初始化 API 工具
19
+ api = HfApi(token=TOKEN)
20
+
21
  # --- 2. 自动下载数据 ---
22
  if not os.path.exists(DATA_FOLDER) or not os.listdir(DATA_FOLDER):
23
  try:
 
33
  except Exception as e:
34
  print(f"⚠️ 下载失败: {e}")
35
 
36
+ # --- (注意:这里删除了 CommitScheduler) ---
37
+ # 我们不再需要 Scheduler,改用手动上传
 
 
 
 
 
 
 
38
 
39
+ # --- 3. 数据加载 ---
40
  def load_data():
41
  groups = {}
42
  if not os.path.exists(DATA_FOLDER):
 
75
 
76
  ALL_GROUPS, ALL_GROUP_IDS = load_data()
77
 
78
+ # --- 图片优化函数 ---
79
  def optimize_image(image_path, max_width=800):
80
+ if not image_path: return None
 
 
 
 
 
81
  try:
82
  img = Image.open(image_path)
 
83
  if img.width > max_width:
84
  ratio = max_width / img.width
85
  new_height = int(img.height * ratio)
86
  img = img.resize((max_width, new_height), Image.LANCZOS)
87
  return img
88
  except Exception as e:
89
+ print(f"Error: {e}")
90
  return None
91
 
92
+ # --- 4. 核心逻辑 ---
93
 
94
  def get_next_question(user_state):
 
95
  idx = user_state["index"]
96
 
97
  if idx >= len(ALL_GROUP_IDS):
98
  return (
99
+ gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
100
+ gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
 
 
 
 
101
  gr.update(value="## 🎉 测试结束!感谢您的参与。", visible=True),
102
+ user_state, []
 
103
  )
104
 
105
  group_id = ALL_GROUP_IDS[idx]
106
  group_data = ALL_GROUPS[group_id]
107
 
 
108
  origin_img = optimize_image(group_data["origin"], max_width=600)
109
 
 
110
  candidates = group_data["candidates"].copy()
111
  random.shuffle(candidates)
112
 
 
116
 
117
  for i, path in enumerate(candidates):
118
  label = f"Option {chr(65+i)}"
 
 
119
  optimized_img = optimize_image(path, max_width=600)
 
120
  gallery_items.append((optimized_img, label))
121
  choices.append(label)
122
  candidates_info.append({"label": label, "path": path})
 
128
  gr.update(value=gallery_items, visible=True),
129
  gr.update(choices=choices, value=[], visible=True),
130
  gr.update(value=instruction, visible=True),
131
+ gr.update(visible=True), gr.update(visible=True), gr.update(visible=False),
132
+ user_state, candidates_info
 
 
 
133
  )
134
 
135
  def save_and_next(user_state, candidates_info, selected_options, is_none=False):
 
142
  else:
143
  if not selected_options:
144
  raise gr.Error("请至少勾选一个选项,或点击“都不满意”")
 
145
  choice_str = "; ".join(selected_options)
146
  selected_methods = []
147
  for opt in selected_options:
 
156
  break
157
  method_str = "; ".join(selected_methods)
158
 
159
+ # --- 关键修改:保存并立即上传 ---
160
+ user_filename = f"user_{user_state['user_id']}.csv"
161
+ user_file_path = LOG_FOLDER / user_filename
162
+
163
+ # 1. 写入本地 CSV
164
+ file_exists = user_file_path.exists()
165
+ with open(user_file_path, "a", newline="", encoding="utf-8") as f:
166
+ writer = csv.writer(f)
167
+ if not file_exists:
168
+ writer.writerow(["user_id", "timestamp", "group_id", "choices", "methods"])
169
+ writer.writerow([
170
+ user_state["user_id"],
171
+ datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
172
+ group_id,
173
+ choice_str,
174
+ method_str
175
+ ])
176
+
177
+ # 2. 立即上传到 Dataset (同步操作)
178
+ try:
179
+ print(f"Uploading {user_filename} to dataset...")
180
+ api.upload_file(
181
+ path_or_fileobj=user_file_path,
182
+ path_in_repo=f"logs/{user_filename}", # 在 Dataset 中创建 logs 文件夹
183
+ repo_id=DATASET_REPO_ID,
184
+ repo_type="dataset"
185
+ )
186
+ print("Upload success!")
187
+ except Exception as e:
188
+ print(f"⚠️ Upload failed: {e}")
189
+ # 如果是 Token 权限问题,这里会在 Space Logs 里报错
190
 
191
  user_state["index"] += 1
192
  return get_next_question(user_state)
193
 
194
+ # --- 5. 界面构建 ---
195
  with gr.Blocks(title="User Study") as demo:
 
196
  state_user = gr.State(lambda: {"user_id": str(uuid.uuid4())[:8], "index": 0})
197
  state_candidates_info = gr.State([])
198
 
 
201
 
202
  with gr.Row():
203
  with gr.Column(scale=1):
 
204
  img_origin = gr.Image(label="Reference (参考原图)", interactive=False, height=400, format="jpeg")
205
 
206
  with gr.Column(scale=2):
207
  gallery_candidates = gr.Gallery(
208
  label="Candidates (候选结果)",
209
+ columns=[2], height="auto", object_fit="contain", interactive=False, format="jpeg"
 
 
 
 
210
  )
 
211
  gr.Markdown("👇 **请在下方勾选您认为最好的结果(可多选):**")
212
+ checkbox_options = gr.CheckboxGroup(choices=[], label="您的选择", info="对应上方图片的标签")
 
 
 
 
 
213
 
214
  with gr.Row():
215
  btn_submit = gr.Button("🚀 提交 (Submit)", variant="primary")
 
217
 
218
  md_end = gr.Markdown(visible=False)
219
 
220
+ demo.load(fn=get_next_question, inputs=[state_user], outputs=[img_origin, gallery_candidates, checkbox_options, md_instruction, btn_submit, btn_none, md_end, state_user, state_candidates_info])
 
 
 
 
221
 
222
+ btn_submit.click(fn=lambda s, c, o: save_and_next(s, c, o, is_none=False), inputs=[state_user, state_candidates_info, checkbox_options], outputs=[img_origin, gallery_candidates, checkbox_options, md_instruction, btn_submit, btn_none, md_end, state_user, state_candidates_info])
 
 
 
 
223
 
224
+ btn_none.click(fn=lambda s, c, o: save_and_next(s, c, o, is_none=True), inputs=[state_user, state_candidates_info, checkbox_options], outputs=[img_origin, gallery_candidates, checkbox_options, md_instruction, btn_submit, btn_none, md_end, state_user, state_candidates_info])
 
 
 
 
225
 
226
  if __name__ == "__main__":
227
  demo.launch()