ragaai-catalyst 2.1.5b32__py3-none-any.whl → 2.1.5b34__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.
@@ -1,7 +1,13 @@
1
1
  import requests
2
2
  import json
3
3
  import os
4
+ import time
5
+ import logging
4
6
  from datetime import datetime
7
+ from urllib.parse import urlparse, urlunparse
8
+ import re
9
+
10
+ logger = logging.getLogger(__name__)
5
11
 
6
12
 
7
13
  class UploadAgenticTraces:
@@ -33,17 +39,41 @@ class UploadAgenticTraces:
33
39
  }
34
40
 
35
41
  try:
42
+ start_time = time.time()
43
+ endpoint = f"{self.base_url}/v1/llm/presigned-url"
36
44
  response = requests.request("GET",
37
- f"{self.base_url}/v1/llm/presigned-url",
45
+ endpoint,
38
46
  headers=headers,
39
47
  data=payload,
40
48
  timeout=self.timeout)
49
+ elapsed_ms = (time.time() - start_time) * 1000
50
+ logger.debug(
51
+ f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
52
+
41
53
  if response.status_code == 200:
42
- presignedUrls = response.json()["data"]["presignedUrls"][0]
43
- return presignedUrls
54
+ presignedURLs = response.json()["data"]["presignedUrls"][0]
55
+ presignedurl = self.update_presigned_url(presignedURLs,self.base_url)
56
+ return presignedurl
57
+
44
58
  except requests.exceptions.RequestException as e:
45
59
  print(f"Error while getting presigned url: {e}")
46
60
  return None
61
+
62
+ def update_presigned_url(self, presigned_url, base_url):
63
+ """Replaces the domain (and port, if applicable) of the presigned URL
64
+ with that of the base URL only if the base URL contains 'localhost' or an IP address."""
65
+ #To Do: If Proxy URL has domain name how do we handle such cases
66
+
67
+ presigned_parts = urlparse(presigned_url)
68
+ base_parts = urlparse(base_url)
69
+ # Check if base_url contains localhost or an IP address
70
+ if re.match(r'^(localhost|\d{1,3}(\.\d{1,3}){3})$', base_parts.hostname):
71
+ new_netloc = base_parts.hostname # Extract domain from base_url
72
+ if base_parts.port: # Add port if present in base_url
73
+ new_netloc += f":{base_parts.port}"
74
+ updated_parts = presigned_parts._replace(netloc=new_netloc)
75
+ return urlunparse(updated_parts)
76
+ return presigned_url
47
77
 
48
78
  def _put_presigned_url(self, presignedUrl, filename):
49
79
  headers = {
@@ -60,11 +90,15 @@ class UploadAgenticTraces:
60
90
  print(f"Error while reading file: {e}")
61
91
  return None
62
92
  try:
93
+ start_time = time.time()
63
94
  response = requests.request("PUT",
64
95
  presignedUrl,
65
96
  headers=headers,
66
97
  data=payload,
67
98
  timeout=self.timeout)
99
+ elapsed_ms = (time.time() - start_time) * 1000
100
+ logger.debug(
101
+ f"API Call: [PUT] {presignedUrl} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
68
102
  if response.status_code != 200 or response.status_code != 201:
69
103
  return response, response.status_code
70
104
  except requests.exceptions.RequestException as e:
@@ -83,11 +117,16 @@ class UploadAgenticTraces:
83
117
  "datasetSpans": self._get_dataset_spans(), #Extra key for agentic traces
84
118
  })
85
119
  try:
120
+ start_time = time.time()
121
+ endpoint = f"{self.base_url}/v1/llm/insert/trace"
86
122
  response = requests.request("POST",
87
- f"{self.base_url}/v1/llm/insert/trace",
123
+ endpoint,
88
124
  headers=headers,
89
125
  data=payload,
90
126
  timeout=self.timeout)
127
+ elapsed_ms = (time.time() - start_time) * 1000
128
+ logger.debug(
129
+ f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
91
130
  if response.status_code != 200:
92
131
  print(f"Error inserting traces: {response.json()['message']}")
93
132
  return None
@@ -116,27 +155,43 @@ class UploadAgenticTraces:
116
155
  "spanType": span["type"],
117
156
  })
118
157
  else:
119
- datasetSpans.append({
158
+ datasetSpans.extend(self._get_agent_dataset_spans(span, datasetSpans))
159
+ datasetSpans = [dict(t) for t in set(tuple(sorted(d.items())) for d in datasetSpans)]
160
+
161
+ return datasetSpans
162
+ except Exception as e:
163
+ print(f"Error while reading dataset spans: {e}")
164
+ return None
165
+
166
+ def _get_agent_dataset_spans(self, span, datasetSpans):
167
+ datasetSpans.append({
120
168
  "spanId": span["id"],
121
169
  "spanName": span["name"],
122
170
  "spanHash": span["hash_id"],
123
171
  "spanType": span["type"],
124
172
  })
125
- children = span["data"]["children"]
126
- for child in children:
127
- existing_span = next((s for s in datasetSpans if s["spanHash"] == child["hash_id"]), None)
128
- if existing_span is None:
129
- datasetSpans.append({
130
- "spanId": child["id"],
131
- "spanName": child["name"],
132
- "spanHash": child["hash_id"],
133
- "spanType": child["type"],
134
- })
135
- return datasetSpans
136
- except Exception as e:
137
- print(f"Error while reading dataset spans: {e}")
138
- return None
139
-
173
+ children = span["data"]["children"]
174
+ for child in children:
175
+ if child["type"] != "agent":
176
+ existing_span = next((s for s in datasetSpans if s["spanHash"] == child["hash_id"]), None)
177
+ if existing_span is None:
178
+ datasetSpans.append({
179
+ "spanId": child["id"],
180
+ "spanName": child["name"],
181
+ "spanHash": child["hash_id"],
182
+ "spanType": child["type"],
183
+ })
184
+ else:
185
+ datasetSpans.append({
186
+ "spanId": child["id"],
187
+ "spanName": child["name"],
188
+ "spanHash": child["hash_id"],
189
+ "spanType": child["type"],
190
+ })
191
+ self._get_agent_dataset_spans(child, datasetSpans)
192
+ return datasetSpans
193
+
194
+
140
195
  def upload_agentic_traces(self):
141
196
  try:
142
197
  presignedUrl = self._get_presigned_url()
@@ -2,23 +2,26 @@ from aiohttp import payload
2
2
  import requests
3
3
  import json
4
4
  import os
5
+ import time
5
6
  import logging
6
7
  from ragaai_catalyst.ragaai_catalyst import RagaAICatalyst
7
8
  logger = logging.getLogger(__name__)
9
+ from urllib.parse import urlparse, urlunparse
10
+ import re
8
11
 
9
- def upload_code(hash_id, zip_path, project_name, dataset_name):
10
- code_hashes_list = _fetch_dataset_code_hashes(project_name, dataset_name)
12
+ def upload_code(hash_id, zip_path, project_name, dataset_name, base_url=None):
13
+ code_hashes_list = _fetch_dataset_code_hashes(project_name, dataset_name, base_url)
11
14
 
12
15
  if hash_id not in code_hashes_list:
13
- presigned_url = _fetch_presigned_url(project_name, dataset_name)
16
+ presigned_url = _fetch_presigned_url(project_name, dataset_name, base_url)
14
17
  _put_zip_presigned_url(project_name, presigned_url, zip_path)
15
18
 
16
- response = _insert_code(dataset_name, hash_id, presigned_url, project_name)
19
+ response = _insert_code(dataset_name, hash_id, presigned_url, project_name, base_url)
17
20
  return response
18
21
  else:
19
22
  return "Code already exists"
20
23
 
21
- def _fetch_dataset_code_hashes(project_name, dataset_name):
24
+ def _fetch_dataset_code_hashes(project_name, dataset_name, base_url=None):
22
25
  payload = {}
23
26
  headers = {
24
27
  "Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
@@ -26,11 +29,17 @@ def _fetch_dataset_code_hashes(project_name, dataset_name):
26
29
  }
27
30
 
28
31
  try:
32
+ url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
33
+ start_time = time.time()
34
+ endpoint = f"{url_base}/v2/llm/dataset/code?datasetName={dataset_name}"
29
35
  response = requests.request("GET",
30
- f"{RagaAICatalyst.BASE_URL}/v2/llm/dataset/code?datasetName={dataset_name}",
36
+ endpoint,
31
37
  headers=headers,
32
38
  data=payload,
33
39
  timeout=99999)
40
+ elapsed_ms = (time.time() - start_time) * 1000
41
+ logger.debug(
42
+ f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
34
43
 
35
44
  if response.status_code == 200:
36
45
  return response.json()["data"]["codeHashes"]
@@ -40,7 +49,24 @@ def _fetch_dataset_code_hashes(project_name, dataset_name):
40
49
  logger.error(f"Failed to list datasets: {e}")
41
50
  raise
42
51
 
43
- def _fetch_presigned_url(project_name, dataset_name):
52
+
53
+ def update_presigned_url(presigned_url, base_url):
54
+ """Replaces the domain (and port, if applicable) of the presigned URL with that of the base URL."""
55
+ #To Do: If Proxy URL has domain name how do we handle such cases? Engineering Dependency.
56
+
57
+ presigned_parts = urlparse(presigned_url)
58
+ base_parts = urlparse(base_url)
59
+ # Check if base_url contains localhost or an IP address
60
+ if re.match(r'^(localhost|\d{1,3}(\.\d{1,3}){3})$', base_parts.hostname):
61
+ new_netloc = base_parts.hostname # Extract domain from base_url
62
+ if base_parts.port: # Add port if present in base_url
63
+ new_netloc += f":{base_parts.port}"
64
+ updated_parts = presigned_parts._replace(netloc=new_netloc)
65
+ return urlunparse(updated_parts)
66
+ return presigned_url
67
+
68
+
69
+ def _fetch_presigned_url(project_name, dataset_name, base_url=None):
44
70
  payload = json.dumps({
45
71
  "datasetName": dataset_name,
46
72
  "numFiles": 1,
@@ -54,14 +80,22 @@ def _fetch_presigned_url(project_name, dataset_name):
54
80
  }
55
81
 
56
82
  try:
83
+ url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
84
+ start_time = time.time()
85
+ endpoint = f"{url_base}/v1/llm/presigned-url"
57
86
  response = requests.request("GET",
58
- f"{RagaAICatalyst.BASE_URL}/v1/llm/presigned-url",
87
+ endpoint,
59
88
  headers=headers,
60
89
  data=payload,
61
90
  timeout=99999)
91
+ elapsed_ms = (time.time() - start_time) * 1000
92
+ logger.debug(
93
+ f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
62
94
 
63
95
  if response.status_code == 200:
64
- return response.json()["data"]["presignedUrls"][0]
96
+ presigned_url = response.json()["data"]["presignedUrls"][0]
97
+ presigned_url = update_presigned_url(presigned_url,url_base)
98
+ return presigned_url
65
99
  else:
66
100
  raise Exception(f"Failed to fetch code hashes: {response.json()['message']}")
67
101
  except requests.exceptions.RequestException as e:
@@ -80,15 +114,19 @@ def _put_zip_presigned_url(project_name, presignedUrl, filename):
80
114
  with open(filename, 'rb') as f:
81
115
  payload = f.read()
82
116
 
117
+ start_time = time.time()
83
118
  response = requests.request("PUT",
84
119
  presignedUrl,
85
120
  headers=headers,
86
121
  data=payload,
87
122
  timeout=99999)
123
+ elapsed_ms = (time.time() - start_time) * 1000
124
+ logger.debug(
125
+ f"API Call: [PUT] {presignedUrl} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
88
126
  if response.status_code != 200 or response.status_code != 201:
89
127
  return response, response.status_code
90
128
 
91
- def _insert_code(dataset_name, hash_id, presigned_url, project_name):
129
+ def _insert_code(dataset_name, hash_id, presigned_url, project_name, base_url=None):
92
130
  payload = json.dumps({
93
131
  "datasetName": dataset_name,
94
132
  "codeHash": hash_id,
@@ -102,11 +140,17 @@ def _insert_code(dataset_name, hash_id, presigned_url, project_name):
102
140
  }
103
141
 
104
142
  try:
143
+ url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
144
+ start_time = time.time()
145
+ endpoint = f"{url_base}/v2/llm/dataset/code"
105
146
  response = requests.request("POST",
106
- f"{RagaAICatalyst.BASE_URL}/v2/llm/dataset/code",
147
+ endpoint,
107
148
  headers=headers,
108
149
  data=payload,
109
150
  timeout=99999)
151
+ elapsed_ms = (time.time() - start_time) * 1000
152
+ logger.debug(
153
+ f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
110
154
  if response.status_code == 200:
111
155
  return response.json()["message"]
112
156
  else:
@@ -3,6 +3,7 @@ import logging
3
3
  import requests
4
4
  import os
5
5
  import json
6
+ import time
6
7
  from ....ragaai_catalyst import RagaAICatalyst
7
8
  from ..utils.get_user_trace_metrics import get_user_trace_metrics
8
9
 
@@ -14,7 +15,7 @@ logging_level = (
14
15
  )
15
16
 
16
17
 
17
- def upload_trace_metric(json_file_path, dataset_name, project_name):
18
+ def upload_trace_metric(json_file_path, dataset_name, project_name, base_url=None):
18
19
  try:
19
20
  with open(json_file_path, "r") as f:
20
21
  traces = json.load(f)
@@ -43,11 +44,17 @@ def upload_trace_metric(json_file_path, dataset_name, project_name):
43
44
  "datasetName": dataset_name,
44
45
  "metrics": metrics
45
46
  })
47
+ url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
48
+ start_time = time.time()
49
+ endpoint = f"{url_base}/v1/llm/trace/metrics"
46
50
  response = requests.request("POST",
47
- f"{RagaAICatalyst.BASE_URL}/v1/llm/trace/metrics",
51
+ endpoint,
48
52
  headers=headers,
49
53
  data=payload,
50
54
  timeout=10)
55
+ elapsed_ms = (time.time() - start_time) * 1000
56
+ logger.debug(
57
+ f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
51
58
  if response.status_code != 200:
52
59
  raise ValueError(f"Error inserting agentic trace metrics")
53
60
  except requests.exceptions.RequestException as e:
@@ -4,7 +4,7 @@ import re
4
4
  import requests
5
5
  from ragaai_catalyst.tracers.agentic_tracing.tracers.base import RagaAICatalyst
6
6
 
7
- def create_dataset_schema_with_trace(project_name, dataset_name):
7
+ def create_dataset_schema_with_trace(project_name, dataset_name, base_url=None):
8
8
  def make_request():
9
9
  headers = {
10
10
  "Content-Type": "application/json",
@@ -15,8 +15,10 @@ def create_dataset_schema_with_trace(project_name, dataset_name):
15
15
  "datasetName": dataset_name,
16
16
  "traceFolderUrl": None,
17
17
  })
18
+ # Use provided base_url or fall back to default
19
+ url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
18
20
  response = requests.request("POST",
19
- f"{RagaAICatalyst.BASE_URL}/v1/llm/dataset/logs",
21
+ f"{url_base}/v1/llm/dataset/logs",
20
22
  headers=headers,
21
23
  data=payload,
22
24
  timeout=10
@@ -4,7 +4,7 @@ from .trace_utils import (
4
4
  convert_usage_to_dict,
5
5
  )
6
6
  from importlib import resources
7
- from litellm import model_cost
7
+ #from litellm import model_cost
8
8
  import json
9
9
  import os
10
10
  import asyncio
@@ -14,6 +14,19 @@ import logging
14
14
 
15
15
  logger = logging.getLogger(__name__)
16
16
 
17
+ def get_model_cost():
18
+ """Load model costs from a JSON file.
19
+ Note: This file should be updated periodically or whenever a new package is created to ensure accurate cost calculations.
20
+ To Do: Implement to do this automatically.
21
+ """
22
+ file="model_prices_and_context_window_backup.json"
23
+ d={}
24
+ with resources.open_text("ragaai_catalyst.tracers.utils", file) as f:
25
+ d= json.load(f)
26
+ return d
27
+
28
+ model_cost = get_model_cost()
29
+
17
30
  def extract_model_name(args, kwargs, result):
18
31
  """Extract model name from kwargs or result"""
19
32
  # First try direct model parameter