ragaai-catalyst 2.1.4.1b0__py3-none-any.whl → 2.1.5__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 (64) hide show
  1. ragaai_catalyst/__init__.py +23 -2
  2. ragaai_catalyst/dataset.py +462 -1
  3. ragaai_catalyst/evaluation.py +76 -7
  4. ragaai_catalyst/ragaai_catalyst.py +52 -10
  5. ragaai_catalyst/redteaming/__init__.py +7 -0
  6. ragaai_catalyst/redteaming/config/detectors.toml +13 -0
  7. ragaai_catalyst/redteaming/data_generator/scenario_generator.py +95 -0
  8. ragaai_catalyst/redteaming/data_generator/test_case_generator.py +120 -0
  9. ragaai_catalyst/redteaming/evaluator.py +125 -0
  10. ragaai_catalyst/redteaming/llm_generator.py +136 -0
  11. ragaai_catalyst/redteaming/llm_generator_old.py +83 -0
  12. ragaai_catalyst/redteaming/red_teaming.py +331 -0
  13. ragaai_catalyst/redteaming/requirements.txt +4 -0
  14. ragaai_catalyst/redteaming/tests/grok.ipynb +97 -0
  15. ragaai_catalyst/redteaming/tests/stereotype.ipynb +2258 -0
  16. ragaai_catalyst/redteaming/upload_result.py +38 -0
  17. ragaai_catalyst/redteaming/utils/issue_description.py +114 -0
  18. ragaai_catalyst/redteaming/utils/rt.png +0 -0
  19. ragaai_catalyst/redteaming_old.py +171 -0
  20. ragaai_catalyst/synthetic_data_generation.py +400 -22
  21. ragaai_catalyst/tracers/__init__.py +17 -1
  22. ragaai_catalyst/tracers/agentic_tracing/data/data_structure.py +4 -2
  23. ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py +212 -148
  24. ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +657 -247
  25. ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py +50 -19
  26. ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +588 -177
  27. ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py +99 -100
  28. ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py +3 -3
  29. ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py +230 -29
  30. ragaai_catalyst/tracers/agentic_tracing/upload/trace_uploader.py +358 -0
  31. ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py +75 -20
  32. ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py +55 -11
  33. ragaai_catalyst/tracers/agentic_tracing/upload/upload_local_metric.py +74 -0
  34. ragaai_catalyst/tracers/agentic_tracing/upload/upload_trace_metric.py +47 -16
  35. ragaai_catalyst/tracers/agentic_tracing/utils/create_dataset_schema.py +4 -2
  36. ragaai_catalyst/tracers/agentic_tracing/utils/file_name_tracker.py +26 -3
  37. ragaai_catalyst/tracers/agentic_tracing/utils/llm_utils.py +182 -17
  38. ragaai_catalyst/tracers/agentic_tracing/utils/model_costs.json +1233 -497
  39. ragaai_catalyst/tracers/agentic_tracing/utils/span_attributes.py +81 -10
  40. ragaai_catalyst/tracers/agentic_tracing/utils/supported_llm_provider.toml +34 -0
  41. ragaai_catalyst/tracers/agentic_tracing/utils/system_monitor.py +215 -0
  42. ragaai_catalyst/tracers/agentic_tracing/utils/trace_utils.py +0 -32
  43. ragaai_catalyst/tracers/agentic_tracing/utils/unique_decorator.py +3 -1
  44. ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py +73 -47
  45. ragaai_catalyst/tracers/distributed.py +300 -0
  46. ragaai_catalyst/tracers/exporters/__init__.py +3 -1
  47. ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py +160 -0
  48. ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py +129 -0
  49. ragaai_catalyst/tracers/langchain_callback.py +809 -0
  50. ragaai_catalyst/tracers/llamaindex_instrumentation.py +424 -0
  51. ragaai_catalyst/tracers/tracer.py +301 -55
  52. ragaai_catalyst/tracers/upload_traces.py +24 -7
  53. ragaai_catalyst/tracers/utils/convert_langchain_callbacks_output.py +61 -0
  54. ragaai_catalyst/tracers/utils/convert_llama_instru_callback.py +69 -0
  55. ragaai_catalyst/tracers/utils/extraction_logic_llama_index.py +74 -0
  56. ragaai_catalyst/tracers/utils/langchain_tracer_extraction_logic.py +82 -0
  57. ragaai_catalyst/tracers/utils/model_prices_and_context_window_backup.json +9365 -0
  58. ragaai_catalyst/tracers/utils/trace_json_converter.py +269 -0
  59. {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5.dist-info}/METADATA +367 -45
  60. ragaai_catalyst-2.1.5.dist-info/RECORD +97 -0
  61. {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5.dist-info}/WHEEL +1 -1
  62. ragaai_catalyst-2.1.4.1b0.dist-info/RECORD +0 -67
  63. {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5.dist-info}/LICENSE +0 -0
  64. {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5.dist-info}/top_level.txt +0 -0
@@ -9,6 +9,7 @@ import contextvars
9
9
  import asyncio
10
10
  from ..utils.file_name_tracker import TrackName
11
11
  from ..utils.span_attributes import SpanAttributes
12
+ from .base import BaseTracer
12
13
  import logging
13
14
 
14
15
  logger = logging.getLogger(__name__)
@@ -44,18 +45,19 @@ class AgentTracerMixin:
44
45
  # Add auto instrument flags
45
46
  self.auto_instrument_agent = False
46
47
  self.auto_instrument_user_interaction = False
48
+ self.auto_instrument_file_io = False
47
49
  self.auto_instrument_network = False
48
50
 
49
51
  def trace_agent(
50
- self,
51
- name: str,
52
- agent_type: str = None,
53
- version: str = None,
54
- capabilities: List[str] = None,
55
- tags: List[str] = [],
56
- metadata: Dict[str, Any] = {},
57
- metrics: List[Dict[str, Any]] = [],
58
- feedback: Optional[Any] = None,
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,
59
61
  ):
60
62
  if name not in self.span_attributes_dict:
61
63
  self.span_attributes_dict[name] = SpanAttributes(name)
@@ -100,49 +102,46 @@ class AgentTracerMixin:
100
102
  original_init = target.__init__
101
103
 
102
104
  def wrapped_init(self, *args, **kwargs):
103
- self.gt = kwargs.get("gt", None) if kwargs else None
104
- # Set agent context before initializing
105
- component_id = str(uuid.uuid4())
106
- hash_id = top_level_hash_id
107
-
108
- # Store the component ID in the instance
109
- self._agent_component_id = component_id
110
-
111
- # Get parent agent ID if exists
112
- parent_agent_id = tracer.current_agent_id.get()
113
-
114
- # Create agent component
115
- agent_component = tracer.create_agent_component(
116
- component_id=component_id,
117
- hash_id=hash_id,
118
- name=name,
119
- agent_type=agent_type,
120
- version=version,
121
- capabilities=capabilities or [],
122
- start_time=datetime.now().astimezone().isoformat(),
123
- memory_used=0,
124
- input_data=tracer._sanitize_input(args, kwargs),
125
- output_data=None,
126
- children=[],
127
- parent_id=parent_agent_id,
128
- )
129
-
130
- # Store component for later updates
131
- if not hasattr(tracer, "_agent_components"):
132
- tracer._agent_components = {}
133
- tracer._agent_components[component_id] = agent_component
134
-
135
- # If this is a nested agent, add it to parent's children
136
- if parent_agent_id:
137
- parent_children = tracer.agent_children.get()
138
- parent_children.append(agent_component)
139
- tracer.agent_children.set(parent_children)
140
- else:
141
- # Only add to root components if no parent
142
- tracer.add_component(agent_component)
143
-
144
- # Call original __init__ with this agent as current
145
- token = tracer.current_agent_id.set(component_id)
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)
146
145
  try:
147
146
  original_init(self, *args, **kwargs)
148
147
  finally:
@@ -155,10 +154,12 @@ class AgentTracerMixin:
155
154
  if callable(attr_value):
156
155
 
157
156
  def wrap_method(method):
158
- @self.file_tracker.trace_decorator
159
157
  @functools.wraps(method)
160
158
  def wrapped_method(self, *args, **kwargs):
161
- self.gt = kwargs.get("gt", None) if kwargs else None
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)
162
163
  # Set this agent as current during method execution
163
164
  token = tracer.current_agent_id.set(
164
165
  self._agent_component_id
@@ -192,8 +193,8 @@ class AgentTracerMixin:
192
193
  children = tracer.agent_children.get()
193
194
  if children:
194
195
  if (
195
- "children"
196
- not in component["data"]
196
+ "children"
197
+ not in component["data"]
197
198
  ):
198
199
  component["data"][
199
200
  "children"
@@ -217,15 +218,60 @@ class AgentTracerMixin:
217
218
  setattr(target, attr_name, wrap_method(attr_value))
218
219
 
219
220
  # Replace __init__ with wrapped version
221
+
220
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
+
221
268
  return target
222
269
  else:
223
- # For function decorators, use existing sync/async tracing
224
- is_async = asyncio.iscoroutinefunction(target)
225
- if is_async:
226
-
227
- async def wrapper(*args, **kwargs):
228
- return await self._trace_agent_execution(
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(
229
275
  target,
230
276
  name,
231
277
  agent_type,
@@ -235,31 +281,24 @@ class AgentTracerMixin:
235
281
  *args,
236
282
  **kwargs,
237
283
  )
238
-
239
- return wrapper
240
- else:
241
-
242
- def wrapper(*args, **kwargs):
243
- return self._trace_sync_agent_execution(
284
+ else:
285
+ return tracer._trace_sync_agent_execution(
244
286
  target,
245
287
  name,
246
288
  agent_type,
247
289
  version,
248
290
  capabilities,
291
+ top_level_hash_id,
249
292
  *args,
250
293
  **kwargs,
251
294
  )
252
-
253
- return wrapper
295
+ return wrapper
254
296
 
255
297
  return decorator
256
298
 
257
299
  def _trace_sync_agent_execution(
258
- self, func, name, agent_type, version, capabilities, *args, **kwargs
300
+ self, func, name, agent_type, version, capabilities, top_level_hash_id, *args, **kwargs
259
301
  ):
260
- # Generate a unique hash_id for this execution context
261
- hash_id = str(uuid.uuid4())
262
-
263
302
  """Synchronous version of agent tracing"""
264
303
  if not self.is_active:
265
304
  return func(*args, **kwargs)
@@ -275,6 +314,9 @@ class AgentTracerMixin:
275
314
 
276
315
  # Extract ground truth if present
277
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)
278
320
 
279
321
  # Get parent agent ID if exists
280
322
  parent_agent_id = self.current_agent_id.get()
@@ -307,7 +349,7 @@ class AgentTracerMixin:
307
349
  # Create agent component with children and parent if exists
308
350
  agent_component = self.create_agent_component(
309
351
  component_id=component_id,
310
- hash_id=hash_id,
352
+ hash_id=top_level_hash_id,
311
353
  name=name,
312
354
  agent_type=agent_type,
313
355
  version=version,
@@ -319,16 +361,18 @@ class AgentTracerMixin:
319
361
  children=children,
320
362
  parent_id=parent_agent_id,
321
363
  )
322
- # Add ground truth to component data if present
323
- if ground_truth is not None:
324
- agent_component["data"]["gt"] = ground_truth
325
364
 
326
- # Add this component as a child to parent's children list
327
- parent_children.append(agent_component)
328
- self.agent_children.set(parent_children)
365
+ # Store component for updates
366
+ if not hasattr(self, "_agent_components"):
367
+ self._agent_components = {}
368
+ self._agent_components[component_id] = agent_component
329
369
 
330
- # Only add to root components if no parent
331
- if not parent_agent_id:
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:
332
376
  self.add_component(agent_component)
333
377
 
334
378
  return result
@@ -343,16 +387,10 @@ class AgentTracerMixin:
343
387
  # Get children even in case of error
344
388
  children = self.agent_children.get()
345
389
 
346
- # Set parent_id for all children
347
- for child in children:
348
- child["parent_id"] = component_id
349
-
350
- # End tracking network calls for this component
351
- self.end_component(component_id)
352
-
390
+ # Create error component
353
391
  agent_component = self.create_agent_component(
354
392
  component_id=component_id,
355
- hash_id=hash_id,
393
+ hash_id=top_level_hash_id,
356
394
  name=name,
357
395
  agent_type=agent_type,
358
396
  version=version,
@@ -365,16 +403,20 @@ class AgentTracerMixin:
365
403
  children=children,
366
404
  parent_id=parent_agent_id, # Add parent ID if exists
367
405
  )
368
- # If this is a nested agent, add it to parent's children
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
369
414
  if parent_agent_id:
370
- parent_component = self._agent_components.get(parent_agent_id)
371
- if parent_component:
372
- if "children" not in parent_component["data"]:
373
- parent_component["data"]["children"] = []
374
- parent_component["data"]["children"].append(agent_component)
415
+ parent_children.append(agent_component)
416
+ self.agent_children.set(parent_children)
375
417
  else:
376
418
  # Only add to root components if no parent
377
- self.add_component(agent_component)
419
+ self.add_component(agent_component, is_error=True)
378
420
 
379
421
  raise
380
422
  finally:
@@ -383,7 +425,7 @@ class AgentTracerMixin:
383
425
  self.agent_children.reset(children_token)
384
426
 
385
427
  async def _trace_agent_execution(
386
- self, func, name, agent_type, version, capabilities, hash_id, *args, **kwargs
428
+ self, func, name, agent_type, version, capabilities, hash_id, *args, **kwargs
387
429
  ):
388
430
  """Asynchronous version of agent tracing"""
389
431
  if not self.is_active:
@@ -398,6 +440,9 @@ class AgentTracerMixin:
398
440
 
399
441
  # Extract ground truth if present
400
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)
401
446
 
402
447
  # Get parent agent ID if exists
403
448
  parent_agent_id = self.current_agent_id.get()
@@ -440,16 +485,17 @@ class AgentTracerMixin:
440
485
  parent_id=parent_agent_id,
441
486
  )
442
487
 
443
- # Add ground truth to component data if present
444
- if ground_truth is not None:
445
- agent_component["data"]["gt"] = ground_truth
488
+ # Store component for updates
489
+ if not hasattr(self, "_agent_components"):
490
+ self._agent_components = {}
491
+ self._agent_components[component_id] = agent_component
446
492
 
447
- # Add this component as a child to parent's children list
448
- parent_children.append(agent_component)
449
- self.agent_children.set(parent_children)
450
-
451
- # Only add to root components if no parent
452
- if not parent_agent_id:
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:
453
499
  self.add_component(agent_component)
454
500
 
455
501
  return result
@@ -464,13 +510,7 @@ class AgentTracerMixin:
464
510
  # Get children even in case of error
465
511
  children = self.agent_children.get()
466
512
 
467
- # Set parent_id for all children
468
- for child in children:
469
- child["parent_id"] = component_id
470
-
471
- # End tracking network calls for this component
472
- self.end_component(component_id)
473
-
513
+ # Create error component
474
514
  agent_component = self.create_agent_component(
475
515
  component_id=component_id,
476
516
  hash_id=hash_id,
@@ -487,16 +527,19 @@ class AgentTracerMixin:
487
527
  parent_id=parent_agent_id, # Add parent ID if exists
488
528
  )
489
529
 
490
- # If this is a nested agent, add it to parent's children
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
491
537
  if parent_agent_id:
492
- parent_component = self._agent_components.get(parent_agent_id)
493
- if parent_component:
494
- if "children" not in parent_component["data"]:
495
- parent_component["data"]["children"] = []
496
- parent_component["data"]["children"].append(agent_component)
538
+ parent_children.append(agent_component)
539
+ self.agent_children.set(parent_children)
497
540
  else:
498
541
  # Only add to root components if no parent
499
- self.add_component(agent_component)
542
+ self.add_component(agent_component, is_error=True)
500
543
 
501
544
  raise
502
545
  finally:
@@ -512,10 +555,22 @@ class AgentTracerMixin:
512
555
  network_calls = self.component_network_calls.get(kwargs["component_id"], [])
513
556
  interactions = []
514
557
  if self.auto_instrument_user_interaction:
515
- interactions = self.component_user_interaction.get(
516
- kwargs["component_id"], []
517
- )
518
- start_time = kwargs["start_time"]
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"]
519
574
 
520
575
  # Get tags, metrics
521
576
  name = kwargs["name"]
@@ -533,9 +588,14 @@ class AgentTracerMixin:
533
588
  counter = sum(1 for x in self.visited_metrics if x.startswith(base_metric_name))
534
589
  metric_name = f'{base_metric_name}_{counter}' if counter > 0 else base_metric_name
535
590
  self.visited_metrics.append(metric_name)
536
- metric["name"] = metric_name
591
+ metric["name"] = metric_name
537
592
  metrics.append(metric)
538
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
+
539
599
  component = {
540
600
  "id": kwargs["component_id"],
541
601
  "hash_id": kwargs["hash_id"],
@@ -563,8 +623,13 @@ class AgentTracerMixin:
563
623
  "interactions": interactions,
564
624
  }
565
625
 
566
- if self.gt:
567
- component["data"]["gt"] = self.gt
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
568
633
 
569
634
  # Reset the SpanAttributes context variable
570
635
  self.span_attributes_dict[kwargs["name"]] = SpanAttributes(kwargs["name"])
@@ -585,27 +650,23 @@ class AgentTracerMixin:
585
650
  component_network_calls[component_id] = []
586
651
  self.component_network_calls.set(component_network_calls)
587
652
 
588
- def _sanitize_input(self, args: tuple, kwargs: dict) -> str:
589
- """Convert input arguments to text format.
653
+ def _sanitize_input(self, args: tuple, kwargs: dict) -> dict:
654
+ """Sanitize and format input data, including handling of nested lists and dictionaries."""
590
655
 
591
- Args:
592
- args: Input arguments tuple
593
- kwargs: Input keyword arguments dict
594
-
595
- Returns:
596
- str: Text representation of the input arguments
597
- """
598
-
599
- def _sanitize_value(value):
600
- if isinstance(value, dict):
601
- return str({k: _sanitize_value(v) for k, v in value.items()})
602
- elif isinstance(value, (list, tuple)):
603
- return str([_sanitize_value(item) for item in value])
604
- return str(value)
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
605
665
 
606
- sanitized_args = [_sanitize_value(arg) for arg in args]
607
- sanitized_kwargs = {k: _sanitize_value(v) for k, v in kwargs.items()}
608
- return str({"args": sanitized_args, "kwargs": sanitized_kwargs})
666
+ return {
667
+ "args": [sanitize_value(arg) for arg in args],
668
+ "kwargs": {key: sanitize_value(val) for key, val in kwargs.items()},
669
+ }
609
670
 
610
671
  def _sanitize_output(self, output: Any) -> Any:
611
672
  """Sanitize and format output data"""
@@ -621,3 +682,6 @@ class AgentTracerMixin:
621
682
 
622
683
  def instrument_network_calls(self):
623
684
  self.auto_instrument_network = True
685
+
686
+ def instrument_file_io_calls(self):
687
+ self.auto_instrument_file_io = True