smolcode / engine /trace.py
seanpoyner's picture
Upload folder using huggingface_hub
daea45b verified
Raw
History Blame Contribute Delete
2.65 kB
"""Shareable agent traces (Build Small "Sharing is Caring" badge).
Turns a completed smolcode run into an OpenTelemetry-style JSON trace: a root
span minted by LiteForge's `Tracer` plus one child span per agent step, carrying
the step kind, duration, and token counts read from `AgentStep`. Publish a trace
file to the Hub so others can see exactly how the tiny model reasoned.
"""
from __future__ import annotations
import json
import time
from pathlib import Path
import liteforge as lf
def build_trace(agent, task: str, final: str, *, preset: str, model: str) -> dict:
"""Build an OTel-ish trace document from a finished agent run."""
tracer = lf.Tracer("smolcode")
root = tracer.start_span("coding_task")
root.set_attribute("preset", preset)
root.set_attribute("model", model)
root.set_attribute("task", task)
trace_id = root.context.trace_id
root_id = root.context.span_id
spans: list[dict] = []
total_tokens = 0
history = agent.raw_history() if hasattr(agent, "raw_history") else getattr(agent, "history", lambda: [])()
for i, s in enumerate(history):
dur = getattr(s, "duration_ms", None) or 0
tot = getattr(s, "total_tokens", None) or 0
step_no = getattr(s, "step_number", getattr(s, "number", i))
step_type = getattr(s, "step_type", getattr(s, "kind", "step"))
result_text = getattr(s, "result", getattr(s, "detail", ""))
total_tokens += tot or 0
spans.append({
"trace_id": trace_id,
"span_id": f"{root_id[:-len(str(step_no))-1]}{step_no:02d}",
"parent_span_id": root_id,
"name": str(step_type),
"duration_ms": dur,
"attributes": {
"step_number": step_no,
"prompt_tokens": getattr(s, "prompt_tokens", None),
"completion_tokens": getattr(s, "completion_tokens", None),
"total_tokens": tot,
"result": str(result_text)[:200],
},
})
root.end()
return {
"trace_id": trace_id,
"service": "smolcode",
"preset": preset,
"model": model,
"task": task,
"final": final,
"n_steps": len(spans),
"total_tokens": total_tokens,
"root": {"span_id": root_id, "name": "coding_task"},
"spans": spans,
}
def save_trace(trace: dict, out_dir: str | Path = "traces") -> Path:
d = Path(out_dir)
d.mkdir(parents=True, exist_ok=True)
stamp = time.strftime("%Y%m%d-%H%M%S")
path = d / f"trace-{stamp}.json"
path.write_text(json.dumps(trace, indent=2))
return path