File size: 1,330 Bytes
44c2f50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6267e20
44c2f50
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
"""Track token usage + cost per extraction."""
from __future__ import annotations

from dataclasses import dataclass, field
from time import perf_counter

from src.utils.config import get_settings


@dataclass
class ExtractionMetrics:
    """Metrics for a single extraction call."""

    input_tokens: int = 0
    output_tokens: int = 0
    latency_ms: float = 0.0
    model: str = ""
    cost_usd: float = field(init=False, default=0.0)

    def __post_init__(self) -> None:
        s = get_settings()
        self.cost_usd = (
            (self.input_tokens / 1000) * s.cost_per_1k_input
            + (self.output_tokens / 1000) * s.cost_per_1k_output
        )

    def to_dict(self) -> dict:
        return {
            "input_tokens": self.input_tokens,
            "output_tokens": self.output_tokens,
            "total_tokens": self.input_tokens + self.output_tokens,
            "latency_ms": round(self.latency_ms, 1),
            "cost_usd": round(self.cost_usd, 6),
            "model": self.model,
        }


class Timer:
    """Context manager for measuring wall-clock latency in ms."""

    def __enter__(self) -> Timer:
        self._start = perf_counter()
        self.elapsed_ms = 0.0
        return self

    def __exit__(self, *_exc) -> None:
        self.elapsed_ms = (perf_counter() - self._start) * 1000