ragaai-catalyst 2.1.5b20__py3-none-any.whl → 2.1.5b22__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 (22) hide show
  1. ragaai_catalyst/dataset.py +54 -1
  2. ragaai_catalyst/synthetic_data_generation.py +39 -6
  3. ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py +28 -18
  4. ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +3 -1
  5. ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py +17 -7
  6. ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +106 -16
  7. ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py +1 -2
  8. ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py +17 -6
  9. ragaai_catalyst/tracers/agentic_tracing/upload/upload_trace_metric.py +6 -5
  10. ragaai_catalyst/tracers/agentic_tracing/utils/file_name_tracker.py +21 -2
  11. ragaai_catalyst/tracers/agentic_tracing/utils/llm_utils.py +30 -11
  12. ragaai_catalyst/tracers/agentic_tracing/utils/model_costs.json +1204 -484
  13. ragaai_catalyst/tracers/agentic_tracing/utils/span_attributes.py +35 -0
  14. ragaai_catalyst/tracers/agentic_tracing/utils/trace_utils.py +0 -32
  15. ragaai_catalyst/tracers/distributed.py +7 -3
  16. ragaai_catalyst/tracers/tracer.py +25 -8
  17. ragaai_catalyst/tracers/utils/langchain_tracer_extraction_logic.py +5 -4
  18. {ragaai_catalyst-2.1.5b20.dist-info → ragaai_catalyst-2.1.5b22.dist-info}/METADATA +2 -2
  19. {ragaai_catalyst-2.1.5b20.dist-info → ragaai_catalyst-2.1.5b22.dist-info}/RECORD +22 -22
  20. {ragaai_catalyst-2.1.5b20.dist-info → ragaai_catalyst-2.1.5b22.dist-info}/LICENSE +0 -0
  21. {ragaai_catalyst-2.1.5b20.dist-info → ragaai_catalyst-2.1.5b22.dist-info}/WHEEL +0 -0
  22. {ragaai_catalyst-2.1.5b20.dist-info → ragaai_catalyst-2.1.5b22.dist-info}/top_level.txt +0 -0
@@ -258,7 +258,10 @@ class ToolTracerMixin:
258
258
  @functools.wraps(func)
259
259
  async def async_wrapper(*args, **kwargs):
260
260
  async_wrapper.metadata = metadata
261
- self.gt = kwargs.get("gt", None) if kwargs else None
261
+ gt = kwargs.get("gt") if kwargs else None
262
+ if gt is not None:
263
+ span = self.span(name)
264
+ span.add_gt(gt)
262
265
  return await self._trace_tool_execution(
263
266
  func, name, tool_type, version, *args, **kwargs
264
267
  )
@@ -267,7 +270,10 @@ class ToolTracerMixin:
267
270
  @functools.wraps(func)
268
271
  def sync_wrapper(*args, **kwargs):
269
272
  sync_wrapper.metadata = metadata
270
- self.gt = kwargs.get("gt", None) if kwargs else None
273
+ gt = kwargs.get("gt") if kwargs else None
274
+ if gt is not None:
275
+ span = self.span(name)
276
+ span.add_gt(gt)
271
277
  return self._trace_sync_tool_execution(
272
278
  func, name, tool_type, version, *args, **kwargs
273
279
  )
@@ -302,7 +308,7 @@ class ToolTracerMixin:
302
308
 
303
309
  try:
304
310
  # Execute the tool
305
- result = func(*args, **kwargs)
311
+ result = self.file_tracker.trace_wrapper(func)(*args, **kwargs)
306
312
 
307
313
  # Calculate resource usage
308
314
  end_memory = psutil.Process().memory_info().rss
@@ -384,7 +390,7 @@ class ToolTracerMixin:
384
390
  self.start_component(component_id)
385
391
  try:
386
392
  # Execute the tool
387
- result = await func(*args, **kwargs)
393
+ result = await self.file_tracker.trace_wrapper(func)(*args, **kwargs)
388
394
 
389
395
  # Calculate resource usage
390
396
  end_memory = psutil.Process().memory_info().rss
@@ -504,8 +510,13 @@ class ToolTracerMixin:
504
510
  "interactions": interactions,
505
511
  }
506
512
 
507
- if self.gt:
508
- component["data"]["gt"] = self.gt
513
+ if name in self.span_attributes_dict:
514
+ span_gt = self.span_attributes_dict[name].gt
515
+ if span_gt is not None:
516
+ component["data"]["gt"] = span_gt
517
+ span_context = self.span_attributes_dict[name].context
518
+ if span_context:
519
+ component["data"]["context"] = span_context
509
520
 
510
521
  # Reset the SpanAttributes context variable
511
522
  self.span_attributes_dict[kwargs["name"]] = SpanAttributes(kwargs["name"])
@@ -8,6 +8,7 @@ def upload_trace_metric(json_file_path, dataset_name, project_name):
8
8
  try:
9
9
  with open(json_file_path, "r") as f:
10
10
  traces = json.load(f)
11
+
11
12
  metrics = get_trace_metrics_from_trace(traces)
12
13
  metrics = _change_metrics_format_for_payload(metrics)
13
14
 
@@ -21,7 +22,6 @@ def upload_trace_metric(json_file_path, dataset_name, project_name):
21
22
  metricConfig = next((user_metric["metricConfig"] for user_metric in user_trace_metrics if user_metric["displayName"] == metric["displayName"]), None)
22
23
  if not metricConfig or metricConfig.get("Metric Source", {}).get("value") != "user":
23
24
  raise ValueError(f"Metrics {metric['displayName']} already exist in dataset {dataset_name} of project {project_name}.")
24
-
25
25
  headers = {
26
26
  "Content-Type": "application/json",
27
27
  "Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
@@ -68,13 +68,14 @@ def get_trace_metrics_from_trace(traces):
68
68
  # get span level metrics
69
69
  for span in traces["data"][0]["spans"]:
70
70
  if span["type"] == "agent":
71
+ # Add children metrics of agent
71
72
  children_metric = _get_children_metrics_of_agent(span["data"]["children"])
72
73
  if children_metric:
73
74
  metrics.extend(children_metric)
74
- else:
75
- metric = span.get("metrics", [])
76
- if metric:
77
- metrics.extend(metric)
75
+
76
+ metric = span.get("metrics", [])
77
+ if metric:
78
+ metrics.extend(metric)
78
79
  return metrics
79
80
 
80
81
  def _change_metrics_format_for_payload(metrics):
@@ -8,13 +8,32 @@ class TrackName:
8
8
  def trace_decorator(self, func):
9
9
  @wraps(func)
10
10
  def wrapper(*args, **kwargs):
11
- file_name = self._get_file_name()
11
+ file_name = self._get_decorated_file_name()
12
12
  self.files.add(file_name)
13
13
 
14
14
  return func(*args, **kwargs)
15
15
  return wrapper
16
+
17
+ def trace_wrapper(self, func):
18
+ @wraps(func)
19
+ def wrapper(*args, **kwargs):
20
+ file_name = self._get_wrapped_file_name()
21
+ self.files.add(file_name)
22
+ return func(*args, **kwargs)
23
+ return wrapper
24
+
25
+ def _get_wrapped_file_name(self):
26
+ try:
27
+ from IPython import get_ipython
28
+ if 'IPKernelApp' in get_ipython().config:
29
+ return self._get_notebook_name()
30
+ except Exception:
31
+ pass
32
+
33
+ frame = inspect.stack()[4]
34
+ return frame.filename
16
35
 
17
- def _get_file_name(self):
36
+ def _get_decorated_file_name(self):
18
37
  # Check if running in a Jupyter notebook
19
38
  try:
20
39
  from IPython import get_ipython
@@ -2,9 +2,9 @@ from ..data.data_structure import LLMCall
2
2
  from .trace_utils import (
3
3
  calculate_cost,
4
4
  convert_usage_to_dict,
5
- load_model_costs,
6
5
  )
7
6
  from importlib import resources
7
+ from litellm import model_cost
8
8
  import json
9
9
  import os
10
10
  import asyncio
@@ -38,7 +38,13 @@ def extract_model_name(args, kwargs, result):
38
38
  metadata = manager.metadata
39
39
  model_name = metadata.get('ls_model_name', None)
40
40
  if model_name:
41
- model = model_name
41
+ model = model_name
42
+
43
+ if not model:
44
+ if 'to_dict' in dir(result):
45
+ result = result.to_dict()
46
+ if 'model_version' in result:
47
+ model = result['model_version']
42
48
 
43
49
 
44
50
  # Normalize Google model names
@@ -50,11 +56,6 @@ def extract_model_name(args, kwargs, result):
50
56
  return "gemini-1.5-pro"
51
57
  if "gemini-pro" in model:
52
58
  return "gemini-pro"
53
-
54
- if 'to_dict' in dir(result):
55
- result = result.to_dict()
56
- if 'model_version' in result:
57
- model = result['model_version']
58
59
 
59
60
  return model or "default"
60
61
 
@@ -268,10 +269,21 @@ def num_tokens_from_messages(model="gpt-4o-mini-2024-07-18", prompt_messages=Non
268
269
  }
269
270
 
270
271
  def extract_input_data(args, kwargs, result):
271
- """Extract input data from function call"""
272
+ """Sanitize and format input data, including handling of nested lists and dictionaries."""
273
+
274
+ def sanitize_value(value):
275
+ if isinstance(value, (int, float, bool, str)):
276
+ return value
277
+ elif isinstance(value, list):
278
+ return [sanitize_value(item) for item in value]
279
+ elif isinstance(value, dict):
280
+ return {key: sanitize_value(val) for key, val in value.items()}
281
+ else:
282
+ return str(value) # Convert non-standard types to string
283
+
272
284
  return {
273
- 'args': args,
274
- 'kwargs': kwargs
285
+ "args": [sanitize_value(arg) for arg in args],
286
+ "kwargs": {key: sanitize_value(val) for key, val in kwargs.items()},
275
287
  }
276
288
 
277
289
 
@@ -370,6 +382,13 @@ def extract_llm_output(result):
370
382
  })
371
383
  return OutputResponse(output)
372
384
 
385
+ # Handle AIMessage Format
386
+ if hasattr(result, "content"):
387
+ return OutputResponse([{
388
+ "content": result.content,
389
+ "role": getattr(result, "role", "assistant")
390
+ }])
391
+
373
392
  # Handle Vertex AI format
374
393
  # format1
375
394
  if hasattr(result, "text"):
@@ -517,7 +536,7 @@ def extract_llm_data(args, kwargs, result):
517
536
  token_usage = extract_token_usage(result)
518
537
 
519
538
  # Load model costs
520
- model_costs = load_model_costs()
539
+ model_costs = model_cost
521
540
 
522
541
  # Calculate cost
523
542
  cost = calculate_llm_cost(token_usage, model_name, model_costs)