Spaces:
Build error
Build error
File size: 11,368 Bytes
364b978 1603571 364b978 16fd4fe 364b978 1603571 16fd4fe 1603571 16fd4fe 1603571 364b978 16fd4fe 0c02234 16fd4fe 0c02234 1603571 0c02234 1603571 16fd4fe 364b978 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | import logging
import os
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional, Union
import pandas as pd
from dotenv import load_dotenv
from gspread_pandas import Client, Spread
from gspread_pandas.conf import get_config
from src.config import Config
logger = logging.getLogger(__name__)
def load_spreadsheet(
sheet_id: Optional[str] = None,
gid: Optional[Union[str, int]] = None
) -> pd.DataFrame:
"""Load data from Google Spreadsheet.
Args:
sheet_id: Spreadsheet ID. If None, loads from BENCHMARK_SPREADSHEET_ID env var
gid: Sheet identifier. Can be either:
- Sheet ID (numeric)
- Sheet name (string)
If None, loads the first sheet
Returns:
DataFrame with loaded data
"""
if sheet_id is None:
load_dotenv()
sheet_id = os.environ.get("BENCHMARK_SPREADSHEET_ID")
if not sheet_id:
raise ValueError("No spreadsheet ID provided")
logger.info(f"Loading questions from spreadsheet ({sheet_id[:15]}...)/{gid}")
# Check if gid is numeric (sheet ID) or string (sheet name)
if gid is None or str(gid).isdigit():
# Use CSV export URL for numeric gid
csv_load_url = f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv"
if gid is not None:
csv_load_url = f"{csv_load_url}&gid={gid}"
df = pd.read_csv(csv_load_url)
else:
# Load by sheet name using gspread_pandas
google_config_dir = Config().navigator.root
google_config = get_config(google_config_dir, "google_config.json")
client = Client(config=google_config)
spread = Spread(sheet_id, client=client)
df = spread.sheet_to_df(sheet=str(gid), index=False)
return df
class GoogleSpreadsheetManager:
def __init__(
self,
spread_id: str,
google_config_dir: Optional[Path] = Config().navigator.root,
google_config_fname: str = "google_config.json",
benchmark_spreadsheet_id: Optional[str] = None,
eval_spreadsheet_id: Optional[str] = None,
):
self.spread_id = spread_id
google_config = get_config(google_config_dir, google_config_fname)
self.google_client = Client(config=google_config)
# if benchmark_spreadsheet_id is None or eval_spreadsheet_id is None:
# load_dotenv()
# benchmark_spreadsheet_id = os.getenv("BENCHMARK_SPREADSHEET_ID")
# eval_spreadsheet_id = os.getenv("EVAL_SPREADSHEET_ID")
#
# self.benchmark_spreadsheet_id = benchmark_spreadsheet_id
# self.eval_spreadsheet_id = self.eval_spreadsheet_id
def write_spreadsheet(
self, df: pd.DataFrame, sheet_id: str, sheet_name: str, start: str
) -> None:
spread = Spread(sheet_id, config=self.google_client)
spread.df_to_sheet(df, index=False, sheet=sheet_name, start=start, replace=True)
def get_spread(self) -> Spread:
return Spread(
self.spread_id,
client=self.google_client,
create_spread=True,
create_sheet=True,
)
class GoogleSpreadsheetManagerMLFlow:
"""Manages Google Spreadsheet operations for evaluation results"""
def __init__(
self,
spread_id: str,
google_config_dir: Optional[Path] = Config().navigator.root,
google_config_fname: str = "google_config.json",
):
"""Initialize spreadsheet manager
Args:
spread_id: ID of the target spreadsheet
google_config_dir: Directory containing Google credentials
google_config_fname: Name of the Google credentials file
"""
self.spread_id = spread_id
self._config = get_config(google_config_dir, google_config_fname)
self._client = Client(config=self._config)
self._spread = self.get_spread()
# Define standard sheet names and layouts
self._summary_sheet = "Evaluation Summary"
self._details_sheet = "Detailed Results"
self._metrics_sheet = "Metrics History"
# Initialize standard sheets if they don't exist
self._init_sheets()
def _init_sheets(self) -> None:
"""Initialize standard sheets with headers if they don't exist"""
# Check and create summary sheet
if self._summary_sheet not in self._spread.sheets:
summary_headers = [
"Timestamp",
"Experiment",
"Retriever",
"Scorer",
"Questions Count",
"Mean Metrics",
]
self._create_sheet(self._summary_sheet, summary_headers)
# Check and create details sheet
if self._details_sheet not in self._spread.sheets:
details_headers = [
"Timestamp",
"Experiment",
"Retriever",
"Scorer",
"Question",
"Expected Presentation",
"Expected Pages",
"Retrieved Presentations",
"Retrieved Pages",
"Metric Scores",
"Metric Explanations",
]
self._create_sheet(self._details_sheet, details_headers)
# Check and create metrics history sheet
if self._metrics_sheet not in self._spread.sheets:
metrics_headers = [
"Timestamp",
"Experiment",
"Retriever",
"Scorer",
"Metric Name",
"Mean Score",
]
self._create_sheet(self._metrics_sheet, metrics_headers)
def _create_sheet(self, sheet_name: str, headers: List[str]) -> None:
"""Create new sheet with headers
Args:
sheet_name: Name for the new sheet
headers: List of column headers
"""
try:
spread = self._spread.find_sheet(sheet_name)
if spread:
logger.info(f"Using existing sheet '{sheet_name}'")
else:
self._spread.create_sheet(sheet_name)
worksheet = self._spread.find_sheet(sheet_name)
if worksheet:
worksheet.update([headers])
logger.info(f"Created sheet '{sheet_name}' with headers")
except Exception as e:
logger.error(f"Failed to create sheet '{sheet_name}': {str(e)}")
raise
def get_spread(self) -> Spread:
"""Get Spread instance for the target spreadsheet"""
return Spread(
self.spread_id,
client=self._client,
create_spread=True,
create_sheet=True,
)
def write_evaluation_results(
self,
results_df: pd.DataFrame,
metric_values: Dict[str, List[float]],
experiment_name: str,
) -> None:
"""Write evaluation results to spreadsheet
Args:
results_df: DataFrame with detailed evaluation results
metric_values: Dictionary mapping metric names to score lists
experiment_name: Name of the experiment
"""
try:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
retriever = results_df["retriever"].iloc[0]
scorer = results_df["scorer"].iloc[0]
# Write summary
summary_row = {
"Timestamp": timestamp,
"Experiment": experiment_name,
"Retriever": retriever,
"Scorer": scorer,
"Questions Count": len(results_df),
"Mean Metrics": ", ".join(
f"{name}: {sum(values)/len(values):.3f}"
for name, values in metric_values.items()
),
}
self._append_rows(self._summary_sheet, [summary_row])
# Write detailed results
details = []
for _, row in results_df.iterrows():
detail_row = {
"Timestamp": timestamp,
"Experiment": experiment_name,
"Retriever": retriever,
"Scorer": scorer,
"Question": row["question"],
"Expected Presentation": row["expected_presentation"],
"Expected Pages": row["expected_pages"],
"Retrieved Presentations": row["retrieved_presentations"],
"Retrieved Pages": row["retrieved_pages"],
"Metric Scores": ", ".join(
f"{col.replace('metric_', '').replace('_score', '')}: {row[col]}"
for col in results_df.columns
if col.endswith("_score")
),
"Metric Explanations": "\n".join(
f"{col.replace('metric_', '').replace('_explanation', '')}: {row[col]}"
for col in results_df.columns
if col.endswith("_explanation")
),
}
details.append(detail_row)
self._append_rows(self._details_sheet, details)
# Write metrics history
metrics = []
for metric_name, values in metric_values.items():
metrics.append(
{
"Timestamp": timestamp,
"Experiment": experiment_name,
"Retriever": retriever,
"Scorer": scorer,
"Metric Name": metric_name,
"Mean Score": sum(values) / len(values),
}
)
self._append_rows(self._metrics_sheet, metrics)
logger.info(
f"Successfully wrote evaluation results to sheets: "
f"{self._summary_sheet}, {self._details_sheet}, {self._metrics_sheet}"
)
except Exception as e:
logger.error(f"Failed to write evaluation results: {str(e)}")
raise
def _append_rows(self, sheet_name: str, rows: List[Dict]) -> None:
"""Append rows to specified sheet
Args:
sheet_name: Target sheet name
rows: List of dictionaries representing rows
"""
try:
df = pd.DataFrame(rows)
worksheet = self._spread.find_sheet(sheet_name)
if worksheet:
start = f"A{len(worksheet.get_all_values()) + 1}"
self.write_spreadsheet(df, self.spread_id, sheet_name, start)
except Exception as e:
logger.error(f"Failed to append rows to '{sheet_name}': {str(e)}")
raise
def write_spreadsheet(
self, df: pd.DataFrame, sheet_id: str, sheet_name: str, start: str
) -> None:
"""Write DataFrame to spreadsheet at specified location
Args:
df: DataFrame to write
sheet_id: Target spreadsheet ID
sheet_name: Target sheet name
start: Starting cell (e.g. 'A1')
"""
spread = Spread(sheet_id, client=self._client)
spread.df_to_sheet(
df, index=False, headers=False, sheet=sheet_name, start=start, replace=False
)
|