ragaai-catalyst 2.1.5b25__py3-none-any.whl → 2.1.5b27__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.
@@ -8,6 +8,7 @@ import ast
8
8
  import importlib.util
9
9
  import json
10
10
  import ipynbname
11
+ from copy import deepcopy
11
12
 
12
13
  from pathlib import Path
13
14
  from IPython import get_ipython
@@ -211,7 +212,6 @@ def comment_magic_commands(script_content: str) -> str:
211
212
  class TraceDependencyTracker:
212
213
  def __init__(self, output_dir=None):
213
214
  self.tracked_files = set()
214
- self.python_imports = set()
215
215
  self.notebook_path = None
216
216
  self.colab_content = None
217
217
 
@@ -302,7 +302,7 @@ class TraceDependencyTracker:
302
302
  except (UnicodeDecodeError, IOError):
303
303
  pass
304
304
 
305
- def analyze_python_imports(self, filepath):
305
+ def analyze_python_imports(self, filepath, ignored_locations):
306
306
  try:
307
307
  with open(filepath, 'r', encoding='utf-8') as file:
308
308
  tree = ast.parse(file.read(), filename=filepath)
@@ -315,8 +315,10 @@ class TraceDependencyTracker:
315
315
  module_name = name.name.split('.')[0]
316
316
  try:
317
317
  spec = importlib.util.find_spec(module_name)
318
- if spec and spec.origin and not spec.origin.startswith(os.path.dirname(importlib.__file__)):
319
- self.python_imports.add(spec.origin)
318
+ if spec and spec.origin:
319
+ if not (any(spec.origin.startswith(location) for location in ignored_locations) or (spec.origin in ['built-in', 'frozen'])):
320
+ self.tracked_files.add(spec.origin)
321
+ self.analyze_python_imports(spec.origin, ignored_locations)
320
322
  except (ImportError, AttributeError):
321
323
  pass
322
324
  except Exception as e:
@@ -332,6 +334,13 @@ class TraceDependencyTracker:
332
334
  except ImportError:
333
335
  logger.error("Error getting Catalyst location")
334
336
  return 'ragaai_catalyst'
337
+
338
+ def should_ignore_path(self, path, main_filepaths):
339
+ if any(os.path.abspath(path) in os.path.abspath(main_filepath) for main_filepath in main_filepaths):
340
+ return False
341
+ if path in ['', os.path.abspath('')]:
342
+ return False
343
+ return True
335
344
 
336
345
  def create_zip(self, filepaths):
337
346
  self.track_jupyter_notebook()
@@ -349,21 +358,32 @@ class TraceDependencyTracker:
349
358
  # Get current cell content
350
359
  self.check_environment_and_save()
351
360
 
361
+ env_location = self.get_env_location()
362
+ catalyst_location = self.get_catalyst_location()
363
+
352
364
  # Process all files (existing code)
365
+ ignored_locations = [env_location, catalyst_location] + [path for path in sys.path if self.should_ignore_path(path, filepaths)]
353
366
  for filepath in filepaths:
354
367
  abs_path = os.path.abspath(filepath)
355
368
  self.track_file_access(abs_path)
356
369
  try:
357
- with open(abs_path, 'r', encoding='utf-8') as file:
370
+ if filepath.endswith('.py'):
371
+ self.analyze_python_imports(abs_path, ignored_locations)
372
+ except Exception as e:
373
+ pass
374
+
375
+ curr_tracked_files = deepcopy(self.tracked_files)
376
+ for filepath in curr_tracked_files:
377
+ try:
378
+ with open(filepath, 'r', encoding='utf-8') as file:
358
379
  content = file.read()
359
380
  # Comment out magic commands before processing
360
381
  content = comment_magic_commands(content)
361
- self.find_config_files(content, abs_path)
362
- if filepath.endswith('.py'):
363
- self.analyze_python_imports(abs_path)
382
+ self.find_config_files(content, filepath)
364
383
  except Exception as e:
365
384
  pass
366
385
 
386
+
367
387
  notebook_content_str = None
368
388
  if self.notebook_path and os.path.exists(self.notebook_path):
369
389
  try:
@@ -386,11 +406,7 @@ class TraceDependencyTracker:
386
406
  except Exception as e:
387
407
  pass
388
408
 
389
- env_location = self.get_env_location()
390
- catalyst_location = self.get_catalyst_location()
391
-
392
409
  # Calculate hash and create zip
393
- self.tracked_files.update(self.python_imports)
394
410
  hash_contents = []
395
411
 
396
412
  for filepath in sorted(self.tracked_files):
@@ -433,7 +449,11 @@ class TraceDependencyTracker:
433
449
  continue
434
450
  try:
435
451
  relative_path = os.path.relpath(filepath, base_path)
436
- zipf.write(filepath, relative_path)
452
+ if relative_path in ['', '.']:
453
+ zipf.write(filepath, os.path.basename(filepath))
454
+ else:
455
+ zipf.write(filepath, relative_path)
456
+
437
457
  logger.debug(f"Added python script to zip: {relative_path}")
438
458
  except Exception as e:
439
459
  pass
@@ -37,7 +37,7 @@ def init_tracing(
37
37
  secret_key: str = None,
38
38
  base_url: str = None,
39
39
  tracer: Tracer = None,
40
- catalyst: RagaAICatalyst = None,
40
+ catalyst: RagaAICatalyst = None,
41
41
  **kwargs
42
42
  ) -> None:
43
43
  """Initialize distributed tracing.
@@ -50,37 +50,20 @@ def init_tracing(
50
50
  base_url: RagaAI Catalyst API base URL
51
51
  tracer: Existing Tracer instance
52
52
  catalyst: Existing RagaAICatalyst instance
53
- **kwargs: Additional tracer configuration
53
+ **kwargs: Additional tracer parameters
54
54
  """
55
55
  global _global_tracer, _global_catalyst
56
56
 
57
57
  with _tracer_lock:
58
58
  if tracer and catalyst:
59
- _global_tracer = tracer
60
- _global_catalyst = catalyst
59
+ if isinstance(tracer, Tracer) and isinstance(catalyst, RagaAICatalyst):
60
+ _global_tracer = tracer
61
+ _global_catalyst = catalyst
62
+ else:
63
+ raise ValueError("Both Tracer and Catalyst objects must be instances of Tracer and RagaAICatalyst, respectively.")
61
64
  else:
62
- # Use env vars as fallback
63
- access_key = access_key or os.getenv("RAGAAI_CATALYST_ACCESS_KEY")
64
- secret_key = secret_key or os.getenv("RAGAAI_CATALYST_SECRET_KEY")
65
- base_url = base_url or os.getenv("RAGAAI_CATALYST_BASE_URL")
65
+ raise ValueError("Both Tracer and Catalyst objects must be provided.")
66
66
 
67
- if not all([access_key, secret_key]):
68
- raise ValueError(
69
- "Missing required credentials. Either provide access_key and secret_key "
70
- "or set RAGAAI_CATALYST_ACCESS_KEY and RAGAAI_CATALYST_SECRET_KEY environment variables."
71
- )
72
-
73
- _global_catalyst = RagaAICatalyst(
74
- access_key=access_key,
75
- secret_key=secret_key,
76
- base_url=base_url
77
- )
78
-
79
- _global_tracer = Tracer(
80
- project_name=project_name,
81
- dataset_name=dataset_name,
82
- **kwargs
83
- )
84
67
 
85
68
  def trace_agent(name: str = None, agent_type: str = "generic", version: str = "1.0.0", **kwargs):
86
69
  """Decorator for tracing agent functions."""
@@ -162,7 +145,7 @@ def trace_llm(name: str = None, model: str = None, **kwargs):
162
145
 
163
146
  try:
164
147
  # Just execute the function within the current span
165
- result = await tracer.file_tracker.trace_wrapper(func)(*args, **kwargs)
148
+ result = await func(*args, **kwargs)
166
149
  return result
167
150
  finally:
168
151
  # Reset using the stored token
@@ -180,7 +163,7 @@ def trace_llm(name: str = None, model: str = None, **kwargs):
180
163
 
181
164
  try:
182
165
  # Just execute the function within the current span
183
- result = tracer.file_tracker.trace_wrapper(func)(*args, **kwargs)
166
+ result = func(*args, **kwargs)
184
167
  return result
185
168
  finally:
186
169
  # Reset using the stored token
@@ -159,7 +159,7 @@ class LangchainTracer(BaseCallbackHandler):
159
159
  else:
160
160
  asyncio.run(self._async_save_trace(force))
161
161
 
162
- def _create_safe_wrapper(self, original_func, component_name):
162
+ def _create_safe_wrapper(self, original_func, component_name, method_name):
163
163
  """Create a safely wrapped version of an original function with enhanced error handling"""
164
164
 
165
165
  @wraps(original_func)
@@ -209,7 +209,59 @@ class LangchainTracer(BaseCallbackHandler):
209
209
 
210
210
  # Fallback to calling the original function without modifications
211
211
  return original_func(*args, **kwargs)
212
+
213
+ @wraps(original_func)
214
+ def wrapped_invoke(*args, **kwargs):
215
+ if not self._active:
216
+ return original_func(*args, **kwargs)
217
+
218
+ try:
219
+ # Deep copy kwargs to avoid modifying the original
220
+ kwargs_copy = kwargs.copy() if kwargs is not None else {}
221
+
222
+ # Handle different calling conventions
223
+ if 'config' not in kwargs_copy:
224
+ kwargs_copy['config'] = {'callbacks': [self]}
225
+ elif 'callbacks' not in kwargs_copy['config']:
226
+ kwargs_copy['config']['callbacks'] = [self]
227
+ elif self not in kwargs_copy['config']['callbacks']:
228
+ kwargs_copy['config']['callbacks'].append(self)
229
+
230
+ # Store model name if available
231
+ if component_name in ["OpenAI", "ChatOpenAI_LangchainOpenAI", "ChatOpenAI_ChatModels",
232
+ "ChatVertexAI", "VertexAI", "ChatGoogleGenerativeAI", "ChatAnthropic",
233
+ "ChatLiteLLM", "ChatBedrock", "AzureChatOpenAI", "ChatAnthropicVertex"]:
234
+ instance = args[0] if args else None
235
+ model_name = kwargs.get('model_name') or kwargs.get('model') or kwargs.get('model_id')
212
236
 
237
+ if instance and model_name:
238
+ self.model_names[id(instance)] = model_name
239
+
240
+ # Try different method signatures
241
+ try:
242
+ # First, try calling with modified kwargs
243
+ return original_func(*args, **kwargs_copy)
244
+ except TypeError:
245
+ # If that fails, try without kwargs
246
+ try:
247
+ return original_func(*args)
248
+ except Exception as e:
249
+ # If all else fails, use original call
250
+ logger.error(f"Failed to invoke {component_name} with modified callbacks: {e}")
251
+ return original_func(*args, **kwargs)
252
+
253
+ except Exception as e:
254
+ # Log any errors that occur during the function call
255
+ logger.error(f"Error in {component_name} wrapper: {e}")
256
+
257
+ # Record the error using the tracer's error handling method
258
+ self.on_error(e, context=f"wrapper_{component_name}")
259
+
260
+ # Fallback to calling the original function without modifications
261
+ return original_func(*args, **kwargs)
262
+
263
+ if method_name == 'invoke':
264
+ return wrapped_invoke
213
265
  return wrapped
214
266
 
215
267
 
@@ -287,6 +339,7 @@ class LangchainTracer(BaseCallbackHandler):
287
339
  from langchain.chains import create_retrieval_chain, RetrievalQA
288
340
  components_to_patch["RetrievalQA"] = (RetrievalQA, "from_chain_type")
289
341
  components_to_patch["create_retrieval_chain"] = (create_retrieval_chain, None)
342
+ components_to_patch['RetrievalQA.invoke'] = (RetrievalQA, 'invoke')
290
343
  except ImportError:
291
344
  logger.debug("Langchain chains not available for patching")
292
345
 
@@ -295,20 +348,20 @@ class LangchainTracer(BaseCallbackHandler):
295
348
  if method_name == "__init__":
296
349
  original = component.__init__
297
350
  self._original_inits[name] = original
298
- component.__init__ = self._create_safe_wrapper(original, name)
351
+ component.__init__ = self._create_safe_wrapper(original, name, method_name)
299
352
  elif method_name:
300
353
  original = getattr(component, method_name)
301
354
  self._original_methods[name] = original
302
355
  if isinstance(original, classmethod):
303
356
  wrapped = classmethod(
304
- self._create_safe_wrapper(original.__func__, name)
357
+ self._create_safe_wrapper(original.__func__, name, method_name)
305
358
  )
306
359
  else:
307
- wrapped = self._create_safe_wrapper(original, name)
360
+ wrapped = self._create_safe_wrapper(original, name, method_name)
308
361
  setattr(component, method_name, wrapped)
309
362
  else:
310
363
  self._original_methods[name] = component
311
- globals()[name] = self._create_safe_wrapper(component, name)
364
+ globals()[name] = self._create_safe_wrapper(component, name, method_name)
312
365
  except Exception as e:
313
366
  logger.error(f"Error patching {name}: {e}")
314
367
  self.on_error(e, context=f"patch_{name}")
@@ -354,7 +407,7 @@ class LangchainTracer(BaseCallbackHandler):
354
407
  elif name == "ChatOpenAI_ChatModels":
355
408
  from langchain.chat_models import ChatOpenAI as ChatOpenAI_ChatModels
356
409
  imported_components[name] = ChatOpenAI_ChatModels
357
- elif name in ["RetrievalQA", "create_retrieval_chain"]:
410
+ elif name in ["RetrievalQA", "create_retrieval_chain", 'RetrievalQA.invoke']:
358
411
  from langchain.chains import create_retrieval_chain, RetrievalQA
359
412
  imported_components["RetrievalQA"] = RetrievalQA
360
413
  imported_components["create_retrieval_chain"] = create_retrieval_chain