ragaai-catalyst 2.2.4b5__py3-none-any.whl → 2.2.5b2__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.
Files changed (45) hide show
  1. ragaai_catalyst/__init__.py +0 -2
  2. ragaai_catalyst/dataset.py +59 -1
  3. ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py +5 -285
  4. ragaai_catalyst/tracers/agentic_tracing/utils/__init__.py +0 -2
  5. ragaai_catalyst/tracers/agentic_tracing/utils/create_dataset_schema.py +1 -1
  6. ragaai_catalyst/tracers/exporters/__init__.py +1 -2
  7. ragaai_catalyst/tracers/exporters/file_span_exporter.py +0 -1
  8. ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py +23 -1
  9. ragaai_catalyst/tracers/tracer.py +6 -186
  10. {ragaai_catalyst-2.2.4b5.dist-info → ragaai_catalyst-2.2.5b2.dist-info}/METADATA +1 -1
  11. {ragaai_catalyst-2.2.4b5.dist-info → ragaai_catalyst-2.2.5b2.dist-info}/RECORD +14 -45
  12. ragaai_catalyst/experiment.py +0 -486
  13. ragaai_catalyst/tracers/agentic_tracing/tests/FinancialAnalysisSystem.ipynb +0 -536
  14. ragaai_catalyst/tracers/agentic_tracing/tests/GameActivityEventPlanner.ipynb +0 -134
  15. ragaai_catalyst/tracers/agentic_tracing/tests/TravelPlanner.ipynb +0 -563
  16. ragaai_catalyst/tracers/agentic_tracing/tests/__init__.py +0 -0
  17. ragaai_catalyst/tracers/agentic_tracing/tests/ai_travel_agent.py +0 -197
  18. ragaai_catalyst/tracers/agentic_tracing/tests/unique_decorator_test.py +0 -172
  19. ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py +0 -687
  20. ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +0 -1319
  21. ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py +0 -347
  22. ragaai_catalyst/tracers/agentic_tracing/tracers/langgraph_tracer.py +0 -0
  23. ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +0 -1182
  24. ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py +0 -288
  25. ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py +0 -557
  26. ragaai_catalyst/tracers/agentic_tracing/tracers/user_interaction_tracer.py +0 -129
  27. ragaai_catalyst/tracers/agentic_tracing/upload/upload_local_metric.py +0 -74
  28. ragaai_catalyst/tracers/agentic_tracing/utils/api_utils.py +0 -21
  29. ragaai_catalyst/tracers/agentic_tracing/utils/generic.py +0 -32
  30. ragaai_catalyst/tracers/agentic_tracing/utils/get_user_trace_metrics.py +0 -28
  31. ragaai_catalyst/tracers/agentic_tracing/utils/span_attributes.py +0 -133
  32. ragaai_catalyst/tracers/agentic_tracing/utils/supported_llm_provider.toml +0 -34
  33. ragaai_catalyst/tracers/exporters/raga_exporter.py +0 -467
  34. ragaai_catalyst/tracers/langchain_callback.py +0 -821
  35. ragaai_catalyst/tracers/llamaindex_callback.py +0 -361
  36. ragaai_catalyst/tracers/llamaindex_instrumentation.py +0 -424
  37. ragaai_catalyst/tracers/upload_traces.py +0 -170
  38. ragaai_catalyst/tracers/utils/convert_langchain_callbacks_output.py +0 -62
  39. ragaai_catalyst/tracers/utils/convert_llama_instru_callback.py +0 -69
  40. ragaai_catalyst/tracers/utils/extraction_logic_llama_index.py +0 -74
  41. ragaai_catalyst/tracers/utils/langchain_tracer_extraction_logic.py +0 -82
  42. ragaai_catalyst/tracers/utils/rag_trace_json_converter.py +0 -403
  43. {ragaai_catalyst-2.2.4b5.dist-info → ragaai_catalyst-2.2.5b2.dist-info}/WHEEL +0 -0
  44. {ragaai_catalyst-2.2.4b5.dist-info → ragaai_catalyst-2.2.5b2.dist-info}/licenses/LICENSE +0 -0
  45. {ragaai_catalyst-2.2.4b5.dist-info → ragaai_catalyst-2.2.5b2.dist-info}/top_level.txt +0 -0
@@ -1,687 +0,0 @@
1
- import os
2
- import functools
3
- import uuid
4
- from datetime import datetime
5
- import psutil
6
- from typing import Optional, Any, Dict, List
7
- from ..utils.unique_decorator import mydecorator, generate_unique_hash_simple
8
- import contextvars
9
- import asyncio
10
- from ..utils.file_name_tracker import TrackName
11
- from ..utils.span_attributes import SpanAttributes
12
- from .base import BaseTracer
13
- import logging
14
-
15
- logger = logging.getLogger(__name__)
16
- logging_level = (
17
- logger.setLevel(logging.DEBUG)
18
- if os.getenv("DEBUG")
19
- else logger.setLevel(logging.INFO)
20
- )
21
-
22
-
23
- class AgentTracerMixin:
24
- def __init__(self, *args, **kwargs):
25
- super().__init__(*args, **kwargs)
26
- self.file_tracker = TrackName()
27
- self.current_agent_id = contextvars.ContextVar("agent_id", default=None)
28
- self.current_agent_name = contextvars.ContextVar("agent_name", default=None)
29
- self.agent_children = contextvars.ContextVar("agent_children", default=[])
30
- self.component_network_calls = contextvars.ContextVar(
31
- "component_network_calls", default={}
32
- )
33
- self.component_user_interaction = contextvars.ContextVar(
34
- "component_user_interaction", default={}
35
- )
36
- self.version = contextvars.ContextVar("version", default=None)
37
- self.agent_type = contextvars.ContextVar("agent_type", default="generic")
38
- self.capabilities = contextvars.ContextVar("capabilities", default=[])
39
- self.start_time = contextvars.ContextVar("start_time", default=None)
40
- self.input_data = contextvars.ContextVar("input_data", default=None)
41
- self.gt = None
42
-
43
- self.span_attributes_dict = {}
44
-
45
- # Add auto instrument flags
46
- self.auto_instrument_agent = False
47
- self.auto_instrument_user_interaction = False
48
- self.auto_instrument_file_io = False
49
- self.auto_instrument_network = False
50
-
51
- def trace_agent(
52
- self,
53
- name: str,
54
- agent_type: str = None,
55
- version: str = None,
56
- capabilities: List[str] = None,
57
- tags: List[str] = [],
58
- metadata: Dict[str, Any] = {},
59
- metrics: List[Dict[str, Any]] = [],
60
- feedback: Optional[Any] = None,
61
- ):
62
- if name not in self.span_attributes_dict:
63
- self.span_attributes_dict[name] = SpanAttributes(name)
64
- if tags:
65
- self.span(name).add_tags(tags)
66
- if metadata:
67
- self.span(name).add_metadata(metadata)
68
- if metrics:
69
- if isinstance(metrics, dict):
70
- metrics = [metrics]
71
- try:
72
- for metric in metrics:
73
- self.span(name).add_metrics(
74
- name=metric["name"],
75
- score=metric["score"],
76
- reasoning=metric.get("reasoning", ""),
77
- cost=metric.get("cost", None),
78
- latency=metric.get("latency", None),
79
- metadata=metric.get("metadata", {}),
80
- config=metric.get("config", {}),
81
- )
82
- except ValueError as e:
83
- logger.error(f"Validation Error: {e}")
84
- except Exception as e:
85
- logger.error(f"Error adding metric: {e}")
86
- if feedback:
87
- self.span(name).add_feedback(feedback)
88
-
89
- def decorator(target):
90
- # Check if target is a class
91
- is_class = isinstance(target, type)
92
- tracer = self # Store reference to tracer instance
93
- top_level_hash_id = generate_unique_hash_simple(
94
- target
95
- ) # Generate hash based on the decorated target code
96
- self.version.set(version)
97
- self.agent_type.set(agent_type)
98
- self.capabilities.set(capabilities)
99
-
100
- if is_class:
101
- # Store original __init__
102
- original_init = target.__init__
103
-
104
- def wrapped_init(self, *args, **kwargs):
105
- gt = kwargs.get("gt") if kwargs else None
106
- if gt is not None:
107
- span = self.span(name)
108
- span.add_gt(gt)
109
-
110
- if not hasattr(self, '_agent_component_id'):
111
- component_id = str(uuid.uuid4())
112
- self._agent_component_id = component_id
113
-
114
- # Get parent agent ID if exists
115
- parent_agent_id = tracer.current_agent_id.get()
116
-
117
- agent_component = tracer.create_agent_component(
118
- component_id=component_id,
119
- hash_id=top_level_hash_id,
120
- name=name,
121
- agent_type=agent_type,
122
- version=version,
123
- capabilities=capabilities or [],
124
- start_time=datetime.now().astimezone().isoformat(),
125
- memory_used=0,
126
- input_data=tracer._sanitize_input(args, kwargs),
127
- output_data=None,
128
- children=[],
129
- parent_id=parent_agent_id,
130
- )
131
-
132
- if not hasattr(tracer, "_agent_components"):
133
- tracer._agent_components = {}
134
- tracer._agent_components[component_id] = agent_component
135
-
136
- # For class agents, only add to parent's children if parent exists
137
- if parent_agent_id and parent_agent_id in tracer._agent_components:
138
- parent_component = tracer._agent_components[parent_agent_id]
139
- if not hasattr(parent_component, "children"):
140
- parent_component["children"] = []
141
- if component_id not in parent_component["children"]:
142
- parent_component["children"].append(component_id)
143
-
144
- token = tracer.current_agent_id.set(self._agent_component_id)
145
- try:
146
- original_init(self, *args, **kwargs)
147
- finally:
148
- tracer.current_agent_id.reset(token)
149
-
150
- # Wrap all public methods to track execution
151
- for attr_name in dir(target):
152
- if not attr_name.startswith("_"):
153
- attr_value = getattr(target, attr_name)
154
- if callable(attr_value):
155
-
156
- def wrap_method(method):
157
- @functools.wraps(method)
158
- def wrapped_method(self, *args, **kwargs):
159
- gt = kwargs.get("gt") if kwargs else None
160
- if gt is not None:
161
- span = tracer.span(name)
162
- span.add_gt(gt)
163
- # Set this agent as current during method execution
164
- token = tracer.current_agent_id.set(
165
- self._agent_component_id
166
- )
167
-
168
- # Store parent's children before setting new empty list
169
- parent_children = tracer.agent_children.get()
170
- children_token = tracer.agent_children.set([])
171
-
172
- try:
173
- start_time = datetime.now().astimezone().isoformat()
174
- result = method(self, *args, **kwargs)
175
-
176
- # Update agent component with method result
177
- if hasattr(tracer, "_agent_components"):
178
- component = tracer._agent_components.get(
179
- self._agent_component_id
180
- )
181
- if component:
182
- component["data"]["output"] = (
183
- tracer._sanitize_output(result)
184
- )
185
- component["data"]["input"] = (
186
- tracer._sanitize_input(args, kwargs)
187
- )
188
- component["start_time"] = (
189
- start_time
190
- )
191
-
192
- # Get children accumulated during method execution
193
- children = tracer.agent_children.get()
194
- if children:
195
- if (
196
- "children"
197
- not in component["data"]
198
- ):
199
- component["data"][
200
- "children"
201
- ] = []
202
- component["data"][
203
- "children"
204
- ].extend(children)
205
-
206
- # Add this component as a child to parent's children list
207
- parent_children.append(component)
208
- tracer.agent_children.set(
209
- parent_children
210
- )
211
- return result
212
- finally:
213
- tracer.current_agent_id.reset(token)
214
- tracer.agent_children.reset(children_token)
215
-
216
- return wrapped_method
217
-
218
- setattr(target, attr_name, wrap_method(attr_value))
219
-
220
- # Replace __init__ with wrapped version
221
-
222
- target.__init__ = wrapped_init
223
-
224
- # Wrap all methods to maintain parent-child relationship
225
- for attr_name, attr_value in target.__dict__.items():
226
- if callable(attr_value) and not attr_name.startswith('__'):
227
- original_method = attr_value
228
-
229
- def create_wrapper(method):
230
- @self.file_tracker.trace_decorator
231
- @functools.wraps(method)
232
- def method_wrapper(self, *args, **kwargs):
233
- gt = kwargs.get("gt") if kwargs else None
234
- if gt is not None:
235
- span = tracer.span(name)
236
- span.add_gt(gt)
237
- # Use the class instance's agent ID as parent
238
- parent_id = getattr(self, '_agent_component_id', None)
239
- if parent_id:
240
- if asyncio.iscoroutinefunction(method):
241
- return tracer._trace_agent_execution(
242
- method.__get__(self, type(self)),
243
- name,
244
- agent_type,
245
- version,
246
- capabilities,
247
- top_level_hash_id,
248
- *args,
249
- **kwargs,
250
- )
251
- else:
252
- return tracer._trace_sync_agent_execution(
253
- method.__get__(self, type(self)),
254
- name,
255
- agent_type,
256
- version,
257
- capabilities,
258
- top_level_hash_id,
259
- *args,
260
- **kwargs,
261
- )
262
- else:
263
- return method(self, *args, **kwargs)
264
- return method_wrapper
265
-
266
- setattr(target, attr_name, create_wrapper(original_method))
267
-
268
- return target
269
- else:
270
- # For non-class targets (e.g., functions), use existing function wrapping logic
271
- @functools.wraps(target)
272
- def wrapper(*args, **kwargs):
273
- if asyncio.iscoroutinefunction(target):
274
- return tracer._trace_agent_execution(
275
- target,
276
- name,
277
- agent_type,
278
- version,
279
- capabilities,
280
- top_level_hash_id,
281
- *args,
282
- **kwargs,
283
- )
284
- else:
285
- return tracer._trace_sync_agent_execution(
286
- target,
287
- name,
288
- agent_type,
289
- version,
290
- capabilities,
291
- top_level_hash_id,
292
- *args,
293
- **kwargs,
294
- )
295
- return wrapper
296
-
297
- return decorator
298
-
299
- def _trace_sync_agent_execution(
300
- self, func, name, agent_type, version, capabilities, top_level_hash_id, *args, **kwargs
301
- ):
302
- """Synchronous version of agent tracing"""
303
- if not self.is_active:
304
- return func(*args, **kwargs)
305
-
306
- if not self.auto_instrument_agent:
307
- return func(*args, **kwargs)
308
-
309
- start_time = datetime.now().astimezone().isoformat()
310
- self.start_time = start_time
311
- self.input_data = self._sanitize_input(args, kwargs)
312
- start_memory = psutil.Process().memory_info().rss
313
- component_id = str(uuid.uuid4())
314
-
315
- # Extract ground truth if present
316
- ground_truth = kwargs.pop("gt", None) if kwargs else None
317
- if ground_truth is not None:
318
- span = self.span(name)
319
- span.add_gt(ground_truth)
320
-
321
- # Get parent agent ID if exists
322
- parent_agent_id = self.current_agent_id.get()
323
-
324
- # Set the current agent context
325
- agent_token = self.current_agent_id.set(component_id)
326
- agent_name_token = self.current_agent_name.set(name)
327
-
328
- # Initialize empty children list for this agent
329
- parent_children = self.agent_children.get()
330
- children_token = self.agent_children.set([])
331
-
332
- # Start tracking network calls for this component
333
- self.start_component(component_id)
334
-
335
- try:
336
- # Execute the agent
337
- result = func(*args, **kwargs)
338
-
339
- # Calculate resource usage
340
- end_memory = psutil.Process().memory_info().rss
341
- memory_used = max(0, end_memory - start_memory)
342
-
343
- # Get children components collected during execution
344
- children = self.agent_children.get()
345
-
346
- # End tracking network calls for this component
347
- self.end_component(component_id)
348
-
349
- # Create agent component with children and parent if exists
350
- agent_component = self.create_agent_component(
351
- component_id=component_id,
352
- hash_id=top_level_hash_id,
353
- name=name,
354
- agent_type=agent_type,
355
- version=version,
356
- capabilities=capabilities or [],
357
- start_time=start_time,
358
- memory_used=memory_used,
359
- input_data=self.input_data,
360
- output_data=self._sanitize_output(result),
361
- children=children,
362
- parent_id=parent_agent_id,
363
- )
364
-
365
- # Store component for updates
366
- if not hasattr(self, "_agent_components"):
367
- self._agent_components = {}
368
- self._agent_components[component_id] = agent_component
369
-
370
- # Only add to hierarchy if this is a root component (no parent)
371
- # or if the parent explicitly added it as a child
372
- if parent_agent_id:
373
- parent_children.append(agent_component)
374
- self.agent_children.set(parent_children)
375
- else:
376
- self.add_component(agent_component)
377
-
378
- return result
379
- except Exception as e:
380
- error_component = {
381
- "code": 500,
382
- "type": type(e).__name__,
383
- "message": str(e),
384
- "details": {},
385
- }
386
-
387
- # Get children even in case of error
388
- children = self.agent_children.get()
389
-
390
- # Create error component
391
- agent_component = self.create_agent_component(
392
- component_id=component_id,
393
- hash_id=top_level_hash_id,
394
- name=name,
395
- agent_type=agent_type,
396
- version=version,
397
- capabilities=capabilities or [],
398
- start_time=start_time,
399
- memory_used=0,
400
- input_data=self.input_data,
401
- output_data=None,
402
- error=error_component,
403
- children=children,
404
- parent_id=parent_agent_id, # Add parent ID if exists
405
- )
406
-
407
- # Store component for updates
408
- if not hasattr(self, "_agent_components"):
409
- self._agent_components = {}
410
- self._agent_components[component_id] = agent_component
411
-
412
- # Only add to hierarchy if this is a root component (no parent)
413
- # or if the parent explicitly added it as a child
414
- if parent_agent_id:
415
- parent_children.append(agent_component)
416
- self.agent_children.set(parent_children)
417
- else:
418
- # Only add to root components if no parent
419
- self.add_component(agent_component, is_error=True)
420
-
421
- raise
422
- finally:
423
- self.current_agent_id.reset(agent_token)
424
- self.current_agent_name.reset(agent_name_token)
425
- self.agent_children.reset(children_token)
426
-
427
- async def _trace_agent_execution(
428
- self, func, name, agent_type, version, capabilities, hash_id, *args, **kwargs
429
- ):
430
- """Asynchronous version of agent tracing"""
431
- if not self.is_active:
432
- return await func(*args, **kwargs)
433
-
434
- if not self.auto_instrument_agent:
435
- return await func(*args, **kwargs)
436
-
437
- start_time = datetime.now().astimezone().isoformat()
438
- start_memory = psutil.Process().memory_info().rss
439
- component_id = str(uuid.uuid4())
440
-
441
- # Extract ground truth if present
442
- ground_truth = kwargs.pop("gt", None) if kwargs else None
443
- if ground_truth is not None:
444
- span = self.span(name)
445
- span.add_gt(ground_truth)
446
-
447
- # Get parent agent ID if exists
448
- parent_agent_id = self.current_agent_id.get()
449
-
450
- # Set the current agent context
451
- agent_token = self.current_agent_id.set(component_id)
452
- agent_name_token = self.current_agent_name.set(name)
453
-
454
- # Initialize empty children list for this agent
455
- parent_children = self.agent_children.get()
456
- children_token = self.agent_children.set([])
457
- self.start_component(component_id)
458
-
459
- try:
460
- # Execute the agent
461
- result = await func(*args, **kwargs)
462
-
463
- # Calculate resource usage
464
- end_memory = psutil.Process().memory_info().rss
465
- memory_used = max(0, end_memory - start_memory)
466
-
467
- # Get children components collected during execution
468
- children = self.agent_children.get()
469
-
470
- self.end_component(component_id)
471
-
472
- # Create agent component with children and parent if exists
473
- agent_component = self.create_agent_component(
474
- component_id=component_id,
475
- hash_id=hash_id,
476
- name=name,
477
- agent_type=agent_type,
478
- version=version,
479
- capabilities=capabilities or [],
480
- start_time=start_time,
481
- memory_used=memory_used,
482
- input_data=self._sanitize_input(args, kwargs),
483
- output_data=self._sanitize_output(result),
484
- children=children,
485
- parent_id=parent_agent_id,
486
- )
487
-
488
- # Store component for updates
489
- if not hasattr(self, "_agent_components"):
490
- self._agent_components = {}
491
- self._agent_components[component_id] = agent_component
492
-
493
- # Only add to hierarchy if this is a root component (no parent)
494
- # or if the parent explicitly added it as a child
495
- if parent_agent_id:
496
- parent_children.append(agent_component)
497
- self.agent_children.set(parent_children)
498
- else:
499
- self.add_component(agent_component)
500
-
501
- return result
502
- except Exception as e:
503
- error_component = {
504
- "code": 500,
505
- "type": type(e).__name__,
506
- "message": str(e),
507
- "details": {},
508
- }
509
-
510
- # Get children even in case of error
511
- children = self.agent_children.get()
512
-
513
- # Create error component
514
- agent_component = self.create_agent_component(
515
- component_id=component_id,
516
- hash_id=hash_id,
517
- name=name,
518
- agent_type=agent_type,
519
- version=version,
520
- capabilities=capabilities or [],
521
- start_time=start_time,
522
- memory_used=0,
523
- input_data=self._sanitize_input(args, kwargs),
524
- output_data=None,
525
- error=error_component,
526
- children=children,
527
- parent_id=parent_agent_id, # Add parent ID if exists
528
- )
529
-
530
- # Store component for updates
531
- if not hasattr(self, "_agent_components"):
532
- self._agent_components = {}
533
- self._agent_components[component_id] = agent_component
534
-
535
- # Only add to hierarchy if this is a root component (no parent)
536
- # or if the parent explicitly added it as a child
537
- if parent_agent_id:
538
- parent_children.append(agent_component)
539
- self.agent_children.set(parent_children)
540
- else:
541
- # Only add to root components if no parent
542
- self.add_component(agent_component, is_error=True)
543
-
544
- raise
545
- finally:
546
- # Reset context variables
547
- self.current_agent_id.reset(agent_token)
548
- self.current_agent_name.reset(agent_name_token)
549
- self.agent_children.reset(children_token)
550
-
551
- def create_agent_component(self, **kwargs):
552
- """Create an agent component according to the data structure"""
553
- network_calls = []
554
- if self.auto_instrument_network:
555
- network_calls = self.component_network_calls.get(kwargs["component_id"], [])
556
- interactions = []
557
- if self.auto_instrument_user_interaction:
558
- input_output_interactions = []
559
- for interaction in self.component_user_interaction.get(kwargs["component_id"], []):
560
- if interaction["interaction_type"] in ["input", "output"]:
561
- input_output_interactions.append(interaction)
562
- interactions.extend(input_output_interactions)
563
- if self.auto_instrument_file_io:
564
- file_io_interactions = []
565
- for interaction in self.component_user_interaction.get(kwargs["component_id"], []):
566
- if interaction["interaction_type"] in ["file_read", "file_write"]:
567
- file_io_interactions.append(interaction)
568
- interactions.extend(file_io_interactions)
569
-
570
- # Get start time
571
- start_time = None
572
- if "start_time" in kwargs:
573
- start_time = kwargs["start_time"]
574
-
575
- # Get tags, metrics
576
- name = kwargs["name"]
577
- # tags
578
- tags = []
579
- if name in self.span_attributes_dict:
580
- tags = self.span_attributes_dict[name].tags or []
581
-
582
- # metrics
583
- metrics = []
584
- if name in self.span_attributes_dict:
585
- raw_metrics = self.span_attributes_dict[name].metrics or []
586
- for metric in raw_metrics:
587
- base_metric_name = metric["name"]
588
- counter = sum(1 for x in self.visited_metrics if x.startswith(base_metric_name))
589
- metric_name = f'{base_metric_name}_{counter}' if counter > 0 else base_metric_name
590
- self.visited_metrics.append(metric_name)
591
- metric["name"] = metric_name
592
- metrics.append(metric)
593
-
594
- # TODO agent_trace execute metric
595
- formatted_metrics = BaseTracer.get_formatted_metric(self.span_attributes_dict, self.project_id, name)
596
- if formatted_metrics:
597
- metrics.extend(formatted_metrics)
598
-
599
- component = {
600
- "id": kwargs["component_id"],
601
- "hash_id": kwargs["hash_id"],
602
- "source_hash_id": None,
603
- "type": "agent",
604
- "name": kwargs["name"],
605
- "start_time": start_time,
606
- "end_time": datetime.now().astimezone().isoformat(),
607
- "error": kwargs.get("error"),
608
- "parent_id": kwargs.get("parent_id"),
609
- "info": {
610
- "agent_type": kwargs["agent_type"],
611
- "version": kwargs["version"],
612
- "capabilities": kwargs["capabilities"],
613
- "memory_used": kwargs["memory_used"],
614
- "tags": tags,
615
- },
616
- "data": {
617
- "input": kwargs["input_data"],
618
- "output": kwargs["output_data"],
619
- "children": kwargs.get("children", []),
620
- },
621
- "metrics": metrics,
622
- "network_calls": network_calls,
623
- "interactions": interactions,
624
- }
625
-
626
- if name in self.span_attributes_dict:
627
- span_gt = self.span_attributes_dict[name].gt
628
- if span_gt is not None:
629
- component["data"]["gt"] = span_gt
630
- span_context = self.span_attributes_dict[name].context
631
- if span_context:
632
- component["data"]["context"] = span_context
633
-
634
- # Reset the SpanAttributes context variable
635
- self.span_attributes_dict[kwargs["name"]] = SpanAttributes(kwargs["name"])
636
-
637
- return component
638
-
639
- def start_component(self, component_id):
640
- """Start tracking network calls for a component"""
641
- component_network_calls = self.component_network_calls.get()
642
- if component_id not in component_network_calls:
643
- component_network_calls[component_id] = []
644
- self.component_network_calls.set(component_network_calls)
645
-
646
- def end_component(self, component_id):
647
- """End tracking network calls for a component"""
648
- component_network_calls = self.component_network_calls.get()
649
- if component_id in component_network_calls:
650
- component_network_calls[component_id] = []
651
- self.component_network_calls.set(component_network_calls)
652
-
653
- def _sanitize_input(self, args: tuple, kwargs: dict) -> dict:
654
- """Sanitize and format input data, including handling of nested lists and dictionaries."""
655
-
656
- def sanitize_value(value):
657
- if isinstance(value, (int, float, bool, str)):
658
- return value
659
- elif isinstance(value, list):
660
- return [sanitize_value(item) for item in value]
661
- elif isinstance(value, dict):
662
- return {key: sanitize_value(val) for key, val in value.items()}
663
- else:
664
- return str(value) # Convert non-standard types to string
665
-
666
- return {
667
- "args": [sanitize_value(arg) for arg in args],
668
- "kwargs": {key: sanitize_value(val) for key, val in kwargs.items()},
669
- }
670
-
671
- def _sanitize_output(self, output: Any) -> Any:
672
- """Sanitize and format output data"""
673
- if isinstance(output, (int, float, bool, str, list, dict)):
674
- return output
675
- return str(output)
676
-
677
- def instrument_agent_calls(self):
678
- self.auto_instrument_agent = True
679
-
680
- def instrument_user_interaction_calls(self):
681
- self.auto_instrument_user_interaction = True
682
-
683
- def instrument_network_calls(self):
684
- self.auto_instrument_network = True
685
-
686
- def instrument_file_io_calls(self):
687
- self.auto_instrument_file_io = True