Stats accumulated over a single agent turn (or full session).
| 55 | |
| 56 | @dataclass |
| 57 | class SessionStats: |
| 58 | """Stats accumulated over a single agent turn (or full session).""" |
| 59 | |
| 60 | request_count: int = 0 |
| 61 | """Total LLM API requests made. |
| 62 | |
| 63 | Each chunk with `usage_metadata` counts as one completed request. |
| 64 | """ |
| 65 | |
| 66 | input_tokens: int = 0 |
| 67 | """Cumulative input tokens across all LLM requests.""" |
| 68 | |
| 69 | output_tokens: int = 0 |
| 70 | """Cumulative output tokens across all LLM requests.""" |
| 71 | |
| 72 | wall_time_seconds: float = 0.0 |
| 73 | """Wall-clock duration from stream start to end.""" |
| 74 | |
| 75 | per_model: dict[ModelStatsKey, ModelStats] = field(default_factory=dict) |
| 76 | """Per-model breakdown keyed by `(provider, model_name)`. |
| 77 | |
| 78 | Populated only when `record_request` receives a non-empty `model_name`. Empty |
| 79 | dict means no named-model requests were recorded; `print_usage_table` omits |
| 80 | the model table in that case and shows only the wall-time line (if applicable). |
| 81 | """ |
| 82 | |
| 83 | def record_request( |
| 84 | self, |
| 85 | model_name: str, |
| 86 | input_toks: int, |
| 87 | output_toks: int, |
| 88 | provider: str = "", |
| 89 | ) -> None: |
| 90 | """Accumulate token counts for one completed LLM request. |
| 91 | |
| 92 | Updates both the session totals and the per-model breakdown. |
| 93 | |
| 94 | Args: |
| 95 | model_name: The model that served this request. Combined with |
| 96 | `provider` to form the per-model key. Pass an empty string to |
| 97 | skip the per-model breakdown for this request. |
| 98 | input_toks: Input tokens for this request. |
| 99 | output_toks: Output tokens for this request. |
| 100 | provider: Provider that served the model (e.g. `openai`). Combined |
| 101 | with `model_name` to form the per-model key, so the same model |
| 102 | served by different providers is tracked separately. |
| 103 | """ |
| 104 | self.request_count += 1 |
| 105 | self.input_tokens += input_toks |
| 106 | self.output_tokens += output_toks |
| 107 | if model_name: |
| 108 | key = (provider, model_name) |
| 109 | entry = self.per_model.setdefault( |
| 110 | key, |
| 111 | ModelStats(provider=provider, model_name=model_name), |
| 112 | ) |
| 113 | entry.request_count += 1 |
| 114 | entry.input_tokens += input_toks |
no outgoing calls