ragaai-catalyst 2.1.5b21__py3-none-any.whl → 2.1.5b23__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/__init__.py +3 -1
- ragaai_catalyst/dataset.py +49 -1
- ragaai_catalyst/redteaming.py +171 -0
- ragaai_catalyst/synthetic_data_generation.py +40 -7
- ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py +57 -46
- ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +218 -47
- ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py +17 -7
- ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +327 -62
- ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py +0 -3
- ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py +17 -6
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_local_metric.py +72 -0
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_trace_metric.py +32 -15
- ragaai_catalyst/tracers/agentic_tracing/utils/file_name_tracker.py +21 -2
- ragaai_catalyst/tracers/agentic_tracing/utils/llm_utils.py +33 -11
- ragaai_catalyst/tracers/agentic_tracing/utils/model_costs.json +1204 -484
- ragaai_catalyst/tracers/agentic_tracing/utils/span_attributes.py +79 -10
- ragaai_catalyst/tracers/agentic_tracing/utils/trace_utils.py +0 -32
- ragaai_catalyst/tracers/agentic_tracing/utils/unique_decorator.py +3 -1
- ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py +40 -21
- ragaai_catalyst/tracers/distributed.py +7 -3
- ragaai_catalyst/tracers/tracer.py +9 -9
- ragaai_catalyst/tracers/utils/langchain_tracer_extraction_logic.py +0 -1
- {ragaai_catalyst-2.1.5b21.dist-info → ragaai_catalyst-2.1.5b23.dist-info}/METADATA +37 -2
- {ragaai_catalyst-2.1.5b21.dist-info → ragaai_catalyst-2.1.5b23.dist-info}/RECORD +27 -25
- {ragaai_catalyst-2.1.5b21.dist-info → ragaai_catalyst-2.1.5b23.dist-info}/LICENSE +0 -0
- {ragaai_catalyst-2.1.5b21.dist-info → ragaai_catalyst-2.1.5b23.dist-info}/WHEEL +0 -0
- {ragaai_catalyst-2.1.5b21.dist-info → ragaai_catalyst-2.1.5b23.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
|
-
|
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
|
-
|
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.
|
508
|
-
|
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"])
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import requests
|
4
|
+
|
5
|
+
from ragaai_catalyst import RagaAICatalyst
|
6
|
+
|
7
|
+
logger = logging.getLogger(__name__)
|
8
|
+
logging_level = (
|
9
|
+
logger.setLevel(logging.DEBUG)
|
10
|
+
if os.getenv("DEBUG")
|
11
|
+
else logger.setLevel(logging.INFO)
|
12
|
+
)
|
13
|
+
|
14
|
+
def calculate_metric(project_id, metric_name, model, provider, prompt, response, context, expected_response=None):
|
15
|
+
user_id = "1"
|
16
|
+
org_domain = "raga"
|
17
|
+
|
18
|
+
headers = {
|
19
|
+
"Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
|
20
|
+
"X-Project-Id": str(project_id), # TODO to change it to project_id
|
21
|
+
"Content-Type": "application/json"
|
22
|
+
}
|
23
|
+
|
24
|
+
payload = {
|
25
|
+
"data": [
|
26
|
+
{
|
27
|
+
"metric_name": metric_name,
|
28
|
+
"metric_config": {
|
29
|
+
"threshold": {
|
30
|
+
"isEditable": True,
|
31
|
+
"lte": 0.3
|
32
|
+
},
|
33
|
+
"model": model,
|
34
|
+
"orgDomain": org_domain,
|
35
|
+
"provider": provider,
|
36
|
+
"user_id": user_id,
|
37
|
+
"job_id": 1,
|
38
|
+
"metric_name": metric_name,
|
39
|
+
"request_id": 1
|
40
|
+
},
|
41
|
+
"trace_object": {
|
42
|
+
"Data": {
|
43
|
+
"DocId": "doc-1",
|
44
|
+
"Prompt": prompt,
|
45
|
+
"Response": response,
|
46
|
+
"Context": context,
|
47
|
+
"ExpectedResponse": "",
|
48
|
+
"ExpectedContext": expected_response,
|
49
|
+
"Chat": "",
|
50
|
+
"Instructions": "",
|
51
|
+
"SystemPrompt": "",
|
52
|
+
"Text": ""
|
53
|
+
},
|
54
|
+
"claims": {},
|
55
|
+
"last_computed_metrics": {
|
56
|
+
metric_name: {
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
]
|
62
|
+
}
|
63
|
+
|
64
|
+
try:
|
65
|
+
BASE_URL = RagaAICatalyst.BASE_URL
|
66
|
+
response = requests.post(f"{BASE_URL}/v1/llm/calculate-metric", headers=headers, json=payload, timeout=30)
|
67
|
+
logger.debug(f"Metric calculation response status {response.status_code}")
|
68
|
+
response.raise_for_status()
|
69
|
+
return response.json()
|
70
|
+
except requests.exceptions.RequestException as e:
|
71
|
+
logger.debug(f"Error in calculate-metric api: {e}, payload: {payload}")
|
72
|
+
raise Exception(f"Error in calculate-metric: {e}")
|
@@ -1,27 +1,39 @@
|
|
1
|
+
import logging
|
2
|
+
|
1
3
|
import requests
|
2
4
|
import os
|
3
5
|
import json
|
4
6
|
from ....ragaai_catalyst import RagaAICatalyst
|
5
7
|
from ..utils.get_user_trace_metrics import get_user_trace_metrics
|
6
8
|
|
9
|
+
logger = logging.getLogger(__name__)
|
10
|
+
logging_level = (
|
11
|
+
logger.setLevel(logging.DEBUG)
|
12
|
+
if os.getenv("DEBUG")
|
13
|
+
else logger.setLevel(logging.INFO)
|
14
|
+
)
|
15
|
+
|
16
|
+
|
7
17
|
def upload_trace_metric(json_file_path, dataset_name, project_name):
|
8
18
|
try:
|
9
19
|
with open(json_file_path, "r") as f:
|
10
20
|
traces = json.load(f)
|
21
|
+
|
11
22
|
metrics = get_trace_metrics_from_trace(traces)
|
12
23
|
metrics = _change_metrics_format_for_payload(metrics)
|
13
24
|
|
14
25
|
user_trace_metrics = get_user_trace_metrics(project_name, dataset_name)
|
15
26
|
if user_trace_metrics:
|
16
27
|
user_trace_metrics_list = [metric["displayName"] for metric in user_trace_metrics]
|
17
|
-
|
28
|
+
|
18
29
|
if user_trace_metrics:
|
19
30
|
for metric in metrics:
|
20
31
|
if metric["displayName"] in user_trace_metrics_list:
|
21
|
-
metricConfig = next((user_metric["metricConfig"] for user_metric in user_trace_metrics if
|
32
|
+
metricConfig = next((user_metric["metricConfig"] for user_metric in user_trace_metrics if
|
33
|
+
user_metric["displayName"] == metric["displayName"]), None)
|
22
34
|
if not metricConfig or metricConfig.get("Metric Source", {}).get("value") != "user":
|
23
|
-
raise ValueError(
|
24
|
-
|
35
|
+
raise ValueError(
|
36
|
+
f"Metrics {metric['displayName']} already exist in dataset {dataset_name} of project {project_name}.")
|
25
37
|
headers = {
|
26
38
|
"Content-Type": "application/json",
|
27
39
|
"Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
|
@@ -31,9 +43,9 @@ def upload_trace_metric(json_file_path, dataset_name, project_name):
|
|
31
43
|
"datasetName": dataset_name,
|
32
44
|
"metrics": metrics
|
33
45
|
})
|
34
|
-
response = requests.request("POST",
|
35
|
-
f"{RagaAICatalyst.BASE_URL}/v1/llm/trace/metrics",
|
36
|
-
headers=headers,
|
46
|
+
response = requests.request("POST",
|
47
|
+
f"{RagaAICatalyst.BASE_URL}/v1/llm/trace/metrics",
|
48
|
+
headers=headers,
|
37
49
|
data=payload,
|
38
50
|
timeout=10)
|
39
51
|
if response.status_code != 200:
|
@@ -68,23 +80,28 @@ def get_trace_metrics_from_trace(traces):
|
|
68
80
|
# get span level metrics
|
69
81
|
for span in traces["data"][0]["spans"]:
|
70
82
|
if span["type"] == "agent":
|
83
|
+
# Add children metrics of agent
|
71
84
|
children_metric = _get_children_metrics_of_agent(span["data"]["children"])
|
72
85
|
if children_metric:
|
73
86
|
metrics.extend(children_metric)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
87
|
+
|
88
|
+
metric = span.get("metrics", [])
|
89
|
+
if metric:
|
90
|
+
metrics.extend(metric)
|
78
91
|
return metrics
|
79
92
|
|
93
|
+
|
80
94
|
def _change_metrics_format_for_payload(metrics):
|
81
95
|
formatted_metrics = []
|
82
96
|
for metric in metrics:
|
83
|
-
if any(m["name"] == metric["name"
|
97
|
+
if any(m["name"] == metric.get("displayName") or m['name'] == metric.get("name") for m in formatted_metrics):
|
84
98
|
continue
|
99
|
+
metric_display_name = metric["name"]
|
100
|
+
if metric.get("displayName"):
|
101
|
+
metric_display_name = metric['displayName']
|
85
102
|
formatted_metrics.append({
|
86
|
-
"name":
|
87
|
-
"displayName":
|
103
|
+
"name": metric_display_name,
|
104
|
+
"displayName": metric_display_name,
|
88
105
|
"config": {"source": "user"},
|
89
106
|
})
|
90
|
-
return formatted_metrics
|
107
|
+
return formatted_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.
|
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
|
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
|
|
@@ -70,6 +71,9 @@ def extract_parameters(kwargs):
|
|
70
71
|
# Remove messages key in parameters (OpenAI message)
|
71
72
|
if 'messages' in parameters:
|
72
73
|
del parameters['messages']
|
74
|
+
|
75
|
+
if 'run_manager' in parameters:
|
76
|
+
del parameters['run_manager']
|
73
77
|
|
74
78
|
if 'generation_config' in parameters:
|
75
79
|
generation_config = parameters['generation_config']
|
@@ -268,10 +272,21 @@ def num_tokens_from_messages(model="gpt-4o-mini-2024-07-18", prompt_messages=Non
|
|
268
272
|
}
|
269
273
|
|
270
274
|
def extract_input_data(args, kwargs, result):
|
271
|
-
"""
|
275
|
+
"""Sanitize and format input data, including handling of nested lists and dictionaries."""
|
276
|
+
|
277
|
+
def sanitize_value(value):
|
278
|
+
if isinstance(value, (int, float, bool, str)):
|
279
|
+
return value
|
280
|
+
elif isinstance(value, list):
|
281
|
+
return [sanitize_value(item) for item in value]
|
282
|
+
elif isinstance(value, dict):
|
283
|
+
return {key: sanitize_value(val) for key, val in value.items()}
|
284
|
+
else:
|
285
|
+
return str(value) # Convert non-standard types to string
|
286
|
+
|
272
287
|
return {
|
273
|
-
|
274
|
-
|
288
|
+
"args": [sanitize_value(arg) for arg in args],
|
289
|
+
"kwargs": {key: sanitize_value(val) for key, val in kwargs.items()},
|
275
290
|
}
|
276
291
|
|
277
292
|
|
@@ -370,6 +385,13 @@ def extract_llm_output(result):
|
|
370
385
|
})
|
371
386
|
return OutputResponse(output)
|
372
387
|
|
388
|
+
# Handle AIMessage Format
|
389
|
+
if hasattr(result, "content"):
|
390
|
+
return OutputResponse([{
|
391
|
+
"content": result.content,
|
392
|
+
"role": getattr(result, "role", "assistant")
|
393
|
+
}])
|
394
|
+
|
373
395
|
# Handle Vertex AI format
|
374
396
|
# format1
|
375
397
|
if hasattr(result, "text"):
|
@@ -517,7 +539,7 @@ def extract_llm_data(args, kwargs, result):
|
|
517
539
|
token_usage = extract_token_usage(result)
|
518
540
|
|
519
541
|
# Load model costs
|
520
|
-
model_costs =
|
542
|
+
model_costs = model_cost
|
521
543
|
|
522
544
|
# Calculate cost
|
523
545
|
cost = calculate_llm_cost(token_usage, model_name, model_costs)
|