ResearchHarness / agent_base /trace_utils.py
black-yt's picture
Create ResearchHarness Hugging Face Space
f209a8f
Raw
History Blame Contribute Delete
3.27 kB
import argparse
import datetime
from pathlib import Path
from typing import Any, Callable, Optional
from uuid import uuid4
from agent_base.utils import append_jsonl, safe_jsonable
TRACE_FIELD_NAMES = [
"run_id",
"event_index",
"turn_index",
"timestamp",
"model_name",
"workspace_root",
"role",
"text",
"tool_call_ids",
"tool_names",
"tool_arguments",
"finish_reason",
"termination",
"error",
"image_paths",
"capture_type",
"payload",
]
class FlatTraceWriter:
def __init__(
self,
*,
trace_dir: Optional[str | Path],
model_name: str,
workspace_root: str | Path,
on_event: Optional[Callable[[dict[str, Any]], None]] = None,
):
self.model_name = model_name
self.workspace_root = str(workspace_root)
self.on_event = on_event
self.run_id = uuid4().hex
self.path = resolve_trace_path(trace_dir, run_id=self.run_id) if trace_dir else None
self.event_index = 0
def append(
self,
*,
role: str,
text: str = "",
turn_index: int = 0,
tool_call_ids: Optional[list[str]] = None,
tool_names: Optional[list[str]] = None,
tool_arguments: Optional[list[Any]] = None,
finish_reason: Optional[str] = None,
termination: Optional[str] = None,
error: Optional[str] = None,
image_paths: Optional[list[str]] = None,
capture_type: str = "",
payload: Optional[dict[str, Any]] = None,
) -> dict[str, Any]:
self.event_index += 1
row = {
"run_id": self.run_id,
"event_index": self.event_index,
"turn_index": turn_index,
"timestamp": datetime.datetime.now().astimezone().isoformat(timespec="seconds"),
"model_name": self.model_name,
"workspace_root": self.workspace_root,
"role": role,
"text": text,
"tool_call_ids": tool_call_ids or [],
"tool_names": tool_names or [],
"tool_arguments": safe_jsonable(tool_arguments or []),
"finish_reason": finish_reason or "",
"termination": termination or "",
"error": error or "",
"image_paths": image_paths or [],
"capture_type": capture_type or "",
"payload": safe_jsonable(payload or {}),
}
if self.path is not None:
append_jsonl(self.path, row)
if self.on_event is not None:
self.on_event(row)
return row
def resolve_trace_path(
trace_dir: str | Path,
*,
run_id: str,
prefix: str = "trace",
suffix: str = ".jsonl",
) -> Path:
directory = Path(trace_dir)
timestamp = datetime.datetime.now().astimezone().strftime("%Y%m%d_%H%M%S")
short_run_id = run_id[:12]
filename = f"{prefix}_{timestamp}_{short_run_id}{suffix}"
return directory / filename
def main(argv: Optional[list[str]] = None) -> int:
parser = argparse.ArgumentParser(description="Inspect the flat trace field order used by the agent.")
parser.parse_args(argv)
print("\n".join(TRACE_FIELD_NAMES))
return 0
if __name__ == "__main__":
raise SystemExit(main())