ragaai-catalyst 2.2.4.2b2__py3-none-any.whl → 2.2.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 (51) 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/upload/trace_uploader.py +3 -1
  5. ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py +5 -6
  6. ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py +13 -12
  7. ragaai_catalyst/tracers/agentic_tracing/utils/__init__.py +0 -2
  8. ragaai_catalyst/tracers/agentic_tracing/utils/create_dataset_schema.py +21 -10
  9. ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py +9 -1
  10. ragaai_catalyst/tracers/exporters/__init__.py +1 -2
  11. ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py +48 -35
  12. ragaai_catalyst/tracers/exporters/file_span_exporter.py +0 -1
  13. ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py +81 -28
  14. ragaai_catalyst/tracers/tracer.py +14 -191
  15. ragaai_catalyst/tracers/utils/trace_json_converter.py +7 -1
  16. {ragaai_catalyst-2.2.4.2b2.dist-info → ragaai_catalyst-2.2.5.dist-info}/METADATA +2 -1
  17. {ragaai_catalyst-2.2.4.2b2.dist-info → ragaai_catalyst-2.2.5.dist-info}/RECORD +20 -51
  18. ragaai_catalyst/experiment.py +0 -486
  19. ragaai_catalyst/tracers/agentic_tracing/tests/FinancialAnalysisSystem.ipynb +0 -536
  20. ragaai_catalyst/tracers/agentic_tracing/tests/GameActivityEventPlanner.ipynb +0 -134
  21. ragaai_catalyst/tracers/agentic_tracing/tests/TravelPlanner.ipynb +0 -563
  22. ragaai_catalyst/tracers/agentic_tracing/tests/__init__.py +0 -0
  23. ragaai_catalyst/tracers/agentic_tracing/tests/ai_travel_agent.py +0 -197
  24. ragaai_catalyst/tracers/agentic_tracing/tests/unique_decorator_test.py +0 -172
  25. ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py +0 -687
  26. ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +0 -1319
  27. ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py +0 -347
  28. ragaai_catalyst/tracers/agentic_tracing/tracers/langgraph_tracer.py +0 -0
  29. ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +0 -1182
  30. ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py +0 -288
  31. ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py +0 -557
  32. ragaai_catalyst/tracers/agentic_tracing/tracers/user_interaction_tracer.py +0 -129
  33. ragaai_catalyst/tracers/agentic_tracing/upload/upload_local_metric.py +0 -74
  34. ragaai_catalyst/tracers/agentic_tracing/utils/api_utils.py +0 -21
  35. ragaai_catalyst/tracers/agentic_tracing/utils/generic.py +0 -32
  36. ragaai_catalyst/tracers/agentic_tracing/utils/get_user_trace_metrics.py +0 -28
  37. ragaai_catalyst/tracers/agentic_tracing/utils/span_attributes.py +0 -133
  38. ragaai_catalyst/tracers/agentic_tracing/utils/supported_llm_provider.toml +0 -34
  39. ragaai_catalyst/tracers/exporters/raga_exporter.py +0 -467
  40. ragaai_catalyst/tracers/langchain_callback.py +0 -821
  41. ragaai_catalyst/tracers/llamaindex_callback.py +0 -361
  42. ragaai_catalyst/tracers/llamaindex_instrumentation.py +0 -424
  43. ragaai_catalyst/tracers/upload_traces.py +0 -170
  44. ragaai_catalyst/tracers/utils/convert_langchain_callbacks_output.py +0 -62
  45. ragaai_catalyst/tracers/utils/convert_llama_instru_callback.py +0 -69
  46. ragaai_catalyst/tracers/utils/extraction_logic_llama_index.py +0 -74
  47. ragaai_catalyst/tracers/utils/langchain_tracer_extraction_logic.py +0 -82
  48. ragaai_catalyst/tracers/utils/rag_trace_json_converter.py +0 -403
  49. {ragaai_catalyst-2.2.4.2b2.dist-info → ragaai_catalyst-2.2.5.dist-info}/WHEEL +0 -0
  50. {ragaai_catalyst-2.2.4.2b2.dist-info → ragaai_catalyst-2.2.5.dist-info}/licenses/LICENSE +0 -0
  51. {ragaai_catalyst-2.2.4.2b2.dist-info → ragaai_catalyst-2.2.5.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,3 @@
1
- from .experiment import Experiment
2
1
  from .ragaai_catalyst import RagaAICatalyst
3
2
  from .utils import response_checker
4
3
  from .dataset import Dataset
@@ -15,7 +14,6 @@ from .redteaming import RedTeaming
15
14
 
16
15
 
17
16
  __all__ = [
18
- "Experiment",
19
17
  "RagaAICatalyst",
20
18
  "Tracer",
21
19
  "PromptManager",
@@ -732,4 +732,62 @@ class Dataset:
732
732
  try:
733
733
  os.remove(tmp_csv_path)
734
734
  except Exception as e:
735
- logger.error(f"Error removing temporary CSV file: {e}")
735
+ logger.error(f"Error removing temporary CSV file: {e}")
736
+
737
+ def delete_dataset(self, dataset_name):
738
+ try:
739
+ def make_request():
740
+ headers = {
741
+ 'Content-Type': 'application/json',
742
+ "Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
743
+ "X-Project-Id": str(self.project_id),
744
+ }
745
+ json_data = {"size": 99999, "page": "0", "projectId": str(self.project_id), "search": ""}
746
+ try:
747
+ response = requests.post(
748
+ f"{Dataset.BASE_URL}/v2/llm/dataset",
749
+ headers=headers,
750
+ json=json_data,
751
+ timeout=Dataset.TIMEOUT,
752
+ )
753
+ response.raise_for_status()
754
+ return response
755
+ except requests.exceptions.RequestException as e:
756
+ logger.error(f"Failed to list datasets: {e}")
757
+ pass
758
+
759
+ response = make_request()
760
+
761
+ datasets = response.json()["data"]["content"]
762
+ dataset_list = [dataset["name"] for dataset in datasets]
763
+ if dataset_name not in dataset_list:
764
+ logger.error(f"Dataset '{dataset_name}' does not exists. Please enter a existing dataset name")
765
+ return
766
+
767
+ # Get dataset id
768
+ dataset_id = [dataset["id"] for dataset in datasets if dataset["name"] == dataset_name][0]
769
+
770
+ response = requests.delete(
771
+ f"{Dataset.BASE_URL}/v1/llm/dataset/{int(dataset_id)}",
772
+ headers={
773
+ 'Authorization': f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
774
+ "X-Project-Id": str(self.project_id)
775
+ },
776
+ timeout=Dataset.TIMEOUT
777
+ )
778
+ response.raise_for_status()
779
+ if response.json()["success"]:
780
+ print(f"Dataset '{dataset_name}' deleted successfully")
781
+ else:
782
+ logger.error("Request was not successful")
783
+ except requests.exceptions.HTTPError as http_err:
784
+ logger.error(f"HTTP error occurred: {http_err}")
785
+ except requests.exceptions.ConnectionError as conn_err:
786
+ logger.error(f"Connection error occurred: {conn_err}")
787
+ except requests.exceptions.Timeout as timeout_err:
788
+ logger.error(f"Timeout error occurred: {timeout_err}")
789
+ except requests.exceptions.RequestException as req_err:
790
+ logger.error(f"An error occurred: {req_err}")
791
+ except Exception as e:
792
+ logger.error(f"An unexpected error occurred: {e}")
793
+
@@ -7,15 +7,7 @@ import os
7
7
  import builtins
8
8
  from pathlib import Path
9
9
  import logging
10
-
11
- from .base import BaseTracer
12
- from .llm_tracer import LLMTracerMixin
13
- from .tool_tracer import ToolTracerMixin
14
- from .agent_tracer import AgentTracerMixin
15
- from .network_tracer import NetworkTracer
16
- from .user_interaction_tracer import UserInteractionTracer
17
- from .custom_tracer import CustomTracerMixin
18
- from ..utils.span_attributes import SpanAttributes
10
+ logger = logging.getLogger(__name__)
19
11
 
20
12
  from ..data.data_structure import (
21
13
  Trace,
@@ -42,20 +34,10 @@ from ..data.data_structure import (
42
34
  )
43
35
 
44
36
  from ....ragaai_catalyst import RagaAICatalyst
45
- from ragaai_catalyst.tracers.upload_traces import UploadTraces
46
37
 
47
38
 
48
- class AgenticTracing(
49
- BaseTracer, LLMTracerMixin, ToolTracerMixin, AgentTracerMixin, CustomTracerMixin
50
- ):
39
+ class AgenticTracing():
51
40
  def __init__(self, user_detail, auto_instrumentation=None, timeout=120):
52
- # Initialize all parent classes
53
- self.user_interaction_tracer = UserInteractionTracer()
54
- LLMTracerMixin.__init__(self)
55
- ToolTracerMixin.__init__(self)
56
- AgentTracerMixin.__init__(self)
57
- CustomTracerMixin.__init__(self)
58
-
59
41
  self.project_name = user_detail["project_name"]
60
42
  self.project_id = user_detail["project_id"]
61
43
  self.trace_user_detail = user_detail["trace_user_detail"]
@@ -65,14 +47,11 @@ class AgenticTracing(
65
47
  # Add warning flag
66
48
  self._warning_shown = False
67
49
 
68
- BaseTracer.__init__(self, user_detail)
69
-
70
50
  self.tools: Dict[str, Tool] = {}
71
51
  self.call_depth = contextvars.ContextVar("call_depth", default=0)
72
52
  self.current_component_id = contextvars.ContextVar(
73
53
  "current_component_id", default=None
74
54
  )
75
- self.network_tracer = NetworkTracer()
76
55
 
77
56
  # Handle auto_instrumentation
78
57
  if auto_instrumentation is None:
@@ -120,272 +99,13 @@ class AgenticTracing(
120
99
  self.component_user_interaction = {}
121
100
 
122
101
 
123
- def start_component(self, component_id: str):
124
- """Start tracking network calls for a component"""
125
- self.component_network_calls[component_id] = []
126
- self.network_tracer.network_calls = [] # Reset network calls
127
- self.current_component_id.set(component_id)
128
- self.user_interaction_tracer.component_id.set(component_id)
129
-
130
- def end_component(self, component_id: str):
131
- """End tracking network calls for a component"""
132
- self.component_network_calls[component_id] = (
133
- self.network_tracer.network_calls.copy()
134
- )
135
- self.network_tracer.network_calls = [] # Reset for next component
136
-
137
- # Store user interactions for the component
138
- for interaction in self.user_interaction_tracer.interactions:
139
- interaction_component_id = interaction.get("component_id")
140
- if interaction_component_id not in self.component_user_interaction:
141
- self.component_user_interaction[interaction_component_id] = []
142
- if interaction not in self.component_user_interaction[interaction_component_id]:
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)
158
-
159
102
  def register_post_processor(self, post_processor_func):
160
103
  """
161
104
  Pass through the post-processor registration to the BaseTracer
162
105
  """
163
- super().register_post_processor(post_processor_func)
164
-
165
- def start(self):
166
- """Start tracing"""
167
- self.is_active = True
168
-
169
- # Setup user interaction tracing
170
- self.user_interaction_tracer.project_id.set(self.project_id)
171
- self.user_interaction_tracer.trace_id.set(self.trace_id)
172
- self.user_interaction_tracer.tracer = self
173
- self.user_interaction_tracer.component_id.set(self.current_component_id.get())
174
-
175
- # Start base tracer (includes system info and resource monitoring)
176
- super().start()
177
-
178
- # Activate network tracing
179
- self.network_tracer.activate_patches()
180
-
181
- # take care of the auto instrumentation
182
- if self.auto_instrument_user_interaction:
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
- builtins.print = self.user_interaction_tracer.traced_print
188
- builtins.input = self.user_interaction_tracer.traced_input
189
-
190
- if self.auto_instrument_network:
191
- ToolTracerMixin.instrument_network_calls(self)
192
- LLMTracerMixin.instrument_network_calls(self)
193
- AgentTracerMixin.instrument_network_calls(self)
194
- CustomTracerMixin.instrument_network_calls(self)
195
-
196
- if self.auto_instrument_file_io:
197
- ToolTracerMixin.instrument_file_io_calls(self)
198
- LLMTracerMixin.instrument_file_io_calls(self)
199
- AgentTracerMixin.instrument_file_io_calls(self)
200
- CustomTracerMixin.instrument_file_io_calls(self)
201
- builtins.open = self.user_interaction_tracer.traced_open
202
-
203
- if self.auto_instrument_llm:
204
- self.instrument_llm_calls()
205
-
206
- if self.auto_instrument_tool:
207
- self.instrument_tool_calls()
208
-
209
- if self.auto_instrument_agent:
210
- self.instrument_agent_calls()
211
-
212
- if self.auto_instrument_custom:
213
- self.instrument_custom_calls()
214
-
215
- def stop(self):
216
- """Stop tracing and save results"""
217
- if self.is_active:
218
- # Restore original print and input functions
219
- builtins.print = self.user_interaction_tracer.original_print
220
- builtins.input = self.user_interaction_tracer.original_input
221
- builtins.open = self.user_interaction_tracer.original_open
222
-
223
- # Calculate final metrics before stopping
224
- self._calculate_final_metrics()
225
-
226
- # Deactivate network tracing
227
- self.network_tracer.deactivate_patches()
228
-
229
- # Clear visited metrics when stopping trace
230
- self.visited_metrics.clear()
231
-
232
- # Stop base tracer (includes saving to file)
233
- super().stop()
234
-
235
- # Cleanup
236
- self.unpatch_llm_calls()
237
- self.user_interaction_tracer.interactions = [] # Clear interactions list
238
- self.is_active = False
239
-
240
- def _calculate_final_metrics(self):
241
- """Calculate total cost and tokens from all components"""
242
- total_cost = 0.0
243
- total_tokens = 0
244
-
245
- processed_components = set()
246
-
247
- def process_component(component):
248
- nonlocal total_cost, total_tokens
249
- # Convert component to dict if it's an object
250
- comp_dict = (
251
- component.__dict__ if hasattr(component, "__dict__") else component
252
- )
253
-
254
- comp_id = comp_dict.get("id") or comp_dict.get("component_id")
255
- if comp_id in processed_components:
256
- return # Skip if already processed
257
- processed_components.add(comp_id)
258
-
259
- if comp_dict.get("type") == "llm":
260
- info = comp_dict.get("info", {})
261
- if isinstance(info, dict):
262
- # Extract cost
263
- cost_info = info.get("cost", {})
264
- if isinstance(cost_info, dict):
265
- total_cost += cost_info.get("total_cost", 0)
266
-
267
- # Extract tokens
268
- token_info = info.get("tokens", {})
269
- if isinstance(token_info, dict):
270
- total_tokens += token_info.get("total_tokens", 0)
271
- else:
272
- token_info = info.get("token_usage", {})
273
- if isinstance(token_info, dict):
274
- total_tokens += token_info.get("total_tokens", 0)
275
-
276
- # Process children if they exist
277
- data = comp_dict.get("data", {})
278
- if isinstance(data, dict):
279
- children = data.get("children", [])
280
- if children:
281
- for child in children:
282
- process_component(child)
283
-
284
- # Process all root components
285
- for component in self.components:
286
- process_component(component)
287
-
288
- # Update metadata in trace
289
- if hasattr(self, "trace"):
290
- if isinstance(self.trace.metadata, dict):
291
- self.trace.metadata["total_cost"] = total_cost
292
- self.trace.metadata["total_tokens"] = total_tokens
293
- else:
294
- self.trace.metadata.total_cost = total_cost
295
- self.trace.metadata.total_tokens = total_tokens
296
-
297
- def add_component(self, component_data: dict, is_error: bool = False):
298
- """Add a component to the trace data"""
299
- # Convert dict to appropriate Component type
300
- filtered_data = {
301
- k: v
302
- for k, v in component_data.items()
303
- if k
304
- in [
305
- "id",
306
- "hash_id",
307
- "source_hash_id",
308
- "type",
309
- "name",
310
- "start_time",
311
- "end_time",
312
- "parent_id",
313
- "info",
314
- "extra_info",
315
- "data",
316
- "metadata",
317
- "metrics",
318
- "feedback",
319
- "network_calls",
320
- "interactions",
321
- "error",
322
- ]
323
- }
324
-
325
- if component_data == None or component_data == {} or component_data.get("type", None) == None:
326
- # Only show warning if it hasn't been shown before
327
- if not self._warning_shown:
328
- import toml
329
- import os
330
- from pathlib import Path
331
-
332
- # Load supported LLM calls from TOML file
333
- current_dir = Path(__file__).parent
334
- toml_path = current_dir / "../utils/supported_llm_provider.toml"
335
- try:
336
- with open(toml_path, "r") as f:
337
- config = toml.load(f)
338
- supported_calls = ", ".join(config["supported_llm_calls"])
339
- except Exception as e:
340
- supported_calls = "Error loading supported LLM calls"
341
-
342
- # ANSI escape codes for colors and formatting
343
- RED = "\033[91m"
344
- BOLD = "\033[1m"
345
- RESET = "\033[0m"
346
- BIG = "\033[1;2m" # Makes text slightly larger in supported terminals
347
-
348
- warning_msg = f"""{RED}{BOLD}{BIG}
349
- ╔════════════════════════ COMPONENT DATA INCOMPLETE ════════════════════════╗
350
- ║ ║
351
- ║ Please ensure these requirements: ║
352
- ║ ✗ trace_llm decorator must have a stand alone llm call ║
353
- ║ ✗ trace_tool decorator must be a stand alone tool/function call ║
354
- ║ ✗ trace_agent decorator can have multiple/nested llm/tool/agent calls ║
355
- ║ ║
356
- ║ Supported LLM calls: ║
357
- ║ {supported_calls} ║
358
- ║ ║
359
- ╚══════════════════════════════════════════════════════════════════════════╝
360
- {RESET}"""
361
- # Use logger.warning for the message
362
- logging.warning(warning_msg)
363
- self._warning_shown = True
364
- return
365
-
366
- if component_data["type"] == "llm":
367
- component = LLMComponent(**filtered_data)
368
- elif component_data["type"] == "agent":
369
- component = AgentComponent(**filtered_data)
370
- elif component_data["type"] == "tool":
371
- component = ToolComponent(**filtered_data)
372
- else:
373
- component = Component(**component_data)
374
-
375
- # Check if there's an active agent context
376
- current_agent_id = self.current_agent_id.get()
377
- if current_agent_id and component_data["type"] in ["llm", "tool", "custom"]:
378
- # Add this component as a child of the current agent
379
- current_children = self.agent_children.get()
380
- current_children.append(component_data)
381
- self.agent_children.set(current_children)
382
- else:
383
- # Add component to the main trace
384
- super().add_component(component)
385
-
386
- # Handle error case
387
- if is_error and not self.current_agent_id.get():
388
- self.stop()
106
+ if not callable(post_processor_func):
107
+ logger.error("post_processor_func must be a callable")
108
+ self.post_processor = post_processor_func
389
109
 
390
110
  def __enter__(self):
391
111
  """Context manager entry"""
@@ -240,6 +240,7 @@ def process_upload(task_id: str, filepath: str, hash_id: str, zip_path: str,
240
240
  user_details=user_details,
241
241
  timeout=timeout
242
242
  )
243
+
243
244
  if response is None:
244
245
  logger.error(f"Dataset schema creation failed for {dataset_name} - received None response")
245
246
  elif hasattr(response, 'status_code') and response.status_code in [200, 201]:
@@ -480,7 +481,8 @@ def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, da
480
481
 
481
482
  return task_id
482
483
  except RuntimeError as e:
483
- if "cannot schedule new futures after shutdown" in str(e):
484
+ if any(msg in str(e) for msg in
485
+ ("cannot schedule new futures after shutdown", "cannot schedule new futures after interpreter shutdown")):
484
486
  logger.warning(f"Executor already shut down, falling back to synchronous processing: {e}")
485
487
  return do_sync_processing()
486
488
  else:
@@ -9,8 +9,6 @@ from requests.exceptions import ConnectionError, Timeout, RequestException
9
9
  from http.client import RemoteDisconnected
10
10
  from .session_manager import session_manager
11
11
 
12
- import requests
13
-
14
12
  logger = logging.getLogger(__name__)
15
13
 
16
14
  from ragaai_catalyst.ragaai_catalyst import RagaAICatalyst
@@ -65,7 +63,7 @@ class UploadAgenticTraces:
65
63
  presignedurl = self.update_presigned_url(presignedURLs, self.base_url)
66
64
  return presignedurl
67
65
  elif response.status_code == 401:
68
- logger.warning("Received 401 error. Attempting to refresh token.")
66
+ logger.warning("Received 401 error while getting presign url. Attempting to refresh token.")
69
67
  token = RagaAICatalyst.get_token(force_refresh=True)
70
68
  headers = {
71
69
  "Content-Type": "application/json",
@@ -90,7 +88,8 @@ class UploadAgenticTraces:
90
88
  return None
91
89
  else:
92
90
  # If POST fails, try GET
93
- logger.warning(f"POST request failed for presign url with status {response.status_code}. Falling back to GET request.")
91
+ logger.warning(
92
+ f"POST request failed for getting presign url with status{response.status_code}.Falling back to GET request.")
94
93
  response = session_manager.make_request_with_retry(
95
94
  "GET", endpoint, headers=headers, data=payload, timeout=self.timeout
96
95
  )
@@ -105,7 +104,7 @@ class UploadAgenticTraces:
105
104
  )
106
105
  return presignedurl
107
106
  elif response.status_code == 401:
108
- logger.warning("Received 401 error. Attempting to refresh token.")
107
+ logger.warning("Received 401 error while getting presign url. Attempting to refresh token.")
109
108
  token = RagaAICatalyst.get_token(force_refresh=True)
110
109
  headers = {
111
110
  "Content-Type": "application/json",
@@ -131,7 +130,7 @@ class UploadAgenticTraces:
131
130
  return presignedurl
132
131
  else:
133
132
  logger.error(
134
- f"Error while getting presigned url: {response.json()['message']}"
133
+ f"Error while getting presigned url after token refresh: {response.json()['message']}"
135
134
  )
136
135
  return None
137
136
  else:
@@ -8,8 +8,6 @@ from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
8
8
  from requests.exceptions import ConnectionError, Timeout, RequestException
9
9
  from http.client import RemoteDisconnected
10
10
 
11
- import requests
12
-
13
11
  from ragaai_catalyst.ragaai_catalyst import RagaAICatalyst
14
12
  from .session_manager import session_manager
15
13
 
@@ -106,7 +104,7 @@ def _fetch_dataset_code_hashes(project_name, dataset_name, base_url=None, timeou
106
104
  session_manager.handle_request_exceptions(e, "fetching dataset code hashes")
107
105
  return None
108
106
  except RequestException as e:
109
- logger.error(f"Failed to list datasets: {e}")
107
+ logger.error(f"Failed to fetch dataset code hashes: {e}")
110
108
  return None
111
109
 
112
110
 
@@ -142,7 +140,7 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
142
140
  start_time = time.time()
143
141
  # Changed to POST from GET
144
142
  endpoint = f"{url_base}/v1/llm/presigned-url"
145
- response = requests.request(
143
+ response = session_manager.make_request_with_retry(
146
144
  "POST", endpoint, headers=headers, data=payload, timeout=timeout
147
145
  )
148
146
  elapsed_ms = (time.time() - start_time) * 1000
@@ -150,20 +148,20 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
150
148
  f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
151
149
  )
152
150
 
153
- if response.status_code == 200:
151
+ if response.status_code in [200, 201]:
154
152
  presigned_url = response.json()["data"]["presignedUrls"][0]
155
153
  presigned_url = update_presigned_url(presigned_url, url_base)
156
154
  return presigned_url
157
155
  else:
158
156
  # If POST fails, try GET
159
- response = requests.request(
157
+ response = session_manager.make_request_with_retry(
160
158
  "POST", endpoint, headers=headers, data=payload, timeout=timeout
161
159
  )
162
160
  elapsed_ms = (time.time() - start_time) * 1000
163
161
  logger.debug(
164
162
  f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
165
163
  )
166
- if response.status_code == 200:
164
+ if response.status_code in [200, 201]:
167
165
  presigned_url = response.json()["data"]["presignedUrls"][0]
168
166
  presigned_url = update_presigned_url(presigned_url, url_base)
169
167
  return presigned_url
@@ -175,7 +173,7 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
175
173
  "Content-Type": "application/json",
176
174
  "X-Project-Name": project_name,
177
175
  }
178
- response = requests.request(
176
+ response = session_manager.make_request_with_retry(
179
177
  "POST", endpoint, headers=headers, data=payload, timeout=timeout
180
178
  )
181
179
  elapsed_ms = (time.time() - start_time) * 1000
@@ -188,15 +186,18 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
188
186
  return presigned_url
189
187
  else:
190
188
  logger.error(
191
- f"Failed to fetch code hashes: {response.json()['message']}"
189
+ f"Failed to fetch presigned URL for code upload after 401: {response.json()['message']}"
192
190
  )
193
191
  else:
194
192
  logger.error(
195
- f"Failed to fetch code hashes: {response.json()['message']}"
193
+ f"Failed to fetch presigned URL for code upload: {response.json()['message']}"
196
194
  )
197
195
  return None
198
- except requests.exceptions.RequestException as e:
199
- logger.error(f"Failed to list datasets: {e}")
196
+ except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
197
+ session_manager.handle_request_exceptions(e, "fetching presigned URL for code upload")
198
+ return None
199
+ except RequestException as e:
200
+ logger.error(f"Failed to fetch presigned URL for code upload: {e}")
200
201
  return None
201
202
 
202
203
 
@@ -1,3 +1 @@
1
- from .generic import get_db_path
2
1
 
3
- __all__ = ["get_db_path"]
@@ -1,8 +1,9 @@
1
1
  import os
2
2
  import json
3
- import re
3
+ import requests
4
4
  import logging
5
5
  import time
6
+ from typing import Optional
6
7
  from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
7
8
  from requests.exceptions import ConnectionError, Timeout, RequestException
8
9
  from http.client import RemoteDisconnected
@@ -10,28 +11,38 @@ from http.client import RemoteDisconnected
10
11
  from ragaai_catalyst import RagaAICatalyst
11
12
  from ragaai_catalyst.tracers.agentic_tracing.upload.session_manager import session_manager
12
13
 
14
+ IGNORED_KEYS = {"log_source", "recorded_on"}
13
15
  logger = logging.getLogger(__name__)
14
16
 
15
- def create_dataset_schema_with_trace(project_name, dataset_name, base_url=None, user_details=None, timeout=120):
16
- SCHEMA_MAPPING = {}
17
- metadata = user_details.get("trace_user_detail").get("metadata")
18
- if metadata and isinstance(metadata, dict):
17
+ def create_dataset_schema_with_trace(
18
+ project_name: str,
19
+ dataset_name: str,
20
+ base_url: Optional[str] = None,
21
+ user_details: Optional[dict] = None,
22
+ timeout: int = 120) -> requests.Response:
23
+ schema_mapping = {}
24
+
25
+ metadata = (
26
+ user_details.get("trace_user_detail", {}).get("metadata", {})
27
+ if user_details else {}
28
+ )
29
+ if isinstance(metadata, dict):
19
30
  for key, value in metadata.items():
20
- if key in ["log_source", "recorded_on"]:
31
+ if key in IGNORED_KEYS:
21
32
  continue
22
- SCHEMA_MAPPING[key] = {"columnType": "metadata"}
33
+ schema_mapping[key] = {"columnType": "metadata"}
23
34
 
24
35
  headers = {
25
36
  "Content-Type": "application/json",
26
37
  "Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
27
38
  "X-Project-Name": project_name,
28
39
  }
29
- logger.info(f"Header for dataset logs api {headers}")
30
- if SCHEMA_MAPPING:
40
+
41
+ if schema_mapping:
31
42
  payload = json.dumps({
32
43
  "datasetName": dataset_name,
33
44
  "traceFolderUrl": None,
34
- "schemaMapping": SCHEMA_MAPPING
45
+ "schemaMapping": schema_mapping
35
46
  })
36
47
  else:
37
48
  payload = json.dumps({
@@ -7,6 +7,8 @@ import re
7
7
  import ast
8
8
  import importlib.util
9
9
  import json
10
+ from typing import List, Optional, Tuple
11
+
10
12
  import ipynbname
11
13
  from copy import deepcopy
12
14
 
@@ -460,8 +462,14 @@ class TraceDependencyTracker:
460
462
  logger.debug(f"Zip file created successfully at: {zip_filename}")
461
463
  return hash_id, zip_filename
462
464
 
463
- def zip_list_of_unique_files(filepaths, output_dir=None):
465
+ def zip_list_of_unique_files(
466
+ filepaths: List[str],
467
+ output_dir: Optional[str] = None
468
+ ) -> Tuple[str, str]:
464
469
  """Create a zip file containing all unique files and their dependencies."""
470
+ if not filepaths:
471
+ logger.warning("The filepaths list is empty. Proceeding with an empty ZIP archive.")
472
+ filepaths = []
465
473
  if output_dir is None:
466
474
  # Set default output directory based on environment
467
475
  if JupyterNotebookHandler.is_running_in_colab():
@@ -1,7 +1,6 @@
1
1
  from .file_span_exporter import FileSpanExporter
2
- from .raga_exporter import RagaExporter
3
2
  from .ragaai_trace_exporter import RAGATraceExporter
4
3
  from .dynamic_trace_exporter import DynamicTraceExporter
5
4
 
6
5
 
7
- __all__ = ["FileSpanExporter", "RagaExporter", "RAGATraceExporter", "DynamicTraceExporter"]
6
+ __all__ = ["FileSpanExporter", "RAGATraceExporter", "DynamicTraceExporter"]