Vik Paruchuri commited on
Commit
cc1d60d
·
1 Parent(s): c57d999

Refactor benchmarks

Browse files
benchmarks/overall/__init__.py ADDED
File without changes
benchmarks/overall/overall.py CHANGED
@@ -1,13 +1,14 @@
1
  import json
2
  import os
3
- import traceback
4
  from collections import defaultdict
5
  from pathlib import Path
 
6
 
7
  import click
8
  import datasets
9
  import tabulate
10
  from tqdm import tqdm
 
11
 
12
  from benchmarks.overall.inference import marker_scoring_func, mathpix_scoring_func
13
  from benchmarks.overall.schema import FullResult
@@ -28,12 +29,17 @@ def get_method_scores(ds, model_dict, max_rows=None, score_func=marker_scoring_f
28
 
29
  gt_blocks = json.loads(sample["gt_blocks"])
30
  doc_type = sample["classification"]
 
31
  try:
32
  gt_html = [block["html"] for block in gt_blocks]
33
  scores = score_func(model_dict, sample, gt_html, **kwargs)
34
  except ValueError as e:
35
  print(f"Error with sample {idx}: {e}")
36
  continue
 
 
 
 
37
  averages_by_type[doc_type].append(scores["overall_score"])
38
 
39
  for score, gt_block in zip(scores["scores"], gt_blocks):
@@ -50,27 +56,48 @@ def get_method_scores(ds, model_dict, max_rows=None, score_func=marker_scoring_f
50
  "average_score": sum([bench_scores[k]["overall_score"] for k in bench_scores]) / len(bench_scores)
51
  }
52
 
53
- def print_scores(scores: FullResult, method: str):
54
- averages_by_type = scores["averages_by_type"]
55
- averages_by_block_type = scores["averages_by_block_type"]
56
- bench_scores = scores["raw_scores"]
57
-
58
- for k in averages_by_type:
59
- averages_by_type[k] = sum(averages_by_type[k]) / len(averages_by_type[k])
60
- averages_by_type = sorted(averages_by_type.items())
61
-
62
- print(f"Scores for method {method}:")
63
- print(tabulate.tabulate(averages_by_type, headers=["Document Type", "Average Score"], tablefmt="github"))
64
-
65
- for k in averages_by_block_type:
66
- averages_by_block_type[k] = sum(averages_by_block_type[k]) / len(averages_by_block_type[k])
67
- averages_by_block_type = sorted(averages_by_block_type.items())
68
-
69
- print(tabulate.tabulate(averages_by_block_type, headers=["Block Type", "Average Score"], tablefmt="github"))
70
-
71
- overall_average = sum([bench_scores[k]["overall_score"] for k in bench_scores]) / len(bench_scores)
72
- print(tabulate.tabulate([["Overall Average", overall_average]], tablefmt="github"))
73
- print()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
  @click.command(help="Benchmark PDF to MD conversion.")
76
  @click.option("--dataset", type=str, help="Path to the benchmark dataset", default="datalab-to/marker_benchmark")
@@ -85,6 +112,9 @@ def main(
85
  max_rows: int,
86
  use_llm: bool
87
  ):
 
 
 
88
  allowed_methods = ["mathpix", ""]
89
  methods = other_methods.split(",")
90
  for method in methods:
@@ -104,11 +134,9 @@ def main(
104
  mathpix_scores = get_method_scores(ds, model_dict, max_rows=max_rows, score_func=mathpix_scoring_func, mathpix_ds=mathpix_ds)
105
  all_scores["mathpix"] = mathpix_scores
106
 
107
- for k,v in all_scores.items():
108
- print_scores(v, k)
109
 
110
- out_path = Path(result_path)
111
- out_path.mkdir(parents=True, exist_ok=True)
112
  with open(out_path / "overall.json", "w", encoding="utf-8") as f:
113
  json.dump(all_scores, f, indent=2, ensure_ascii=False)
114
 
 
1
  import json
2
  import os
 
3
  from collections import defaultdict
4
  from pathlib import Path
5
+ from typing import Dict
6
 
7
  import click
8
  import datasets
9
  import tabulate
10
  from tqdm import tqdm
11
+ import pypdfium2 as pdfium
12
 
13
  from benchmarks.overall.inference import marker_scoring_func, mathpix_scoring_func
14
  from benchmarks.overall.schema import FullResult
 
29
 
30
  gt_blocks = json.loads(sample["gt_blocks"])
31
  doc_type = sample["classification"]
32
+
33
  try:
34
  gt_html = [block["html"] for block in gt_blocks]
35
  scores = score_func(model_dict, sample, gt_html, **kwargs)
36
  except ValueError as e:
37
  print(f"Error with sample {idx}: {e}")
38
  continue
39
+ except pdfium.PdfiumError as e:
40
+ print(f"Error opening pdf: {e}")
41
+ continue
42
+
43
  averages_by_type[doc_type].append(scores["overall_score"])
44
 
45
  for score, gt_block in zip(scores["scores"], gt_blocks):
 
56
  "average_score": sum([bench_scores[k]["overall_score"] for k in bench_scores]) / len(bench_scores)
57
  }
58
 
59
+ def print_scores(scores: Dict[str, FullResult], out_path: Path, default_method="marker"):
60
+ inference_types = [default_method] + [k for k in scores.keys() if k != default_method]
61
+
62
+ document_types = list(scores[default_method]["averages_by_type"].keys())
63
+ document_rows = [[k] for k in document_types]
64
+ for k in inference_types:
65
+ for i, doc_type in enumerate(document_types):
66
+ avg = sum(scores[k]["averages_by_type"][doc_type]) / max(1, len(scores[k]["averages_by_type"][doc_type]))
67
+ document_rows[i].append(avg)
68
+
69
+ print("Document types")
70
+ document_type_table = tabulate.tabulate(document_rows, headers=["Document Type"] + inference_types, tablefmt="github")
71
+ print(document_type_table)
72
+ with open(out_path / "document_types.md", "w", encoding="utf-8") as f:
73
+ f.write(document_type_table)
74
+
75
+ block_types = list(scores[default_method]["averages_by_block_type"].keys())
76
+ block_rows = [[k] for k in block_types]
77
+ for k in inference_types:
78
+ for i, block_type in enumerate(block_types):
79
+ avg = sum(scores[k]["averages_by_block_type"][block_type]) / max(1, len(scores[k]["averages_by_block_type"][block_type]))
80
+ block_rows[i].append(avg)
81
+
82
+ print("Block types")
83
+ block_type_table = tabulate.tabulate(block_rows, headers=["Block Type"] + inference_types, tablefmt="github")
84
+ print(block_type_table)
85
+ with open(out_path / "block_types.md", "w", encoding="utf-8") as f:
86
+ f.write(block_type_table)
87
+
88
+ headers = ["Method", "Avg Score", "Avg Time"]
89
+ inference_rows = [[k] for k in inference_types]
90
+ for i, k in enumerate(inference_types):
91
+ inference_rows[i].append(scores[k]["average_score"])
92
+ inference_rows[i].append(scores[k]["average_time"])
93
+
94
+ print("Overall")
95
+ overall_table = tabulate.tabulate(inference_rows, headers=headers, tablefmt="github")
96
+ print(overall_table)
97
+ with open(out_path / "overall.md", "w", encoding="utf-8") as f:
98
+ f.write(overall_table)
99
+
100
+ print("Scores computed by aligning ground truth markdown blocks with predicted markdown for each method. The scores are 0-100 based on edit distance.")
101
 
102
  @click.command(help="Benchmark PDF to MD conversion.")
103
  @click.option("--dataset", type=str, help="Path to the benchmark dataset", default="datalab-to/marker_benchmark")
 
112
  max_rows: int,
113
  use_llm: bool
114
  ):
115
+ out_path = Path(result_path)
116
+ out_path.mkdir(parents=True, exist_ok=True)
117
+
118
  allowed_methods = ["mathpix", ""]
119
  methods = other_methods.split(",")
120
  for method in methods:
 
134
  mathpix_scores = get_method_scores(ds, model_dict, max_rows=max_rows, score_func=mathpix_scoring_func, mathpix_ds=mathpix_ds)
135
  all_scores["mathpix"] = mathpix_scores
136
 
137
+ # Display formatted score tables
138
+ print_scores(all_scores, out_path)
139
 
 
 
140
  with open(out_path / "overall.json", "w", encoding="utf-8") as f:
141
  json.dump(all_scores, f, indent=2, ensure_ascii=False)
142
 
benchmarks/table/__init__.py ADDED
File without changes
benchmarks/table/inference.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datasets
2
+ import numpy as np
3
+ from bs4 import BeautifulSoup
4
+ import pypdfium2 as pdfium
5
+ from tqdm import tqdm
6
+ import base64
7
+ import tempfile
8
+
9
+ from benchmarks.table.gemini import gemini_table_rec
10
+ from marker.config.parser import ConfigParser
11
+ from marker.converters.table import TableConverter
12
+ from marker.models import create_model_dict
13
+ from marker.util import matrix_intersection_area
14
+
15
+
16
+ def inference_tables(dataset, use_llm: bool, table_rec_batch_size: int | None, max_rows: int, use_gemini: bool):
17
+ models = create_model_dict()
18
+ config_parser = ConfigParser({'output_format': 'json', "use_llm": use_llm, "table_rec_batch_size": table_rec_batch_size, "disable_tqdm": True})
19
+ total_unaligned = 0
20
+ results = []
21
+
22
+ dataset = datasets.load_dataset(dataset, split='train')
23
+ dataset = dataset.shuffle(seed=0)
24
+
25
+ iterations = len(dataset)
26
+ if max_rows is not None:
27
+ iterations = min(max_rows, len(dataset))
28
+
29
+ for i in tqdm(range(iterations), desc='Converting Tables'):
30
+ try:
31
+ row = dataset[i]
32
+ pdf_binary = base64.b64decode(row['pdf'])
33
+ gt_tables = row['tables'] # Already sorted by reading order, which is what marker returns
34
+
35
+ converter = TableConverter(
36
+ config=config_parser.generate_config_dict(),
37
+ artifact_dict=models,
38
+ processor_list=config_parser.get_processors(),
39
+ renderer=config_parser.get_renderer()
40
+ )
41
+
42
+ with tempfile.NamedTemporaryFile(suffix=".pdf", mode="wb") as temp_pdf_file:
43
+ temp_pdf_file.write(pdf_binary)
44
+ temp_pdf_file.seek(0)
45
+ marker_json = converter(temp_pdf_file.name).children
46
+
47
+ doc = pdfium.PdfDocument(temp_pdf_file.name)
48
+ page_image = doc[0].render(scale=92 / 72).to_pil()
49
+
50
+ if len(marker_json) == 0 or len(gt_tables) == 0:
51
+ print(f'No tables detected, skipping...')
52
+ total_unaligned += len(gt_tables)
53
+ continue
54
+
55
+ marker_tables = extract_tables(marker_json)
56
+ marker_table_boxes = [table.bbox for table in marker_tables]
57
+ page_bbox = marker_json[0].bbox
58
+ w_scaler, h_scaler = page_image.width / page_bbox[2], page_image.height / page_bbox[3]
59
+ table_images = [
60
+ page_image.crop([bbox[0] * w_scaler, bbox[1] * h_scaler, bbox[2] * w_scaler, bbox[3] * h_scaler]) for bbox
61
+ in marker_table_boxes]
62
+
63
+ # Normalize the bboxes
64
+ for bbox in marker_table_boxes:
65
+ bbox[0] = bbox[0] / page_bbox[2]
66
+ bbox[1] = bbox[1] / page_bbox[3]
67
+ bbox[2] = bbox[2] / page_bbox[2]
68
+ bbox[3] = bbox[3] / page_bbox[3]
69
+
70
+ gt_boxes = [table['normalized_bbox'] for table in gt_tables]
71
+ gt_areas = [(bbox[2] - bbox[0]) * (bbox[3] - bbox[1]) for bbox in gt_boxes]
72
+ marker_areas = [(bbox[2] - bbox[0]) * (bbox[3] - bbox[1]) for bbox in marker_table_boxes]
73
+ table_alignments = matrix_intersection_area(gt_boxes, marker_table_boxes)
74
+
75
+ aligned_tables = []
76
+ used_tables = set()
77
+ unaligned_tables = set()
78
+ for table_idx, alignment in enumerate(table_alignments):
79
+ try:
80
+ max_area = np.max(alignment)
81
+ aligned_idx = np.argmax(alignment)
82
+ except ValueError:
83
+ # No alignment found
84
+ unaligned_tables.add(table_idx)
85
+ continue
86
+
87
+ if aligned_idx in used_tables:
88
+ # Marker table already aligned with another gt table
89
+ unaligned_tables.add(table_idx)
90
+ continue
91
+
92
+ # Gt table doesn't align well with any marker table
93
+ gt_table_pct = gt_areas[table_idx] / max_area
94
+ if not .75 < gt_table_pct < 1.25:
95
+ unaligned_tables.add(table_idx)
96
+ continue
97
+
98
+ # Marker table doesn't align with gt table
99
+ marker_table_pct = marker_areas[aligned_idx] / max_area
100
+ if not .75 < marker_table_pct < 1.25:
101
+ unaligned_tables.add(table_idx)
102
+ continue
103
+
104
+ gemini_html = ""
105
+ if use_gemini:
106
+ gemini_html = gemini_table_rec(table_images[aligned_idx])
107
+
108
+ aligned_tables.append(
109
+ (marker_tables[aligned_idx], gt_tables[table_idx], gemini_html)
110
+ )
111
+ used_tables.add(aligned_idx)
112
+
113
+ total_unaligned += len(unaligned_tables)
114
+
115
+ for marker_table, gt_table, gemini_table in aligned_tables:
116
+ gt_table_html = gt_table['html']
117
+
118
+ # marker wraps the table in <tbody> which fintabnet data doesn't
119
+ # Fintabnet doesn't use th tags, need to be replaced for fair comparison
120
+ marker_table_soup = BeautifulSoup(marker_table.html, 'html.parser')
121
+ tbody = marker_table_soup.find('tbody')
122
+ if tbody:
123
+ tbody.unwrap()
124
+ for th_tag in marker_table_soup.find_all('th'):
125
+ th_tag.name = 'td'
126
+ marker_table_html = str(marker_table_soup)
127
+ marker_table_html = marker_table_html.replace("<br>", " ") # Fintabnet uses spaces instead of newlines
128
+ marker_table_html = marker_table_html.replace("\n", " ") # Fintabnet uses spaces instead of newlines
129
+ gemini_table_html = gemini_table.replace("\n", " ") # Fintabnet uses spaces instead of newlines
130
+
131
+ results.append({
132
+ "marker_table": marker_table_html,
133
+ "gt_table": gt_table_html,
134
+ "gemini_table": gemini_table_html
135
+ })
136
+ except pdfium.PdfiumError:
137
+ print('Broken PDF, Skipping...')
138
+ continue
139
+ return results, total_unaligned
benchmarks/table/table.py CHANGED
@@ -1,33 +1,27 @@
1
  import os
 
 
 
2
  os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1" # Transformers uses .isin for an op, which is not supported on MPS
3
 
4
  from pathlib import Path
5
  from itertools import repeat
6
  from typing import List
7
 
8
- import numpy as np
9
- import base64
10
  import time
11
  import datasets
12
  from tqdm import tqdm
13
- import tempfile
14
  import click
15
  from tabulate import tabulate
16
  import json
17
- from bs4 import BeautifulSoup
18
  from concurrent.futures import ProcessPoolExecutor
19
- from pypdfium2._helpers.misc import PdfiumError
20
- import pypdfium2 as pdfium
21
- from marker.util import matrix_intersection_area
22
- from marker.renderers.json import JSONOutput, JSONBlockOutput
23
  from marker.settings import settings
24
 
25
  from marker.config.parser import ConfigParser
26
- from marker.converters.table import TableConverter
27
  from marker.models import create_model_dict
28
 
29
  from scoring import wrap_table_html, similarity_eval_html
30
- from gemini import gemini_table_rec
31
 
32
  def update_teds_score(result, prefix: str = "marker"):
33
  prediction, ground_truth = result[f'{prefix}_table'], result['gt_table']
@@ -64,128 +58,13 @@ def main(
64
  table_rec_batch_size: int | None,
65
  use_gemini: bool = False
66
  ):
67
- models = create_model_dict()
68
- config_parser = ConfigParser({'output_format': 'json', "use_llm": use_llm, "table_rec_batch_size": table_rec_batch_size, "disable_tqdm": True})
69
  start = time.time()
70
 
71
 
72
  dataset = datasets.load_dataset(dataset, split='train')
73
  dataset = dataset.shuffle(seed=0)
74
 
75
- iterations = len(dataset)
76
- if max_rows is not None:
77
- iterations = min(max_rows, len(dataset))
78
-
79
- results = []
80
- total_unaligned = 0
81
- for i in tqdm(range(iterations), desc='Converting Tables'):
82
- try:
83
- row = dataset[i]
84
- pdf_binary = base64.b64decode(row['pdf'])
85
- gt_tables = row['tables'] #Already sorted by reading order, which is what marker returns
86
-
87
- converter = TableConverter(
88
- config=config_parser.generate_config_dict(),
89
- artifact_dict=models,
90
- processor_list=config_parser.get_processors(),
91
- renderer=config_parser.get_renderer()
92
- )
93
-
94
- with tempfile.NamedTemporaryFile(suffix=".pdf", mode="wb") as temp_pdf_file:
95
- temp_pdf_file.write(pdf_binary)
96
- temp_pdf_file.seek(0)
97
- marker_json = converter(temp_pdf_file.name).children
98
-
99
- doc = pdfium.PdfDocument(temp_pdf_file.name)
100
- page_image = doc[0].render(scale=92/72).to_pil()
101
-
102
- if len(marker_json) == 0 or len(gt_tables) == 0:
103
- print(f'No tables detected, skipping...')
104
- total_unaligned += len(gt_tables)
105
- continue
106
-
107
- marker_tables = extract_tables(marker_json)
108
- marker_table_boxes = [table.bbox for table in marker_tables]
109
- page_bbox = marker_json[0].bbox
110
- w_scaler, h_scaler = page_image.width / page_bbox[2], page_image.height / page_bbox[3]
111
- table_images = [page_image.crop([bbox[0] * w_scaler, bbox[1] * h_scaler, bbox[2] * w_scaler, bbox[3] * h_scaler]) for bbox in marker_table_boxes]
112
-
113
- # Normalize the bboxes
114
- for bbox in marker_table_boxes:
115
- bbox[0] = bbox[0] / page_bbox[2]
116
- bbox[1] = bbox[1] / page_bbox[3]
117
- bbox[2] = bbox[2] / page_bbox[2]
118
- bbox[3] = bbox[3] / page_bbox[3]
119
-
120
- gt_boxes = [table['normalized_bbox'] for table in gt_tables]
121
- gt_areas = [(bbox[2] - bbox[0]) * (bbox[3] - bbox[1]) for bbox in gt_boxes]
122
- marker_areas = [(bbox[2] - bbox[0]) * (bbox[3] - bbox[1]) for bbox in marker_table_boxes]
123
- table_alignments = matrix_intersection_area(gt_boxes, marker_table_boxes)
124
-
125
- aligned_tables = []
126
- used_tables = set()
127
- unaligned_tables = set()
128
- for table_idx, alignment in enumerate(table_alignments):
129
- try:
130
- max_area = np.max(alignment)
131
- aligned_idx = np.argmax(alignment)
132
- except ValueError:
133
- # No alignment found
134
- unaligned_tables.add(table_idx)
135
- continue
136
-
137
- if aligned_idx in used_tables:
138
- # Marker table already aligned with another gt table
139
- unaligned_tables.add(table_idx)
140
- continue
141
-
142
- # Gt table doesn't align well with any marker table
143
- gt_table_pct = gt_areas[table_idx] / max_area
144
- if not .75 < gt_table_pct < 1.25:
145
- unaligned_tables.add(table_idx)
146
- continue
147
-
148
- # Marker table doesn't align with gt table
149
- marker_table_pct = marker_areas[aligned_idx] / max_area
150
- if not .75 < marker_table_pct < 1.25:
151
- unaligned_tables.add(table_idx)
152
- continue
153
-
154
- gemini_html = ""
155
- if use_gemini:
156
- gemini_html = gemini_table_rec(table_images[aligned_idx])
157
-
158
- aligned_tables.append(
159
- (marker_tables[aligned_idx], gt_tables[table_idx], gemini_html)
160
- )
161
- used_tables.add(aligned_idx)
162
-
163
- total_unaligned += len(unaligned_tables)
164
-
165
- for marker_table, gt_table, gemini_table in aligned_tables:
166
- gt_table_html = gt_table['html']
167
-
168
- #marker wraps the table in <tbody> which fintabnet data doesn't
169
- #Fintabnet doesn't use th tags, need to be replaced for fair comparison
170
- marker_table_soup = BeautifulSoup(marker_table.html, 'html.parser')
171
- tbody = marker_table_soup.find('tbody')
172
- if tbody:
173
- tbody.unwrap()
174
- for th_tag in marker_table_soup.find_all('th'):
175
- th_tag.name = 'td'
176
- marker_table_html = str(marker_table_soup)
177
- marker_table_html = marker_table_html.replace("<br>", " ") # Fintabnet uses spaces instead of newlines
178
- marker_table_html = marker_table_html.replace("\n", " ") # Fintabnet uses spaces instead of newlines
179
- gemini_table_html = gemini_table.replace("\n", " ") # Fintabnet uses spaces instead of newlines
180
-
181
- results.append({
182
- "marker_table": marker_table_html,
183
- "gt_table": gt_table_html,
184
- "gemini_table": gemini_table_html
185
- })
186
- except PdfiumError:
187
- print('Broken PDF, Skipping...')
188
- continue
189
 
190
  print(f"Total time: {time.time() - start}.")
191
  print(f"Could not align {total_unaligned} tables from fintabnet.")
 
1
  import os
2
+
3
+ from benchmarks.table.inference import inference_tables
4
+
5
  os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1" # Transformers uses .isin for an op, which is not supported on MPS
6
 
7
  from pathlib import Path
8
  from itertools import repeat
9
  from typing import List
10
 
 
 
11
  import time
12
  import datasets
13
  from tqdm import tqdm
 
14
  import click
15
  from tabulate import tabulate
16
  import json
 
17
  from concurrent.futures import ProcessPoolExecutor
18
+ from marker.renderers.json import JSONBlockOutput
 
 
 
19
  from marker.settings import settings
20
 
21
  from marker.config.parser import ConfigParser
 
22
  from marker.models import create_model_dict
23
 
24
  from scoring import wrap_table_html, similarity_eval_html
 
25
 
26
  def update_teds_score(result, prefix: str = "marker"):
27
  prediction, ground_truth = result[f'{prefix}_table'], result['gt_table']
 
58
  table_rec_batch_size: int | None,
59
  use_gemini: bool = False
60
  ):
 
 
61
  start = time.time()
62
 
63
 
64
  dataset = datasets.load_dataset(dataset, split='train')
65
  dataset = dataset.shuffle(seed=0)
66
 
67
+ results, total_unaligned = inference_tables(dataset, use_llm, table_rec_batch_size, max_rows, use_gemini)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  print(f"Total time: {time.time() - start}.")
70
  print(f"Could not align {total_unaligned} tables from fintabnet.")
benchmarks/verify_scores.py CHANGED
@@ -15,7 +15,7 @@ def verify_table_scores(file_path):
15
  with open(file_path, 'r') as file:
16
  data = json.load(file)
17
 
18
- avg = sum([r["score"] for r in data]) / len(data)
19
  if avg < 0.7:
20
  raise ValueError("Average score is below the required threshold of 0.7")
21
 
 
15
  with open(file_path, 'r') as file:
16
  data = json.load(file)
17
 
18
+ avg = sum([r["marker_score"] for r in data["marker"]]) / len(data)
19
  if avg < 0.7:
20
  raise ValueError("Average score is below the required threshold of 0.7")
21