Python: Lab: Updates to GAIA module (#1763)

* Lab: Updates to GAIA module

* update

* emoj!

* fix lint

* update lab test workflow to only trigger for python changes

* lint

* lint

* Fix broken OpenAI agents JS documentation link
This commit is contained in:
Eric Zhu
2025-10-30 15:02:31 -07:00
committed by GitHub
Unverified
parent 7431b46bf0
commit 1543370027
9 changed files with 575 additions and 89 deletions
-15
View File
@@ -43,21 +43,6 @@ async def main() -> None:
See the [gaia_sample.py](./samples/gaia_sample.py) for more detail.
### Run the evaluation
Run the evaluation script using `uv`:
```bash
uv run python run_gaia.py
```
By default, the script will first look for cached GAIA data in the `data_gaia_hub` directory,
and download it if not found.
The result will be saved to `gaia_results_<timestamp>.jsonl`.
**Don't run the script inside this directory because it will confuse the local `agent_framework` namespace
package with the real one.**
## View results
We provide a console viewer for reading GAIA results:
@@ -54,17 +54,29 @@ class GAIATelemetryConfig:
if not self.enable_tracing:
return
from agent_framework.observability import setup_observability
# If only file tracing is requested (no OTLP or Application Insights),
# skip the default setup_observability which adds console exporter
if self.trace_to_file and not self.otlp_endpoint and not self.applicationinsights_connection_string:
# Set up minimal tracing with only file export
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.trace import set_tracer_provider
setup_observability(
enable_sensitive_data=True, # Enable for detailed task traces
otlp_endpoint=self.otlp_endpoint,
applicationinsights_connection_string=self.applicationinsights_connection_string,
)
# Set up local file export if requested
if self.trace_to_file:
tracer_provider = TracerProvider()
set_tracer_provider(tracer_provider)
self._setup_file_export()
else:
# Use full observability setup for OTLP/AppInsights
from agent_framework.observability import setup_observability
setup_observability(
enable_sensitive_data=True, # Enable for detailed task traces
otlp_endpoint=self.otlp_endpoint,
applicationinsights_connection_string=self.applicationinsights_connection_string,
)
# Set up local file export if requested
if self.trace_to_file:
self._setup_file_export()
def _setup_file_export(self) -> None:
"""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
"""Load GAIA tasks from local repository directory."""
tasks: list[Task] = []
for p in repo_dir.rglob("metadata.jsonl"):
for rec in _read_jsonl(p):
# Robustly extract fields used across variants
q = rec.get("Question") or rec.get("question") or rec.get("query") or rec.get("prompt")
ans = rec.get("Final answer") or rec.get("answer") or rec.get("final_answer")
qid = str(
rec.get("task_id")
or rec.get("question_id")
or rec.get("id")
or rec.get("uuid")
or f"{p.stem}:{len(tasks)}"
)
lvl = rec.get("Level") or rec.get("level")
fname = rec.get("file_name") or rec.get("filename") or None
# First try to load from parquet files (new format)
# Prioritize validation split over test split (validation has answers)
parquet_files = sorted(
repo_dir.rglob("metadata*.parquet"), key=lambda p: (0 if "validation" in str(p) else 1, str(p))
)
# Only evaluate examples with public answers (dev/validation split)
if not q or ans is None:
continue
for p in parquet_files:
try:
import pyarrow.parquet as pq
if wanted_levels and (lvl not in wanted_levels):
continue
table = pq.read_table(p)
for row in table.to_pylist():
# Robustly extract fields used across variants
q = row.get("Question") or row.get("question") or row.get("query") or row.get("prompt")
ans = row.get("Final answer") or row.get("answer") or row.get("final_answer")
qid = str(
row.get("task_id")
or row.get("question_id")
or row.get("id")
or row.get("uuid")
or f"{p.stem}:{len(tasks)}"
)
lvl = row.get("Level") or row.get("level")
tasks.append(Task(task_id=qid, question=q, answer=str(ans), level=lvl, file_name=fname, metadata=rec))
# Convert level to int if it's a string
def _parse_level(lvl: Any) -> int | None:
"""Parse level value to integer if possible."""
if isinstance(lvl, int):
return lvl
if isinstance(lvl, str) and lvl.isdigit():
return int(lvl)
return None
lvl = _parse_level(lvl)
fname = row.get("file_name") or row.get("filename") or None
# Only evaluate examples with public answers (dev/validation split)
# Skip if no question, no answer, or answer is placeholder like "?"
if not q or ans is None or str(ans).strip() in ["?", ""]:
continue
if wanted_levels and (lvl not in wanted_levels):
continue
tasks.append(Task(task_id=qid, question=q, answer=str(ans), level=lvl, file_name=fname, metadata=row))
except ImportError:
print("Warning: pyarrow not installed. Install with: pip install pyarrow")
continue
except Exception as e:
print(f"Warning: Could not load parquet file {p}: {e}")
continue
# Fall back to jsonl files (old format) if no parquet files found
if not tasks:
for p in repo_dir.rglob("metadata.jsonl"):
for rec in _read_jsonl(p):
# Robustly extract fields used across variants
q = rec.get("Question") or rec.get("question") or rec.get("query") or rec.get("prompt")
ans = rec.get("Final answer") or rec.get("answer") or rec.get("final_answer")
qid = str(
rec.get("task_id")
or rec.get("question_id")
or rec.get("id")
or rec.get("uuid")
or f"{p.stem}:{len(tasks)}"
)
lvl = rec.get("Level") or rec.get("level")
# Convert level to int if it's a string
if isinstance(lvl, str) and lvl.isdigit():
lvl = int(lvl)
fname = rec.get("file_name") or rec.get("filename") or None
# Only evaluate examples with public answers (dev/validation split)
# Skip if no question, no answer, or answer is placeholder like "?"
if not q or ans is None or str(ans).strip() in ["?", ""]:
continue
if wanted_levels and (lvl not in wanted_levels):
continue
tasks.append(Task(task_id=qid, question=q, answer=str(ans), level=lvl, file_name=fname, metadata=rec))
# Shuffle to help with rate-limits and fairness if max_n is provided
random.shuffle(tasks)
@@ -290,7 +360,6 @@ class GAIA:
"with access to gaia-benchmark/GAIA."
)
print(f"Downloading GAIA dataset to {self.data_dir}...")
from huggingface_hub import snapshot_download
local_dir = snapshot_download( # type: ignore
@@ -438,8 +507,6 @@ class GAIA:
"Make sure you have dataset access and selected valid levels."
)
print(f"Running {len(tasks)} GAIA tasks (levels={levels}) with {parallel} parallel workers...")
# Update benchmark span with task info
if benchmark_span:
benchmark_span.set_attributes({
@@ -473,17 +540,12 @@ class GAIA:
"gaia.benchmark.avg_runtime_seconds": avg_runtime,
})
print("\nGAIA Benchmark Results:")
print(f"Accuracy: {accuracy:.3f} ({correct}/{len(results)})")
print(f"Average runtime: {avg_runtime:.2f}s")
# Save results if requested
if out:
with self.tracer.start_as_current_span(
"gaia.results.save", kind=SpanKind.INTERNAL, attributes={"gaia.results.output_file": out}
):
self._save_results(results, out)
print(f"Results saved to {out}")
return results
@@ -0,0 +1,67 @@
# Copyright (c) Microsoft. All rights reserved.
"""Azure AI Agent factory for GAIA benchmark.
This module provides a factory function to create an Azure AI agent
configured for GAIA benchmark tasks.
Required Environment Variables:
AZURE_AI_PROJECT_ENDPOINT: Azure AI project endpoint URL
AZURE_AI_MODEL_DEPLOYMENT_NAME: Name of the model deployment to use
Optional Environment Variables:
BING_CONNECTION_NAME: Name of the Bing connection for web search
OR
BING_CONNECTION_ID: ID of the Bing connection for web search
Authentication:
Uses Azure CLI credentials via AzureCliCredential.
Run `az login` before executing to authenticate.
Example:
export AZURE_AI_PROJECT_ENDPOINT="https://your-project.azure.com"
export AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o"
export BING_CONNECTION_NAME="bing-grounding-connection"
az login
"""
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from agent_framework import ChatAgent, HostedCodeInterpreterTool, HostedWebSearchTool
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@asynccontextmanager
async def create_gaia_agent() -> AsyncIterator[ChatAgent]:
"""Create an Azure AI agent configured for GAIA benchmark tasks.
The agent is configured with:
- Bing Search tool for web information retrieval
- Code Interpreter tool for calculations and data analysis
Yields:
ChatAgent: A configured agent ready to run GAIA tasks.
Example:
async with create_gaia_agent() as agent:
result = await agent.run("What is the capital of France?")
print(result.text)
"""
async with (
AzureCliCredential() as credential,
AzureAIAgentClient(async_credential=credential).create_agent(
name="GaiaAgent",
instructions="Solve tasks to your best ability. Use Bing Search to find "
"information and Code Interpreter to perform calculations and data analysis.",
tools=[
HostedWebSearchTool(
name="Bing Grounding Search",
description="Search the web for current information using Bing",
),
HostedCodeInterpreterTool(),
],
) as agent,
):
yield agent
+250 -33
View File
@@ -2,43 +2,148 @@
"""GAIA Benchmark Sample.
To run this sample, execute it from the root directory of the agent-framework repository:
cd /path/to/agent-framework
uv run python python/packages/lab/gaia/gaia_sample.py
Run the GAIA (General AI Assistant) benchmark with configurable agent providers,
telemetry options, and benchmark parameters.
This avoids namespace package conflicts that occur when running from within the gaia package directory.
Agent Providers:
- Azure AI (default): See azure_ai_agent.py for required environment variables
- OpenAI: See openai_agent.py for required environment variables
Prerequisites:
1. Set HF_TOKEN environment variable with your Hugging Face token:
- Get token: https://huggingface.co/settings/tokens
- Request dataset access: https://huggingface.co/datasets/gaia-benchmark/GAIA
- Set: export HF_TOKEN="your-huggingface-token"
2. Configure your chosen agent provider (see agent module files for details)
Telemetry:
When using --otlp-endpoint or --trace-file, OpenTelemetry will export trace data
in JSON format to the console in addition to the configured endpoints. This is
expected behavior from the OpenTelemetry SDK and provides visibility into the
telemetry being captured. The traces are also exported to:
- OTLP endpoint (e.g., Aspire Dashboard) if --otlp-endpoint is specified
- Local file if --trace-file is specified
To suppress console output, redirect stderr: `python gaia_sample.py 2>/dev/null`
Usage:
# Run with default settings (Azure AI agent)
uv run python gaia_sample.py
# Run with OpenAI agent
uv run python gaia_sample.py --agent-provider openai
# Run with telemetry export to Aspire Dashboard
uv run python gaia_sample.py --otlp-endpoint http://localhost:4318
# See all options
uv run python gaia_sample.py --help
"""
from agent_framework.azure import AzureAIAgentClient
import argparse
from agent_framework.lab.gaia import GAIA, Evaluation, GAIATelemetryConfig, Prediction, Task
from azure.identity.aio import AzureCliCredential
def evaluate_task(task: Task, prediction: Prediction) -> Evaluation:
async def evaluate_task(task: Task, prediction: Prediction) -> Evaluation:
"""Evaluate the prediction for a given task."""
# Simple evaluation: check if the prediction contains the answer
is_correct = (task.answer or "").lower() in prediction.prediction.lower()
return Evaluation(is_correct=is_correct, score=1 if is_correct else 0)
async def main() -> None:
"""Run GAIA benchmark with telemetry configuration."""
async def main(
otlp_endpoint: str | None = None,
trace_file: str | None = None,
result_file: str | None = None,
data_dir: str | None = None,
agent_provider: str = "azure-ai",
level: int | list[int] = 1,
max_n: int = 2,
parallel: int = 1,
timeout: int = 120,
) -> None:
"""Run GAIA benchmark with telemetry configuration.
Args:
otlp_endpoint: Optional OTLP endpoint URL for exporting traces (e.g., http://localhost:4318)
trace_file: Optional file path to export traces to. If None, traces won't be saved to file.
result_file: Optional file path to save benchmark results. If None, results won't be saved to file.
data_dir: Directory to cache GAIA dataset. If None, uses temp directory.
agent_provider: Agent provider to use: 'azure-ai' or 'openai' (default: 'azure-ai')
level: GAIA level(s) to run (1, 2, or 3)
max_n: Maximum number of tasks to run per level
parallel: Number of parallel tasks to run
timeout: Timeout per task in seconds
"""
# Check for required Hugging Face token
import logging
import os
# Suppress console logging for traces and verbose SDK output
logging.getLogger("opentelemetry").setLevel(logging.ERROR)
logging.getLogger("azure").setLevel(logging.WARNING)
logging.getLogger("agent_framework").setLevel(logging.WARNING)
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("httpcore").setLevel(logging.WARNING)
# Suppress OpenTelemetry exporters console output
import os as _os
_os.environ.setdefault("OTEL_PYTHON_LOG_LEVEL", "error")
# Print trace export configuration
print("\n=== Telemetry Configuration ===")
if trace_file:
print(f"📁 Trace file: {os.path.abspath(trace_file)}")
else:
print("📁 Trace file: disabled")
if otlp_endpoint:
print(f"🌐 OTLP endpoint: {otlp_endpoint}")
else:
print("🌐 OTLP endpoint: disabled")
if result_file:
print(f"📊 Results file: {os.path.abspath(result_file)}")
else:
print("📊 Results file: disabled")
print("\n=== Run Configuration ===")
print(f"🤖 Agent provider: {agent_provider}")
if data_dir:
print(f"📂 Data directory: {os.path.abspath(data_dir)}")
else:
import tempfile
from pathlib import Path
default_data_dir = Path(tempfile.gettempdir()) / "data_gaia_hub"
print(f"📂 Data directory: {default_data_dir} (default)")
print(f"🎯 Level: {level}")
print(f"🔢 Max tasks: {max_n}")
print(f"⚡ Parallel: {parallel}")
print(f"⏱️ Timeout: {timeout}s")
print()
# Import the appropriate agent factory based on provider
if agent_provider == "azure-ai":
from azure_ai_agent import create_gaia_agent
elif agent_provider == "openai":
from openai_agent import create_gaia_agent
else:
raise ValueError(f"Unknown agent provider: {agent_provider}. Use 'azure-ai' or 'openai'.")
# Configure telemetry for tracing
telemetry_config = GAIATelemetryConfig(
enable_tracing=True, # Enable OpenTelemetry tracing
# Configure local file tracing
trace_to_file=True, # Export traces to local file
file_path="gaia_benchmark_traces.jsonl", # Custom file path for traces
trace_to_file=trace_file is not None, # Export traces to local file only if path provided
file_path=trace_file, # Custom file path for traces (can be None)
otlp_endpoint=otlp_endpoint, # Optional OTLP endpoint for Aspire Dashboard or other collectors
)
# Create a single agent once and reuse it for all tasks
async with (
AzureCliCredential() as credential,
AzureAIAgentClient(async_credential=credential).create_agent(
name="GaiaAgent",
instructions="Solve tasks to your best ability.",
) as agent,
):
async with create_gaia_agent() as agent:
async def run_task(task: Task) -> Prediction:
"""Run a single GAIA task and return the prediction using the shared agent."""
@@ -49,30 +154,142 @@ async def main() -> None:
return Prediction(prediction=result.text, messages=result.messages)
# Create the GAIA benchmark runner with telemetry configuration
runner = GAIA(evaluator=evaluate_task, telemetry_config=telemetry_config)
runner = GAIA(
evaluator=evaluate_task,
telemetry_config=telemetry_config,
data_dir=data_dir,
)
# Run the benchmark with the task runner.
# By default, this will check for locally cached benchmark data and checkout
# the latest version from HuggingFace if not found.
# Note: The GAIA dataset has been updated to use Parquet format.
# If you encounter issues, try using validation split which has labeled data.
results = await runner.run(
run_task,
level=1, # Level 1, 2, or 3 or multiple levels like [1, 2]
max_n=5, # Maximum number of tasks to run per level
parallel=2, # Number of parallel tasks to run
timeout=60, # Timeout per task in seconds
out="gaia_results_level1.jsonl", # Output file to save results including detailed traces (optional)
level=level,
max_n=max_n,
parallel=parallel,
timeout=timeout,
out=result_file, # Output file to save results including detailed traces (optional, None = no file output)
)
# Print the results.
print("\n=== GAIA Benchmark Results ===")
for result in results:
print(f"\n--- Task ID: {result.task_id} ---")
print(f"Task: {result.task.question[:100]}...")
print(f"Prediction: {result.prediction.prediction}")
print(f"Evaluation: Correct={result.evaluation.is_correct}, Score={result.evaluation.score}")
# Print summary similar to the viewer in gaia.py
total = len(results)
correct = sum(1 for r in results if r.evaluation.is_correct)
accuracy = correct / total if total > 0 else 0.0
avg_runtime = sum(r.runtime_seconds or 0 for r in results) / total if total > 0 else 0.0
print("\n=== GAIA Benchmark Summary ===")
print(f"📝 Total: {total}, ✅ Correct: {correct}, 🎯 Accuracy: {accuracy:.3f}")
print(f"⏱️ Average runtime: {avg_runtime:.2f}s")
if result_file:
print(f"💾 Detailed results saved to: {result_file}")
if __name__ == "__main__":
import asyncio
asyncio.run(main())
# Parse command line arguments
parser = argparse.ArgumentParser(
description="Run GAIA benchmark with optional telemetry export to OTLP endpoint and/or file",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Run with default settings
python gaia_sample.py
# Run with custom data directory
python gaia_sample.py --data-dir ./gaia_data
# Run with OpenAI agent provider
python gaia_sample.py --agent-provider openai
# Run with trace file export
python gaia_sample.py --trace-file gaia_benchmark_traces.jsonl
# Run level 2 tasks with 5 maximum tasks
python gaia_sample.py --level 2 --max-n 5
# Run with OTLP export to Aspire Dashboard and custom settings
python gaia_sample.py --otlp-endpoint http://localhost:4318 --level 1 --max-n 10 --parallel 2
# Run with all options configured
python gaia_sample.py --agent-provider openai \
--trace-file traces.jsonl \
--result-file results.jsonl \
--otlp-endpoint http://localhost:4318 --level 1 --max-n 5 --parallel 2 --timeout 180
""",
)
parser.add_argument(
"--otlp-endpoint",
type=str,
default=None,
help="OTLP endpoint URL for exporting traces (e.g., http://localhost:4318 for Aspire Dashboard)",
)
parser.add_argument(
"--trace-file",
type=str,
default=None,
help="File path to export traces to (e.g., gaia_benchmark_traces.jsonl). "
"If not set, traces won't be saved to file.",
)
parser.add_argument(
"--result-file",
type=str,
default="gaia_results_level1.jsonl",
help="File path to save benchmark results (default: gaia_results_level1.jsonl)",
)
parser.add_argument(
"--data-dir",
type=str,
default=None,
help="Directory to cache GAIA dataset. If not set, uses system temp directory.",
)
parser.add_argument(
"--agent-provider",
type=str,
default="azure-ai",
choices=["azure-ai", "openai"],
help="Agent provider to use: 'azure-ai' or 'openai' (default: 'azure-ai')",
)
parser.add_argument(
"--level",
type=int,
default=1,
choices=[1, 2, 3],
help="GAIA benchmark level to run: 1, 2, or 3 (default: 1)",
)
parser.add_argument(
"--max-n",
type=int,
default=2,
help="Maximum number of tasks to run per level (default: 2)",
)
parser.add_argument(
"--parallel",
type=int,
default=1,
help="Number of parallel tasks to run (default: 1)",
)
parser.add_argument(
"--timeout",
type=int,
default=120,
help="Timeout per task in seconds (default: 120)",
)
args = parser.parse_args()
asyncio.run(
main(
otlp_endpoint=args.otlp_endpoint,
trace_file=args.trace_file,
result_file=args.result_file,
data_dir=args.data_dir,
agent_provider=args.agent_provider,
level=args.level,
max_n=args.max_n,
parallel=args.parallel,
timeout=args.timeout,
)
)
@@ -0,0 +1,64 @@
# Copyright (c) Microsoft. All rights reserved.
"""OpenAI Agent factory for GAIA benchmark.
This module provides a factory function to create an OpenAI agent
configured for GAIA benchmark tasks using the OpenAI Responses API.
Required Environment Variables:
OPENAI_API_KEY: Your OpenAI API key
OPENAI_RESPONSES_MODEL_ID: Model to use with Responses API (e.g., gpt-4o, gpt-4o-mini)
Optional Environment Variables:
OPENAI_BASE_URL: Custom API base URL if using a proxy or compatible service
OPENAI_ORG_ID: Organization ID for OpenAI API (if applicable)
Authentication:
Uses OPENAI_API_KEY environment variable.
Get your API key from: https://platform.openai.com/api-keys
Example:
export OPENAI_API_KEY="sk-..."
export OPENAI_RESPONSES_MODEL_ID="gpt-4o"
"""
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from agent_framework import ChatAgent, HostedCodeInterpreterTool, HostedWebSearchTool
from agent_framework.openai import OpenAIResponsesClient
@asynccontextmanager
async def create_gaia_agent() -> AsyncIterator[ChatAgent]:
"""Create an OpenAI agent configured for GAIA benchmark tasks.
Uses OpenAI Responses API for enhanced capabilities.
The agent is configured with:
- Web Search tool for information retrieval
- Code Interpreter tool for calculations and data analysis
Yields:
ChatAgent: A configured agent ready to run GAIA tasks.
Example:
async with create_gaia_agent() as agent:
result = await agent.run("What is the capital of France?")
print(result.text)
"""
chat_client = OpenAIResponsesClient()
async with chat_client.create_agent(
name="GaiaAgent",
instructions="Solve tasks to your best ability. Use Web Search to find "
"information and Code Interpreter to perform calculations and data analysis.",
tools=[
HostedWebSearchTool(
name="Web Search",
description="Search the web for current information",
),
HostedCodeInterpreterTool(),
],
) as agent:
yield agent
+8 -1
View File
@@ -32,6 +32,7 @@ gaia = [
"tqdm>=4.60.0",
"huggingface-hub>=0.20.0",
"orjson>=3.8.0",
"pyarrow>=10.0.0", # For reading parquet files
]
# Lightning RL training module dependencies
@@ -111,7 +112,13 @@ extend = "../../pyproject.toml"
extend-exclude = ["**/data/**"]
[tool.ruff.lint]
ignore = ["T201", "ASYNC230", "INP001"] # Allow print statements, blocking file operations, and implicit namespace packages in lab modules
ignore = [
"T201", # Allow print statements in experimental/lab code for debugging purposes.
"ASYNC230", # Allow 'await' outside of async functions in test and experimental code.
"INP001", # Ignore missing __init__.py in namespace packages.
"RUF029", # Allow use of 'assert' statements; assertions are used for internal checks in experimental code.
"ASYNC240", # Allow 'async for' outside of async functions in test and experimental code.
]
[tool.coverage.run]
omit = [
+61 -2
View File
@@ -297,6 +297,7 @@ gaia = [
{ name = "huggingface-hub", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "opentelemetry-api", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "orjson", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "pyarrow", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
@@ -344,6 +345,7 @@ requires-dist = [
{ name = "numpy", marker = "extra == 'tau2'" },
{ name = "opentelemetry-api", marker = "extra == 'gaia'", specifier = ">=1.24.0" },
{ name = "orjson", marker = "extra == 'gaia'", specifier = ">=3.8.0" },
{ name = "pyarrow", marker = "extra == 'gaia'", specifier = ">=10.0.0" },
{ name = "pydantic", marker = "extra == 'gaia'", specifier = ">=2.0.0" },
{ name = "pydantic", marker = "extra == 'tau2'", specifier = ">=2.0.0" },
{ name = "sympy", marker = "extra == 'math'", specifier = ">=1.13.0" },
@@ -909,7 +911,7 @@ name = "cffi"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pycparser", marker = "(implementation_name != 'PyPy' and sys_platform == 'darwin') or (implementation_name != 'PyPy' and sys_platform == 'linux') or (implementation_name != 'PyPy' and sys_platform == 'win32')" },
{ name = "pycparser", marker = "(python_full_version < '3.13' and implementation_name != 'PyPy' and sys_platform == 'darwin') or (python_full_version < '3.13' and implementation_name != 'PyPy' and sys_platform == 'linux') or (python_full_version < '3.13' and implementation_name != 'PyPy' and sys_platform == 'win32') or (implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' and sys_platform == 'darwin') or (implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' and sys_platform == 'linux') or (implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' and sys_platform == 'win32')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
wheels = [
@@ -1571,7 +1573,7 @@ name = "exceptiongroup"
version = "1.3.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "(python_full_version < '3.13' and sys_platform == 'darwin') or (python_full_version < '3.13' and sys_platform == 'linux') or (python_full_version < '3.13' and sys_platform == 'win32')" },
{ name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" }
wheels = [
@@ -4169,6 +4171,63 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c2/94/6475c7faa94a1d90303f624936471cd0f4c20430bd2c92deab607cd0ff31/py2docfx-0.1.22-py3-none-any.whl", hash = "sha256:ccee611af2aefe9f39f446f72b5e07d3369bbdb77c13ebafb69ed1a116116467", size = 11420273, upload-time = "2025-10-10T07:16:25.294Z" },
]
[[package]]
name = "pyarrow"
version = "22.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d9/9b/cb3f7e0a345353def531ca879053e9ef6b9f38ed91aebcf68b09ba54dec0/pyarrow-22.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:77718810bd3066158db1e95a63c160ad7ce08c6b0710bc656055033e39cdad88", size = 34223968, upload-time = "2025-10-24T10:03:31.21Z" },
{ url = "https://files.pythonhosted.org/packages/6c/41/3184b8192a120306270c5307f105b70320fdaa592c99843c5ef78aaefdcf/pyarrow-22.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:44d2d26cda26d18f7af7db71453b7b783788322d756e81730acb98f24eb90ace", size = 35942085, upload-time = "2025-10-24T10:03:38.146Z" },
{ url = "https://files.pythonhosted.org/packages/d9/3d/a1eab2f6f08001f9fb714b8ed5cfb045e2fe3e3e3c0c221f2c9ed1e6d67d/pyarrow-22.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:b9d71701ce97c95480fecb0039ec5bb889e75f110da72005743451339262f4ce", size = 44964613, upload-time = "2025-10-24T10:03:46.516Z" },
{ url = "https://files.pythonhosted.org/packages/46/46/a1d9c24baf21cfd9ce994ac820a24608decf2710521b29223d4334985127/pyarrow-22.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:710624ab925dc2b05a6229d47f6f0dac1c1155e6ed559be7109f684eba048a48", size = 47627059, upload-time = "2025-10-24T10:03:55.353Z" },
{ url = "https://files.pythonhosted.org/packages/3a/4c/f711acb13075c1391fd54bc17e078587672c575f8de2a6e62509af026dcf/pyarrow-22.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f963ba8c3b0199f9d6b794c90ec77545e05eadc83973897a4523c9e8d84e9340", size = 47947043, upload-time = "2025-10-24T10:04:05.408Z" },
{ url = "https://files.pythonhosted.org/packages/4e/70/1f3180dd7c2eab35c2aca2b29ace6c519f827dcd4cfeb8e0dca41612cf7a/pyarrow-22.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd0d42297ace400d8febe55f13fdf46e86754842b860c978dfec16f081e5c653", size = 50206505, upload-time = "2025-10-24T10:04:15.786Z" },
{ url = "https://files.pythonhosted.org/packages/80/07/fea6578112c8c60ffde55883a571e4c4c6bc7049f119d6b09333b5cc6f73/pyarrow-22.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:00626d9dc0f5ef3a75fe63fd68b9c7c8302d2b5bbc7f74ecaedba83447a24f84", size = 28101641, upload-time = "2025-10-24T10:04:22.57Z" },
{ url = "https://files.pythonhosted.org/packages/2e/b7/18f611a8cdc43417f9394a3ccd3eace2f32183c08b9eddc3d17681819f37/pyarrow-22.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:3e294c5eadfb93d78b0763e859a0c16d4051fc1c5231ae8956d61cb0b5666f5a", size = 34272022, upload-time = "2025-10-24T10:04:28.973Z" },
{ url = "https://files.pythonhosted.org/packages/26/5c/f259e2526c67eb4b9e511741b19870a02363a47a35edbebc55c3178db22d/pyarrow-22.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:69763ab2445f632d90b504a815a2a033f74332997052b721002298ed6de40f2e", size = 35995834, upload-time = "2025-10-24T10:04:35.467Z" },
{ url = "https://files.pythonhosted.org/packages/50/8d/281f0f9b9376d4b7f146913b26fac0aa2829cd1ee7e997f53a27411bbb92/pyarrow-22.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:b41f37cabfe2463232684de44bad753d6be08a7a072f6a83447eeaf0e4d2a215", size = 45030348, upload-time = "2025-10-24T10:04:43.366Z" },
{ url = "https://files.pythonhosted.org/packages/f5/e5/53c0a1c428f0976bf22f513d79c73000926cb00b9c138d8e02daf2102e18/pyarrow-22.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:35ad0f0378c9359b3f297299c3309778bb03b8612f987399a0333a560b43862d", size = 47699480, upload-time = "2025-10-24T10:04:51.486Z" },
{ url = "https://files.pythonhosted.org/packages/95/e1/9dbe4c465c3365959d183e6345d0a8d1dc5b02ca3f8db4760b3bc834cf25/pyarrow-22.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8382ad21458075c2e66a82a29d650f963ce51c7708c7c0ff313a8c206c4fd5e8", size = 48011148, upload-time = "2025-10-24T10:04:59.585Z" },
{ url = "https://files.pythonhosted.org/packages/c5/b4/7caf5d21930061444c3cf4fa7535c82faf5263e22ce43af7c2759ceb5b8b/pyarrow-22.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1a812a5b727bc09c3d7ea072c4eebf657c2f7066155506ba31ebf4792f88f016", size = 50276964, upload-time = "2025-10-24T10:05:08.175Z" },
{ url = "https://files.pythonhosted.org/packages/ae/f3/cec89bd99fa3abf826f14d4e53d3d11340ce6f6af4d14bdcd54cd83b6576/pyarrow-22.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:ec5d40dd494882704fb876c16fa7261a69791e784ae34e6b5992e977bd2e238c", size = 28106517, upload-time = "2025-10-24T10:05:14.314Z" },
{ url = "https://files.pythonhosted.org/packages/af/63/ba23862d69652f85b615ca14ad14f3bcfc5bf1b99ef3f0cd04ff93fdad5a/pyarrow-22.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:bea79263d55c24a32b0d79c00a1c58bb2ee5f0757ed95656b01c0fb310c5af3d", size = 34211578, upload-time = "2025-10-24T10:05:21.583Z" },
{ url = "https://files.pythonhosted.org/packages/b1/d0/f9ad86fe809efd2bcc8be32032fa72e8b0d112b01ae56a053006376c5930/pyarrow-22.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:12fe549c9b10ac98c91cf791d2945e878875d95508e1a5d14091a7aaa66d9cf8", size = 35989906, upload-time = "2025-10-24T10:05:29.485Z" },
{ url = "https://files.pythonhosted.org/packages/b4/a8/f910afcb14630e64d673f15904ec27dd31f1e009b77033c365c84e8c1e1d/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:334f900ff08ce0423407af97e6c26ad5d4e3b0763645559ece6fbf3747d6a8f5", size = 45021677, upload-time = "2025-10-24T10:05:38.274Z" },
{ url = "https://files.pythonhosted.org/packages/13/95/aec81f781c75cd10554dc17a25849c720d54feafb6f7847690478dcf5ef8/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c6c791b09c57ed76a18b03f2631753a4960eefbbca80f846da8baefc6491fcfe", size = 47726315, upload-time = "2025-10-24T10:05:47.314Z" },
{ url = "https://files.pythonhosted.org/packages/bb/d4/74ac9f7a54cfde12ee42734ea25d5a3c9a45db78f9def949307a92720d37/pyarrow-22.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c3200cb41cdbc65156e5f8c908d739b0dfed57e890329413da2748d1a2cd1a4e", size = 47990906, upload-time = "2025-10-24T10:05:58.254Z" },
{ url = "https://files.pythonhosted.org/packages/2e/71/fedf2499bf7a95062eafc989ace56572f3343432570e1c54e6599d5b88da/pyarrow-22.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ac93252226cf288753d8b46280f4edf3433bf9508b6977f8dd8526b521a1bbb9", size = 50306783, upload-time = "2025-10-24T10:06:08.08Z" },
{ url = "https://files.pythonhosted.org/packages/68/ed/b202abd5a5b78f519722f3d29063dda03c114711093c1995a33b8e2e0f4b/pyarrow-22.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:44729980b6c50a5f2bfcc2668d36c569ce17f8b17bccaf470c4313dcbbf13c9d", size = 27972883, upload-time = "2025-10-24T10:06:14.204Z" },
{ url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" },
{ url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" },
{ url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" },
{ url = "https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e0a15757fccb38c410947df156f9749ae4a3c89b2393741a50521f39a8cf202a", size = 47724601, upload-time = "2025-10-24T10:06:43.551Z" },
{ url = "https://files.pythonhosted.org/packages/69/4d/76e567a4fc2e190ee6072967cb4672b7d9249ac59ae65af2d7e3047afa3b/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cedb9dd9358e4ea1d9bce3665ce0797f6adf97ff142c8e25b46ba9cdd508e9b6", size = 48001050, upload-time = "2025-10-24T10:06:52.284Z" },
{ url = "https://files.pythonhosted.org/packages/01/5e/5653f0535d2a1aef8223cee9d92944cb6bccfee5cf1cd3f462d7cb022790/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:252be4a05f9d9185bb8c18e83764ebcfea7185076c07a7a662253af3a8c07941", size = 50307877, upload-time = "2025-10-24T10:07:02.405Z" },
{ url = "https://files.pythonhosted.org/packages/2d/f8/1d0bd75bf9328a3b826e24a16e5517cd7f9fbf8d34a3184a4566ef5a7f29/pyarrow-22.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:a4893d31e5ef780b6edcaf63122df0f8d321088bb0dee4c8c06eccb1ca28d145", size = 27977099, upload-time = "2025-10-24T10:08:07.259Z" },
{ url = "https://files.pythonhosted.org/packages/90/81/db56870c997805bf2b0f6eeeb2d68458bf4654652dccdcf1bf7a42d80903/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:f7fe3dbe871294ba70d789be16b6e7e52b418311e166e0e3cba9522f0f437fb1", size = 34336685, upload-time = "2025-10-24T10:07:11.47Z" },
{ url = "https://files.pythonhosted.org/packages/1c/98/0727947f199aba8a120f47dfc229eeb05df15bcd7a6f1b669e9f882afc58/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:ba95112d15fd4f1105fb2402c4eab9068f0554435e9b7085924bcfaac2cc306f", size = 36032158, upload-time = "2025-10-24T10:07:18.626Z" },
{ url = "https://files.pythonhosted.org/packages/96/b4/9babdef9c01720a0785945c7cf550e4acd0ebcd7bdd2e6f0aa7981fa85e2/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c064e28361c05d72eed8e744c9605cbd6d2bb7481a511c74071fd9b24bc65d7d", size = 44892060, upload-time = "2025-10-24T10:07:26.002Z" },
{ url = "https://files.pythonhosted.org/packages/f8/ca/2f8804edd6279f78a37062d813de3f16f29183874447ef6d1aadbb4efa0f/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6f9762274496c244d951c819348afbcf212714902742225f649cf02823a6a10f", size = 47504395, upload-time = "2025-10-24T10:07:34.09Z" },
{ url = "https://files.pythonhosted.org/packages/b9/f0/77aa5198fd3943682b2e4faaf179a674f0edea0d55d326d83cb2277d9363/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a9d9ffdc2ab696f6b15b4d1f7cec6658e1d788124418cb30030afbae31c64746", size = 48066216, upload-time = "2025-10-24T10:07:43.528Z" },
{ url = "https://files.pythonhosted.org/packages/79/87/a1937b6e78b2aff18b706d738c9e46ade5bfcf11b294e39c87706a0089ac/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ec1a15968a9d80da01e1d30349b2b0d7cc91e96588ee324ce1b5228175043e95", size = 50288552, upload-time = "2025-10-24T10:07:53.519Z" },
{ url = "https://files.pythonhosted.org/packages/60/ae/b5a5811e11f25788ccfdaa8f26b6791c9807119dffcf80514505527c384c/pyarrow-22.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bba208d9c7decf9961998edf5c65e3ea4355d5818dd6cd0f6809bec1afb951cc", size = 28262504, upload-time = "2025-10-24T10:08:00.932Z" },
{ url = "https://files.pythonhosted.org/packages/bd/b0/0fa4d28a8edb42b0a7144edd20befd04173ac79819547216f8a9f36f9e50/pyarrow-22.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:9bddc2cade6561f6820d4cd73f99a0243532ad506bc510a75a5a65a522b2d74d", size = 34224062, upload-time = "2025-10-24T10:08:14.101Z" },
{ url = "https://files.pythonhosted.org/packages/0f/a8/7a719076b3c1be0acef56a07220c586f25cd24de0e3f3102b438d18ae5df/pyarrow-22.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e70ff90c64419709d38c8932ea9fe1cc98415c4f87ea8da81719e43f02534bc9", size = 35990057, upload-time = "2025-10-24T10:08:21.842Z" },
{ url = "https://files.pythonhosted.org/packages/89/3c/359ed54c93b47fb6fe30ed16cdf50e3f0e8b9ccfb11b86218c3619ae50a8/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:92843c305330aa94a36e706c16209cd4df274693e777ca47112617db7d0ef3d7", size = 45068002, upload-time = "2025-10-24T10:08:29.034Z" },
{ url = "https://files.pythonhosted.org/packages/55/fc/4945896cc8638536ee787a3bd6ce7cec8ec9acf452d78ec39ab328efa0a1/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6dda1ddac033d27421c20d7a7943eec60be44e0db4e079f33cc5af3b8280ccde", size = 47737765, upload-time = "2025-10-24T10:08:38.559Z" },
{ url = "https://files.pythonhosted.org/packages/cd/5e/7cb7edeb2abfaa1f79b5d5eb89432356155c8426f75d3753cbcb9592c0fd/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:84378110dd9a6c06323b41b56e129c504d157d1a983ce8f5443761eb5256bafc", size = 48048139, upload-time = "2025-10-24T10:08:46.784Z" },
{ url = "https://files.pythonhosted.org/packages/88/c6/546baa7c48185f5e9d6e59277c4b19f30f48c94d9dd938c2a80d4d6b067c/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:854794239111d2b88b40b6ef92aa478024d1e5074f364033e73e21e3f76b25e0", size = 50314244, upload-time = "2025-10-24T10:08:55.771Z" },
{ url = "https://files.pythonhosted.org/packages/3c/79/755ff2d145aafec8d347bf18f95e4e81c00127f06d080135dfc86aea417c/pyarrow-22.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:b883fe6fd85adad7932b3271c38ac289c65b7337c2c132e9569f9d3940620730", size = 28757501, upload-time = "2025-10-24T10:09:59.891Z" },
{ url = "https://files.pythonhosted.org/packages/0e/d2/237d75ac28ced3147912954e3c1a174df43a95f4f88e467809118a8165e0/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7a820d8ae11facf32585507c11f04e3f38343c1e784c9b5a8b1da5c930547fe2", size = 34355506, upload-time = "2025-10-24T10:09:02.953Z" },
{ url = "https://files.pythonhosted.org/packages/1e/2c/733dfffe6d3069740f98e57ff81007809067d68626c5faef293434d11bd6/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:c6ec3675d98915bf1ec8b3c7986422682f7232ea76cad276f4c8abd5b7319b70", size = 36047312, upload-time = "2025-10-24T10:09:10.334Z" },
{ url = "https://files.pythonhosted.org/packages/7c/2b/29d6e3782dc1f299727462c1543af357a0f2c1d3c160ce199950d9ca51eb/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3e739edd001b04f654b166204fc7a9de896cf6007eaff33409ee9e50ceaff754", size = 45081609, upload-time = "2025-10-24T10:09:18.61Z" },
{ url = "https://files.pythonhosted.org/packages/8d/42/aa9355ecc05997915af1b7b947a7f66c02dcaa927f3203b87871c114ba10/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:7388ac685cab5b279a41dfe0a6ccd99e4dbf322edfb63e02fc0443bf24134e91", size = 47703663, upload-time = "2025-10-24T10:09:27.369Z" },
{ url = "https://files.pythonhosted.org/packages/ee/62/45abedde480168e83a1de005b7b7043fd553321c1e8c5a9a114425f64842/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f633074f36dbc33d5c05b5dc75371e5660f1dbf9c8b1d95669def05e5425989c", size = 48066543, upload-time = "2025-10-24T10:09:34.908Z" },
{ url = "https://files.pythonhosted.org/packages/84/e9/7878940a5b072e4f3bf998770acafeae13b267f9893af5f6d4ab3904b67e/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4c19236ae2402a8663a2c8f21f1870a03cc57f0bef7e4b6eb3238cc82944de80", size = 50288838, upload-time = "2025-10-24T10:09:44.394Z" },
{ url = "https://files.pythonhosted.org/packages/7b/03/f335d6c52b4a4761bcc83499789a1e2e16d9d201a58c327a9b5cc9a41bd9/pyarrow-22.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0c34fe18094686194f204a3b1787a27456897d8a2d62caf84b61e8dfbc0252ae", size = 29185594, upload-time = "2025-10-24T10:09:53.111Z" },
]
[[package]]
name = "pyasn1"
version = "0.6.1"