@@ -54,17 +54,29 @@ def setup_observability(self) -> None:
5454 if not self .enable_tracing :
5555 return
5656
57- from agent_framework .observability import setup_observability
57+ # If only file tracing is requested (no OTLP or Application Insights),
58+ # skip the default setup_observability which adds console exporter
59+ if self .trace_to_file and not self .otlp_endpoint and not self .applicationinsights_connection_string :
60+ # Set up minimal tracing with only file export
61+ from opentelemetry .sdk .trace import TracerProvider
62+ from opentelemetry .trace import set_tracer_provider
63+
64+ tracer_provider = TracerProvider ()
65+ set_tracer_provider (tracer_provider )
66+ self ._setup_file_export ()
67+ else :
68+ # Use full observability setup for OTLP/AppInsights
69+ from agent_framework .observability import setup_observability
5870
59- setup_observability (
60- enable_sensitive_data = True , # Enable for detailed task traces
61- otlp_endpoint = self .otlp_endpoint ,
62- applicationinsights_connection_string = self .applicationinsights_connection_string ,
63- )
71+ setup_observability (
72+ enable_sensitive_data = True , # Enable for detailed task traces
73+ otlp_endpoint = self .otlp_endpoint ,
74+ applicationinsights_connection_string = self .applicationinsights_connection_string ,
75+ )
6476
65- # Set up local file export if requested
66- if self .trace_to_file :
67- self ._setup_file_export ()
77+ # Set up local file export if requested
78+ if self .trace_to_file :
79+ self ._setup_file_export ()
6880
6981 def _setup_file_export (self ) -> None :
7082 """Set up local file export for traces."""
@@ -204,29 +216,87 @@ def _load_gaia_local(repo_dir: Path, wanted_levels: list[int] | None = None, max
204216 """Load GAIA tasks from local repository directory."""
205217 tasks : list [Task ] = []
206218
207- for p in repo_dir .rglob ("metadata.jsonl" ):
208- for rec in _read_jsonl (p ):
209- # Robustly extract fields used across variants
210- q = rec .get ("Question" ) or rec .get ("question" ) or rec .get ("query" ) or rec .get ("prompt" )
211- ans = rec .get ("Final answer" ) or rec .get ("answer" ) or rec .get ("final_answer" )
212- qid = str (
213- rec .get ("task_id" )
214- or rec .get ("question_id" )
215- or rec .get ("id" )
216- or rec .get ("uuid" )
217- or f"{ p .stem } :{ len (tasks )} "
218- )
219- lvl = rec .get ("Level" ) or rec .get ("level" )
220- fname = rec .get ("file_name" ) or rec .get ("filename" ) or None
219+ # First try to load from parquet files (new format)
220+ # Prioritize validation split over test split (validation has answers)
221+ parquet_files = sorted (
222+ repo_dir .rglob ("metadata*.parquet" ), key = lambda p : (0 if "validation" in str (p ) else 1 , str (p ))
223+ )
221224
222- # Only evaluate examples with public answers (dev/validation split)
223- if not q or ans is None :
224- continue
225+ for p in parquet_files :
226+ try :
227+ import pyarrow .parquet as pq
228+
229+ table = pq .read_table (p )
230+ for row in table .to_pylist ():
231+ # Robustly extract fields used across variants
232+ q = row .get ("Question" ) or row .get ("question" ) or row .get ("query" ) or row .get ("prompt" )
233+ ans = row .get ("Final answer" ) or row .get ("answer" ) or row .get ("final_answer" )
234+ qid = str (
235+ row .get ("task_id" )
236+ or row .get ("question_id" )
237+ or row .get ("id" )
238+ or row .get ("uuid" )
239+ or f"{ p .stem } :{ len (tasks )} "
240+ )
241+ lvl = row .get ("Level" ) or row .get ("level" )
225242
226- if wanted_levels and (lvl not in wanted_levels ):
227- continue
243+ # Convert level to int if it's a string
244+ def _parse_level (lvl : Any ) -> int | None :
245+ """Parse level value to integer if possible."""
246+ if isinstance (lvl , int ):
247+ return lvl
248+ if isinstance (lvl , str ) and lvl .isdigit ():
249+ return int (lvl )
250+ return None
228251
229- tasks .append (Task (task_id = qid , question = q , answer = str (ans ), level = lvl , file_name = fname , metadata = rec ))
252+ lvl = _parse_level (lvl )
253+ fname = row .get ("file_name" ) or row .get ("filename" ) or None
254+
255+ # Only evaluate examples with public answers (dev/validation split)
256+ # Skip if no question, no answer, or answer is placeholder like "?"
257+ if not q or ans is None or str (ans ).strip () in ["?" , "" ]:
258+ continue
259+
260+ if wanted_levels and (lvl not in wanted_levels ):
261+ continue
262+
263+ tasks .append (Task (task_id = qid , question = q , answer = str (ans ), level = lvl , file_name = fname , metadata = row ))
264+ except ImportError :
265+ print ("Warning: pyarrow not installed. Install with: pip install pyarrow" )
266+ continue
267+ except Exception as e :
268+ print (f"Warning: Could not load parquet file { p } : { e } " )
269+ continue
270+
271+ # Fall back to jsonl files (old format) if no parquet files found
272+ if not tasks :
273+ for p in repo_dir .rglob ("metadata.jsonl" ):
274+ for rec in _read_jsonl (p ):
275+ # Robustly extract fields used across variants
276+ q = rec .get ("Question" ) or rec .get ("question" ) or rec .get ("query" ) or rec .get ("prompt" )
277+ ans = rec .get ("Final answer" ) or rec .get ("answer" ) or rec .get ("final_answer" )
278+ qid = str (
279+ rec .get ("task_id" )
280+ or rec .get ("question_id" )
281+ or rec .get ("id" )
282+ or rec .get ("uuid" )
283+ or f"{ p .stem } :{ len (tasks )} "
284+ )
285+ lvl = rec .get ("Level" ) or rec .get ("level" )
286+ # Convert level to int if it's a string
287+ if isinstance (lvl , str ) and lvl .isdigit ():
288+ lvl = int (lvl )
289+ fname = rec .get ("file_name" ) or rec .get ("filename" ) or None
290+
291+ # Only evaluate examples with public answers (dev/validation split)
292+ # Skip if no question, no answer, or answer is placeholder like "?"
293+ if not q or ans is None or str (ans ).strip () in ["?" , "" ]:
294+ continue
295+
296+ if wanted_levels and (lvl not in wanted_levels ):
297+ continue
298+
299+ tasks .append (Task (task_id = qid , question = q , answer = str (ans ), level = lvl , file_name = fname , metadata = rec ))
230300
231301 # Shuffle to help with rate-limits and fairness if max_n is provided
232302 random .shuffle (tasks )
@@ -290,7 +360,6 @@ def _ensure_data(self) -> Path:
290360 "with access to gaia-benchmark/GAIA."
291361 )
292362
293- print (f"Downloading GAIA dataset to { self .data_dir } ..." )
294363 from huggingface_hub import snapshot_download
295364
296365 local_dir = snapshot_download ( # type: ignore
@@ -438,8 +507,6 @@ async def run(
438507 "Make sure you have dataset access and selected valid levels."
439508 )
440509
441- print (f"Running { len (tasks )} GAIA tasks (levels={ levels } ) with { parallel } parallel workers..." )
442-
443510 # Update benchmark span with task info
444511 if benchmark_span :
445512 benchmark_span .set_attributes ({
@@ -473,17 +540,12 @@ async def run(
473540 "gaia.benchmark.avg_runtime_seconds" : avg_runtime ,
474541 })
475542
476- print ("\n GAIA Benchmark Results:" )
477- print (f"Accuracy: { accuracy :.3f} ({ correct } /{ len (results )} )" )
478- print (f"Average runtime: { avg_runtime :.2f} s" )
479-
480543 # Save results if requested
481544 if out :
482545 with self .tracer .start_as_current_span (
483546 "gaia.results.save" , kind = SpanKind .INTERNAL , attributes = {"gaia.results.output_file" : out }
484547 ):
485548 self ._save_results (results , out )
486- print (f"Results saved to { out } " )
487549
488550 return results
489551
0 commit comments