DataEval commited on
Commit
28b65b3
·
verified ·
1 Parent(s): 95cc0d2

update v2.0

Browse files
Files changed (1) hide show
  1. app.py +279 -218
app.py CHANGED
@@ -14,17 +14,17 @@ from dingo.model import Model
14
 
15
  def dingo_demo(
16
  uploaded_file,
17
- dataset_source, data_format, input_path, max_workers, batch_size,
18
- column_id, column_prompt, column_content, column_image,
19
- rule_list, prompt_list, scene_list,
20
- model, key, api_url
 
21
  ):
22
  if not data_format:
23
  raise gr.Error('ValueError: data_format can not be empty, please input.')
24
- # if not column_content:
25
- # raise gr.Error('ValueError: column_content can not be empty, please input.')
26
- if not rule_list and not prompt_list:
27
- raise gr.Error('ValueError: rule_list and prompt_list can not be empty at the same time.')
28
 
29
  # Handle input path based on dataset source
30
  if dataset_source == "hugging_face":
@@ -47,42 +47,127 @@ def dingo_demo(
47
  raise gr.Error('Please input value > 0 in batch_size.')
48
 
49
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  input_data = {
51
  "input_path": final_input_path,
52
  "output_path": "" if dataset_source == 'hugging_face' else os.path.dirname(final_input_path),
53
  "dataset": {
54
  "source": dataset_source,
55
  "format": data_format,
56
- "field": {}
57
  },
58
  "executor": {
59
- "rule_list": rule_list,
60
- "prompt_list": prompt_list,
61
  "result_save": {
62
  "bad": True,
63
- "raw": True
64
  },
65
  "max_workers": max_workers,
66
  "batch_size": batch_size,
67
  },
68
- "evaluator": {
69
- "llm_config": {
70
- scene_list: {
71
- "model": model,
72
- "key": key,
73
- "api_url": api_url,
74
- }
75
  }
76
- }
77
  }
78
- if column_id:
79
- input_data['dataset']['field']['id'] = column_id
80
- if column_prompt:
81
- input_data['dataset']['field']['prompt'] = column_prompt
82
- if column_content:
83
- input_data['dataset']['field']['content'] = column_content
84
- if column_image:
85
- input_data['dataset']['field']['image'] = column_image
86
 
87
  # print(input_data)
88
  # exit(0)
@@ -91,28 +176,33 @@ def dingo_demo(
91
  executor = Executor.exec_map["local"](input_args)
92
  summary = executor.execute().to_dict()
93
  detail = executor.get_bad_info_list()
 
94
  new_detail = []
95
  for item in detail:
96
- new_detail.append(item)
 
 
97
  if summary['output_path']:
98
- shutil.rmtree(summary['output_path'])
 
 
99
 
100
- # 返回两个值:概要信息和详细信息
101
  return json.dumps(summary, indent=4), new_detail
102
  except Exception as e:
103
  raise gr.Error(str(e))
104
 
105
 
106
  def update_input_components(dataset_source):
107
- # 根据数据源的不同,返回不同的输入组件
108
  if dataset_source == "hugging_face":
109
- # 如果数据源是huggingface,返回一个可见的文本框和一个不可见的文件组件
110
  return [
111
  gr.Textbox(visible=True),
112
  gr.File(visible=False),
113
  ]
114
  else: # local
115
- # 如果数据源是本地,返回一个不可见的文本框和一个可见的文件组件
116
  return [
117
  gr.Textbox(visible=False),
118
  gr.File(visible=True),
@@ -123,72 +213,66 @@ def update_rule_list(rule_type_mapping, rule_type):
123
  return gr.CheckboxGroup(
124
  choices=rule_type_mapping.get(rule_type, []),
125
  value=[],
126
- label="rule_list"
 
127
  )
128
 
129
 
130
- def update_prompt_list(scene_prompt_mapping, scene):
131
- """根据选择的场景更新可用的prompt列表,并清空所有勾选"""
132
- return gr.CheckboxGroup(
133
- choices=scene_prompt_mapping.get(scene, []),
134
- value=[], # 清空所有勾选
135
- label="prompt_list"
136
- )
 
 
 
 
 
137
 
138
 
139
- # prompt_list变化时,动态控制model、key、api_url的显示
140
- def toggle_llm_fields(prompt_values):
141
- visible = bool(prompt_values)
142
- return (
143
- gr.update(visible=visible),
144
- gr.update(visible=visible),
145
- gr.update(visible=visible)
146
- )
 
147
 
 
148
 
149
- # 控制column_id、column_prompt、column_content、column_image的显示
150
- def update_column_fields(rule_list, prompt_list):
 
 
 
 
151
  rule_type_mapping = get_rule_type_mapping()
152
- scene_prompt_mapping = get_scene_prompt_mapping()
153
  data_column_mapping = get_data_column_mapping()
154
- status_mapping = {
155
- 'id': False,
156
- 'prompt': False,
157
- 'content': False,
158
- 'image': False,
159
- }
160
 
161
- res = (
162
- gr.update(visible=status_mapping['id']),
163
- gr.update(visible=status_mapping['prompt']),
164
- gr.update(visible=status_mapping['content']),
165
- gr.update(visible=status_mapping['image'])
166
- )
167
- if not rule_list and not prompt_list:
168
- return res
169
 
170
- key_list = []
171
- key_list += get_key_by_mapping(rule_type_mapping, rule_list)
172
- key_list += get_key_by_mapping(scene_prompt_mapping, prompt_list)
 
 
173
 
174
- data_column = []
175
- for key in key_list:
176
- if not data_column:
177
- data_column = data_column_mapping[key]
178
- else:
179
- new_data_column = data_column_mapping[key]
180
- if data_column != new_data_column:
181
- raise gr.Error(f'ConflictError: {key} need data type is different from other.')
182
-
183
- for c in data_column:
184
- status_mapping[c] = True
185
- res = (
186
- gr.update(visible=status_mapping['id']),
187
- gr.update(visible=status_mapping['prompt']),
188
- gr.update(visible=status_mapping['content']),
189
- gr.update(visible=status_mapping['image'])
190
- )
191
- return res
192
 
193
 
194
  def get_rule_type_mapping():
@@ -208,50 +292,32 @@ def get_rule_type_mapping():
208
  return process_map
209
 
210
 
211
- def get_scene_prompt_mapping():
212
- origin_map = Model.get_scenario_prompt_map()
213
- process_map = {'LLMTextQualityModelBase': [], 'LLMTextQualityPromptBase': []} # can adjust the order
214
- for k, v in origin_map.items():
215
- for p in v:
216
- if k not in process_map:
217
- process_map[k] = []
218
- process_map[k].append(p.__name__)
219
- # print(process_map)
220
-
221
- return process_map
222
-
223
-
224
- def get_key_by_mapping(map_dict: dict, value_list: list):
225
- key_list = []
226
- for k, v in map_dict.items():
227
- if bool(set(v) & set(value_list)):
228
- key_list.append(k)
229
-
230
- return key_list
 
231
 
232
 
233
  def get_data_column_mapping():
234
  return {
235
- # llm
236
- 'LLMTextQualityPromptBase': ['content'],
237
- 'LLMTextQualityModelBase': ['content'],
238
- 'LLMSecurityPolitics': ['content'],
239
- 'LLMSecurityProhibition': ['content'],
240
- 'LLMText3HHarmless': ['content'],
241
- 'LLMText3HHelpful': ['content'],
242
- 'LLMText3HHonest': ['content'],
243
- 'LLMClassifyTopic': ['content'],
244
- 'LLMClassifyQR': ['content'],
245
- 'LLMDatamanAssessment': ['content'],
246
- 'VLMImageRelevant': ['prompt', 'content'],
247
-
248
- # rule
249
- # 'QUALITY_BAD_COMPLETENESS': ['content'],
250
- # 'QUALITY_BAD_EFFECTIVENESS': ['content'],
251
- # 'QUALITY_BAD_FLUENCY': ['content'],
252
- # 'QUALITY_BAD_RELEVANCE': ['content'],
253
- # 'QUALITY_BAD_SIMILARITY': ['content'],
254
- # 'QUALITY_BAD_UNDERSTANDABILITY': ['content'],
255
  'Rule-Based TEXT Quality Metrics': ['content'],
256
  'QUALITY_BAD_SECURITY': ['content'],
257
  'QUALITY_BAD_IMG_EFFECTIVENESS': ['image'],
@@ -264,8 +330,7 @@ if __name__ == '__main__':
264
  rule_type_mapping = get_rule_type_mapping()
265
  rule_type_options = list(rule_type_mapping.keys())
266
 
267
- scene_prompt_mapping = get_scene_prompt_mapping()
268
- scene_options = list(scene_prompt_mapping.keys())
269
 
270
  current_dir = Path(__file__).parent
271
  with open(os.path.join(current_dir, 'header.html'), "r") as file:
@@ -291,10 +356,16 @@ if __name__ == '__main__':
291
  visible=False
292
  )
293
 
294
- data_format = gr.Dropdown(
295
- ["jsonl", "json", "plaintext", "listjson","image"],
296
- label="data_format"
297
- )
 
 
 
 
 
 
298
  with gr.Row():
299
  max_workers = gr.Number(
300
  value=1,
@@ -313,84 +384,72 @@ if __name__ == '__main__':
313
  rule_type = gr.Dropdown(
314
  choices=rule_type_options,
315
  value=rule_type_options[0],
316
- label="rule_type",
317
  interactive=True
318
  )
319
  rule_list = gr.CheckboxGroup(
320
  choices=rule_type_mapping.get(rule_type_options[0], []),
321
- label="rule_list"
 
322
  )
323
- # 添加场景选择下拉框
324
- scene_list = gr.Dropdown(
325
- choices=scene_options,
326
- value=scene_options[0],
327
- label="scenario_list",
328
- interactive=True
329
  )
330
- prompt_list = gr.CheckboxGroup(
331
- choices=scene_prompt_mapping.get(scene_options[0], []),
332
- label="prompt_list"
333
- )
334
- # LLM模型名
335
- model = gr.Textbox(
336
- placeholder="If want to use llm, please input model, such as: deepseek-chat",
337
- label="model",
338
- visible=False
339
- )
340
- # LLM API KEY
341
- key = gr.Textbox(
342
- placeholder="If want to use llm, please input key, such as: 123456789012345678901234567890xx",
343
- label="API KEY",
344
- visible=False
345
  )
346
- # LLM API URL
347
- api_url = gr.Textbox(
348
- placeholder="If want to use llm, please input api_url, such as: https://api.deepseek.com/v1",
349
- label="API URL",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  visible=False
351
  )
352
 
353
- with gr.Row():
354
- # 字段映射说明文本,带示例链接
355
- with gr.Column():
356
- gr.Markdown(
357
- "Please input the column name of dataset in the input boxes below ( [examples](https://github.com/MigoXLab/dingo/tree/main/examples) )")
358
-
359
- column_id = gr.Textbox(
360
- value="",
361
- placeholder="Column name of id in the input file. If exists multiple levels, use '.' separate",
362
- label="column_id",
363
- visible=False
364
- )
365
- column_prompt = gr.Textbox(
366
- value="",
367
- placeholder="Column name of prompt in the input file. If exists multiple levels, use '.' separate",
368
- label="column_prompt",
369
- visible=False
370
- )
371
- column_content = gr.Textbox(
372
- value="content",
373
- placeholder="Column name of content in the input file. If exists multiple levels, use '.' separate",
374
- label="column_content",
375
- visible=False
376
- )
377
- column_image = gr.Textbox(
378
- value="",
379
- placeholder="Column name of image in the input file. If exists multiple levels, use '.' separate",
380
- label="column_image",
381
- visible=False
382
- )
383
-
384
  with gr.Row():
385
  submit_single = gr.Button(value="Submit", interactive=True, variant="primary")
386
 
387
  with gr.Column():
388
- # 修改输出组件部分,使用Tabs
389
  with gr.Tabs():
390
  with gr.Tab("Result Summary"):
391
- summary_output = gr.JSON(label="summary", max_height=800)
392
  with gr.Tab("Result Detail"):
393
- detail_output = gr.JSON(label="detail", max_height=800) # 使用JSON组件来更好地展示结构化数据
394
 
395
  dataset_source.change(
396
  fn=update_input_components,
@@ -404,38 +463,40 @@ if __name__ == '__main__':
404
  outputs=rule_list
405
  )
406
 
407
- # 场景变化时更新prompt列表
408
- scene_list.change(
409
- fn=partial(update_prompt_list, scene_prompt_mapping),
410
- inputs=scene_list,
411
- outputs=prompt_list
412
- )
413
-
414
- prompt_list.change(
415
- fn=toggle_llm_fields,
416
- inputs=prompt_list,
417
- outputs=[model, key, api_url]
 
418
  )
419
 
420
- # column字段显示控制
421
- for comp in [rule_list, prompt_list]:
422
  comp.change(
423
- fn=update_column_fields,
424
- inputs=[rule_list, prompt_list],
425
- outputs=[column_id, column_prompt, column_content, column_image]
426
  )
427
 
428
  submit_single.click(
429
  fn=dingo_demo,
430
  inputs=[
431
  uploaded_file,
432
- dataset_source, data_format, input_path, max_workers, batch_size,
433
- column_id, column_prompt, column_content, column_image,
434
- rule_list, prompt_list, scene_list,
435
- model, key, api_url
 
436
  ],
437
- outputs=[summary_output, detail_output] # 修改输出为两个组件
438
  )
439
 
440
- # 启动界面
441
- demo.launch(share=True)
 
14
 
15
  def dingo_demo(
16
  uploaded_file,
17
+ dataset_source, data_format, remove_output, input_path, max_workers, batch_size,
18
+ fields_data,
19
+ rule_list, llm_list,
20
+ # rule_config_data,
21
+ llm_config_data
22
  ):
23
  if not data_format:
24
  raise gr.Error('ValueError: data_format can not be empty, please input.')
25
+
26
+ if not rule_list and not llm_list:
27
+ raise gr.Error('ValueError: rule_list and llm_list can not be empty at the same time.')
 
28
 
29
  # Handle input path based on dataset source
30
  if dataset_source == "hugging_face":
 
47
  raise gr.Error('Please input value > 0 in batch_size.')
48
 
49
  try:
50
+ # Parse fields from dataframe
51
+ fields = {}
52
+ if fields_data is not None and len(fields_data) > 0:
53
+ for row in fields_data.values.tolist():
54
+ if len(row) >= 2 and row[0] and row[1]: # Both key and value are not empty
55
+ fields[row[0]] = row[1]
56
+
57
+ # Parse rule configs from dataframe
58
+ rule_configs = {}
59
+ # if rule_config_data is not None and len(rule_config_data) > 0:
60
+ # for row in rule_config_data.values.tolist():
61
+ # if len(row) >= 6 and row[0]: # Rule name exists
62
+ # rule_name = row[0]
63
+ # config = {}
64
+ #
65
+ # # threshold
66
+ # if row[1] is not None and str(row[1]).strip():
67
+ # try:
68
+ # config['threshold'] = float(row[1])
69
+ # except:
70
+ # pass
71
+ #
72
+ # # pattern
73
+ # if row[2] and str(row[2]).strip():
74
+ # config['pattern'] = str(row[2])
75
+ #
76
+ # # key_list
77
+ # if row[3] and str(row[3]).strip():
78
+ # try:
79
+ # val = str(row[3])
80
+ # config['key_list'] = json.loads(val) if val.startswith('[') else [k.strip() for k in val.split(',') if k.strip()]
81
+ # except:
82
+ # config['key_list'] = [k.strip() for k in str(row[3]).split(',') if k.strip()]
83
+ #
84
+ # # refer_path
85
+ # if row[4] and str(row[4]).strip():
86
+ # try:
87
+ # val = str(row[4])
88
+ # config['refer_path'] = json.loads(val) if val.startswith('[') else [p.strip() for p in val.split(',') if p.strip()]
89
+ # except:
90
+ # config['refer_path'] = [p.strip() for p in str(row[4]).split(',') if p.strip()]
91
+ #
92
+ # # parameters
93
+ # if row[5] and str(row[5]).strip():
94
+ # try:
95
+ # config['parameters'] = json.loads(str(row[5]))
96
+ # except:
97
+ # pass
98
+ #
99
+ # if config:
100
+ # rule_configs[rule_name] = config
101
+
102
+ # Parse llm configs from dataframe
103
+ llm_configs = {}
104
+ if llm_config_data is not None and len(llm_config_data) > 0:
105
+ for row in llm_config_data.values.tolist():
106
+ if len(row) >= 5 and row[0]: # LLM name exists
107
+ llm_name = row[0]
108
+ config = {}
109
+
110
+ # model
111
+ if row[1] and str(row[1]).strip():
112
+ config['model'] = str(row[1])
113
+
114
+ # key
115
+ if row[2] and str(row[2]).strip():
116
+ config['key'] = str(row[2])
117
+
118
+ # api_url
119
+ if row[3] and str(row[3]).strip():
120
+ config['api_url'] = str(row[3])
121
+
122
+ # parameters
123
+ if row[4] and str(row[4]).strip():
124
+ try:
125
+ config['parameters'] = json.loads(str(row[4]))
126
+ except json.JSONDecodeError as e:
127
+ raise gr.Error(f"Invalid JSON in 'parameters' for LLM '{llm_name}': {e}")
128
+
129
+ if config:
130
+ llm_configs[llm_name] = config
131
+
132
+ # Build evals array
133
+ evals = []
134
+
135
+ # Add rule evaluators and their configurations
136
+ for rule in rule_list:
137
+ eval_item = {"name": rule}
138
+ if rule in rule_configs:
139
+ eval_item["config"] = rule_configs[rule]
140
+ evals.append(eval_item)
141
+
142
+ # Add LLM evaluators and their configurations
143
+ for llm in llm_list:
144
+ eval_item = {"name": llm}
145
+ if llm in llm_configs:
146
+ eval_item["config"] = llm_configs[llm]
147
+ evals.append(eval_item)
148
+
149
  input_data = {
150
  "input_path": final_input_path,
151
  "output_path": "" if dataset_source == 'hugging_face' else os.path.dirname(final_input_path),
152
  "dataset": {
153
  "source": dataset_source,
154
  "format": data_format,
 
155
  },
156
  "executor": {
 
 
157
  "result_save": {
158
  "bad": True,
159
+ # "raw": True
160
  },
161
  "max_workers": max_workers,
162
  "batch_size": batch_size,
163
  },
164
+ "evaluator": [
165
+ {
166
+ "fields": fields,
167
+ "evals": evals
 
 
 
168
  }
169
+ ]
170
  }
 
 
 
 
 
 
 
 
171
 
172
  # print(input_data)
173
  # exit(0)
 
176
  executor = Executor.exec_map["local"](input_args)
177
  summary = executor.execute().to_dict()
178
  detail = executor.get_bad_info_list()
179
+ dingo_id_set = set()
180
  new_detail = []
181
  for item in detail:
182
+ if item['dingo_id'] not in dingo_id_set:
183
+ dingo_id_set.add(item['dingo_id'])
184
+ new_detail.append(item)
185
  if summary['output_path']:
186
+ if remove_output == "true":
187
+ shutil.rmtree(summary['output_path'])
188
+ summary['output_path'] = ""
189
 
190
+ # Return summary and detail information
191
  return json.dumps(summary, indent=4), new_detail
192
  except Exception as e:
193
  raise gr.Error(str(e))
194
 
195
 
196
  def update_input_components(dataset_source):
197
+ # Return different input components based on data source
198
  if dataset_source == "hugging_face":
199
+ # If data source is huggingface, return a visible textbox and an invisible file component
200
  return [
201
  gr.Textbox(visible=True),
202
  gr.File(visible=False),
203
  ]
204
  else: # local
205
+ # If data source is local, return an invisible textbox and a visible file component
206
  return [
207
  gr.Textbox(visible=False),
208
  gr.File(visible=True),
 
213
  return gr.CheckboxGroup(
214
  choices=rule_type_mapping.get(rule_type, []),
215
  value=[],
216
+ label="rule_list",
217
+ elem_classes="limited-height-checkboxgroup"
218
  )
219
 
220
 
221
+ # Generate configuration dataframes based on selected evaluators
222
+ # def generate_rule_config_dataframe(rule_list):
223
+ # """Generate rule configuration dataframe based on selected rules"""
224
+ # if not rule_list:
225
+ # return gr.update(value=[], visible=False)
226
+ #
227
+ # # Create rows for each rule
228
+ # rows = []
229
+ # for rule in rule_list:
230
+ # rows.append([rule, None, "", "", "", ""])
231
+ #
232
+ # return gr.update(value=rows, visible=True)
233
 
234
 
235
+ def generate_llm_config_dataframe(llm_list):
236
+ """Generate LLM configuration dataframe based on selected LLMs"""
237
+ if not llm_list:
238
+ return gr.update(value=[], visible=False)
239
+
240
+ # Create rows for each LLM
241
+ rows = []
242
+ for llm in llm_list:
243
+ rows.append([llm, "deepseek-chat", "your-api-key", "https://api.deepseek.com/v1", ""])
244
 
245
+ return gr.update(value=rows, visible=True)
246
 
247
+
248
+ def suggest_fields_dataframe(rule_list, llm_list):
249
+ """Suggest required field mappings based on selected evaluators"""
250
+ suggested_fields = set()
251
+
252
+ # Fields required by rule evaluators
253
  rule_type_mapping = get_rule_type_mapping()
 
254
  data_column_mapping = get_data_column_mapping()
 
 
 
 
 
 
255
 
256
+ for rule in rule_list:
257
+ # Find which type this rule belongs to
258
+ for rule_type, rules in rule_type_mapping.items():
259
+ if rule in rules:
260
+ if rule_type in data_column_mapping:
261
+ suggested_fields.update(data_column_mapping[rule_type])
262
+ break
 
263
 
264
+ # Fields required by LLM evaluators
265
+ llm_column_mapping = get_llm_column_mapping()
266
+ for llm in llm_list:
267
+ if llm in llm_column_mapping:
268
+ suggested_fields.update(llm_column_mapping[llm])
269
 
270
+ # Generate suggested fields rows
271
+ rows = []
272
+ for field in sorted(suggested_fields):
273
+ rows.append([field, field])
274
+
275
+ return gr.update(value=rows if rows else [["content", "content"]])
 
 
 
 
 
 
 
 
 
 
 
 
276
 
277
 
278
  def get_rule_type_mapping():
 
292
  return process_map
293
 
294
 
295
+ def get_llm_list():
296
+ """Get LLM list from Model.llm_name_map"""
297
+ llm_name_map = Model.get_llm_name_map()
298
+ return list(llm_name_map.keys())
299
+
300
+
301
+ def get_llm_column_mapping():
302
+ """Get column mapping required by each LLM"""
303
+ # Define columns required by each LLM based on actual needs
304
+ # Can be dynamically obtained from Model information, using default configuration for now
305
+ llm_list = get_llm_list()
306
+ mapping = {}
307
+ for llm_name in llm_list:
308
+ # Specify different field requirements based on specific LLM type
309
+ if 'VLM' in llm_name or 'Image' in llm_name:
310
+ mapping[llm_name] = ['content', 'image']
311
+ elif 'Relevant' in llm_name:
312
+ mapping[llm_name] = ['prompt', 'content']
313
+ else:
314
+ mapping[llm_name] = ['content']
315
+ return mapping
316
 
317
 
318
  def get_data_column_mapping():
319
  return {
320
+ # Rule mapping
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  'Rule-Based TEXT Quality Metrics': ['content'],
322
  'QUALITY_BAD_SECURITY': ['content'],
323
  'QUALITY_BAD_IMG_EFFECTIVENESS': ['image'],
 
330
  rule_type_mapping = get_rule_type_mapping()
331
  rule_type_options = list(rule_type_mapping.keys())
332
 
333
+ llm_options = get_llm_list()
 
334
 
335
  current_dir = Path(__file__).parent
336
  with open(os.path.join(current_dir, 'header.html'), "r") as file:
 
356
  visible=False
357
  )
358
 
359
+ with gr.Row():
360
+ data_format = gr.Dropdown(
361
+ ["jsonl", "json", "plaintext", "listjson","image"],
362
+ label="data_format"
363
+ )
364
+ remove_output = gr.Dropdown(
365
+ ["true"],
366
+ value="true",
367
+ label="remove_output"
368
+ )
369
  with gr.Row():
370
  max_workers = gr.Number(
371
  value=1,
 
384
  rule_type = gr.Dropdown(
385
  choices=rule_type_options,
386
  value=rule_type_options[0],
387
+ label="Rule Type",
388
  interactive=True
389
  )
390
  rule_list = gr.CheckboxGroup(
391
  choices=rule_type_mapping.get(rule_type_options[0], []),
392
+ label="Rule List",
393
+ elem_classes="limited-height-checkboxgroup"
394
  )
395
+ # LLM evaluator list
396
+ llm_list = gr.CheckboxGroup(
397
+ choices=llm_options,
398
+ label="LLM List",
399
+ elem_classes="limited-height-checkboxgroup"
 
400
  )
401
+
402
+ gr.Markdown("### EvalPipline Configuration")
403
+ gr.Markdown("Configure field mappings and evaluator parameters based on selected evaluators ([Examples](https://github.com/MigoXLab/dingo/tree/main/examples))")
404
+
405
+ # Field mapping configuration
406
+ gr.Markdown("**EvalPipline.fields** - Field Mapping")
407
+ fields_dataframe = gr.Dataframe(
408
+ value=[["content", "content"]],
409
+ headers=["Field Key", "Dataset Column"],
410
+ datatype=["str", "str"],
411
+ column_count=(2, "fixed"),
412
+ row_count=(1, "dynamic"),
413
+ label="Field Mappings (add/remove rows as needed)",
414
+ interactive=True
 
415
  )
416
+
417
+ # Rule configuration
418
+ # gr.Markdown("**Rule Config** - EvalPiplineConfig.config for Rules")
419
+ # rule_config_dataframe = gr.Dataframe(
420
+ # value=[],
421
+ # headers=["Rule Name", "threshold", "pattern", "key_list", "refer_path", "parameters"],
422
+ # datatype=["str", "number", "str", "str", "str", "str"],
423
+ # column_count=(6, "fixed"),
424
+ # row_count=(0, "dynamic"),
425
+ # label="Rule Configurations (auto-generated based on rule_list selection)",
426
+ # interactive=True,
427
+ # visible=False
428
+ # )
429
+
430
+ # LLM configuration
431
+ gr.Markdown("**LLM Config** - EvalPiplineConfig.config for LLMs")
432
+ llm_config_dataframe = gr.Dataframe(
433
+ value=[],
434
+ headers=["LLM Name", "model", "key", "api_url", "parameters"],
435
+ datatype=["str", "str", "str", "str", "str"],
436
+ column_count=(5, "fixed"),
437
+ row_count=(0, "dynamic"),
438
+ label="LLM Configurations (auto-generated based on llm_list selection)",
439
+ interactive=True,
440
  visible=False
441
  )
442
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  with gr.Row():
444
  submit_single = gr.Button(value="Submit", interactive=True, variant="primary")
445
 
446
  with gr.Column():
447
+ # Output component section, using Tabs
448
  with gr.Tabs():
449
  with gr.Tab("Result Summary"):
450
+ summary_output = gr.JSON(label="Summary", max_height=800)
451
  with gr.Tab("Result Detail"):
452
+ detail_output = gr.JSON(label="Detail", max_height=800) # Use JSON component for better structured data display
453
 
454
  dataset_source.change(
455
  fn=update_input_components,
 
463
  outputs=rule_list
464
  )
465
 
466
+ # Auto-generate configuration dataframes when rule_list changes
467
+ # rule_list.change(
468
+ # fn=generate_rule_config_dataframe,
469
+ # inputs=rule_list,
470
+ # outputs=rule_config_dataframe
471
+ # )
472
+
473
+ # Auto-generate configuration dataframes when llm_list changes
474
+ llm_list.change(
475
+ fn=generate_llm_config_dataframe,
476
+ inputs=llm_list,
477
+ outputs=llm_config_dataframe
478
  )
479
 
480
+ # Suggest field mappings when evaluators change
481
+ for comp in [rule_list, llm_list]:
482
  comp.change(
483
+ fn=suggest_fields_dataframe,
484
+ inputs=[rule_list, llm_list],
485
+ outputs=fields_dataframe
486
  )
487
 
488
  submit_single.click(
489
  fn=dingo_demo,
490
  inputs=[
491
  uploaded_file,
492
+ dataset_source, data_format, remove_output, input_path, max_workers, batch_size,
493
+ fields_dataframe,
494
+ rule_list, llm_list,
495
+ # rule_config_dataframe,
496
+ llm_config_dataframe
497
  ],
498
+ outputs=[summary_output, detail_output]
499
  )
500
 
501
+ # Launch interface
502
+ demo.launch(share=False)