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.
@@ -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
- result[column] = {"columnType": schema_element}
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:
@@ -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.lower(), metric_name, schema_mapping, metric_to_evaluate)
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
- @staticmethod
147
- def get_token() -> Union[str, None]:
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 from the server using the provided access key and secret key.
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 the access key or secret key is not set or if there is an error retrieving the token.
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
- access_key = os.getenv("RAGAAI_CATALYST_ACCESS_KEY")
162
- secret_key = os.getenv("RAGAAI_CATALYST_SECRET_KEY")
180
+ with self._token_refresh_lock:
181
+ current_token = os.getenv("RAGAAI_CATALYST_TOKEN")
182
+ current_time = time.time()
163
183
 
164
- if not access_key or not secret_key:
165
- logger.error(
166
- "RAGAAI_CATALYST_ACCESS_KEY or RAGAAI_CATALYST_SECRET_KEY is not set"
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
- headers = {"Content-Type": "application/json"}
171
- json_data = {"accessKey": access_key, "secretKey": secret_key}
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
- start_time = time.time()
174
- endpoint = f"{RagaAICatalyst.BASE_URL}/token"
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
- # Handle specific status codes before raising an error
186
- if response.status_code == 400:
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
- if token_response.get("message") == "Please enter valid credentials":
189
- raise Exception(
190
- "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."
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
- response.raise_for_status()
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
- token_response = response.json()
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
- if not token_response.get("success", False):
198
- logger.error(
199
- "Token retrieval was not successful: %s",
200
- token_response.get("message", "Unknown error"),
201
- )
202
- return None
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
- token = token_response.get("data", {}).get("token")
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
- os.environ["RAGAAI_CATALYST_TOKEN"] = token
207
- print("Token(s) set successfully")
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
- print(f"Error while getting presigned url: {e}")
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.5b2
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=LefpZDCTkLoimZr0GEGK2awjOjhy8zSU-29EtqLrSG0,29404
4
- ragaai_catalyst/evaluation.py,sha256=O96CydYVPh3duUmXjY6REIXMOR-tOPixSG-Qhrf636A,22955
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=1FaeK_VZpJLQ1ZqEWpMyI8J8M2MI0abLLLDFWY9W-4A,19580
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=10mSqz9X83wfEuciVlPnbCcAqG4N9dgoZ4EFxH1jQb4,8636
59
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=DjHOh7JpS3ksJ0swsXItAgYZhxlXsIOzt9kYtdxoUQY,6727
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.5b2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
92
- ragaai_catalyst-2.1.7.5b2.dist-info/METADATA,sha256=elCAm8gzY4PlNrlyL5G3iicELxdvr8j-Yr7niKTE-z8,17607
93
- ragaai_catalyst-2.1.7.5b2.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
94
- ragaai_catalyst-2.1.7.5b2.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
95
- ragaai_catalyst-2.1.7.5b2.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5