ragaai-catalyst 2.1.4b0__py3-none-any.whl → 2.1.4b2__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.
- ragaai_catalyst/tracers/agentic_tracing/data/data_structure.py +36 -10
- ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py +226 -76
- ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +568 -107
- ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py +325 -0
- ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +218 -81
- ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py +210 -58
- ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py +2 -0
- ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py +137 -28
- ragaai_catalyst/tracers/agentic_tracing/tracers/user_interaction_tracer.py +86 -0
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py +9 -51
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_trace_metric.py +83 -0
- ragaai_catalyst/tracers/agentic_tracing/utils/create_dataset_schema.py +26 -0
- ragaai_catalyst/tracers/agentic_tracing/utils/get_user_trace_metrics.py +28 -0
- ragaai_catalyst/tracers/agentic_tracing/utils/llm_utils.py +45 -15
- ragaai_catalyst/tracers/agentic_tracing/utils/model_costs.json +2476 -2122
- ragaai_catalyst/tracers/agentic_tracing/utils/span_attributes.py +59 -0
- ragaai_catalyst/tracers/agentic_tracing/utils/trace_utils.py +23 -0
- ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py +284 -15
- ragaai_catalyst/tracers/tracer.py +77 -8
- {ragaai_catalyst-2.1.4b0.dist-info → ragaai_catalyst-2.1.4b2.dist-info}/METADATA +2 -1
- {ragaai_catalyst-2.1.4b0.dist-info → ragaai_catalyst-2.1.4b2.dist-info}/RECORD +23 -18
- {ragaai_catalyst-2.1.4b0.dist-info → ragaai_catalyst-2.1.4b2.dist-info}/WHEEL +0 -0
- {ragaai_catalyst-2.1.4b0.dist-info → ragaai_catalyst-2.1.4b2.dist-info}/top_level.txt +0 -0
@@ -13,46 +13,113 @@ from .tool_tracer import ToolTracerMixin
|
|
13
13
|
from .agent_tracer import AgentTracerMixin
|
14
14
|
from .network_tracer import NetworkTracer
|
15
15
|
from .user_interaction_tracer import UserInteractionTracer
|
16
|
+
from .custom_tracer import CustomTracerMixin
|
17
|
+
from ..utils.span_attributes import SpanAttributes
|
16
18
|
|
17
19
|
from ..data.data_structure import (
|
18
|
-
Trace,
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
Trace,
|
21
|
+
Metadata,
|
22
|
+
SystemInfo,
|
23
|
+
OSInfo,
|
24
|
+
EnvironmentInfo,
|
25
|
+
Resources,
|
26
|
+
CPUResource,
|
27
|
+
MemoryResource,
|
28
|
+
DiskResource,
|
29
|
+
NetworkResource,
|
30
|
+
ResourceInfo,
|
31
|
+
MemoryInfo,
|
32
|
+
DiskInfo,
|
33
|
+
NetworkInfo,
|
34
|
+
Component,
|
35
|
+
LLMComponent,
|
36
|
+
AgentComponent,
|
37
|
+
ToolComponent,
|
38
|
+
NetworkCall,
|
39
|
+
Interaction,
|
40
|
+
Error,
|
23
41
|
)
|
24
42
|
|
25
43
|
from ....ragaai_catalyst import RagaAICatalyst
|
26
44
|
from ragaai_catalyst.tracers.upload_traces import UploadTraces
|
27
45
|
|
28
|
-
|
29
|
-
|
46
|
+
|
47
|
+
class AgenticTracing(
|
48
|
+
BaseTracer, LLMTracerMixin, ToolTracerMixin, AgentTracerMixin, CustomTracerMixin
|
49
|
+
):
|
50
|
+
def __init__(self, user_detail, auto_instrumentation=None):
|
30
51
|
# Initialize all parent classes
|
31
52
|
self.user_interaction_tracer = UserInteractionTracer()
|
32
53
|
LLMTracerMixin.__init__(self)
|
33
54
|
ToolTracerMixin.__init__(self)
|
34
55
|
AgentTracerMixin.__init__(self)
|
35
|
-
|
56
|
+
CustomTracerMixin.__init__(self)
|
57
|
+
|
36
58
|
self.project_name = user_detail["project_name"]
|
37
59
|
self.project_id = user_detail["project_id"]
|
38
|
-
self.dataset_name = user_detail["dataset_name"]
|
60
|
+
# self.dataset_name = user_detail["dataset_name"]
|
39
61
|
self.trace_user_detail = user_detail["trace_user_detail"]
|
40
62
|
self.base_url = f"{RagaAICatalyst.BASE_URL}"
|
41
63
|
self.timeout = 10
|
42
64
|
|
43
65
|
BaseTracer.__init__(self, user_detail)
|
44
|
-
|
45
|
-
self.auto_instrument_llm = auto_instrument_llm
|
66
|
+
|
46
67
|
self.tools: Dict[str, Tool] = {}
|
47
68
|
self.call_depth = contextvars.ContextVar("call_depth", default=0)
|
48
|
-
self.current_component_id = contextvars.ContextVar(
|
69
|
+
self.current_component_id = contextvars.ContextVar(
|
70
|
+
"current_component_id", default=None
|
71
|
+
)
|
49
72
|
self.network_tracer = NetworkTracer()
|
50
|
-
|
73
|
+
|
74
|
+
# Handle auto_instrumentation
|
75
|
+
if auto_instrumentation is None:
|
76
|
+
# Default behavior: everything enabled
|
77
|
+
self.is_active = True
|
78
|
+
self.auto_instrument_llm = True
|
79
|
+
self.auto_instrument_tool = True
|
80
|
+
self.auto_instrument_agent = True
|
81
|
+
self.auto_instrument_user_interaction = True
|
82
|
+
self.auto_instrument_file_io = True
|
83
|
+
self.auto_instrument_network = True
|
84
|
+
self.auto_instrument_custom = True
|
85
|
+
else:
|
86
|
+
# Set global active state
|
87
|
+
self.is_active = (
|
88
|
+
any(auto_instrumentation.values())
|
89
|
+
if isinstance(auto_instrumentation, dict)
|
90
|
+
else bool(auto_instrumentation)
|
91
|
+
)
|
92
|
+
|
93
|
+
# Set individual components
|
94
|
+
if isinstance(auto_instrumentation, dict):
|
95
|
+
self.auto_instrument_llm = auto_instrumentation.get("llm", False)
|
96
|
+
self.auto_instrument_tool = auto_instrumentation.get("tool", False)
|
97
|
+
self.auto_instrument_agent = auto_instrumentation.get("agent", False)
|
98
|
+
self.auto_instrument_user_interaction = auto_instrumentation.get(
|
99
|
+
"user_interaction", False
|
100
|
+
)
|
101
|
+
self.auto_instrument_file_io = auto_instrumentation.get(
|
102
|
+
"file_io", False
|
103
|
+
)
|
104
|
+
self.auto_instrument_network = auto_instrumentation.get(
|
105
|
+
"network", False
|
106
|
+
)
|
107
|
+
self.auto_instrument_custom = auto_instrumentation.get("custom", False)
|
108
|
+
else:
|
109
|
+
# If boolean provided, apply to all components
|
110
|
+
self.auto_instrument_llm = bool(auto_instrumentation)
|
111
|
+
self.auto_instrument_tool = bool(auto_instrumentation)
|
112
|
+
self.auto_instrument_agent = bool(auto_instrumentation)
|
113
|
+
self.auto_instrument_user_interaction = bool(auto_instrumentation)
|
114
|
+
self.auto_instrument_file_io = bool(auto_instrumentation)
|
115
|
+
self.auto_instrument_network = bool(auto_instrumentation)
|
116
|
+
self.auto_instrument_custom = bool(auto_instrumentation)
|
117
|
+
|
51
118
|
self.current_agent_id = contextvars.ContextVar("current_agent_id", default=None)
|
52
119
|
self.agent_children = contextvars.ContextVar("agent_children", default=[])
|
53
120
|
self.component_network_calls = {} # Store network calls per component
|
54
121
|
self.component_user_interaction = {}
|
55
|
-
|
122
|
+
|
56
123
|
# Create output directory if it doesn't exist
|
57
124
|
self.output_dir = Path("./traces") # Using default traces directory
|
58
125
|
self.output_dir.mkdir(exist_ok=True)
|
@@ -61,19 +128,28 @@ class AgenticTracing(BaseTracer, LLMTracerMixin, ToolTracerMixin, AgentTracerMix
|
|
61
128
|
"""Start tracking network calls for a component"""
|
62
129
|
self.component_network_calls[component_id] = []
|
63
130
|
self.network_tracer.network_calls = [] # Reset network calls
|
64
|
-
self.component_user_interaction[component_id] = []
|
65
131
|
self.current_component_id.set(component_id)
|
66
132
|
self.user_interaction_tracer.component_id.set(component_id)
|
67
133
|
|
68
134
|
def end_component(self, component_id: str):
|
69
135
|
"""End tracking network calls for a component"""
|
70
|
-
self.component_network_calls[component_id] =
|
136
|
+
self.component_network_calls[component_id] = (
|
137
|
+
self.network_tracer.network_calls.copy()
|
138
|
+
)
|
71
139
|
self.network_tracer.network_calls = [] # Reset for next component
|
72
|
-
self.component_user_interaction[component_id] = self.user_interaction_tracer.interactions.
|
73
|
-
self.user_interaction_tracer.interactions
|
140
|
+
# self.component_user_interaction[component_id] = [interaction for interaction in self.user_interaction_tracer.interactions if interaction.get('component_id') == component_id]
|
141
|
+
for interaction in self.user_interaction_tracer.interactions:
|
142
|
+
interaction_component_id = interaction.get("component_id")
|
143
|
+
if interaction_component_id not in self.component_user_interaction:
|
144
|
+
self.component_user_interaction[interaction_component_id] = []
|
145
|
+
if interaction not in self.component_user_interaction[interaction_component_id]:
|
146
|
+
self.component_user_interaction[interaction_component_id].append(interaction)
|
74
147
|
|
75
148
|
def start(self):
|
76
149
|
"""Start tracing"""
|
150
|
+
if not self.is_active:
|
151
|
+
return
|
152
|
+
|
77
153
|
# Setup user interaction tracing
|
78
154
|
self.user_interaction_tracer.project_id.set(self.project_id)
|
79
155
|
self.user_interaction_tracer.trace_id.set(self.trace_id)
|
@@ -81,84 +157,112 @@ class AgenticTracing(BaseTracer, LLMTracerMixin, ToolTracerMixin, AgentTracerMix
|
|
81
157
|
self.user_interaction_tracer.component_id.set(self.current_component_id.get())
|
82
158
|
builtins.print = self.user_interaction_tracer.traced_print
|
83
159
|
builtins.input = self.user_interaction_tracer.traced_input
|
84
|
-
|
160
|
+
builtins.open = self.user_interaction_tracer.traced_open
|
161
|
+
|
85
162
|
# Start base tracer (includes system info and resource monitoring)
|
86
163
|
super().start()
|
87
|
-
|
88
|
-
|
164
|
+
|
89
165
|
# Activate network tracing
|
90
166
|
self.network_tracer.activate_patches()
|
91
|
-
|
92
|
-
#
|
167
|
+
|
168
|
+
# take care of the auto instrumentation
|
93
169
|
if self.auto_instrument_llm:
|
94
170
|
self.instrument_llm_calls()
|
95
171
|
|
172
|
+
if self.auto_instrument_tool:
|
173
|
+
self.instrument_tool_calls()
|
174
|
+
|
175
|
+
if self.auto_instrument_agent:
|
176
|
+
self.instrument_agent_calls()
|
177
|
+
|
178
|
+
if self.auto_instrument_custom:
|
179
|
+
self.instrument_custom_calls()
|
180
|
+
|
181
|
+
if self.auto_instrument_user_interaction:
|
182
|
+
|
183
|
+
ToolTracerMixin.instrument_user_interaction_calls(self)
|
184
|
+
LLMTracerMixin.instrument_user_interaction_calls(self)
|
185
|
+
AgentTracerMixin.instrument_user_interaction_calls(self)
|
186
|
+
CustomTracerMixin.instrument_user_interaction_calls(self)
|
187
|
+
|
188
|
+
if self.auto_instrument_network:
|
189
|
+
ToolTracerMixin.instrument_network_calls(self)
|
190
|
+
LLMTracerMixin.instrument_network_calls(self)
|
191
|
+
AgentTracerMixin.instrument_network_calls(self)
|
192
|
+
CustomTracerMixin.instrument_network_calls(self)
|
193
|
+
|
194
|
+
# These will be implemented later
|
195
|
+
# if self.auto_instrument_file_io:
|
196
|
+
# self.instrument_file_io_calls()
|
197
|
+
|
96
198
|
def stop(self):
|
97
199
|
"""Stop tracing and save results"""
|
98
200
|
if self.is_active:
|
99
201
|
# Restore original print and input functions
|
100
202
|
builtins.print = self.user_interaction_tracer.original_print
|
101
203
|
builtins.input = self.user_interaction_tracer.original_input
|
102
|
-
|
204
|
+
builtins.open = self.user_interaction_tracer.original_open
|
205
|
+
|
103
206
|
# Calculate final metrics before stopping
|
104
207
|
self._calculate_final_metrics()
|
105
|
-
|
208
|
+
|
106
209
|
# Deactivate network tracing
|
107
210
|
self.network_tracer.deactivate_patches()
|
108
|
-
|
211
|
+
|
109
212
|
# Stop base tracer (includes saving to file)
|
110
213
|
super().stop()
|
111
|
-
|
214
|
+
|
112
215
|
# Cleanup
|
113
216
|
self.unpatch_llm_calls()
|
114
217
|
self.user_interaction_tracer.interactions = [] # Clear interactions list
|
115
218
|
self.is_active = False
|
116
219
|
|
117
|
-
|
118
220
|
def _calculate_final_metrics(self):
|
119
221
|
"""Calculate total cost and tokens from all components"""
|
120
222
|
total_cost = 0.0
|
121
223
|
total_tokens = 0
|
122
|
-
|
224
|
+
|
123
225
|
def process_component(component):
|
124
226
|
nonlocal total_cost, total_tokens
|
125
227
|
# Convert component to dict if it's an object
|
126
|
-
comp_dict =
|
127
|
-
|
128
|
-
|
129
|
-
|
228
|
+
comp_dict = (
|
229
|
+
component.__dict__ if hasattr(component, "__dict__") else component
|
230
|
+
)
|
231
|
+
|
232
|
+
if comp_dict.get("type") == "llm":
|
233
|
+
info = comp_dict.get("info", {})
|
130
234
|
if isinstance(info, dict):
|
131
235
|
# Extract cost
|
132
|
-
cost_info = info.get(
|
236
|
+
cost_info = info.get("cost", {})
|
133
237
|
if isinstance(cost_info, dict):
|
134
|
-
total_cost += cost_info.get(
|
135
|
-
|
238
|
+
total_cost += cost_info.get("total_cost", 0)
|
239
|
+
|
136
240
|
# Extract tokens
|
137
|
-
token_info = info.get(
|
241
|
+
token_info = info.get("tokens", {})
|
138
242
|
if isinstance(token_info, dict):
|
139
|
-
total_tokens += token_info.get(
|
243
|
+
total_tokens += token_info.get("total_tokens", 0)
|
140
244
|
else:
|
141
|
-
token_info = info.get(
|
245
|
+
token_info = info.get("token_usage", {})
|
142
246
|
if isinstance(token_info, dict):
|
143
|
-
total_tokens += token_info.get(
|
144
|
-
|
247
|
+
total_tokens += token_info.get("total_tokens", 0)
|
248
|
+
|
145
249
|
# Process children if they exist
|
146
|
-
data = comp_dict.get(
|
250
|
+
data = comp_dict.get("data", {})
|
147
251
|
if isinstance(data, dict):
|
148
|
-
children = data.get(
|
252
|
+
children = data.get("children", [])
|
149
253
|
if children:
|
150
254
|
for child in children:
|
151
255
|
process_component(child)
|
152
|
-
|
256
|
+
|
153
257
|
# Process all root components
|
154
258
|
for component in self.components:
|
155
259
|
process_component(component)
|
156
|
-
|
260
|
+
|
157
261
|
# Update metadata in trace
|
158
|
-
if hasattr(self,
|
262
|
+
if hasattr(self, "trace"):
|
159
263
|
if isinstance(self.trace.metadata, dict):
|
160
|
-
self.trace.metadata[
|
161
|
-
self.trace.metadata[
|
264
|
+
self.trace.metadata["total_cost"] = total_cost
|
265
|
+
self.trace.metadata["total_tokens"] = total_tokens
|
162
266
|
else:
|
163
267
|
self.trace.metadata.total_cost = total_cost
|
164
268
|
self.trace.metadata.total_tokens = total_tokens
|
@@ -166,11 +270,34 @@ class AgenticTracing(BaseTracer, LLMTracerMixin, ToolTracerMixin, AgentTracerMix
|
|
166
270
|
def add_component(self, component_data: dict, is_error: bool = False):
|
167
271
|
"""Add a component to the trace data"""
|
168
272
|
# Convert dict to appropriate Component type
|
169
|
-
filtered_data = {
|
273
|
+
filtered_data = {
|
274
|
+
k: v
|
275
|
+
for k, v in component_data.items()
|
276
|
+
if k
|
277
|
+
in [
|
278
|
+
"id",
|
279
|
+
"hash_id",
|
280
|
+
"source_hash_id",
|
281
|
+
"type",
|
282
|
+
"name",
|
283
|
+
"start_time",
|
284
|
+
"end_time",
|
285
|
+
"parent_id",
|
286
|
+
"info",
|
287
|
+
"extra_info",
|
288
|
+
"data",
|
289
|
+
"metadata",
|
290
|
+
"metrics",
|
291
|
+
"feedback",
|
292
|
+
"network_calls",
|
293
|
+
"interactions",
|
294
|
+
"error",
|
295
|
+
]
|
296
|
+
}
|
170
297
|
|
171
298
|
if component_data["type"] == "llm":
|
172
299
|
component = LLMComponent(**filtered_data)
|
173
|
-
elif component_data["type"] == "agent":
|
300
|
+
elif component_data["type"] == "agent":
|
174
301
|
component = AgentComponent(**filtered_data)
|
175
302
|
elif component_data["type"] == "tool":
|
176
303
|
component = ToolComponent(**filtered_data)
|
@@ -187,21 +314,27 @@ class AgenticTracing(BaseTracer, LLMTracerMixin, ToolTracerMixin, AgentTracerMix
|
|
187
314
|
else:
|
188
315
|
# Add component to the main trace
|
189
316
|
super().add_component(component)
|
190
|
-
|
317
|
+
|
191
318
|
# Handle error case
|
192
319
|
if is_error:
|
193
320
|
# Get the parent component if it exists
|
194
321
|
parent_id = component_data.get("parent_id")
|
195
322
|
children = self.agent_children.get()
|
196
|
-
|
323
|
+
|
197
324
|
# Set parent_id for all children
|
198
325
|
for child in children:
|
199
326
|
child["parent_id"] = parent_id
|
200
|
-
|
327
|
+
|
201
328
|
agent_tracer_mixin = AgentTracerMixin()
|
202
329
|
agent_tracer_mixin.component_network_calls = self.component_network_calls
|
203
|
-
agent_tracer_mixin.component_user_interaction =
|
204
|
-
|
330
|
+
agent_tracer_mixin.component_user_interaction = (
|
331
|
+
self.component_user_interaction
|
332
|
+
)
|
333
|
+
|
334
|
+
agent_tracer_mixin.span_attributes_dict[self.current_agent_name.get()] = (
|
335
|
+
SpanAttributes(self.current_agent_name.get())
|
336
|
+
)
|
337
|
+
|
205
338
|
# Create parent component with error info
|
206
339
|
parent_component = agent_tracer_mixin.create_agent_component(
|
207
340
|
component_id=parent_id,
|
@@ -218,10 +351,29 @@ class AgenticTracing(BaseTracer, LLMTracerMixin, ToolTracerMixin, AgentTracerMix
|
|
218
351
|
input_data=self.input_data,
|
219
352
|
output_data=None,
|
220
353
|
children=children,
|
221
|
-
parent_id=None # Add parent ID if exists
|
354
|
+
parent_id=None, # Add parent ID if exists
|
222
355
|
)
|
223
356
|
|
224
|
-
filtered_data = {
|
357
|
+
filtered_data = {
|
358
|
+
k: v
|
359
|
+
for k, v in parent_component.items()
|
360
|
+
if k
|
361
|
+
in [
|
362
|
+
"id",
|
363
|
+
"hash_id",
|
364
|
+
"source_hash_id",
|
365
|
+
"type",
|
366
|
+
"name",
|
367
|
+
"start_time",
|
368
|
+
"end_time",
|
369
|
+
"parent_id",
|
370
|
+
"info",
|
371
|
+
"data",
|
372
|
+
"network_calls",
|
373
|
+
"interactions",
|
374
|
+
"error",
|
375
|
+
]
|
376
|
+
}
|
225
377
|
parent_agent_component = AgentComponent(**filtered_data)
|
226
378
|
# Add the parent component to trace and stop tracing
|
227
379
|
super().add_component(parent_agent_component)
|
@@ -234,4 +386,4 @@ class AgenticTracing(BaseTracer, LLMTracerMixin, ToolTracerMixin, AgentTracerMix
|
|
234
386
|
|
235
387
|
def __exit__(self, exc_type, exc_value, traceback):
|
236
388
|
"""Context manager exit"""
|
237
|
-
self.stop()
|
389
|
+
self.stop()
|
@@ -47,6 +47,8 @@ class NetworkTracer:
|
|
47
47
|
"url": url,
|
48
48
|
"method": method,
|
49
49
|
"status_code": status_code,
|
50
|
+
"start_time": start_time.isoformat() if start_time else None,
|
51
|
+
"end_time": end_time.isoformat() if end_time else None,
|
50
52
|
"response_time": duration,
|
51
53
|
"bytes_sent": bytes_sent,
|
52
54
|
"bytes_received": bytes_received,
|