praisonaiagents 0.0.152__py3-none-any.whl → 0.0.153__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,170 @@
1
+ """
2
+ Token usage collector for tracking LLM token consumption.
3
+ Provides comprehensive tracking with minimal overhead.
4
+ """
5
+
6
+ from dataclasses import dataclass, field
7
+ from typing import Dict, Optional, List
8
+ from datetime import datetime
9
+ import threading
10
+ from collections import defaultdict
11
+
12
+
13
+ @dataclass
14
+ class TokenMetrics:
15
+ """Represents token usage metrics for a single LLM interaction."""
16
+ input_tokens: int = 0
17
+ output_tokens: int = 0
18
+ cached_tokens: int = 0
19
+ reasoning_tokens: int = 0
20
+ audio_input_tokens: int = 0
21
+ audio_output_tokens: int = 0
22
+
23
+ @property
24
+ def total_tokens(self) -> int:
25
+ """Calculate total tokens across all types."""
26
+ return (
27
+ self.input_tokens +
28
+ self.output_tokens +
29
+ self.cached_tokens +
30
+ self.reasoning_tokens +
31
+ self.audio_input_tokens +
32
+ self.audio_output_tokens
33
+ )
34
+
35
+ def to_dict(self) -> Dict[str, int]:
36
+ """Convert to dictionary format."""
37
+ return {
38
+ "input_tokens": self.input_tokens,
39
+ "output_tokens": self.output_tokens,
40
+ "cached_tokens": self.cached_tokens,
41
+ "reasoning_tokens": self.reasoning_tokens,
42
+ "audio_input_tokens": self.audio_input_tokens,
43
+ "audio_output_tokens": self.audio_output_tokens,
44
+ "total_tokens": self.total_tokens
45
+ }
46
+
47
+ def __add__(self, other: 'TokenMetrics') -> 'TokenMetrics':
48
+ """Add two TokenMetrics instances together."""
49
+ if not isinstance(other, TokenMetrics):
50
+ return NotImplemented
51
+
52
+ return TokenMetrics(
53
+ input_tokens=self.input_tokens + other.input_tokens,
54
+ output_tokens=self.output_tokens + other.output_tokens,
55
+ cached_tokens=self.cached_tokens + other.cached_tokens,
56
+ reasoning_tokens=self.reasoning_tokens + other.reasoning_tokens,
57
+ audio_input_tokens=self.audio_input_tokens + other.audio_input_tokens,
58
+ audio_output_tokens=self.audio_output_tokens + other.audio_output_tokens
59
+ )
60
+
61
+
62
+ @dataclass
63
+ class SessionTokenMetrics:
64
+ """Aggregated token metrics for a session."""
65
+ total_interactions: int = 0
66
+ metrics_by_model: Dict[str, TokenMetrics] = field(default_factory=dict)
67
+ metrics_by_agent: Dict[str, TokenMetrics] = field(default_factory=dict)
68
+ total_metrics: TokenMetrics = field(default_factory=TokenMetrics)
69
+
70
+ def add_interaction(self, model: str, agent: Optional[str], metrics: TokenMetrics):
71
+ """Add a new interaction's metrics."""
72
+ self.total_interactions += 1
73
+
74
+ # Update total metrics
75
+ self.total_metrics = self.total_metrics + metrics
76
+
77
+ # Update model-specific metrics
78
+ if model not in self.metrics_by_model:
79
+ self.metrics_by_model[model] = TokenMetrics()
80
+ self.metrics_by_model[model] = self.metrics_by_model[model] + metrics
81
+
82
+ # Update agent-specific metrics
83
+ if agent:
84
+ if agent not in self.metrics_by_agent:
85
+ self.metrics_by_agent[agent] = TokenMetrics()
86
+ self.metrics_by_agent[agent] = self.metrics_by_agent[agent] + metrics
87
+
88
+ def get_summary(self) -> Dict:
89
+ """Get a summary of session token usage."""
90
+ return {
91
+ "total_interactions": self.total_interactions,
92
+ "total_tokens": self.total_metrics.total_tokens,
93
+ "total_metrics": self.total_metrics.to_dict(),
94
+ "by_model": {
95
+ model: metrics.to_dict()
96
+ for model, metrics in self.metrics_by_model.items()
97
+ },
98
+ "by_agent": {
99
+ agent: metrics.to_dict()
100
+ for agent, metrics in self.metrics_by_agent.items()
101
+ }
102
+ }
103
+
104
+
105
+ class TokenCollector:
106
+ """
107
+ Global token collector for tracking token usage across the application.
108
+ Thread-safe implementation for concurrent access.
109
+ """
110
+
111
+ def __init__(self):
112
+ self._lock = threading.Lock()
113
+ self._session_metrics = SessionTokenMetrics()
114
+ self._recent_interactions: List[Dict] = []
115
+ self._max_recent = 100
116
+
117
+ def track_tokens(
118
+ self,
119
+ model: str,
120
+ agent: Optional[str],
121
+ metrics: TokenMetrics,
122
+ metadata: Optional[Dict] = None
123
+ ):
124
+ """Track token usage for an interaction."""
125
+ with self._lock:
126
+ # Add to session metrics
127
+ self._session_metrics.add_interaction(model, agent, metrics)
128
+
129
+ # Track recent interaction
130
+ interaction = {
131
+ "timestamp": datetime.now().isoformat(),
132
+ "model": model,
133
+ "agent": agent,
134
+ "metrics": metrics.to_dict(),
135
+ "metadata": metadata or {}
136
+ }
137
+
138
+ self._recent_interactions.append(interaction)
139
+
140
+ # Limit recent interactions
141
+ if len(self._recent_interactions) > self._max_recent:
142
+ self._recent_interactions.pop(0)
143
+
144
+ def get_session_summary(self) -> Dict:
145
+ """Get summary of token usage for the session."""
146
+ with self._lock:
147
+ return self._session_metrics.get_summary()
148
+
149
+ def get_recent_interactions(self, limit: int = 10) -> List[Dict]:
150
+ """Get recent interactions with token metrics."""
151
+ with self._lock:
152
+ return self._recent_interactions[-limit:]
153
+
154
+ def reset(self):
155
+ """Reset all collected metrics."""
156
+ with self._lock:
157
+ self._session_metrics = SessionTokenMetrics()
158
+ self._recent_interactions.clear()
159
+
160
+ def export_metrics(self) -> Dict:
161
+ """Export all metrics for external use."""
162
+ with self._lock:
163
+ return {
164
+ "session": self._session_metrics.get_summary(),
165
+ "recent_interactions": self._recent_interactions.copy()
166
+ }
167
+
168
+
169
+ # Global token collector instance
170
+ _token_collector = TokenCollector()
@@ -0,0 +1,89 @@
1
+ """
2
+ Token telemetry integration for bridging token tracking with the main telemetry system.
3
+ """
4
+
5
+ from typing import Optional, Dict, Any
6
+ import logging
7
+
8
+ # Import dependencies
9
+ from .token_collector import _token_collector, TokenMetrics
10
+ from .telemetry import get_telemetry
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class TokenTelemetryBridge:
16
+ """Bridges token tracking with the main telemetry system."""
17
+
18
+ def __init__(self):
19
+ self.telemetry = get_telemetry()
20
+ self.enabled = self.telemetry.enabled if self.telemetry else False
21
+
22
+ def track_token_usage(
23
+ self,
24
+ event_type: str,
25
+ model: str,
26
+ agent: Optional[str],
27
+ metrics: TokenMetrics,
28
+ metadata: Optional[Dict[str, Any]] = None
29
+ ):
30
+ """Track token usage event in telemetry."""
31
+ if not self.enabled or not self.telemetry:
32
+ return
33
+
34
+ try:
35
+ # Prepare event data
36
+ event_data = {
37
+ "event_type": event_type,
38
+ "model": model,
39
+ "agent": agent,
40
+ "total_tokens": metrics.total_tokens,
41
+ "input_tokens": metrics.input_tokens,
42
+ "output_tokens": metrics.output_tokens,
43
+ "cached_tokens": metrics.cached_tokens,
44
+ "reasoning_tokens": metrics.reasoning_tokens,
45
+ }
46
+
47
+ # Add metadata if provided
48
+ if metadata:
49
+ event_data.update(metadata)
50
+
51
+ # Track in telemetry
52
+ self.telemetry.track_feature_usage("token_usage", event_data)
53
+
54
+ except Exception as e:
55
+ logger.debug(f"Failed to track token usage in telemetry: {e}")
56
+
57
+ def export_token_metrics(self) -> Dict[str, Any]:
58
+ """Export token metrics for telemetry reporting."""
59
+ if not _token_collector:
60
+ return {}
61
+
62
+ try:
63
+ metrics = _token_collector.export_metrics()
64
+
65
+ # Prepare telemetry-friendly format
66
+ return {
67
+ "token_metrics": {
68
+ "session_summary": metrics.get("session", {}),
69
+ "total_interactions": metrics.get("session", {}).get("total_interactions", 0),
70
+ "total_tokens": metrics.get("session", {}).get("total_tokens", 0),
71
+ }
72
+ }
73
+
74
+ except Exception as e:
75
+ logger.debug(f"Failed to export token metrics: {e}")
76
+ return {}
77
+
78
+ def reset_token_metrics(self):
79
+ """Reset token metrics collection."""
80
+ if _token_collector:
81
+ _token_collector.reset()
82
+
83
+
84
+ # Global telemetry bridge instance
85
+ _token_telemetry_bridge = TokenTelemetryBridge()
86
+
87
+ # Export convenience functions
88
+ track_token_usage = _token_telemetry_bridge.track_token_usage
89
+ export_token_metrics = _token_telemetry_bridge.export_token_metrics
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praisonaiagents
3
- Version: 0.0.152
3
+ Version: 0.0.153
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Python: >=3.10
@@ -1,18 +1,18 @@
1
- praisonaiagents/__init__.py,sha256=RJfNHR2k00o_U8W_YJb05uwemrvQ_7SmyNhjp__G29E,3887
1
+ praisonaiagents/__init__.py,sha256=zWX90TqZVLXppvVlnwwidc1ooBs3ZDGzr7XRje649Mw,6291
2
2
  praisonaiagents/_logging.py,sha256=WfgUX6jo9hClpgHVKSGz8gqkna9DDNhPJBv-wjhcJoM,4648
3
3
  praisonaiagents/_warning_patch.py,sha256=FSLdw1SnA9b1PSxHWaRIcuG9IiIwO5JT6uo_m3CM0NI,2816
4
4
  praisonaiagents/approval.py,sha256=UJ4OhfihpFGR5CAaMphqpSvqdZCHi5w2MGw1MByZ1FQ,9813
5
5
  praisonaiagents/flow_display.py,sha256=E84J_H3h8L-AqL_F1JzEUInQYdjmIEuNL1LZr4__Hes,6935
6
- praisonaiagents/main.py,sha256=BqqskwUP-qrqCsHF9h_Wv99uS24ZeFTD8CaN6o6bnCE,17150
6
+ praisonaiagents/main.py,sha256=NuAmE-ZrH4X0O9ysNA2AfxEQ8APPssO_ZR_f7h97QOo,17370
7
7
  praisonaiagents/session.py,sha256=FHWButPBaFGA4x1U_2gImroQChHnFy231_aAa_n5KOQ,20364
8
8
  praisonaiagents/agent/__init__.py,sha256=KBqW_augD-HcaV3FL88gUmhDCpwnSTavGENi7RqneTo,505
9
- praisonaiagents/agent/agent.py,sha256=_EhjCKaqM4z2Dcgkndr2b2UmJJuKCjDkeIItvH_Bnok,143723
9
+ praisonaiagents/agent/agent.py,sha256=VXRMG1xwog1x_YP71AXvFT7p5Ik4kXU0016AEQMzdHc,143988
10
10
  praisonaiagents/agent/context_agent.py,sha256=zNI2Waghn5eo8g3QM1Dc7ZNSr2xw41D87GIK81FjW-Y,107489
11
11
  praisonaiagents/agent/handoff.py,sha256=Saq0chqfvC6Zf5UbXvmctybbehqnotrXn72JsS-76Q0,13099
12
12
  praisonaiagents/agent/image_agent.py,sha256=xKDhW8T1Y3e15lQpY6N2pdvBNJmAoWDibJa4BYa-Njs,10205
13
13
  praisonaiagents/agent/router_agent.py,sha256=a_b6w5Ti05gvK80uKGMIcT14fiCTKv8rCQPCWAUfIiE,12713
14
14
  praisonaiagents/agents/__init__.py,sha256=_1d6Pqyk9EoBSo7E68sKyd1jDRlN1vxvVIRpoMc0Jcw,168
15
- praisonaiagents/agents/agents.py,sha256=POZ-CbFabOSY7UUBDgh5IE6bXv0qERPO4Hpah6MSvQ8,65983
15
+ praisonaiagents/agents/agents.py,sha256=sGXnRwBa49DhL7jMDE12IRcstpEg-QrkNyXw0K8BiRU,70995
16
16
  praisonaiagents/agents/autoagents.py,sha256=v5pJfTgHnFzG5K2gHwfRA0nZ7Ikptir6hUNvOZ--E44,20777
17
17
  praisonaiagents/guardrails/__init__.py,sha256=HA8zhp-KRHTxo0194MUwXOUJjPyjOu7E3d7xUIKYVVY,310
18
18
  praisonaiagents/guardrails/guardrail_result.py,sha256=2K1WIYRyT_s1H6vBGa-7HEHzXCFIyZXZVY4f0hnQyWc,1352
@@ -21,13 +21,13 @@ praisonaiagents/knowledge/__init__.py,sha256=xL1Eh-a3xsHyIcU4foOWF-JdWYIYBALJH9b
21
21
  praisonaiagents/knowledge/chunking.py,sha256=G6wyHa7_8V0_7VpnrrUXbEmUmptlT16ISJYaxmkSgmU,7678
22
22
  praisonaiagents/knowledge/knowledge.py,sha256=OzK81oA6sjk9nAUWphS7AkXxvalrv2AHB4FtHjzYgxI,30115
23
23
  praisonaiagents/llm/__init__.py,sha256=SqdU1pRqPrR6jZeWYyDeTvmZKCACywk0v4P0k5Fuowk,1107
24
- praisonaiagents/llm/llm.py,sha256=ChQQoBkfVoVaPg13qZ9S3rM0rhrQJjVMCuJv4irvTVY,173421
24
+ praisonaiagents/llm/llm.py,sha256=HFN5pJUogqeCYcDk1b4JJe6VXbEFMXyQBZ-byKaObVQ,176229
25
25
  praisonaiagents/llm/model_capabilities.py,sha256=cxOvZcjZ_PIEpUYKn3S2FMyypfOSfbGpx4vmV7Y5vhI,3967
26
26
  praisonaiagents/llm/model_router.py,sha256=Jy2pShlkLxqXF3quz-MRB3-6L9vaUSgUrf2YJs_Tsg0,13995
27
27
  praisonaiagents/llm/openai_client.py,sha256=3EVjIs3tnBNFDy_4ZxX9DJVq54kS0FMm38m5Gkpun7U,57234
28
28
  praisonaiagents/mcp/__init__.py,sha256=ibbqe3_7XB7VrIcUcetkZiUZS1fTVvyMy_AqCSFG8qc,240
29
29
  praisonaiagents/mcp/mcp.py,sha256=ChaSwLCcFBB9b8eNuj0DoKbK1EqpyF1T_7xz0FX-5-A,23264
30
- praisonaiagents/mcp/mcp_http_stream.py,sha256=Yh-69eIlLQS_M0bd__y7NzSjOqqX6R8Ed4eJQw6xXgg,18314
30
+ praisonaiagents/mcp/mcp_http_stream.py,sha256=3lCzZWdY6_X6fgQjQWDsB9_bB2vxdKsUs2PFmNt98Pw,19763
31
31
  praisonaiagents/mcp/mcp_sse.py,sha256=KO10tAgZ5vSKeRhkJIZcdJ0ZmhRybS39i1KybWt4D7M,9128
32
32
  praisonaiagents/memory/__init__.py,sha256=aEFdhgtTqDdMhc_JCWM-f4XI9cZIj7Wz5g_MUa-0amg,397
33
33
  praisonaiagents/memory/memory.py,sha256=HjanP8sSi91wifvPkQDH40uGYdDZPOeir29fCu6y-b8,64584
@@ -35,12 +35,14 @@ praisonaiagents/process/__init__.py,sha256=lkYbL7Hn5a0ldvJtkdH23vfIIZLIcanK-65C0
35
35
  praisonaiagents/process/process.py,sha256=wXKZ2Z26vB9osmVbD5xqkUlUQRvWEpvL8j9hiuiHrQ0,78246
36
36
  praisonaiagents/task/__init__.py,sha256=VL5hXVmyGjINb34AalxpBMl-YW9m5EDcRkMTKkSSl7c,80
37
37
  praisonaiagents/task/task.py,sha256=j1KgaqeMfVm7lcO3puyIjX1r8Uf5GHtTRvd4NlK5Vk8,24203
38
- praisonaiagents/telemetry/__init__.py,sha256=RnAZjxUaLfylbrRfVTc-k1LonRvjvMSFwJzXCQHd9fA,5330
39
- praisonaiagents/telemetry/integration.py,sha256=2uIDI5AUiZNr2GfOe3P1AQMOP-DdaqnodFpFmEW82Dc,12082
38
+ praisonaiagents/telemetry/__init__.py,sha256=HtJxYIPPsYpE92CE4zpyrzYMIy5qxVIxkw_2GCgUq_k,6483
39
+ praisonaiagents/telemetry/integration.py,sha256=nhLkp8AnitKlumMxQj8aNt5DkoeKukPA6u6bHbsk8wA,23205
40
40
  praisonaiagents/telemetry/performance_cli.py,sha256=8OGeqqE5yAQk1mAqz2fYCd6VeNPLRlUM9oTkJA6ge-E,15456
41
- praisonaiagents/telemetry/performance_monitor.py,sha256=G0m2V8RcFrwKqZQ4ziktyXO7tFtm_opA3b14HxV8P0Q,22935
42
- praisonaiagents/telemetry/performance_utils.py,sha256=eHQ_oJod5Oi2Hr_7QTzBtZ3C-cew07raNx_RjU03_HY,22947
43
- praisonaiagents/telemetry/telemetry.py,sha256=526aXKYjuMLITuLvUOFOq4ynFUlHuAdO4KxTPSyJlFk,24504
41
+ praisonaiagents/telemetry/performance_monitor.py,sha256=yDR-bQuZhFlKInmO5T_Ih3PfWgZNodjvGeUNp2Dvhu4,29003
42
+ praisonaiagents/telemetry/performance_utils.py,sha256=8sfiaBv2Hg_NY0JXlLWT-PDbfrGxTVgL-pRVTBV6VaU,24446
43
+ praisonaiagents/telemetry/telemetry.py,sha256=VEprwpst0-1pSbt2jUtIlpJbzJfO1IS2eyT5qhVym6Q,28542
44
+ praisonaiagents/telemetry/token_collector.py,sha256=1T8uz6vOFGAtHwI1Ph2_kTu5wNT0kCF-hNxS45Tw36A,6040
45
+ praisonaiagents/telemetry/token_telemetry.py,sha256=9ktsLF26CdCdTmpXxt25KSH4kIT6weNuws9X_jCOxB8,2909
44
46
  praisonaiagents/tools/README.md,sha256=am9mlHp46sC1U9HfyXtX-E_cckxpazprl4tuVFYHP_0,4905
45
47
  praisonaiagents/tools/__init__.py,sha256=Q5pYRhdLHEOtQ6V2Dc0dJ0ppDxM9qiegeI8dz97MAiI,10176
46
48
  praisonaiagents/tools/arxiv_tools.py,sha256=1stb31zTjLTon4jCnpZG5de9rKc9QWgC0leLegvPXWo,10528
@@ -65,7 +67,7 @@ praisonaiagents/tools/xml_tools.py,sha256=iYTMBEk5l3L3ryQ1fkUnNVYK-Nnua2Kx2S0dxN
65
67
  praisonaiagents/tools/yaml_tools.py,sha256=uogAZrhXV9O7xvspAtcTfpKSQYL2nlOTvCQXN94-G9A,14215
66
68
  praisonaiagents/tools/yfinance_tools.py,sha256=s2PBj_1v7oQnOobo2fDbQBACEHl61ftG4beG6Z979ZE,8529
67
69
  praisonaiagents/tools/train/data/generatecot.py,sha256=H6bNh-E2hqL5MW6kX3hqZ05g9ETKN2-kudSjiuU_SD8,19403
68
- praisonaiagents-0.0.152.dist-info/METADATA,sha256=a-HyisF8Pw70UqkSloPXYxFj9p1e4pe1BITREE9xlkU,2146
69
- praisonaiagents-0.0.152.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
- praisonaiagents-0.0.152.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
71
- praisonaiagents-0.0.152.dist-info/RECORD,,
70
+ praisonaiagents-0.0.153.dist-info/METADATA,sha256=XSemYARB8KbWxIROYpBGh21HcmzkANfMVG7aBt2frsc,2146
71
+ praisonaiagents-0.0.153.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
+ praisonaiagents-0.0.153.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
73
+ praisonaiagents-0.0.153.dist-info/RECORD,,