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.
- ragaai_catalyst/evaluation.py +3 -0
- ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py +137 -101
- ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +1 -0
- ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py +4 -6
- ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +193 -155
- ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py +7 -60
- ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py +4 -6
- ragaai_catalyst/tracers/agentic_tracing/utils/file_name_tracker.py +5 -1
- ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py +33 -13
- ragaai_catalyst/tracers/distributed.py +10 -27
- ragaai_catalyst/tracers/langchain_callback.py +59 -6
- ragaai_catalyst/tracers/llamaindex_instrumentation.py +424 -0
- ragaai_catalyst/tracers/tracer.py +37 -20
- ragaai_catalyst/tracers/upload_traces.py +4 -1
- ragaai_catalyst/tracers/utils/convert_llama_instru_callback.py +69 -0
- ragaai_catalyst/tracers/utils/extraction_logic_llama_index.py +74 -0
- {ragaai_catalyst-2.1.5b25.dist-info → ragaai_catalyst-2.1.5b27.dist-info}/METADATA +11 -4
- {ragaai_catalyst-2.1.5b25.dist-info → ragaai_catalyst-2.1.5b27.dist-info}/RECORD +21 -18
- {ragaai_catalyst-2.1.5b25.dist-info → ragaai_catalyst-2.1.5b27.dist-info}/LICENSE +0 -0
- {ragaai_catalyst-2.1.5b25.dist-info → ragaai_catalyst-2.1.5b27.dist-info}/WHEEL +0 -0
- {ragaai_catalyst-2.1.5b25.dist-info → ragaai_catalyst-2.1.5b27.dist-info}/top_level.txt +0 -0
@@ -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
|
319
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
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
|
-
|
60
|
-
|
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
|
-
|
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
|
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 =
|
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
|