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
@@ -6,6 +6,7 @@ import uuid
6
6
  import os
7
7
  import builtins
8
8
  from pathlib import Path
9
+ import logging
9
10
 
10
11
  from .base import BaseTracer
11
12
  from .llm_tracer import LLMTracerMixin
@@ -57,10 +58,12 @@ class AgenticTracing(
57
58
 
58
59
  self.project_name = user_detail["project_name"]
59
60
  self.project_id = user_detail["project_id"]
60
- # self.dataset_name = user_detail["dataset_name"]
61
61
  self.trace_user_detail = user_detail["trace_user_detail"]
62
62
  self.base_url = f"{RagaAICatalyst.BASE_URL}"
63
63
  self.timeout = 10
64
+
65
+ # Add warning flag
66
+ self._warning_shown = False
64
67
 
65
68
  BaseTracer.__init__(self, user_detail)
66
69
 
@@ -84,27 +87,23 @@ class AgenticTracing(
84
87
  self.auto_instrument_custom = True
85
88
  else:
86
89
  # 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
- )
90
+ self.is_active = True
92
91
 
93
92
  # Set individual components
94
93
  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)
94
+ self.auto_instrument_llm = auto_instrumentation.get("llm", True)
95
+ self.auto_instrument_tool = auto_instrumentation.get("tool", True)
96
+ self.auto_instrument_agent = auto_instrumentation.get("agent", True)
98
97
  self.auto_instrument_user_interaction = auto_instrumentation.get(
99
- "user_interaction", False
98
+ "user_interaction", True
100
99
  )
101
100
  self.auto_instrument_file_io = auto_instrumentation.get(
102
- "file_io", False
101
+ "file_io", True
103
102
  )
104
103
  self.auto_instrument_network = auto_instrumentation.get(
105
- "network", False
104
+ "network", True
106
105
  )
107
- self.auto_instrument_custom = auto_instrumentation.get("custom", False)
106
+ self.auto_instrument_custom = auto_instrumentation.get("custom", True)
108
107
  else:
109
108
  # If boolean provided, apply to all components
110
109
  self.auto_instrument_llm = bool(auto_instrumentation)
@@ -120,9 +119,6 @@ class AgenticTracing(
120
119
  self.component_network_calls = {} # Store network calls per component
121
120
  self.component_user_interaction = {}
122
121
 
123
- # Create output directory if it doesn't exist
124
- self.output_dir = Path("./traces") # Using default traces directory
125
- self.output_dir.mkdir(exist_ok=True)
126
122
 
127
123
  def start_component(self, component_id: str):
128
124
  """Start tracking network calls for a component"""
@@ -137,27 +133,38 @@ class AgenticTracing(
137
133
  self.network_tracer.network_calls.copy()
138
134
  )
139
135
  self.network_tracer.network_calls = [] # Reset for next component
140
- # self.component_user_interaction[component_id] = [interaction for interaction in self.user_interaction_tracer.interactions if interaction.get('component_id') == component_id]
136
+
137
+ # Store user interactions for the component
141
138
  for interaction in self.user_interaction_tracer.interactions:
142
139
  interaction_component_id = interaction.get("component_id")
143
140
  if interaction_component_id not in self.component_user_interaction:
144
141
  self.component_user_interaction[interaction_component_id] = []
145
142
  if interaction not in self.component_user_interaction[interaction_component_id]:
146
143
  self.component_user_interaction[interaction_component_id].append(interaction)
144
+
145
+ # Only reset component_id if it matches the current one
146
+ # This ensures we don't reset a parent's component_id when a child component ends
147
+ if self.current_component_id.get() == component_id:
148
+ # Get the parent agent's component_id if it exists
149
+ parent_agent_id = self.current_agent_id.get()
150
+ # If there's a parent agent, set the component_id back to the parent's
151
+ if parent_agent_id:
152
+ self.current_component_id.set(parent_agent_id)
153
+ self.user_interaction_tracer.component_id.set(parent_agent_id)
154
+ else:
155
+ # Only reset to None if there's no parent
156
+ self.current_component_id.set(None)
157
+ self.user_interaction_tracer.component_id.set(None)
147
158
 
148
159
  def start(self):
149
160
  """Start tracing"""
150
- if not self.is_active:
151
- return
161
+ self.is_active = True
152
162
 
153
163
  # Setup user interaction tracing
154
164
  self.user_interaction_tracer.project_id.set(self.project_id)
155
165
  self.user_interaction_tracer.trace_id.set(self.trace_id)
156
166
  self.user_interaction_tracer.tracer = self
157
167
  self.user_interaction_tracer.component_id.set(self.current_component_id.get())
158
- builtins.print = self.user_interaction_tracer.traced_print
159
- builtins.input = self.user_interaction_tracer.traced_input
160
- builtins.open = self.user_interaction_tracer.traced_open
161
168
 
162
169
  # Start base tracer (includes system info and resource monitoring)
163
170
  super().start()
@@ -166,24 +173,13 @@ class AgenticTracing(
166
173
  self.network_tracer.activate_patches()
167
174
 
168
175
  # take care of the auto instrumentation
169
- if self.auto_instrument_llm:
170
- self.instrument_llm_calls()
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
176
  if self.auto_instrument_user_interaction:
182
-
183
177
  ToolTracerMixin.instrument_user_interaction_calls(self)
184
178
  LLMTracerMixin.instrument_user_interaction_calls(self)
185
179
  AgentTracerMixin.instrument_user_interaction_calls(self)
186
180
  CustomTracerMixin.instrument_user_interaction_calls(self)
181
+ builtins.print = self.user_interaction_tracer.traced_print
182
+ builtins.input = self.user_interaction_tracer.traced_input
187
183
 
188
184
  if self.auto_instrument_network:
189
185
  ToolTracerMixin.instrument_network_calls(self)
@@ -191,9 +187,24 @@ class AgenticTracing(
191
187
  AgentTracerMixin.instrument_network_calls(self)
192
188
  CustomTracerMixin.instrument_network_calls(self)
193
189
 
194
- # These will be implemented later
195
- # if self.auto_instrument_file_io:
196
- # self.instrument_file_io_calls()
190
+ if self.auto_instrument_file_io:
191
+ ToolTracerMixin.instrument_file_io_calls(self)
192
+ LLMTracerMixin.instrument_file_io_calls(self)
193
+ AgentTracerMixin.instrument_file_io_calls(self)
194
+ CustomTracerMixin.instrument_file_io_calls(self)
195
+ builtins.open = self.user_interaction_tracer.traced_open
196
+
197
+ if self.auto_instrument_llm:
198
+ self.instrument_llm_calls()
199
+
200
+ if self.auto_instrument_tool:
201
+ self.instrument_tool_calls()
202
+
203
+ if self.auto_instrument_agent:
204
+ self.instrument_agent_calls()
205
+
206
+ if self.auto_instrument_custom:
207
+ self.instrument_custom_calls()
197
208
 
198
209
  def stop(self):
199
210
  """Stop tracing and save results"""
@@ -225,6 +236,8 @@ class AgenticTracing(
225
236
  total_cost = 0.0
226
237
  total_tokens = 0
227
238
 
239
+ processed_components = set()
240
+
228
241
  def process_component(component):
229
242
  nonlocal total_cost, total_tokens
230
243
  # Convert component to dict if it's an object
@@ -232,6 +245,11 @@ class AgenticTracing(
232
245
  component.__dict__ if hasattr(component, "__dict__") else component
233
246
  )
234
247
 
248
+ comp_id = comp_dict.get("id") or comp_dict.get("component_id")
249
+ if comp_id in processed_components:
250
+ return # Skip if already processed
251
+ processed_components.add(comp_id)
252
+
235
253
  if comp_dict.get("type") == "llm":
236
254
  info = comp_dict.get("info", {})
237
255
  if isinstance(info, dict):
@@ -298,6 +316,47 @@ class AgenticTracing(
298
316
  ]
299
317
  }
300
318
 
319
+ if component_data == None or component_data == {} or component_data.get("type", None) == None:
320
+ # Only show warning if it hasn't been shown before
321
+ if not self._warning_shown:
322
+ import toml
323
+ import os
324
+ from pathlib import Path
325
+
326
+ # Load supported LLM calls from TOML file
327
+ current_dir = Path(__file__).parent
328
+ toml_path = current_dir / "../utils/supported_llm_provider.toml"
329
+ try:
330
+ with open(toml_path, "r") as f:
331
+ config = toml.load(f)
332
+ supported_calls = ", ".join(config["supported_llm_calls"])
333
+ except Exception as e:
334
+ supported_calls = "Error loading supported LLM calls"
335
+
336
+ # ANSI escape codes for colors and formatting
337
+ RED = "\033[91m"
338
+ BOLD = "\033[1m"
339
+ RESET = "\033[0m"
340
+ BIG = "\033[1;2m" # Makes text slightly larger in supported terminals
341
+
342
+ warning_msg = f"""{RED}{BOLD}{BIG}
343
+ ╔════════════════════════ COMPONENT DATA INCOMPLETE ════════════════════════╗
344
+ ║ ║
345
+ ║ Please ensure these requirements: ║
346
+ ║ ✗ trace_llm decorator must have a stand alone llm call ║
347
+ ║ ✗ trace_tool decorator must be a stand alone tool/function call ║
348
+ ║ ✗ trace_agent decorator can have multiple/nested llm/tool/agent calls ║
349
+ ║ ║
350
+ ║ Supported LLM calls: ║
351
+ ║ {supported_calls} ║
352
+ ║ ║
353
+ ╚══════════════════════════════════════════════════════════════════════════╝
354
+ {RESET}"""
355
+ # Use logger.warning for the message
356
+ logging.warning(warning_msg)
357
+ self._warning_shown = True
358
+ return
359
+
301
360
  if component_data["type"] == "llm":
302
361
  component = LLMComponent(**filtered_data)
303
362
  elif component_data["type"] == "agent":
@@ -309,7 +368,7 @@ class AgenticTracing(
309
368
 
310
369
  # Check if there's an active agent context
311
370
  current_agent_id = self.current_agent_id.get()
312
- if current_agent_id and component_data["type"] in ["llm", "tool"]:
371
+ if current_agent_id and component_data["type"] in ["llm", "tool", "custom"]:
313
372
  # Add this component as a child of the current agent
314
373
  current_children = self.agent_children.get()
315
374
  current_children.append(component_data)
@@ -319,67 +378,7 @@ class AgenticTracing(
319
378
  super().add_component(component)
320
379
 
321
380
  # Handle error case
322
- if is_error:
323
- # Get the parent component if it exists
324
- parent_id = component_data.get("parent_id")
325
- children = self.agent_children.get()
326
-
327
- # Set parent_id for all children
328
- for child in children:
329
- child["parent_id"] = parent_id
330
-
331
- agent_tracer_mixin = AgentTracerMixin()
332
- agent_tracer_mixin.component_network_calls = self.component_network_calls
333
- agent_tracer_mixin.component_user_interaction = (
334
- self.component_user_interaction
335
- )
336
-
337
- agent_tracer_mixin.span_attributes_dict[self.current_agent_name.get()] = (
338
- SpanAttributes(self.current_agent_name.get())
339
- )
340
-
341
- # Create parent component with error info
342
- parent_component = agent_tracer_mixin.create_agent_component(
343
- component_id=parent_id,
344
- hash_id=str(uuid.uuid4()),
345
- source_hash_id=None,
346
- type="agent",
347
- name=self.current_agent_name.get(),
348
- agent_type=self.agent_type.get(),
349
- version=self.version.get(),
350
- capabilities=self.capabilities.get(),
351
- start_time=self.start_time,
352
- end_time=datetime.now().astimezone().isoformat(),
353
- memory_used=0,
354
- input_data=self.input_data,
355
- output_data=None,
356
- children=children,
357
- parent_id=None, # Add parent ID if exists
358
- )
359
-
360
- filtered_data = {
361
- k: v
362
- for k, v in parent_component.items()
363
- if k
364
- in [
365
- "id",
366
- "hash_id",
367
- "source_hash_id",
368
- "type",
369
- "name",
370
- "start_time",
371
- "end_time",
372
- "parent_id",
373
- "info",
374
- "data",
375
- "network_calls",
376
- "interactions",
377
- "error",
378
- ]
379
- }
380
- parent_agent_component = AgentComponent(**filtered_data)
381
- # Add the parent component to trace and stop tracing
382
- super().add_component(parent_agent_component)
381
+ if is_error and not self.current_agent_id.get():
383
382
  self.stop()
384
383
 
385
384
  def __enter__(self):
@@ -41,7 +41,7 @@ class NetworkTracer:
41
41
 
42
42
  # Extract protocol from URL
43
43
  protocol = "https" if url.startswith("https") else "http"
44
-
44
+
45
45
  self.network_calls.append(
46
46
  {
47
47
  "url": url,
@@ -57,11 +57,11 @@ class NetworkTracer:
57
57
  "parent_id": None, # Will be set by the component
58
58
  "request": {
59
59
  "headers": request_headers,
60
- "body": request_body[:1000] if request_body else None, # Limit to 1000 chars
60
+ "body": request_body if request_body else None,
61
61
  },
62
62
  "response": {
63
63
  "headers": response_headers,
64
- "body": response_body[:1000] if response_body else None, # Limit to 1000 chars
64
+ "body": response_body if response_body else None,
65
65
  },
66
66
  "error": str(error) if error else None,
67
67
  }