ragaai-catalyst 2.1.7.5b2__py3-none-any.whl → 2.1.7.5b3__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/dataset.py +4 -1
- ragaai_catalyst/evaluation.py +2 -2
- ragaai_catalyst/ragaai_catalyst.py +114 -53
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py +18 -1
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py +14 -0
- {ragaai_catalyst-2.1.7.5b2.dist-info → ragaai_catalyst-2.1.7.5b3.dist-info}/METADATA +1 -1
- {ragaai_catalyst-2.1.7.5b2.dist-info → ragaai_catalyst-2.1.7.5b3.dist-info}/RECORD +10 -10
- {ragaai_catalyst-2.1.7.5b2.dist-info → ragaai_catalyst-2.1.7.5b3.dist-info}/WHEEL +1 -1
- {ragaai_catalyst-2.1.7.5b2.dist-info → ragaai_catalyst-2.1.7.5b3.dist-info}/licenses/LICENSE +0 -0
- {ragaai_catalyst-2.1.7.5b2.dist-info → ragaai_catalyst-2.1.7.5b3.dist-info}/top_level.txt +0 -0
ragaai_catalyst/dataset.py
CHANGED
@@ -257,7 +257,10 @@ class Dataset:
|
|
257
257
|
def generate_schema(mapping):
|
258
258
|
result = {}
|
259
259
|
for column, schema_element in mapping.items():
|
260
|
-
|
260
|
+
if isinstance(schema_element, dict):
|
261
|
+
result[column] = schema_element
|
262
|
+
else:
|
263
|
+
result[column] = {"columnType": schema_element}
|
261
264
|
return result
|
262
265
|
|
263
266
|
try:
|
ragaai_catalyst/evaluation.py
CHANGED
@@ -171,7 +171,7 @@ class Evaluation:
|
|
171
171
|
user_dataset_columns = [item["displayName"] for item in user_dataset_schema]
|
172
172
|
variableName = None
|
173
173
|
for key, val in schema_mapping.items():
|
174
|
-
if "".join(val.split("_")).lower()==schemaName:
|
174
|
+
if val==schemaName: #"".join(val.split("_")).lower()==schemaName or val.lower()==schemaName:
|
175
175
|
if key in user_dataset_columns:
|
176
176
|
variableName=key
|
177
177
|
else:
|
@@ -198,7 +198,7 @@ class Evaluation:
|
|
198
198
|
|
199
199
|
for field in requiredFields:
|
200
200
|
schemaName = field["name"]
|
201
|
-
variableName = self._get_variablename_from_user_schema_mapping(schemaName
|
201
|
+
variableName = self._get_variablename_from_user_schema_mapping(schemaName, metric_name, schema_mapping, metric_to_evaluate)
|
202
202
|
mapping.append({"schemaName": schemaName, "variableName": variableName})
|
203
203
|
return mapping
|
204
204
|
|
@@ -2,6 +2,7 @@ import os
|
|
2
2
|
import logging
|
3
3
|
import requests
|
4
4
|
import time
|
5
|
+
import threading
|
5
6
|
from typing import Dict, Optional, Union
|
6
7
|
import re
|
7
8
|
logger = logging.getLogger("RagaAICatalyst")
|
@@ -49,6 +50,11 @@ class RagaAICatalyst:
|
|
49
50
|
access_key, secret_key
|
50
51
|
)
|
51
52
|
|
53
|
+
# Initialize token management
|
54
|
+
self._token_expiry = None
|
55
|
+
self._token_refresh_lock = threading.Lock()
|
56
|
+
self._refresh_thread = None
|
57
|
+
|
52
58
|
RagaAICatalyst.BASE_URL = (
|
53
59
|
os.getenv("RAGAAI_CATALYST_BASE_URL")
|
54
60
|
if os.getenv("RAGAAI_CATALYST_BASE_URL")
|
@@ -143,78 +149,133 @@ class RagaAICatalyst:
|
|
143
149
|
"""Get the API key for a specific service."""
|
144
150
|
return self.api_keys.get(service)
|
145
151
|
|
146
|
-
|
147
|
-
|
152
|
+
# Token expiration time in seconds (6 hours by default)
|
153
|
+
# TODO: Change this to 23 hours
|
154
|
+
TOKEN_EXPIRATION_TIME = 6 * 60 * 60
|
155
|
+
|
156
|
+
def _get_credentials(self) -> tuple[str, str]:
|
157
|
+
"""Get access key and secret key from instance or environment."""
|
158
|
+
access_key = self.access_key or os.getenv("RAGAAI_CATALYST_ACCESS_KEY")
|
159
|
+
secret_key = self.secret_key or os.getenv("RAGAAI_CATALYST_SECRET_KEY")
|
160
|
+
return access_key, secret_key
|
161
|
+
|
162
|
+
def _refresh_token_async(self):
|
163
|
+
"""Refresh token in background thread."""
|
164
|
+
try:
|
165
|
+
self.get_token(force_refresh=True)
|
166
|
+
except Exception as e:
|
167
|
+
logger.error(f"Background token refresh failed: {str(e)}")
|
168
|
+
|
169
|
+
def get_token(self, force_refresh=False) -> Union[str, None]:
|
148
170
|
"""
|
149
|
-
Retrieves a token
|
171
|
+
Retrieves or refreshes a token using the provided credentials.
|
172
|
+
|
173
|
+
Args:
|
174
|
+
force_refresh (bool): If True, forces a token refresh regardless of expiration.
|
150
175
|
|
151
176
|
Returns:
|
152
177
|
- A string representing the token if successful.
|
153
|
-
- None if
|
154
|
-
|
155
|
-
Raises:
|
156
|
-
- requests.exceptions.HTTPError: If there is an HTTP error while retrieving the token.
|
157
|
-
- requests.exceptions.RequestException: If there is an error while retrieving the token.
|
158
|
-
- ValueError: If there is a JSON decoding error or if authentication fails.
|
159
|
-
- Exception: If there is an unexpected error while retrieving the token.
|
178
|
+
- None if credentials are not set or if there is an error.
|
160
179
|
"""
|
161
|
-
|
162
|
-
|
180
|
+
with self._token_refresh_lock:
|
181
|
+
current_token = os.getenv("RAGAAI_CATALYST_TOKEN")
|
182
|
+
current_time = time.time()
|
163
183
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
)
|
168
|
-
return None
|
184
|
+
# Check if we need to refresh the token
|
185
|
+
if not force_refresh and current_token and self._token_expiry and current_time < self._token_expiry:
|
186
|
+
return current_token
|
169
187
|
|
170
|
-
|
171
|
-
|
188
|
+
access_key, secret_key = self._get_credentials()
|
189
|
+
if not access_key or not secret_key:
|
190
|
+
logger.error("Access key or secret key is not set")
|
191
|
+
return None
|
172
192
|
|
173
|
-
|
174
|
-
|
175
|
-
response = requests.post(
|
176
|
-
endpoint,
|
177
|
-
headers=headers,
|
178
|
-
json=json_data,
|
179
|
-
timeout=RagaAICatalyst.TIMEOUT,
|
180
|
-
)
|
181
|
-
elapsed_ms = (time.time() - start_time) * 1000
|
182
|
-
logger.debug(
|
183
|
-
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
193
|
+
headers = {"Content-Type": "application/json"}
|
194
|
+
json_data = {"accessKey": access_key, "secretKey": secret_key}
|
184
195
|
|
185
|
-
|
186
|
-
|
196
|
+
start_time = time.time()
|
197
|
+
endpoint = f"{self.BASE_URL}/token"
|
198
|
+
response = requests.post(
|
199
|
+
endpoint,
|
200
|
+
headers=headers,
|
201
|
+
json=json_data,
|
202
|
+
timeout=self.TIMEOUT,
|
203
|
+
)
|
204
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
205
|
+
logger.debug(
|
206
|
+
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
207
|
+
|
208
|
+
# Handle specific status codes before raising an error
|
209
|
+
if response.status_code == 400:
|
210
|
+
token_response = response.json()
|
211
|
+
if token_response.get("message") == "Please enter valid credentials":
|
212
|
+
raise Exception(
|
213
|
+
"Authentication failed. Invalid credentials provided. Please check your Access key and Secret key. \nTo view or create new keys, navigate to Settings -> Authenticate in the RagaAI Catalyst dashboard."
|
214
|
+
)
|
215
|
+
|
216
|
+
response.raise_for_status()
|
187
217
|
token_response = response.json()
|
188
|
-
|
189
|
-
|
190
|
-
|
218
|
+
|
219
|
+
if not token_response.get("success", False):
|
220
|
+
logger.error(
|
221
|
+
"Token retrieval was not successful: %s",
|
222
|
+
token_response.get("message", "Unknown error"),
|
191
223
|
)
|
224
|
+
return None
|
225
|
+
|
226
|
+
token = token_response.get("data", {}).get("token")
|
227
|
+
if token:
|
228
|
+
os.environ["RAGAAI_CATALYST_TOKEN"] = token
|
229
|
+
self._token_expiry = time.time() + self.TOKEN_EXPIRATION_TIME
|
230
|
+
logger.info(f"Token refreshed successfully. Next refresh in {self.TOKEN_EXPIRATION_TIME/3600:.1f} hours")
|
231
|
+
return token
|
232
|
+
else:
|
233
|
+
logger.error("Token(s) not set")
|
234
|
+
return None
|
192
235
|
|
193
|
-
|
236
|
+
def ensure_valid_token(self) -> Union[str, None]:
|
237
|
+
"""
|
238
|
+
Ensures a valid token is available, with different handling for missing token vs expired token:
|
239
|
+
- Missing token: Synchronous retrieval (fail fast)
|
240
|
+
- Expired token: Asynchronous refresh in background
|
194
241
|
|
195
|
-
|
242
|
+
Returns:
|
243
|
+
- A string representing the valid token if successful.
|
244
|
+
- None if unable to obtain a valid token.
|
245
|
+
"""
|
246
|
+
current_token = os.getenv("RAGAAI_CATALYST_TOKEN")
|
247
|
+
current_time = time.time()
|
196
248
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
249
|
+
# Case 1: No token - synchronous retrieval (fail fast)
|
250
|
+
if not current_token:
|
251
|
+
return self.get_token(force_refresh=True)
|
252
|
+
|
253
|
+
# Case 2: Token expired or about to expire - async refresh
|
254
|
+
if not self._token_expiry or current_time >= self._token_expiry:
|
255
|
+
if not self._refresh_thread or not self._refresh_thread.is_alive():
|
256
|
+
self._refresh_thread = threading.Thread(target=self._refresh_token_async)
|
257
|
+
self._refresh_thread.daemon = True
|
258
|
+
self._refresh_thread.start()
|
259
|
+
|
260
|
+
return current_token
|
203
261
|
|
204
|
-
|
262
|
+
def get_auth_header(self) -> Dict[str, str]:
|
263
|
+
"""
|
264
|
+
Returns a dictionary containing the Authorization header with a valid token.
|
265
|
+
This method should be used instead of directly accessing os.getenv("RAGAAI_CATALYST_TOKEN").
|
266
|
+
|
267
|
+
Returns:
|
268
|
+
- A dictionary with the Authorization header if successful.
|
269
|
+
- An empty dictionary if no valid token could be obtained.
|
270
|
+
"""
|
271
|
+
token = self.ensure_valid_token()
|
205
272
|
if token:
|
206
|
-
|
207
|
-
|
208
|
-
return token
|
209
|
-
else:
|
210
|
-
logger.error("Token(s) not set")
|
211
|
-
return None
|
273
|
+
return {"Authorization": f"Bearer {token}"}
|
274
|
+
return {}
|
212
275
|
|
213
276
|
def project_use_cases(self):
|
214
277
|
try:
|
215
|
-
headers =
|
216
|
-
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
217
|
-
}
|
278
|
+
headers = self.get_auth_header()
|
218
279
|
start_time = time.time()
|
219
280
|
endpoint = f"{RagaAICatalyst.BASE_URL}/v2/llm/usecase"
|
220
281
|
response = requests.get(
|
@@ -57,9 +57,26 @@ class UploadAgenticTraces:
|
|
57
57
|
presignedURLs = response.json()["data"]["presignedUrls"][0]
|
58
58
|
presignedurl = self.update_presigned_url(presignedURLs,self.base_url)
|
59
59
|
return presignedurl
|
60
|
+
else:
|
61
|
+
# If POST fails, try GET
|
62
|
+
response = requests.request("GET",
|
63
|
+
endpoint,
|
64
|
+
headers=headers,
|
65
|
+
data=payload,
|
66
|
+
timeout=self.timeout)
|
67
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
68
|
+
logger.debug(
|
69
|
+
f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
70
|
+
if response.status_code == 200:
|
71
|
+
presignedURLs = response.json()["data"]["presignedUrls"][0]
|
72
|
+
presignedurl = self.update_presigned_url(presignedURLs,self.base_url)
|
73
|
+
return presignedurl
|
74
|
+
|
75
|
+
logger.error(f"Error while getting presigned url: {response.json()['message']}")
|
76
|
+
return None
|
60
77
|
|
61
78
|
except requests.exceptions.RequestException as e:
|
62
|
-
|
79
|
+
logger.error(f"Error while getting presigned url: {e}")
|
63
80
|
return None
|
64
81
|
|
65
82
|
def update_presigned_url(self, presigned_url, base_url):
|
@@ -98,6 +98,20 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
|
|
98
98
|
presigned_url = update_presigned_url(presigned_url,url_base)
|
99
99
|
return presigned_url
|
100
100
|
else:
|
101
|
+
# If POST fails, try GET
|
102
|
+
response = requests.request("GET",
|
103
|
+
endpoint,
|
104
|
+
headers=headers,
|
105
|
+
data=payload,
|
106
|
+
timeout=timeout)
|
107
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
108
|
+
logger.debug(
|
109
|
+
f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
110
|
+
if response.status_code == 200:
|
111
|
+
presigned_url = response.json()["data"]["presignedUrls"][0]
|
112
|
+
presigned_url = update_presigned_url(presigned_url,url_base)
|
113
|
+
return presigned_url
|
114
|
+
|
101
115
|
logger.error(f"Failed to fetch code hashes: {response.json()['message']}")
|
102
116
|
raise Exception(f"Failed to fetch code hashes: {response.json()['message']}")
|
103
117
|
except requests.exceptions.RequestException as e:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ragaai_catalyst
|
3
|
-
Version: 2.1.7.
|
3
|
+
Version: 2.1.7.5b3
|
4
4
|
Summary: RAGA AI CATALYST
|
5
5
|
Author-email: Kiran Scaria <kiran.scaria@raga.ai>, Kedar Gaikwad <kedar.gaikwad@raga.ai>, Dushyant Mahajan <dushyant.mahajan@raga.ai>, Siddhartha Kosti <siddhartha.kosti@raga.ai>, Ritika Goel <ritika.goel@raga.ai>, Vijay Chaurasia <vijay.chaurasia@raga.ai>, Tushar Kumar <tushar.kumar@raga.ai>
|
6
6
|
Requires-Python: <=3.13.2,>=3.10
|
@@ -1,14 +1,14 @@
|
|
1
1
|
ragaai_catalyst/__init__.py,sha256=2wfkucAbb3Bt_p2KHelkg9zBQp4yC4iZanltyieG18w,895
|
2
2
|
ragaai_catalyst/_version.py,sha256=JKt9KaVNOMVeGs8ojO6LvIZr7ZkMzNN-gCcvryy4x8E,460
|
3
|
-
ragaai_catalyst/dataset.py,sha256=
|
4
|
-
ragaai_catalyst/evaluation.py,sha256=
|
3
|
+
ragaai_catalyst/dataset.py,sha256=kQy-fiU9zxVrNJkHG8ILGR_3UTIz4rUM7iOsEf4jVZs,29535
|
4
|
+
ragaai_catalyst/evaluation.py,sha256=acCNQtoN2eM9NTehKEATquZ5hNu6Ijv7wisvaaJ4u7c,22993
|
5
5
|
ragaai_catalyst/experiment.py,sha256=8yQo1phCHlpnJ-4CqCaIbLXg_1ZlAuLGI9kqGBl-OTE,18859
|
6
6
|
ragaai_catalyst/guard_executor.py,sha256=f2FXQSW17z4-eor61J_mtD0z-xBm9yordq8giB-GN_U,14006
|
7
7
|
ragaai_catalyst/guardrails_manager.py,sha256=_VrARJ1udmCF8TklNKy7XTQUaM8ATDhTOAGDonBkFro,14245
|
8
8
|
ragaai_catalyst/internal_api_completion.py,sha256=DdICI5yfEudiOAIC8L4oxH0Qz7kX-BZCdo9IWsi2gNo,2965
|
9
9
|
ragaai_catalyst/prompt_manager.py,sha256=W8ypramzOprrJ7-22d5vkBXIuIQ8v9XAzKDGxKsTK28,16550
|
10
10
|
ragaai_catalyst/proxy_call.py,sha256=CHxldeceZUaLU-to_hs_Kf1z_b2vHMssLS_cOBedu78,5499
|
11
|
-
ragaai_catalyst/ragaai_catalyst.py,sha256=
|
11
|
+
ragaai_catalyst/ragaai_catalyst.py,sha256=lMmWPqRMr1IGVCKrCxk6Vfip-z7yfzTh9jqE-rb4I3Q,22248
|
12
12
|
ragaai_catalyst/redteaming_old.py,sha256=W2d89Ok8W-C8g7TBM3fDIFLof3q9FuYSr0jcryH2XQo,7097
|
13
13
|
ragaai_catalyst/synthetic_data_generation.py,sha256=7lIWa3nwgW2-FlJrDaGxTN6OE4-dbbhLtKNOBQufhho,37952
|
14
14
|
ragaai_catalyst/utils.py,sha256=TlhEFwLyRU690HvANbyoRycR3nQ67lxVUQoUOfTPYQ0,3772
|
@@ -55,8 +55,8 @@ ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py,sha256=xxrliKPfdf
|
|
55
55
|
ragaai_catalyst/tracers/agentic_tracing/tracers/user_interaction_tracer.py,sha256=bhSUhNQCuJXKjgJAXhjKEYjnHMpYN90FSZdR84fNIKU,4614
|
56
56
|
ragaai_catalyst/tracers/agentic_tracing/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
57
|
ragaai_catalyst/tracers/agentic_tracing/upload/trace_uploader.py,sha256=qGinKWnb-NSEfIfIOsL37tB9AS8-dKa_-nNNHkUmtuE,12955
|
58
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py,sha256=
|
59
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=
|
58
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py,sha256=u7QwUbG73zeWi-5WQ4scLo7wfw184Qd8c03TxgfoUe4,9567
|
59
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=eNjKt8xC2IIs_mC9WdLaP_vUxWpYHVi2OXgJyn2oSx8,7443
|
60
60
|
ragaai_catalyst/tracers/agentic_tracing/upload/upload_local_metric.py,sha256=m1O8lKpxKwtHofXLW3fTHX5yfqDW5GxoveARlg5cTw4,2571
|
61
61
|
ragaai_catalyst/tracers/agentic_tracing/upload/upload_trace_metric.py,sha256=hRuh-cczHbeM_Spbf9HTYd149uSs1zP0TvkYuZKF4ec,4296
|
62
62
|
ragaai_catalyst/tracers/agentic_tracing/utils/__init__.py,sha256=XdB3X_ufe4RVvGorxSqAiB9dYv4UD7Hvvuw3bsDUppY,60
|
@@ -88,8 +88,8 @@ ragaai_catalyst/tracers/utils/model_prices_and_context_window_backup.json,sha256
|
|
88
88
|
ragaai_catalyst/tracers/utils/rag_trace_json_converter.py,sha256=adCKk7Nj8307XYYg2sB-QT-66OShOs2iTGwNVwqbHig,19373
|
89
89
|
ragaai_catalyst/tracers/utils/trace_json_converter.py,sha256=E0_QfciQMMpCtQYrNB4l8HJhlaFalr5bkMqkVRgQahY,14073
|
90
90
|
ragaai_catalyst/tracers/utils/utils.py,sha256=ViygfJ7vZ7U0CTSA1lbxVloHp4NSlmfDzBRNCJuMhis,2374
|
91
|
-
ragaai_catalyst-2.1.7.
|
92
|
-
ragaai_catalyst-2.1.7.
|
93
|
-
ragaai_catalyst-2.1.7.
|
94
|
-
ragaai_catalyst-2.1.7.
|
95
|
-
ragaai_catalyst-2.1.7.
|
91
|
+
ragaai_catalyst-2.1.7.5b3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
92
|
+
ragaai_catalyst-2.1.7.5b3.dist-info/METADATA,sha256=gn-nsj810EAkUigEje4FodHJ7AA-vCvslLPRcBAlH94,17607
|
93
|
+
ragaai_catalyst-2.1.7.5b3.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
94
|
+
ragaai_catalyst-2.1.7.5b3.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
|
95
|
+
ragaai_catalyst-2.1.7.5b3.dist-info/RECORD,,
|
{ragaai_catalyst-2.1.7.5b2.dist-info → ragaai_catalyst-2.1.7.5b3.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
File without changes
|