Skip to content

Commit ed345a1

Browse files
committed
Improve visibility of evaluate command status
1 parent 52c6e3a commit ed345a1

1 file changed

Lines changed: 77 additions & 39 deletions

File tree

src/parxyval/cli/commands/evaluate.py

Lines changed: 77 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@
33
import os
44
import sys
55
import time
6+
from typing import Optional, List
67

78
import pandas as pd
9+
from rich.console import Console
10+
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn
11+
from rich.table import Table
12+
from rich import print
813
from dotenv import load_dotenv
914
from parxy_core.models import Document
1015

@@ -64,7 +69,7 @@ def evaluate(
6469
):
6570

6671
logging.basicConfig(
67-
level=logging.DEBUG,
72+
level=logging.WARNING,
6873
format="%(asctime)s : %(levelname)s : %(name)s : %(message)s"
6974
)
7075

@@ -89,51 +94,84 @@ def evaluate(
8994

9095
metrics_fn = list([get_metric(metric) for metric in metrics_name])
9196

97+
console = Console()
98+
9299
logging.debug(f"Input folder: {input_folder}")
93100
logging.debug(f"Output folder: {output_folder}")
94-
logging.debug(f"Metric: {metrics_name}")
101+
logging.debug(f"Metrics: {metrics_name}")
102+
103+
# Get total number of files to process
104+
files = os.listdir(input_folder)
105+
total_files = len(files)
95106

96107
res_list = []
97-
for filename in os.listdir(input_folder):
98-
logging.debug(f"Processing {filename}")
99-
100-
# Read the parsing result
101-
with open(os.path.join(input_folder, filename), "r") as f:
102-
doc = Document(**json.loads(f.read()))
103-
104-
# Read the ground truth
105-
try:
106-
with open(os.path.join(golden_folder, filename), "r") as f:
107-
golden_doc = Document(**json.loads(f.read()))
108-
except FileNotFoundError:
109-
logging.error(f"File [{filename}] does not exist!")
110-
continue
111-
112-
base_data = {
113-
"filename": filename,
114-
"collection": golden_doc.source_data["collection"],
115-
"doc_category": golden_doc.source_data["doc_category"],
116-
"original_filename": golden_doc.source_data["original_filename"],
117-
"page_no": golden_doc.source_data["page_no"],
118-
"processing_time_seconds": doc.source_data["processing_time_seconds"],
119-
}
120-
121-
# merge all metrics dicts into one
122-
metrics_dict = {}
123-
for metric_fn in metrics_fn:
124-
metrics_dict.update(metric_fn(golden_doc, doc))
125-
126-
# merge base data + metrics
127-
row = {**base_data, **metrics_dict}
128-
res_list.append(row)
129-
130-
logging.debug(f"Processed {len(res_list)} documents.")
108+
with Progress(
109+
SpinnerColumn(),
110+
TextColumn("[progress.description]{task.description}"),
111+
BarColumn(),
112+
TaskProgressColumn(),
113+
console=console,
114+
transient=True
115+
) as progress:
116+
task = progress.add_task("Evaluating documents...", total=total_files)
117+
118+
for filename in files:
119+
progress.update(task, description=f"Processing {filename}...")
120+
121+
# Read the parsing result
122+
with open(os.path.join(input_folder, filename), "r") as f:
123+
doc = Document(**json.loads(f.read()))
124+
125+
# Read the ground truth
126+
try:
127+
with open(os.path.join(golden_folder, filename), "r") as f:
128+
golden_doc = Document(**json.loads(f.read()))
129+
except FileNotFoundError:
130+
logging.error(f"File [{filename}] does not exist!")
131+
progress.advance(task)
132+
continue
133+
134+
base_data = {
135+
"filename": filename,
136+
"collection": golden_doc.source_data["collection"],
137+
"doc_category": golden_doc.source_data["doc_category"],
138+
"original_filename": golden_doc.source_data["original_filename"],
139+
"page_no": golden_doc.source_data["page_no"],
140+
"processing_time_seconds": doc.source_data["processing_time_seconds"],
141+
}
142+
143+
# merge all metrics dicts into one
144+
metrics_dict = {}
145+
for metric_fn in metrics_fn:
146+
metrics_dict.update(metric_fn(golden_doc, doc))
147+
148+
# merge base data + metrics
149+
row = {**base_data, **metrics_dict}
150+
res_list.append(row)
151+
progress.advance(task)
152+
131153
timestamp_str = str(time.time()).replace(".", "")
132154
res_df = pd.DataFrame(res_list)
133155
input_folder_name = input_folder.replace(os.sep, "/").replace("\\", "/")
134156
input_folder_name = input_folder_name.split("/")[-1].replace(" ", "_").lower()
135-
res_df.to_csv(os.path.join(output_folder, f"eval_{input_folder_name}_{timestamp_str}.csv"), index=False)
136-
logging.debug(f"Results written to {output_folder}/eval_{input_folder_name}_{timestamp_str}.csv")
157+
output_file = f"eval_{input_folder_name}_{timestamp_str}.csv"
158+
output_path = os.path.join(output_folder, output_file)
159+
res_df.to_csv(output_path, index=False)
137160

161+
print(f"\n[green]✓[/green] Evaluation completed. Results saved to: [blue]{output_path}[/blue]")
162+
163+
# Print evaluation statistics
164+
table = Table()
165+
table.add_column("Metric")
166+
table.add_column("Value", justify="right", style="green")
167+
168+
table.add_row("Documents processed", str(len(res_list)))
169+
table.add_row("Average parsing time", f"{res_df['processing_time_seconds'].mean():.2f}s")
170+
171+
for metric_column in metrics_name:
172+
if metric_column in res_df.columns and not res_df[metric_column].isna().all():
173+
if res_df[metric_column].dtype in ['float64', 'int64']:
174+
table.add_row(metric_column, f"{res_df[metric_column].mean():.4f}")
175+
176+
console.print(table)
138177

139-
# TODO: print out some basic data from res_df, like average score for each metric and average processing_time_seconds

0 commit comments

Comments
 (0)