praisonaiagents 0.0.152__py3-none-any.whl → 0.0.154__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.
- praisonaiagents/__init__.py +57 -7
- praisonaiagents/agent/agent.py +11 -1
- praisonaiagents/agents/agents.py +116 -1
- praisonaiagents/llm/llm.py +77 -0
- praisonaiagents/main.py +7 -0
- praisonaiagents/mcp/mcp_http_stream.py +151 -4
- praisonaiagents/telemetry/__init__.py +31 -3
- praisonaiagents/telemetry/integration.py +385 -84
- praisonaiagents/telemetry/performance_monitor.py +162 -1
- praisonaiagents/telemetry/performance_utils.py +35 -7
- praisonaiagents/telemetry/telemetry.py +145 -42
- praisonaiagents/telemetry/token_collector.py +170 -0
- praisonaiagents/telemetry/token_telemetry.py +89 -0
- {praisonaiagents-0.0.152.dist-info → praisonaiagents-0.0.154.dist-info}/METADATA +1 -1
- {praisonaiagents-0.0.152.dist-info → praisonaiagents-0.0.154.dist-info}/RECORD +17 -15
- {praisonaiagents-0.0.152.dist-info → praisonaiagents-0.0.154.dist-info}/WHEEL +0 -0
- {praisonaiagents-0.0.152.dist-info → praisonaiagents-0.0.154.dist-info}/top_level.txt +0 -0
@@ -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,18 +1,18 @@
|
|
1
|
-
praisonaiagents/__init__.py,sha256=
|
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=
|
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=
|
9
|
+
praisonaiagents/agent/agent.py,sha256=pecp8Bt7_vXCB4MfUuMTZ3no4WipKOzFPGhFF5ADC5Y,144243
|
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=
|
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=
|
24
|
+
praisonaiagents/llm/llm.py,sha256=155R1XHZLSDZsq67Hmglwc4N_SE2gKgid0KCFYNX3ww,176594
|
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=
|
30
|
+
praisonaiagents/mcp/mcp_http_stream.py,sha256=TDFWMJMo8VqLXtXCW73REpmkU3t9n7CAGMa9b4dhI-c,23366
|
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=
|
39
|
-
praisonaiagents/telemetry/integration.py,sha256=
|
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=
|
42
|
-
praisonaiagents/telemetry/performance_utils.py,sha256=
|
43
|
-
praisonaiagents/telemetry/telemetry.py,sha256=
|
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.
|
69
|
-
praisonaiagents-0.0.
|
70
|
-
praisonaiagents-0.0.
|
71
|
-
praisonaiagents-0.0.
|
70
|
+
praisonaiagents-0.0.154.dist-info/METADATA,sha256=55cpHdKamPJ_tSTDYyXli-REfXLqafPKW7GH-Gf_Sdo,2146
|
71
|
+
praisonaiagents-0.0.154.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
72
|
+
praisonaiagents-0.0.154.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
|
73
|
+
praisonaiagents-0.0.154.dist-info/RECORD,,
|
File without changes
|
File without changes
|