jdev8 commited on
Commit
81c187c
·
verified ·
1 Parent(s): 44e2555

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +142 -61
app.py CHANGED
@@ -20,11 +20,23 @@ HF_INPUT_DATASET_URL_COLUMN = os.getenv("HF_INPUT_DATASET_URL_COLUMN")
20
  HF_OUTPUT_DATASET = os.getenv("HF_OUTPUT_DATASET")
21
  HF_OUTPUT_DATASET_DIR = os.getenv("HF_OUTPUT_DATASET_DIR")
22
  INSTRUCTIONS = """
23
- # Pairwise Model Output Labeling
 
 
 
 
 
 
 
 
 
 
 
 
24
  Please compare the two model outputs shown below and select which one you think is better.
25
  - Choose "A is better" if the output from Model A (left) is superior
26
  - Choose "B is better" if the output from Model B (right) is superior
27
- - Choose "Tie" if you think they are equally good or bad
28
  - Choose "Can't choose" if you cannot make a determination
29
  """
30
  SAVE_EVERY_N_EXAMPLES = 5
@@ -34,11 +46,12 @@ class PairwiseLabeler:
34
  def __init__(self):
35
  self.current_index = defaultdict(int)
36
  self.results = defaultdict(list)
37
- self.df = self.read_hf_dataset()
38
- self.has_url_column = HF_INPUT_DATASET_URL_COLUMN and HF_INPUT_DATASET_URL_COLUMN in self.df.columns
 
39
 
40
  def __len__(self):
41
- return len(self.df)
42
 
43
  def read_hf_dataset(self) -> pd.DataFrame:
44
  try:
@@ -69,13 +82,16 @@ class PairwiseLabeler:
69
  return pd.DataFrame(sample_data)
70
 
71
  def get_current_pair(self, session_id):
72
- if self.current_index[session_id] >= len(self.df):
 
 
 
73
  if self.has_url_column:
74
  return None, None, None, None
75
  else:
76
  return None, None, None
77
 
78
- item = self.df.iloc[self.current_index[session_id]]
79
  item_id = item.get(HF_INPUT_DATASET_ID_COLUMN, f"item_{self.current_index[session_id]}")
80
  left_text = item.get(HF_INPUT_DATASET_COLUMN_A, "")
81
  right_text = item.get(HF_INPUT_DATASET_COLUMN_B, "")
@@ -93,11 +109,6 @@ class PairwiseLabeler:
93
  else:
94
  return item_id, left_text, right_text, self.current_index[session_id]
95
 
96
- # Get the current URL if available
97
- current_url = None
98
- if self.has_url_column:
99
- current_url = self.df.iloc[self.current_index[session_id]].get(HF_INPUT_DATASET_URL_COLUMN, "")
100
-
101
  # Record the judgment
102
  result = {
103
  "item_id": item_id,
@@ -105,7 +116,7 @@ class PairwiseLabeler:
105
  "timestamp": datetime.datetime.now().isoformat(),
106
  "labeler_id": session_id
107
  }
108
-
109
  self.results[session_id].append(result)
110
 
111
  # Move to next item
@@ -158,27 +169,44 @@ class PairwiseLabeler:
158
  # Initialize the labeler
159
  labeler = PairwiseLabeler()
160
 
161
- # Create a unique session ID
162
- def create_new_session():
163
  return str(uuid.uuid4())[:8]
164
 
165
- with gr.Blocks() as app:
 
 
 
 
 
 
 
 
 
166
  # State for the session ID
167
  session_id = gr.State(value=None)
 
168
 
169
- # The actual interface components will be created here
170
  gr.Markdown(INSTRUCTIONS)
171
 
 
 
 
 
 
 
 
 
172
  # URL display component - only shown if URL column is defined
173
- url_display = None
174
  if labeler.has_url_column:
175
- url_display = gr.HTML(label="Reference URL")
176
-
177
- session_id_display = gr.Textbox(label="Session Information", interactive=False)
178
 
 
179
  with gr.Row():
180
  with gr.Column():
181
  left_output = gr.Textbox(
 
182
  label="Model A Output",
183
  lines=10,
184
  interactive=False
@@ -186,68 +214,109 @@ with gr.Blocks() as app:
186
 
187
  with gr.Column():
188
  right_output = gr.Textbox(
 
189
  label="Model B Output",
190
  lines=10,
191
  interactive=False
192
  )
193
 
194
- item_id = gr.Textbox(visible=False)
195
 
 
196
  with gr.Row():
197
- left_btn = gr.Button("⬅️ A is better", variant="primary")
198
- right_btn = gr.Button("➡️ B is better", variant="primary")
199
- tie_btn = gr.Button("🤝 Tie", variant="primary")
200
- cant_choose_btn = gr.Button("🤔 Can't choose")
201
-
202
- current_sample_sld = gr.Slider(minimum=0, maximum=len(labeler), step=1,
203
- interactive=False,
204
- label='sample_ind',
205
- info=f"Samples labeled (out of {len(labeler)})",
206
- show_label=False,
207
- container=False,
208
- scale=5)
209
 
 
 
 
 
 
 
 
 
 
 
 
210
  # Initialize the session and get the first pair
211
- def init_session():
212
- new_session_id = create_new_session()
 
213
 
 
214
  if labeler.has_url_column:
215
- initial_id, initial_left, initial_right, initial_url = labeler.get_current_pair(new_session_id)
216
  url_html = f'<a href="{initial_url}" target="_blank">{initial_url}</a>' if initial_url else ""
217
 
218
  return (
219
- new_session_id, # session_id state
220
- f"Session ID: {new_session_id}", # session_id_display
221
- url_html, # url_display
222
- initial_left, # left_output
223
- initial_right, # right_output
224
- initial_id, # item_id
225
- labeler.current_index[new_session_id] # current_sample_sld
 
 
 
 
226
  )
227
  else:
228
- initial_id, initial_left, initial_right = labeler.get_current_pair(new_session_id)
 
 
 
229
 
230
  return (
231
- new_session_id, # session_id state
232
- f"Session ID: {new_session_id}", # session_id_display
233
- initial_left, # left_output
234
- initial_right, # right_output
235
- initial_id, # item_id
236
- labeler.current_index[new_session_id] # current_sample_sld
 
 
 
 
237
  )
238
 
239
- # Run the initialization when the app loads
240
  if labeler.has_url_column:
241
- app.load(
242
  init_session,
243
- inputs=None,
244
- outputs=[session_id, session_id_display, url_display, left_output, right_output, item_id, current_sample_sld]
 
 
 
 
 
 
 
 
 
 
 
 
245
  )
246
  else:
247
- app.load(
248
  init_session,
249
- inputs=None,
250
- outputs=[session_id, session_id_display, left_output, right_output, item_id, current_sample_sld]
 
 
 
 
 
 
 
 
 
 
 
251
  )
252
 
253
  def judge_left(session_id, item_id, left_text, right_text):
@@ -263,17 +332,29 @@ with gr.Blocks() as app:
263
  return judge("Can't choose", session_id, item_id, left_text, right_text)
264
 
265
  def judge(choice, session_id, item_id, left_text, right_text):
 
 
 
 
266
  if labeler.has_url_column:
267
  new_id, new_left, new_right, new_url, new_index = labeler.submit_judgment(
268
  item_id, left_text, right_text, choice, session_id
269
  )
270
  url_html = f'<a href="{new_url}" target="_blank">{new_url}</a>' if new_url else ""
271
- return new_id, new_left, new_right, url_html, new_index
 
 
 
 
272
  else:
273
  new_id, new_left, new_right, new_index = labeler.submit_judgment(
274
  item_id, left_text, right_text, choice, session_id
275
  )
276
- return new_id, new_left, new_right, new_index
 
 
 
 
277
 
278
  if labeler.has_url_column:
279
  left_btn.click(
@@ -325,4 +406,4 @@ with gr.Blocks() as app:
325
  )
326
 
327
  if __name__ == "__main__":
328
- app.launch()
 
20
  HF_OUTPUT_DATASET = os.getenv("HF_OUTPUT_DATASET")
21
  HF_OUTPUT_DATASET_DIR = os.getenv("HF_OUTPUT_DATASET_DIR")
22
  INSTRUCTIONS = """
23
+ # Pairwise Model Output Labeling Space
24
+
25
+ ### How-to:
26
+
27
+ * Duplicate this Space
28
+ * Add a `HF_TOKEN` secret in the Space settings (it saves the results to a given dataset, so it requires write access)
29
+ * Set the environment variables in the [`.env`](https://huggingface.co/spaces/saridormi/labeling-template/blob/main/.env) file to point to correct datasets/columns/paths for your input and output data
30
+ * Adjust `INSTRUCTIONS` (it's what's rendered here) and `SAVE_EVERY_N_EXAMPLES` (how often should answers be saved to the output dataset) in the [`app.py`](https://huggingface.co/spaces/saridormi/labeling-template/blob/main/app.py) file
31
+
32
+ Done! 💛
33
+
34
+ ### About:
35
+
36
  Please compare the two model outputs shown below and select which one you think is better.
37
  - Choose "A is better" if the output from Model A (left) is superior
38
  - Choose "B is better" if the output from Model B (right) is superior
39
+ - Choose "Tie" if they are equally good or bad
40
  - Choose "Can't choose" if you cannot make a determination
41
  """
42
  SAVE_EVERY_N_EXAMPLES = 5
 
46
  def __init__(self):
47
  self.current_index = defaultdict(int)
48
  self.results = defaultdict(list)
49
+ self._df = self.read_hf_dataset()
50
+ self.df = {}
51
+ self.has_url_column = HF_INPUT_DATASET_URL_COLUMN and HF_INPUT_DATASET_URL_COLUMN in self._df.columns
52
 
53
  def __len__(self):
54
+ return len(self._df)
55
 
56
  def read_hf_dataset(self) -> pd.DataFrame:
57
  try:
 
82
  return pd.DataFrame(sample_data)
83
 
84
  def get_current_pair(self, session_id):
85
+ if session_id not in self.df:
86
+ self.df[session_id] = self._df.sample(frac=1).reset_index(drop=True)
87
+
88
+ if self.current_index[session_id] >= len(self.df[session_id]):
89
  if self.has_url_column:
90
  return None, None, None, None
91
  else:
92
  return None, None, None
93
 
94
+ item = self.df[session_id].iloc[self.current_index[session_id]]
95
  item_id = item.get(HF_INPUT_DATASET_ID_COLUMN, f"item_{self.current_index[session_id]}")
96
  left_text = item.get(HF_INPUT_DATASET_COLUMN_A, "")
97
  right_text = item.get(HF_INPUT_DATASET_COLUMN_B, "")
 
109
  else:
110
  return item_id, left_text, right_text, self.current_index[session_id]
111
 
 
 
 
 
 
112
  # Record the judgment
113
  result = {
114
  "item_id": item_id,
 
116
  "timestamp": datetime.datetime.now().isoformat(),
117
  "labeler_id": session_id
118
  }
119
+
120
  self.results[session_id].append(result)
121
 
122
  # Move to next item
 
169
  # Initialize the labeler
170
  labeler = PairwiseLabeler()
171
 
172
+ # Create a default session ID
173
+ def create_default_session():
174
  return str(uuid.uuid4())[:8]
175
 
176
+ # Create a demo session ID for initial display
177
+ demo_session = create_default_session()
178
+ demo_item_id, demo_left_text, demo_right_text = None, "", ""
179
+ demo_url = None
180
+ if labeler.has_url_column:
181
+ demo_item_id, demo_left_text, demo_right_text, demo_url = labeler.get_current_pair(demo_session)
182
+ else:
183
+ demo_item_id, demo_left_text, demo_right_text = labeler.get_current_pair(demo_session)
184
+
185
+ with gr.Blocks(css="footer {visibility: hidden}") as app:
186
  # State for the session ID
187
  session_id = gr.State(value=None)
188
+ is_session_started = gr.State(value=False)
189
 
190
+ # Header with instructions
191
  gr.Markdown(INSTRUCTIONS)
192
 
193
+ # Session and progress bar in one line
194
+ user_session_id = gr.Textbox(
195
+ placeholder="Enter your unique ID or leave blank for random",
196
+ label="Session ID",
197
+ scale=2
198
+ )
199
+ start_btn = gr.Button("Start Session", variant="primary", scale=1)
200
+
201
  # URL display component - only shown if URL column is defined
 
202
  if labeler.has_url_column:
203
+ url_display = gr.HTML(label="Reference URL", value="", visible=True)
 
 
204
 
205
+ # Main content area (shown with placeholder text)
206
  with gr.Row():
207
  with gr.Column():
208
  left_output = gr.Textbox(
209
+ value=demo_left_text,
210
  label="Model A Output",
211
  lines=10,
212
  interactive=False
 
214
 
215
  with gr.Column():
216
  right_output = gr.Textbox(
217
+ value=demo_right_text,
218
  label="Model B Output",
219
  lines=10,
220
  interactive=False
221
  )
222
 
223
+ item_id = gr.Textbox(value=demo_item_id, visible=False)
224
 
225
+ # Buttons row (initially disabled)
226
  with gr.Row():
227
+ left_btn = gr.Button("⬅️ A is better", variant="primary", interactive=False)
228
+ right_btn = gr.Button("➡️ B is better", variant="primary", interactive=False)
229
+ tie_btn = gr.Button("🤝 Tie", variant="primary", interactive=False)
230
+ cant_choose_btn = gr.Button("🤔 Can't choose", interactive=False)
 
 
 
 
 
 
 
 
231
 
232
+ # Progress slider (initially disabled)
233
+ current_sample_sld = gr.Slider(
234
+ minimum=0,
235
+ maximum=len(labeler),
236
+ step=1,
237
+ value=0,
238
+ interactive=False,
239
+ label='Progress',
240
+ show_label=False
241
+ )
242
+
243
  # Initialize the session and get the first pair
244
+ def init_session(entered_id):
245
+ # Use entered ID or generate a new one if empty
246
+ session_id_value = entered_id.strip() if entered_id and entered_id.strip() else create_default_session()
247
 
248
+ # Get the initial data for this session ID
249
  if labeler.has_url_column:
250
+ initial_id, initial_left, initial_right, initial_url = labeler.get_current_pair(session_id_value)
251
  url_html = f'<a href="{initial_url}" target="_blank">{initial_url}</a>' if initial_url else ""
252
 
253
  return (
254
+ session_id_value, # session_id state
255
+ True, # is_session_started state
256
+ labeler.current_index[session_id_value], # current_sample_sld
257
+ url_html, # url_display
258
+ initial_left, # left_output
259
+ initial_right, # right_output
260
+ initial_id, # item_id
261
+ gr.update(interactive=True), # left_btn
262
+ gr.update(interactive=True), # right_btn
263
+ gr.update(interactive=True), # tie_btn
264
+ gr.update(interactive=True) # cant_choose_btn
265
  )
266
  else:
267
+ initial_id, initial_left, initial_right = labeler.get_current_pair(session_id_value)
268
+
269
+ # Create session info text
270
+ progress_text = f"Session: {session_id_value} | {labeler.current_index[session_id_value] + 1}/{len(labeler)}"
271
 
272
  return (
273
+ session_id_value, # session_id state
274
+ True, # is_session_started state
275
+ labeler.current_index[session_id_value], # current_sample_sld
276
+ initial_left, # left_output
277
+ initial_right, # right_output
278
+ initial_id, # item_id
279
+ gr.update(interactive=True), # left_btn
280
+ gr.update(interactive=True), # right_btn
281
+ gr.update(interactive=True), # tie_btn
282
+ gr.update(interactive=True) # cant_choose_btn
283
  )
284
 
285
+ # Connect the start button
286
  if labeler.has_url_column:
287
+ start_btn.click(
288
  init_session,
289
+ inputs=[user_session_id],
290
+ outputs=[
291
+ session_id,
292
+ is_session_started,
293
+ current_sample_sld,
294
+ url_display,
295
+ left_output,
296
+ right_output,
297
+ item_id,
298
+ left_btn,
299
+ right_btn,
300
+ tie_btn,
301
+ cant_choose_btn
302
+ ]
303
  )
304
  else:
305
+ start_btn.click(
306
  init_session,
307
+ inputs=[user_session_id],
308
+ outputs=[
309
+ session_id,
310
+ is_session_started,
311
+ current_sample_sld,
312
+ left_output,
313
+ right_output,
314
+ item_id,
315
+ left_btn,
316
+ right_btn,
317
+ tie_btn,
318
+ cant_choose_btn
319
+ ]
320
  )
321
 
322
  def judge_left(session_id, item_id, left_text, right_text):
 
332
  return judge("Can't choose", session_id, item_id, left_text, right_text)
333
 
334
  def judge(choice, session_id, item_id, left_text, right_text):
335
+ if not session_id:
336
+ # Session not initialized, do nothing
337
+ return item_id, left_text, right_text, 0, "Not started"
338
+
339
  if labeler.has_url_column:
340
  new_id, new_left, new_right, new_url, new_index = labeler.submit_judgment(
341
  item_id, left_text, right_text, choice, session_id
342
  )
343
  url_html = f'<a href="{new_url}" target="_blank">{new_url}</a>' if new_url else ""
344
+
345
+ # Update session info text with new progress
346
+ progress_text = f"Session: {session_id} | {new_index + 1}/{len(labeler)}" if new_index < len(labeler) else f"Session: {session_id} | Complete! {len(labeler)}/{len(labeler)}"
347
+
348
+ return new_id, new_left, new_right, url_html, new_index, progress_text
349
  else:
350
  new_id, new_left, new_right, new_index = labeler.submit_judgment(
351
  item_id, left_text, right_text, choice, session_id
352
  )
353
+
354
+ # Update session info text with new progress
355
+ progress_text = f"Session: {session_id} | {new_index + 1}/{len(labeler)}" if new_index < len(labeler) else f"Session: {session_id} | Complete! {len(labeler)}/{len(labeler)}"
356
+
357
+ return new_id, new_left, new_right, new_index, progress_text
358
 
359
  if labeler.has_url_column:
360
  left_btn.click(
 
406
  )
407
 
408
  if __name__ == "__main__":
409
+ app.launch()