ragaai-catalyst 2.2.5b5__py3-none-any.whl → 2.2.6b1__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/prompt_manager.py +285 -112
- ragaai_catalyst/tracers/agentic_tracing/upload/trace_uploader.py +4 -9
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py +1 -1
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py +1 -1
- ragaai_catalyst/tracers/agentic_tracing/utils/create_dataset_schema.py +21 -10
- ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py +9 -1
- ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py +48 -35
- ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py +56 -28
- ragaai_catalyst/tracers/tracer.py +3 -3
- ragaai_catalyst/tracers/utils/trace_json_converter.py +7 -1
- {ragaai_catalyst-2.2.5b5.dist-info → ragaai_catalyst-2.2.6b1.dist-info}/METADATA +1 -1
- {ragaai_catalyst-2.2.5b5.dist-info → ragaai_catalyst-2.2.6b1.dist-info}/RECORD +16 -16
- /ragaai_catalyst/{tracers/agentic_tracing/upload/session_manager.py → session_manager.py} +0 -0
- {ragaai_catalyst-2.2.5b5.dist-info → ragaai_catalyst-2.2.6b1.dist-info}/WHEEL +0 -0
- {ragaai_catalyst-2.2.5b5.dist-info → ragaai_catalyst-2.2.6b1.dist-info}/licenses/LICENSE +0 -0
- {ragaai_catalyst-2.2.5b5.dist-info → ragaai_catalyst-2.2.6b1.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,16 @@
|
|
1
1
|
import os
|
2
|
-
import
|
2
|
+
from ragaai_catalyst.session_manager import session_manager
|
3
3
|
import json
|
4
4
|
import re
|
5
5
|
from .ragaai_catalyst import RagaAICatalyst
|
6
6
|
import copy
|
7
|
+
import logging
|
8
|
+
import time
|
9
|
+
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
10
|
+
from requests.exceptions import ConnectionError, Timeout, RequestException
|
11
|
+
from http.client import RemoteDisconnected
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
7
14
|
|
8
15
|
class PromptManager:
|
9
16
|
NUM_PROJECTS = 100
|
@@ -17,38 +24,80 @@ class PromptManager:
|
|
17
24
|
project_name (str): The name of the project.
|
18
25
|
|
19
26
|
Raises:
|
20
|
-
requests.RequestException: If there's an error with the API request.
|
21
27
|
ValueError: If the project is not found.
|
22
28
|
"""
|
23
29
|
self.project_name = project_name
|
24
30
|
self.base_url = f"{RagaAICatalyst.BASE_URL}/playground/prompt"
|
25
31
|
self.timeout = 10
|
26
32
|
self.size = 99999 #Number of projects to fetch
|
33
|
+
self.project_id = None
|
34
|
+
self.headers = {}
|
27
35
|
|
28
36
|
try:
|
29
|
-
|
37
|
+
start_time = time.time()
|
38
|
+
response = session_manager.make_request_with_retry(
|
39
|
+
"GET",
|
30
40
|
f"{RagaAICatalyst.BASE_URL}/v2/llm/projects?size={self.size}",
|
31
41
|
headers={
|
32
42
|
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
33
43
|
},
|
34
44
|
timeout=self.timeout,
|
35
45
|
)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
47
|
+
logger.debug(f"API Call: [GET] /v2/llm/projects | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
48
|
+
|
49
|
+
if response.status_code in [200, 201]:
|
50
|
+
# logger.debug("Projects list retrieved successfully")
|
51
|
+
project_list = [
|
52
|
+
project["name"] for project in response.json()["data"]["content"]
|
53
|
+
]
|
54
|
+
self.project_id = [
|
55
|
+
project["id"] for project in response.json()["data"]["content"] if project["name"]==project_name
|
56
|
+
][0]
|
57
|
+
elif response.status_code == 401:
|
58
|
+
logger.warning("Received 401 error during fetching project list. Attempting to refresh token.")
|
59
|
+
token = RagaAICatalyst.get_token(force_refresh=True)
|
60
|
+
headers = {
|
61
|
+
"Authorization": f"Bearer {token}",
|
62
|
+
}
|
63
|
+
start_time = time.time()
|
64
|
+
response = session_manager.make_request_with_retry(
|
65
|
+
"GET", f"{RagaAICatalyst.BASE_URL}/v2/llm/projects?size={self.size}",
|
66
|
+
headers=headers, timeout=self.timeout
|
67
|
+
)
|
68
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
69
|
+
logger.debug(f"API Call: [GET] /v2/llm/projects (retry) | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
70
|
+
|
71
|
+
if response.status_code in [200, 201]:
|
72
|
+
logger.info("Project list fetched successfully after 401 token refresh")
|
73
|
+
project_list = [
|
74
|
+
project["name"] for project in response.json()["data"]["content"]
|
75
|
+
]
|
76
|
+
self.project_id = [
|
77
|
+
project["id"] for project in response.json()["data"]["content"] if project["name"]==project_name
|
78
|
+
][0]
|
79
|
+
else:
|
80
|
+
logger.error("Failed to fetch project list after 401 token refresh")
|
81
|
+
return
|
82
|
+
else:
|
83
|
+
logger.error(f"HTTP {response.status_code} error when fetching project list")
|
84
|
+
return
|
85
|
+
|
86
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
87
|
+
session_manager.handle_request_exceptions(e, "fetching project list")
|
88
|
+
logger.error(f"Failed to fetch project list, PromptManager will have limited functionality")
|
89
|
+
return
|
90
|
+
except RequestException as e:
|
91
|
+
logger.error(f"Error while fetching project list: {e}")
|
92
|
+
logger.error(f"PromptManager will have limited functionality")
|
93
|
+
return
|
46
94
|
except (KeyError, json.JSONDecodeError) as e:
|
47
|
-
|
95
|
+
logger.error(f"Error parsing project list: {str(e)}")
|
96
|
+
return
|
48
97
|
|
49
98
|
if self.project_name not in project_list:
|
50
|
-
|
51
|
-
|
99
|
+
logger.error("Project not found. Please enter a valid project name")
|
100
|
+
return
|
52
101
|
|
53
102
|
self.headers = {
|
54
103
|
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
@@ -61,17 +110,19 @@ class PromptManager:
|
|
61
110
|
List all available prompts.
|
62
111
|
|
63
112
|
Returns:
|
64
|
-
list: A list of prompt names.
|
65
|
-
|
66
|
-
Raises:
|
67
|
-
requests.RequestException: If there's an error with the API request.
|
113
|
+
list: A list of prompt names, or empty list if error occurs.
|
68
114
|
"""
|
115
|
+
if not self.project_id:
|
116
|
+
logger.error("PromptManager not properly initialized, cannot list prompts")
|
117
|
+
return []
|
118
|
+
|
69
119
|
prompt = Prompt()
|
70
120
|
try:
|
71
121
|
prompt_list = prompt.list_prompts(self.base_url, self.headers, self.timeout)
|
72
122
|
return prompt_list
|
73
|
-
except
|
74
|
-
|
123
|
+
except Exception as e:
|
124
|
+
logger.error(f"Error listing prompts: {str(e)}")
|
125
|
+
return []
|
75
126
|
|
76
127
|
def get_prompt(self, prompt_name, version=None):
|
77
128
|
"""
|
@@ -82,34 +133,39 @@ class PromptManager:
|
|
82
133
|
version (str, optional): The version of the prompt. Defaults to None.
|
83
134
|
|
84
135
|
Returns:
|
85
|
-
PromptObject: An object representing the prompt.
|
86
|
-
|
87
|
-
Raises:
|
88
|
-
ValueError: If the prompt or version is not found.
|
89
|
-
requests.RequestException: If there's an error with the API request.
|
136
|
+
PromptObject: An object representing the prompt, or None if error occurs.
|
90
137
|
"""
|
138
|
+
if not self.project_id:
|
139
|
+
logger.error("PromptManager not properly initialized, cannot get prompt")
|
140
|
+
return None
|
141
|
+
|
91
142
|
try:
|
92
143
|
prompt_list = self.list_prompts()
|
93
|
-
except
|
94
|
-
|
144
|
+
except Exception as e:
|
145
|
+
logger.error(f"Error fetching prompt list: {str(e)}")
|
146
|
+
return None
|
95
147
|
|
96
148
|
if prompt_name not in prompt_list:
|
97
|
-
|
149
|
+
logger.error("Prompt not found. Please enter a valid prompt name")
|
150
|
+
return None
|
98
151
|
|
99
152
|
try:
|
100
153
|
prompt_versions = self.list_prompt_versions(prompt_name)
|
101
|
-
except
|
102
|
-
|
154
|
+
except Exception as e:
|
155
|
+
logger.error(f"Error fetching prompt versions: {str(e)}")
|
156
|
+
return None
|
103
157
|
|
104
158
|
if version and version not in prompt_versions.keys():
|
105
|
-
|
159
|
+
logger.error("Version not found. Please enter a valid version name")
|
160
|
+
return None
|
106
161
|
|
107
162
|
prompt = Prompt()
|
108
163
|
try:
|
109
164
|
prompt_object = prompt.get_prompt(self.base_url, self.headers, self.timeout, prompt_name, version)
|
110
165
|
return prompt_object
|
111
|
-
except
|
112
|
-
|
166
|
+
except Exception as e:
|
167
|
+
logger.error(f"Error fetching prompt: {str(e)}")
|
168
|
+
return None
|
113
169
|
|
114
170
|
def list_prompt_versions(self, prompt_name):
|
115
171
|
"""
|
@@ -119,26 +175,29 @@ class PromptManager:
|
|
119
175
|
prompt_name (str): The name of the prompt.
|
120
176
|
|
121
177
|
Returns:
|
122
|
-
dict: A dictionary mapping version names to prompt texts.
|
123
|
-
|
124
|
-
Raises:
|
125
|
-
ValueError: If the prompt is not found.
|
126
|
-
requests.RequestException: If there's an error with the API request.
|
178
|
+
dict: A dictionary mapping version names to prompt texts, or empty dict if error occurs.
|
127
179
|
"""
|
180
|
+
if not self.project_id:
|
181
|
+
logger.error("PromptManager not properly initialized, cannot list prompt versions")
|
182
|
+
return {}
|
183
|
+
|
128
184
|
try:
|
129
185
|
prompt_list = self.list_prompts()
|
130
|
-
except
|
131
|
-
|
186
|
+
except Exception as e:
|
187
|
+
logger.error(f"Error fetching prompt list: {str(e)}")
|
188
|
+
return {}
|
132
189
|
|
133
190
|
if prompt_name not in prompt_list:
|
134
|
-
|
191
|
+
logger.error("Prompt not found. Please enter a valid prompt name")
|
192
|
+
return {}
|
135
193
|
|
136
194
|
prompt = Prompt()
|
137
195
|
try:
|
138
196
|
prompt_versions = prompt.list_prompt_versions(self.base_url, self.headers, self.timeout, prompt_name)
|
139
197
|
return prompt_versions
|
140
|
-
except
|
141
|
-
|
198
|
+
except Exception as e:
|
199
|
+
logger.error(f"Error fetching prompt versions: {str(e)}")
|
200
|
+
return {}
|
142
201
|
|
143
202
|
|
144
203
|
class Prompt:
|
@@ -158,21 +217,48 @@ class Prompt:
|
|
158
217
|
timeout (int): The timeout for the request.
|
159
218
|
|
160
219
|
Returns:
|
161
|
-
list: A list of prompt names.
|
162
|
-
|
163
|
-
Raises:
|
164
|
-
requests.RequestException: If there's an error with the API request.
|
165
|
-
ValueError: If there's an error parsing the prompt list.
|
220
|
+
list: A list of prompt names, or empty list if error occurs.
|
166
221
|
"""
|
167
222
|
try:
|
168
|
-
|
169
|
-
response.
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
223
|
+
start_time = time.time()
|
224
|
+
response = session_manager.make_request_with_retry("GET", url, headers=headers, timeout=timeout)
|
225
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
226
|
+
logger.debug(f"API Call: [GET] {url} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
227
|
+
|
228
|
+
if response.status_code in [200, 201]:
|
229
|
+
prompt_list = [prompt["name"] for prompt in response.json()["data"]]
|
230
|
+
return prompt_list
|
231
|
+
elif response.status_code == 401:
|
232
|
+
logger.warning("Received 401 error during listing prompts. Attempting to refresh token.")
|
233
|
+
token = RagaAICatalyst.get_token(force_refresh=True)
|
234
|
+
new_headers = headers.copy()
|
235
|
+
new_headers["Authorization"] = f"Bearer {token}"
|
236
|
+
|
237
|
+
start_time = time.time()
|
238
|
+
response = session_manager.make_request_with_retry("GET", url, headers=new_headers, timeout=timeout)
|
239
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
240
|
+
logger.debug(f"API Call: [GET] {url} (retry) | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
241
|
+
|
242
|
+
if response.status_code in [200, 201]:
|
243
|
+
logger.info("Prompts listed successfully after 401 token refresh")
|
244
|
+
prompt_list = [prompt["name"] for prompt in response.json()["data"]]
|
245
|
+
return prompt_list
|
246
|
+
else:
|
247
|
+
logger.error("Failed to list prompts after 401 token refresh")
|
248
|
+
return []
|
249
|
+
else:
|
250
|
+
logger.error(f"HTTP {response.status_code} error when listing prompts")
|
251
|
+
return []
|
252
|
+
|
253
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
254
|
+
session_manager.handle_request_exceptions(e, "listing prompts")
|
255
|
+
return []
|
256
|
+
except RequestException as e:
|
257
|
+
logger.error(f"Error while listing prompts: {e}")
|
258
|
+
return []
|
174
259
|
except (KeyError, json.JSONDecodeError) as e:
|
175
|
-
|
260
|
+
logger.error(f"Error parsing prompt list: {str(e)}")
|
261
|
+
return []
|
176
262
|
|
177
263
|
def _get_response_by_version(self, base_url, headers, timeout, prompt_name, version):
|
178
264
|
"""
|
@@ -186,21 +272,47 @@ class Prompt:
|
|
186
272
|
version (str): The version of the prompt.
|
187
273
|
|
188
274
|
Returns:
|
189
|
-
response: The response object containing the prompt version data.
|
190
|
-
|
191
|
-
Raises:
|
192
|
-
requests.RequestException: If there's an error with the API request.
|
193
|
-
ValueError: If there's an error parsing the prompt version.
|
275
|
+
response: The response object containing the prompt version data, or None if error occurs.
|
194
276
|
"""
|
195
277
|
try:
|
196
|
-
|
197
|
-
|
198
|
-
response.
|
199
|
-
|
200
|
-
|
278
|
+
url = f"{base_url}/version/{prompt_name}?version={version}"
|
279
|
+
start_time = time.time()
|
280
|
+
response = session_manager.make_request_with_retry("GET", url, headers=headers, timeout=timeout)
|
281
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
282
|
+
logger.debug(f"API Call: [GET] {url} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
283
|
+
|
284
|
+
if response.status_code in [200, 201]:
|
285
|
+
return response
|
286
|
+
elif response.status_code == 401:
|
287
|
+
logger.warning(f"Received 401 error during fetching prompt version {version} for {prompt_name}. Attempting to refresh token.")
|
288
|
+
token = RagaAICatalyst.get_token(force_refresh=True)
|
289
|
+
new_headers = headers.copy()
|
290
|
+
new_headers["Authorization"] = f"Bearer {token}"
|
291
|
+
|
292
|
+
start_time = time.time()
|
293
|
+
response = session_manager.make_request_with_retry("GET", url, headers=new_headers, timeout=timeout)
|
294
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
295
|
+
logger.debug(f"API Call: [GET] {url} (retry) | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
296
|
+
|
297
|
+
if response.status_code in [200, 201]:
|
298
|
+
logger.info(f"Prompt version {version} for {prompt_name} fetched successfully after 401 token refresh")
|
299
|
+
return response
|
300
|
+
else:
|
301
|
+
logger.error(f"Failed to fetch prompt version {version} for {prompt_name} after 401 token refresh")
|
302
|
+
return None
|
303
|
+
else:
|
304
|
+
logger.error(f"HTTP {response.status_code} error when fetching prompt version {version} for {prompt_name}")
|
305
|
+
return None
|
306
|
+
|
307
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
308
|
+
session_manager.handle_request_exceptions(e, f"fetching prompt version {version} for {prompt_name}")
|
309
|
+
return None
|
310
|
+
except RequestException as e:
|
311
|
+
logger.error(f"Error while fetching prompt version {version} for {prompt_name}: {e}")
|
312
|
+
return None
|
201
313
|
except (KeyError, json.JSONDecodeError, IndexError) as e:
|
202
|
-
|
203
|
-
|
314
|
+
logger.error(f"Error parsing prompt version: {str(e)}")
|
315
|
+
return None
|
204
316
|
|
205
317
|
def _get_response(self, base_url, headers, timeout, prompt_name):
|
206
318
|
"""
|
@@ -213,21 +325,47 @@ class Prompt:
|
|
213
325
|
prompt_name (str): The name of the prompt.
|
214
326
|
|
215
327
|
Returns:
|
216
|
-
response: The response object containing the latest prompt version data.
|
217
|
-
|
218
|
-
Raises:
|
219
|
-
requests.RequestException: If there's an error with the API request.
|
220
|
-
ValueError: If there's an error parsing the prompt version.
|
328
|
+
response: The response object containing the latest prompt version data, or None if error occurs.
|
221
329
|
"""
|
222
330
|
try:
|
223
|
-
|
224
|
-
|
225
|
-
response.
|
226
|
-
|
227
|
-
|
331
|
+
url = f"{base_url}/version/{prompt_name}"
|
332
|
+
start_time = time.time()
|
333
|
+
response = session_manager.make_request_with_retry("GET", url, headers=headers, timeout=timeout)
|
334
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
335
|
+
logger.debug(f"API Call: [GET] {url} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
336
|
+
|
337
|
+
if response.status_code in [200, 201]:
|
338
|
+
return response
|
339
|
+
elif response.status_code == 401:
|
340
|
+
logger.warning(f"Received 401 error during fetching latest prompt version for {prompt_name}. Attempting to refresh token.")
|
341
|
+
token = RagaAICatalyst.get_token(force_refresh=True)
|
342
|
+
new_headers = headers.copy()
|
343
|
+
new_headers["Authorization"] = f"Bearer {token}"
|
344
|
+
|
345
|
+
start_time = time.time()
|
346
|
+
response = session_manager.make_request_with_retry("GET", url, headers=new_headers, timeout=timeout)
|
347
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
348
|
+
logger.debug(f"API Call: [GET] {url} (retry) | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
349
|
+
|
350
|
+
if response.status_code in [200, 201]:
|
351
|
+
logger.info(f"Latest prompt version for {prompt_name} fetched successfully after 401 token refresh")
|
352
|
+
return response
|
353
|
+
else:
|
354
|
+
logger.error(f"Failed to fetch latest prompt version for {prompt_name} after 401 token refresh")
|
355
|
+
return None
|
356
|
+
else:
|
357
|
+
logger.error(f"HTTP {response.status_code} error when fetching latest prompt version for {prompt_name}")
|
358
|
+
return None
|
359
|
+
|
360
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
361
|
+
session_manager.handle_request_exceptions(e, f"fetching latest prompt version for {prompt_name}")
|
362
|
+
return None
|
363
|
+
except RequestException as e:
|
364
|
+
logger.error(f"Error while fetching latest prompt version for {prompt_name}: {e}")
|
365
|
+
return None
|
228
366
|
except (KeyError, json.JSONDecodeError, IndexError) as e:
|
229
|
-
|
230
|
-
|
367
|
+
logger.error(f"Error parsing prompt version: {str(e)}")
|
368
|
+
return None
|
231
369
|
|
232
370
|
def _get_prompt_by_version(self, base_url, headers, timeout, prompt_name, version):
|
233
371
|
"""
|
@@ -241,14 +379,17 @@ class Prompt:
|
|
241
379
|
version (str): The version of the prompt.
|
242
380
|
|
243
381
|
Returns:
|
244
|
-
str: The text of the prompt.
|
245
|
-
|
246
|
-
Raises:
|
247
|
-
requests.RequestException: If there's an error with the API request.
|
382
|
+
str: The text of the prompt, or empty string if error occurs.
|
248
383
|
"""
|
249
384
|
response = self._get_response_by_version(base_url, headers, timeout, prompt_name, version)
|
250
|
-
|
251
|
-
|
385
|
+
if response is None:
|
386
|
+
return ""
|
387
|
+
try:
|
388
|
+
prompt_text = response.json()["data"]["docs"][0]["textFields"]
|
389
|
+
return prompt_text
|
390
|
+
except (KeyError, json.JSONDecodeError, IndexError) as e:
|
391
|
+
logger.error(f"Error parsing prompt text: {str(e)}")
|
392
|
+
return ""
|
252
393
|
|
253
394
|
def get_prompt(self, base_url, headers, timeout, prompt_name, version=None):
|
254
395
|
"""
|
@@ -262,22 +403,24 @@ class Prompt:
|
|
262
403
|
version (str, optional): The version of the prompt. Defaults to None.
|
263
404
|
|
264
405
|
Returns:
|
265
|
-
PromptObject: An object representing the prompt.
|
266
|
-
|
267
|
-
Raises:
|
268
|
-
requests.RequestException: If there's an error with the API request.
|
406
|
+
PromptObject: An object representing the prompt, or None if error occurs.
|
269
407
|
"""
|
270
408
|
if version:
|
271
409
|
response = self._get_response_by_version(base_url, headers, timeout, prompt_name, version)
|
272
|
-
prompt_text = response.json()["data"]["docs"][0]["textFields"]
|
273
|
-
prompt_parameters = response.json()["data"]["docs"][0]["modelSpecs"]["parameters"]
|
274
|
-
model = response.json()["data"]["docs"][0]["modelSpecs"]["model"]
|
275
410
|
else:
|
276
411
|
response = self._get_response(base_url, headers, timeout, prompt_name)
|
412
|
+
|
413
|
+
if response is None:
|
414
|
+
return None
|
415
|
+
|
416
|
+
try:
|
277
417
|
prompt_text = response.json()["data"]["docs"][0]["textFields"]
|
278
418
|
prompt_parameters = response.json()["data"]["docs"][0]["modelSpecs"]["parameters"]
|
279
419
|
model = response.json()["data"]["docs"][0]["modelSpecs"]["model"]
|
280
|
-
|
420
|
+
return PromptObject(prompt_text, prompt_parameters, model)
|
421
|
+
except (KeyError, json.JSONDecodeError, IndexError) as e:
|
422
|
+
logger.error(f"Error parsing prompt data: {str(e)}")
|
423
|
+
return None
|
281
424
|
|
282
425
|
|
283
426
|
def list_prompt_versions(self, base_url, headers, timeout, prompt_name):
|
@@ -291,25 +434,55 @@ class Prompt:
|
|
291
434
|
prompt_name (str): The name of the prompt.
|
292
435
|
|
293
436
|
Returns:
|
294
|
-
dict: A dictionary mapping version names to prompt texts.
|
295
|
-
|
296
|
-
Raises:
|
297
|
-
requests.RequestException: If there's an error with the API request.
|
298
|
-
ValueError: If there's an error parsing the prompt versions.
|
437
|
+
dict: A dictionary mapping version names to prompt texts, or empty dict if error occurs.
|
299
438
|
"""
|
300
439
|
try:
|
301
|
-
|
302
|
-
|
303
|
-
response.
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
440
|
+
url = f"{base_url}/{prompt_name}/version"
|
441
|
+
start_time = time.time()
|
442
|
+
response = session_manager.make_request_with_retry("GET", url, headers=headers, timeout=timeout)
|
443
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
444
|
+
logger.debug(f"API Call: [GET] {url} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
445
|
+
|
446
|
+
if response.status_code in [200, 201]:
|
447
|
+
version_names = [version["name"] for version in response.json()["data"]]
|
448
|
+
prompt_versions = {}
|
449
|
+
for version in version_names:
|
450
|
+
prompt_versions[version] = self._get_prompt_by_version(base_url, headers, timeout, prompt_name, version)
|
451
|
+
return prompt_versions
|
452
|
+
elif response.status_code == 401:
|
453
|
+
logger.warning(f"Received 401 error during listing prompt versions for {prompt_name}. Attempting to refresh token.")
|
454
|
+
token = RagaAICatalyst.get_token(force_refresh=True)
|
455
|
+
new_headers = headers.copy()
|
456
|
+
new_headers["Authorization"] = f"Bearer {token}"
|
457
|
+
|
458
|
+
start_time = time.time()
|
459
|
+
response = session_manager.make_request_with_retry("GET", url, headers=new_headers, timeout=timeout)
|
460
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
461
|
+
logger.debug(f"API Call: [GET] {url} (retry) | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
462
|
+
|
463
|
+
if response.status_code in [200, 201]:
|
464
|
+
logger.info(f"Prompt versions for {prompt_name} listed successfully after 401 token refresh")
|
465
|
+
version_names = [version["name"] for version in response.json()["data"]]
|
466
|
+
prompt_versions = {}
|
467
|
+
for version in version_names:
|
468
|
+
prompt_versions[version] = self._get_prompt_by_version(base_url, new_headers, timeout, prompt_name, version)
|
469
|
+
return prompt_versions
|
470
|
+
else:
|
471
|
+
logger.error(f"Failed to list prompt versions for {prompt_name} after 401 token refresh")
|
472
|
+
return {}
|
473
|
+
else:
|
474
|
+
logger.error(f"HTTP {response.status_code} error when listing prompt versions for {prompt_name}")
|
475
|
+
return {}
|
476
|
+
|
477
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
478
|
+
session_manager.handle_request_exceptions(e, f"listing prompt versions for {prompt_name}")
|
479
|
+
return {}
|
480
|
+
except RequestException as e:
|
481
|
+
logger.error(f"Error while listing prompt versions for {prompt_name}: {e}")
|
482
|
+
return {}
|
311
483
|
except (KeyError, json.JSONDecodeError) as e:
|
312
|
-
|
484
|
+
logger.error(f"Error parsing prompt versions: {str(e)}")
|
485
|
+
return {}
|
313
486
|
|
314
487
|
|
315
488
|
class PromptObject:
|
@@ -325,7 +498,7 @@ class PromptObject:
|
|
325
498
|
self.text = text
|
326
499
|
self.parameters = parameters
|
327
500
|
self.model = model
|
328
|
-
|
501
|
+
|
329
502
|
def _extract_variable_from_content(self, content):
|
330
503
|
"""
|
331
504
|
Extract variables from the content.
|
@@ -3,22 +3,16 @@ trace_uploader.py - A dedicated process for handling trace uploads
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import os
|
6
|
-
import sys
|
7
6
|
import json
|
8
7
|
import time
|
9
|
-
import signal
|
10
8
|
import logging
|
11
9
|
import argparse
|
12
10
|
import tempfile
|
13
|
-
from pathlib import Path
|
14
|
-
import multiprocessing
|
15
|
-
import queue
|
16
11
|
from datetime import datetime
|
17
12
|
import atexit
|
18
|
-
import glob
|
19
13
|
from logging.handlers import RotatingFileHandler
|
20
14
|
import concurrent.futures
|
21
|
-
from typing import Dict, Any
|
15
|
+
from typing import Dict, Any
|
22
16
|
import threading
|
23
17
|
import uuid
|
24
18
|
|
@@ -50,7 +44,7 @@ try:
|
|
50
44
|
from ragaai_catalyst.tracers.agentic_tracing.upload.upload_code import upload_code
|
51
45
|
# from ragaai_catalyst.tracers.agentic_tracing.upload.upload_trace_metric import upload_trace_metric
|
52
46
|
from ragaai_catalyst.tracers.agentic_tracing.utils.create_dataset_schema import create_dataset_schema_with_trace
|
53
|
-
from ragaai_catalyst.
|
47
|
+
from ragaai_catalyst.session_manager import session_manager
|
54
48
|
from ragaai_catalyst import RagaAICatalyst
|
55
49
|
IMPORTS_AVAILABLE = True
|
56
50
|
except ImportError:
|
@@ -481,7 +475,8 @@ def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, da
|
|
481
475
|
|
482
476
|
return task_id
|
483
477
|
except RuntimeError as e:
|
484
|
-
if
|
478
|
+
if any(msg in str(e) for msg in
|
479
|
+
("cannot schedule new futures after shutdown", "cannot schedule new futures after interpreter shutdown")):
|
485
480
|
logger.warning(f"Executor already shut down, falling back to synchronous processing: {e}")
|
486
481
|
return do_sync_processing()
|
487
482
|
else:
|
@@ -7,7 +7,7 @@ from urllib.parse import urlparse, urlunparse
|
|
7
7
|
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
8
8
|
from requests.exceptions import ConnectionError, Timeout, RequestException
|
9
9
|
from http.client import RemoteDisconnected
|
10
|
-
from .session_manager import session_manager
|
10
|
+
from ragaai_catalyst.session_manager import session_manager
|
11
11
|
|
12
12
|
logger = logging.getLogger(__name__)
|
13
13
|
|
@@ -9,7 +9,7 @@ from requests.exceptions import ConnectionError, Timeout, RequestException
|
|
9
9
|
from http.client import RemoteDisconnected
|
10
10
|
|
11
11
|
from ragaai_catalyst.ragaai_catalyst import RagaAICatalyst
|
12
|
-
from .session_manager import session_manager
|
12
|
+
from ragaai_catalyst.session_manager import session_manager
|
13
13
|
|
14
14
|
logger = logging.getLogger(__name__)
|
15
15
|
|
@@ -1,25 +1,36 @@
|
|
1
1
|
import os
|
2
2
|
import json
|
3
|
-
import
|
3
|
+
import requests
|
4
4
|
import logging
|
5
5
|
import time
|
6
|
+
from typing import Optional
|
6
7
|
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
7
8
|
from requests.exceptions import ConnectionError, Timeout, RequestException
|
8
9
|
from http.client import RemoteDisconnected
|
9
10
|
|
10
11
|
from ragaai_catalyst import RagaAICatalyst
|
11
|
-
from ragaai_catalyst.
|
12
|
+
from ragaai_catalyst.session_manager import session_manager
|
12
13
|
|
14
|
+
IGNORED_KEYS = {"log_source", "recorded_on"}
|
13
15
|
logger = logging.getLogger(__name__)
|
14
16
|
|
15
|
-
def create_dataset_schema_with_trace(
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
def create_dataset_schema_with_trace(
|
18
|
+
project_name: str,
|
19
|
+
dataset_name: str,
|
20
|
+
base_url: Optional[str] = None,
|
21
|
+
user_details: Optional[dict] = None,
|
22
|
+
timeout: int = 120) -> requests.Response:
|
23
|
+
schema_mapping = {}
|
24
|
+
|
25
|
+
metadata = (
|
26
|
+
user_details.get("trace_user_detail", {}).get("metadata", {})
|
27
|
+
if user_details else {}
|
28
|
+
)
|
29
|
+
if isinstance(metadata, dict):
|
19
30
|
for key, value in metadata.items():
|
20
|
-
if key in
|
31
|
+
if key in IGNORED_KEYS:
|
21
32
|
continue
|
22
|
-
|
33
|
+
schema_mapping[key] = {"columnType": "metadata"}
|
23
34
|
|
24
35
|
headers = {
|
25
36
|
"Content-Type": "application/json",
|
@@ -27,11 +38,11 @@ def create_dataset_schema_with_trace(project_name, dataset_name, base_url=None,
|
|
27
38
|
"X-Project-Name": project_name,
|
28
39
|
}
|
29
40
|
|
30
|
-
if
|
41
|
+
if schema_mapping:
|
31
42
|
payload = json.dumps({
|
32
43
|
"datasetName": dataset_name,
|
33
44
|
"traceFolderUrl": None,
|
34
|
-
"schemaMapping":
|
45
|
+
"schemaMapping": schema_mapping
|
35
46
|
})
|
36
47
|
else:
|
37
48
|
payload = json.dumps({
|
@@ -7,6 +7,8 @@ import re
|
|
7
7
|
import ast
|
8
8
|
import importlib.util
|
9
9
|
import json
|
10
|
+
from typing import List, Optional, Tuple
|
11
|
+
|
10
12
|
import ipynbname
|
11
13
|
from copy import deepcopy
|
12
14
|
|
@@ -460,8 +462,14 @@ class TraceDependencyTracker:
|
|
460
462
|
logger.debug(f"Zip file created successfully at: {zip_filename}")
|
461
463
|
return hash_id, zip_filename
|
462
464
|
|
463
|
-
def zip_list_of_unique_files(
|
465
|
+
def zip_list_of_unique_files(
|
466
|
+
filepaths: List[str],
|
467
|
+
output_dir: Optional[str] = None
|
468
|
+
) -> Tuple[str, str]:
|
464
469
|
"""Create a zip file containing all unique files and their dependencies."""
|
470
|
+
if not filepaths:
|
471
|
+
logger.warning("The filepaths list is empty. Proceeding with an empty ZIP archive.")
|
472
|
+
filepaths = []
|
465
473
|
if output_dir is None:
|
466
474
|
# Set default output directory based on environment
|
467
475
|
if JupyterNotebookHandler.is_running_in_colab():
|
@@ -4,17 +4,34 @@ Dynamic Trace Exporter - A wrapper for RAGATraceExporter that allows dynamic upd
|
|
4
4
|
import logging
|
5
5
|
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
6
6
|
from ragaai_catalyst.tracers.exporters.ragaai_trace_exporter import RAGATraceExporter
|
7
|
+
from typing import Optional, List, Dict, Callable
|
7
8
|
|
8
9
|
logger = logging.getLogger("RagaAICatalyst")
|
9
10
|
|
11
|
+
|
10
12
|
class DynamicTraceExporter(SpanExporter):
|
11
13
|
"""
|
12
14
|
A wrapper around RAGATraceExporter that allows dynamic updates to properties.
|
13
15
|
This exporter forwards all calls to the underlying RAGATraceExporter but allows
|
14
16
|
certain properties to be updated dynamically during execution.
|
15
17
|
"""
|
16
|
-
|
17
|
-
|
18
|
+
def __init__(
|
19
|
+
self,
|
20
|
+
project_name: str,
|
21
|
+
dataset_name: str,
|
22
|
+
base_url: str,
|
23
|
+
tracer_type: str,
|
24
|
+
files_to_zip: Optional[List[str]] = None,
|
25
|
+
project_id: Optional[str] = None,
|
26
|
+
user_details: Optional[Dict] = None,
|
27
|
+
custom_model_cost: Optional[dict] = None,
|
28
|
+
timeout: int = 120,
|
29
|
+
post_processor: Optional[Callable] = None,
|
30
|
+
max_upload_workers: int = 30,
|
31
|
+
user_context: Optional[str] = None,
|
32
|
+
user_gt: Optional[str] = None,
|
33
|
+
external_id: Optional[str] = None
|
34
|
+
):
|
18
35
|
"""
|
19
36
|
Initialize the DynamicTraceExporter.
|
20
37
|
|
@@ -30,22 +47,22 @@ class DynamicTraceExporter(SpanExporter):
|
|
30
47
|
max_upload_workers: Maximum number of upload workers
|
31
48
|
"""
|
32
49
|
self._exporter = RAGATraceExporter(
|
50
|
+
project_name=project_name,
|
51
|
+
dataset_name=dataset_name,
|
52
|
+
base_url=base_url,
|
33
53
|
tracer_type=tracer_type,
|
34
54
|
files_to_zip=files_to_zip,
|
35
|
-
project_name=project_name,
|
36
55
|
project_id=project_id,
|
37
|
-
dataset_name=dataset_name,
|
38
56
|
user_details=user_details,
|
39
|
-
base_url=base_url,
|
40
57
|
custom_model_cost=custom_model_cost,
|
41
58
|
timeout=timeout,
|
42
|
-
post_processor=
|
43
|
-
max_upload_workers
|
44
|
-
user_context
|
45
|
-
user_gt
|
59
|
+
post_processor=post_processor,
|
60
|
+
max_upload_workers=max_upload_workers,
|
61
|
+
user_context=user_context,
|
62
|
+
user_gt=user_gt,
|
46
63
|
external_id=external_id
|
47
64
|
)
|
48
|
-
|
65
|
+
|
49
66
|
# Store the initial values
|
50
67
|
self._files_to_zip = files_to_zip
|
51
68
|
self._project_name = project_name
|
@@ -60,7 +77,6 @@ class DynamicTraceExporter(SpanExporter):
|
|
60
77
|
self._user_gt = user_gt
|
61
78
|
self._external_id = external_id
|
62
79
|
|
63
|
-
|
64
80
|
def export(self, spans):
|
65
81
|
"""
|
66
82
|
Export spans by forwarding to the underlying exporter.
|
@@ -84,8 +100,6 @@ class DynamicTraceExporter(SpanExporter):
|
|
84
100
|
return result
|
85
101
|
except Exception as e:
|
86
102
|
logger.error(f"Error exporting trace: {e}")
|
87
|
-
|
88
|
-
|
89
103
|
|
90
104
|
def shutdown(self):
|
91
105
|
"""
|
@@ -103,7 +117,7 @@ class DynamicTraceExporter(SpanExporter):
|
|
103
117
|
return self._exporter.shutdown()
|
104
118
|
except Exception as e:
|
105
119
|
logger.error(f"Error shutting down exporter: {e}")
|
106
|
-
|
120
|
+
|
107
121
|
def _update_exporter_properties(self):
|
108
122
|
"""
|
109
123
|
Update the underlying exporter's properties with the current values.
|
@@ -118,55 +132,55 @@ class DynamicTraceExporter(SpanExporter):
|
|
118
132
|
self._exporter.post_processor = self._post_processor
|
119
133
|
self._exporter.max_upload_workers = self._max_upload_workers
|
120
134
|
self._exporter.user_context = self._user_context
|
121
|
-
self._exporter.user_gt = self._user_gt
|
135
|
+
self._exporter.user_gt = self._user_gt
|
122
136
|
self._exporter.external_id = self._external_id
|
123
|
-
|
137
|
+
|
124
138
|
# Getter and setter methods for dynamic properties
|
125
|
-
|
139
|
+
|
126
140
|
@property
|
127
141
|
def files_to_zip(self):
|
128
142
|
return self._files_to_zip
|
129
|
-
|
143
|
+
|
130
144
|
@files_to_zip.setter
|
131
145
|
def files_to_zip(self, value):
|
132
146
|
self._files_to_zip = value
|
133
|
-
|
147
|
+
|
134
148
|
@property
|
135
149
|
def project_name(self):
|
136
150
|
return self._project_name
|
137
|
-
|
151
|
+
|
138
152
|
@project_name.setter
|
139
153
|
def project_name(self, value):
|
140
154
|
self._project_name = value
|
141
|
-
|
155
|
+
|
142
156
|
@property
|
143
157
|
def project_id(self):
|
144
158
|
return self._project_id
|
145
|
-
|
159
|
+
|
146
160
|
@project_id.setter
|
147
161
|
def project_id(self, value):
|
148
162
|
self._project_id = value
|
149
|
-
|
163
|
+
|
150
164
|
@property
|
151
165
|
def dataset_name(self):
|
152
166
|
return self._dataset_name
|
153
|
-
|
167
|
+
|
154
168
|
@dataset_name.setter
|
155
169
|
def dataset_name(self, value):
|
156
170
|
self._dataset_name = value
|
157
|
-
|
171
|
+
|
158
172
|
@property
|
159
173
|
def user_details(self):
|
160
174
|
return self._user_details
|
161
|
-
|
175
|
+
|
162
176
|
@user_details.setter
|
163
177
|
def user_details(self, value):
|
164
178
|
self._user_details = value
|
165
|
-
|
179
|
+
|
166
180
|
@property
|
167
181
|
def base_url(self):
|
168
182
|
return self._base_url
|
169
|
-
|
183
|
+
|
170
184
|
@base_url.setter
|
171
185
|
def base_url(self, value):
|
172
186
|
self._base_url = value
|
@@ -174,15 +188,15 @@ class DynamicTraceExporter(SpanExporter):
|
|
174
188
|
@property
|
175
189
|
def custom_model_cost(self):
|
176
190
|
return self._custom_model_cost
|
177
|
-
|
191
|
+
|
178
192
|
@custom_model_cost.setter
|
179
193
|
def custom_model_cost(self, value):
|
180
194
|
self._custom_model_cost = value
|
181
|
-
|
195
|
+
|
182
196
|
@property
|
183
197
|
def max_upload_workers(self):
|
184
198
|
return self._max_upload_workers
|
185
|
-
|
199
|
+
|
186
200
|
@max_upload_workers.setter
|
187
201
|
def max_upload_workers(self, value):
|
188
202
|
self._max_upload_workers = value
|
@@ -190,7 +204,7 @@ class DynamicTraceExporter(SpanExporter):
|
|
190
204
|
@property
|
191
205
|
def user_context(self):
|
192
206
|
return self._user_context
|
193
|
-
|
207
|
+
|
194
208
|
@user_context.setter
|
195
209
|
def user_context(self, value):
|
196
210
|
self._user_context = value
|
@@ -198,7 +212,7 @@ class DynamicTraceExporter(SpanExporter):
|
|
198
212
|
@property
|
199
213
|
def user_gt(self):
|
200
214
|
return self._user_gt
|
201
|
-
|
215
|
+
|
202
216
|
@user_gt.setter
|
203
217
|
def user_gt(self, value):
|
204
218
|
self._user_gt = value
|
@@ -206,8 +220,7 @@ class DynamicTraceExporter(SpanExporter):
|
|
206
220
|
@property
|
207
221
|
def external_id(self):
|
208
222
|
return self._external_id
|
209
|
-
|
223
|
+
|
210
224
|
@external_id.setter
|
211
225
|
def external_id(self, value):
|
212
226
|
self._external_id = value
|
213
|
-
|
@@ -3,6 +3,7 @@ import logging
|
|
3
3
|
import os
|
4
4
|
import tempfile
|
5
5
|
from dataclasses import asdict
|
6
|
+
from typing import Optional, Callable, Dict, List
|
6
7
|
|
7
8
|
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
8
9
|
|
@@ -23,6 +24,7 @@ logging_level = (
|
|
23
24
|
logger.setLevel(logging.DEBUG) if os.getenv("DEBUG") == "1" else logging.INFO
|
24
25
|
)
|
25
26
|
|
27
|
+
|
26
28
|
class TracerJSONEncoder(json.JSONEncoder):
|
27
29
|
def default(self, obj):
|
28
30
|
if isinstance(obj, datetime):
|
@@ -47,8 +49,25 @@ class TracerJSONEncoder(json.JSONEncoder):
|
|
47
49
|
except:
|
48
50
|
return None # Last resort: return None instead of failing
|
49
51
|
|
52
|
+
|
50
53
|
class RAGATraceExporter(SpanExporter):
|
51
|
-
def __init__(
|
54
|
+
def __init__(
|
55
|
+
self,
|
56
|
+
project_name: str,
|
57
|
+
dataset_name: str,
|
58
|
+
base_url: str,
|
59
|
+
tracer_type: str,
|
60
|
+
files_to_zip: Optional[List[str]] = None,
|
61
|
+
project_id: Optional[str] = None,
|
62
|
+
user_details: Optional[Dict] = None,
|
63
|
+
custom_model_cost: Optional[dict] = None,
|
64
|
+
timeout: int = 120,
|
65
|
+
post_processor: Optional[Callable] = None,
|
66
|
+
max_upload_workers: int = 30,
|
67
|
+
user_context: Optional[str] = None,
|
68
|
+
user_gt: Optional[str] = None,
|
69
|
+
external_id: Optional[str] = None
|
70
|
+
):
|
52
71
|
self.trace_spans = dict()
|
53
72
|
self.tmp_dir = tempfile.gettempdir()
|
54
73
|
self.tracer_type = tracer_type
|
@@ -77,7 +96,7 @@ class RAGATraceExporter(SpanExporter):
|
|
77
96
|
|
78
97
|
if trace_id not in self.trace_spans:
|
79
98
|
self.trace_spans[trace_id] = list()
|
80
|
-
|
99
|
+
|
81
100
|
if span_json.get("attributes").get("openinference.span.kind", None) is None:
|
82
101
|
span_json["attributes"]["openinference.span.kind"] = "UNKNOWN"
|
83
102
|
|
@@ -118,10 +137,10 @@ class RAGATraceExporter(SpanExporter):
|
|
118
137
|
if ragaai_trace_details is None:
|
119
138
|
logger.error(f"Cannot upload trace {trace_id}: conversion failed and returned None")
|
120
139
|
return # Exit early if conversion failed
|
121
|
-
|
140
|
+
|
122
141
|
# Upload the trace if upload_trace function is provided
|
123
142
|
try:
|
124
|
-
if self.post_processor!=None:
|
143
|
+
if self.post_processor != None:
|
125
144
|
ragaai_trace_details['trace_file_path'] = self.post_processor(ragaai_trace_details['trace_file_path'])
|
126
145
|
self.upload_trace(ragaai_trace_details, trace_id)
|
127
146
|
except Exception as e:
|
@@ -130,13 +149,14 @@ class RAGATraceExporter(SpanExporter):
|
|
130
149
|
def prepare_trace(self, spans, trace_id):
|
131
150
|
try:
|
132
151
|
try:
|
133
|
-
ragaai_trace = convert_json_format(spans, self.custom_model_cost, self.user_context, self.user_gt,
|
152
|
+
ragaai_trace = convert_json_format(spans, self.custom_model_cost, self.user_context, self.user_gt,
|
153
|
+
self.external_id)
|
134
154
|
except Exception as e:
|
135
155
|
print(f"Error in convert_json_format function: {trace_id}: {e}")
|
136
156
|
return None
|
137
|
-
|
157
|
+
|
138
158
|
try:
|
139
|
-
interactions = format_interactions(ragaai_trace)
|
159
|
+
interactions = format_interactions(ragaai_trace)
|
140
160
|
ragaai_trace["workflow"] = interactions['workflow']
|
141
161
|
except Exception as e:
|
142
162
|
print(f"Error in format_interactions function: {trace_id}: {e}")
|
@@ -183,18 +203,26 @@ class RAGATraceExporter(SpanExporter):
|
|
183
203
|
except Exception as e:
|
184
204
|
print(f"Error in adding tracer type: {trace_id}: {e}")
|
185
205
|
return None
|
186
|
-
|
187
|
-
#Add user passed metadata to the trace
|
206
|
+
|
207
|
+
# Add user passed metadata to the trace
|
188
208
|
try:
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
209
|
+
logger.debug("Started adding user passed metadata")
|
210
|
+
|
211
|
+
metadata = (
|
212
|
+
self.user_details.get("trace_user_detail", {}).get("metadata", {})
|
213
|
+
if self.user_details else {}
|
214
|
+
)
|
215
|
+
|
216
|
+
if isinstance(metadata, dict):
|
217
|
+
for key, value in metadata.items():
|
218
|
+
if key not in {"log_source", "recorded_on"}:
|
219
|
+
ragaai_trace.setdefault("metadata", {})[key] = value
|
220
|
+
|
221
|
+
logger.debug("Completed adding user passed metadata")
|
194
222
|
except Exception as e:
|
195
223
|
print(f"Error in adding metadata: {trace_id}: {e}")
|
196
224
|
return None
|
197
|
-
|
225
|
+
|
198
226
|
try:
|
199
227
|
# Save the trace_json
|
200
228
|
trace_file_path = os.path.join(self.tmp_dir, f"{trace_id}.json")
|
@@ -220,16 +248,16 @@ class RAGATraceExporter(SpanExporter):
|
|
220
248
|
hash_id = ragaai_trace_details['hash_id']
|
221
249
|
zip_path = ragaai_trace_details['code_zip_path']
|
222
250
|
self.upload_task_id = submit_upload_task(
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
logger.info(f"Submitted upload task with ID: {self.upload_task_id}")
|
251
|
+
filepath=filepath,
|
252
|
+
hash_id=hash_id,
|
253
|
+
zip_path=zip_path,
|
254
|
+
project_name=self.project_name,
|
255
|
+
project_id=self.project_id,
|
256
|
+
dataset_name=self.dataset_name,
|
257
|
+
user_details=self.user_details,
|
258
|
+
base_url=self.base_url,
|
259
|
+
tracer_type=self.tracer_type,
|
260
|
+
timeout=self.timeout
|
261
|
+
)
|
262
|
+
|
263
|
+
logger.info(f"Submitted upload task with ID: {self.upload_task_id}")
|
@@ -600,13 +600,13 @@ class Tracer(AgenticTracing):
|
|
600
600
|
|
601
601
|
# Create a dynamic exporter that allows property updates
|
602
602
|
self.dynamic_exporter = DynamicTraceExporter(
|
603
|
+
project_name=self.project_name,
|
604
|
+
dataset_name=self.dataset_name,
|
605
|
+
base_url=self.base_url,
|
603
606
|
tracer_type=self.tracer_type,
|
604
607
|
files_to_zip=list_of_unique_files,
|
605
|
-
project_name=self.project_name,
|
606
608
|
project_id=self.project_id,
|
607
|
-
dataset_name=self.dataset_name,
|
608
609
|
user_details=self.user_details,
|
609
|
-
base_url=self.base_url,
|
610
610
|
custom_model_cost=self.model_custom_cost,
|
611
611
|
timeout = self.timeout,
|
612
612
|
post_processor= self.post_processor,
|
@@ -188,7 +188,13 @@ def convert_json_format(
|
|
188
188
|
]
|
189
189
|
model_name = next((name for name in reversed(model_names) if name), "")
|
190
190
|
if not model_name and span["attributes"].get("openinference.span.kind")=="LLM":
|
191
|
-
|
191
|
+
try:
|
192
|
+
metadata = span["attributes"].get("metadata") or span["attributes"].get("aiq.metadata")
|
193
|
+
metadata = json.loads(metadata)
|
194
|
+
model_name = metadata.get("ls_model_name", "")
|
195
|
+
except Exception as e:
|
196
|
+
model_name = ""
|
197
|
+
logger.error(f"Failed to parse metadata: {e}", exc_info=True)
|
192
198
|
if model_name and span["attributes"].get("openinference.span.kind") == "LLM":
|
193
199
|
try:
|
194
200
|
model_costs = get_model_cost()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ragaai_catalyst
|
3
|
-
Version: 2.2.
|
3
|
+
Version: 2.2.6b1
|
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>, Rishabh Pandey <rishabh.pandey@raga.ai>, Jyotsana C G <jyotsana@raga.ai>
|
6
6
|
Requires-Python: <=3.13.2,>=3.10
|
@@ -5,10 +5,11 @@ ragaai_catalyst/evaluation.py,sha256=8P2zUMSMsQGmKdv7_dZ8F0iXWYddvappgKPN5oJXWuY
|
|
5
5
|
ragaai_catalyst/guard_executor.py,sha256=VLqVO1gAEBaovoQQUjdNkivH1dXACFTsuXQ1nzAALQQ,14008
|
6
6
|
ragaai_catalyst/guardrails_manager.py,sha256=_VrARJ1udmCF8TklNKy7XTQUaM8ATDhTOAGDonBkFro,14245
|
7
7
|
ragaai_catalyst/internal_api_completion.py,sha256=DdICI5yfEudiOAIC8L4oxH0Qz7kX-BZCdo9IWsi2gNo,2965
|
8
|
-
ragaai_catalyst/prompt_manager.py,sha256=
|
8
|
+
ragaai_catalyst/prompt_manager.py,sha256=9IoCTxjCY9FKopq6BoB0fVb3FtuSj3BBsNyD9AeH7ds,26265
|
9
9
|
ragaai_catalyst/proxy_call.py,sha256=CHxldeceZUaLU-to_hs_Kf1z_b2vHMssLS_cOBedu78,5499
|
10
10
|
ragaai_catalyst/ragaai_catalyst.py,sha256=ZlcpOgJA9lVRi51YFy4dVfsxU0I79LJu0MnVI5BIL-c,25201
|
11
11
|
ragaai_catalyst/redteaming_old.py,sha256=W2d89Ok8W-C8g7TBM3fDIFLof3q9FuYSr0jcryH2XQo,7097
|
12
|
+
ragaai_catalyst/session_manager.py,sha256=sOlxeIYIP8tycaTtZC9xkZosi6EDJUxvDw0_rc_NLI8,6823
|
12
13
|
ragaai_catalyst/synthetic_data_generation.py,sha256=AumjIzKk-Uvn7RQGatpx7TPvlI4NjU-rUiVFockoGNg,37969
|
13
14
|
ragaai_catalyst/utils.py,sha256=TlhEFwLyRU690HvANbyoRycR3nQ67lxVUQoUOfTPYQ0,3772
|
14
15
|
ragaai_catalyst/redteaming/__init__.py,sha256=TJdvZpaZGFsg9qKONdjTosSVLZGadYFpHG6KE0xapKU,155
|
@@ -27,7 +28,7 @@ ragaai_catalyst/redteaming/utils/issue_description.py,sha256=iB0XbeOjdqHTPrikCKS
|
|
27
28
|
ragaai_catalyst/redteaming/utils/rt.png,sha256=HzVC8bz_4UgwafKXuMe8RJVI6CyK_UmSgo53ceAOQK8,282154
|
28
29
|
ragaai_catalyst/tracers/__init__.py,sha256=LfgTes-nHpazssbGKnn8kyLZNr49kIPrlkrqqoTFTfc,301
|
29
30
|
ragaai_catalyst/tracers/distributed.py,sha256=CGPuOh4CsgEk428PPibieLaAG2Tt3BVygF6ZlmbXxg4,10009
|
30
|
-
ragaai_catalyst/tracers/tracer.py,sha256=
|
31
|
+
ragaai_catalyst/tracers/tracer.py,sha256=uLSrN4HZT19YmEG5dTPx_aauuNU8UfflNTn3xjshfmI,33649
|
31
32
|
ragaai_catalyst/tracers/agentic_tracing/README.md,sha256=X4QwLb7-Jg7GQMIXj-SerZIgDETfw-7VgYlczOR8ZeQ,4508
|
32
33
|
ragaai_catalyst/tracers/agentic_tracing/__init__.py,sha256=yf6SKvOPSpH-9LiKaoLKXwqj5sez8F_5wkOb91yp0oE,260
|
33
34
|
ragaai_catalyst/tracers/agentic_tracing/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -35,31 +36,30 @@ ragaai_catalyst/tracers/agentic_tracing/data/data_structure.py,sha256=icAtNzKN_I
|
|
35
36
|
ragaai_catalyst/tracers/agentic_tracing/tracers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
36
37
|
ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py,sha256=Wq4LFclPlLy47LyXvbaLeYiSMQABj7VYS3J87xyea_E,4159
|
37
38
|
ragaai_catalyst/tracers/agentic_tracing/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
39
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
40
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
41
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=IAhNFS-nbV_ImNz8Xp98qU4r-2naj49qg9q08x53TFE,12521
|
39
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/trace_uploader.py,sha256=mDpLqTE6j7gnxTS1Siev-gW_mnUJ086UB5l1bBoA9vU,25007
|
40
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py,sha256=oAiP6k3wYc6LTi4tHQctTMhTzpk492x5JTt5wEKcwC4,14541
|
41
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=a3pqyVvu5OJ9oDesHO6TeeCPHG-V0RSu1ZLKB-rYxCw,12536
|
42
42
|
ragaai_catalyst/tracers/agentic_tracing/utils/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
43
|
-
ragaai_catalyst/tracers/agentic_tracing/utils/create_dataset_schema.py,sha256=
|
43
|
+
ragaai_catalyst/tracers/agentic_tracing/utils/create_dataset_schema.py,sha256=GJex8B7mgzFDQgxzFIolce0RUWGYRYog_ijkC9nNt1E,3856
|
44
44
|
ragaai_catalyst/tracers/agentic_tracing/utils/file_name_tracker.py,sha256=YG601l1a29ov9VPu9Vl4RXxgL7l16k54_WWnoTNoG58,2064
|
45
45
|
ragaai_catalyst/tracers/agentic_tracing/utils/llm_utils.py,sha256=PiyXvEj_qu0EnJFjk4GfGyWFZbwlvQQh0hdQ_lm0p8E,22976
|
46
46
|
ragaai_catalyst/tracers/agentic_tracing/utils/model_costs.json,sha256=2tzGw_cKCTPcfjEm7iGvFE6pTw7gMTPzeBov_MTaXNY,321336
|
47
47
|
ragaai_catalyst/tracers/agentic_tracing/utils/system_monitor.py,sha256=H8WNsk4v_5T6OUw4TFOzlDLjQhJwjh1nAMyMAoqMEi4,6946
|
48
48
|
ragaai_catalyst/tracers/agentic_tracing/utils/trace_utils.py,sha256=W7Nw-IpugejIoHbCtQiN4Sn4ughLocQ9AUCjuAtOhOo,17258
|
49
49
|
ragaai_catalyst/tracers/agentic_tracing/utils/unique_decorator.py,sha256=G027toV-Km20JjKrc-Y_PilQ8ABEKrBvvzgLTnqVg7I,5819
|
50
|
-
ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py,sha256=
|
50
|
+
ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py,sha256=Q3KXaqpvCPl7CL4bzwKvE6xhY5JNvfxar6QUXXXz3w0,19688
|
51
51
|
ragaai_catalyst/tracers/exporters/__init__.py,sha256=qA3vx7z9CQ5kTGCn9LIDtIFvW9fJHQLkvF9-xBQUm94,237
|
52
|
-
ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py,sha256=
|
52
|
+
ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py,sha256=cQvBGFOgSNLoyPIvkTrHottlpmg1vcgFgej-J2PwGtY,7149
|
53
53
|
ragaai_catalyst/tracers/exporters/file_span_exporter.py,sha256=_icciSCktK6c86KB2HV3GZMFHvUitgKJ8x_IdPmgi1M,6363
|
54
|
-
ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py,sha256=
|
54
|
+
ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py,sha256=aUooYU7SlT29pYK_p9WO5udlFO-yOEZNeR3RSB-DOBo,10549
|
55
55
|
ragaai_catalyst/tracers/instrumentators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
56
56
|
ragaai_catalyst/tracers/utils/__init__.py,sha256=KeMaZtYaTojilpLv65qH08QmpYclfpacDA0U3wg6Ybw,64
|
57
57
|
ragaai_catalyst/tracers/utils/model_prices_and_context_window_backup.json,sha256=WlZCZeOQ54aMVjYS8BAeka2uaFC3ftBTMZ8zzzA8TAI,495947
|
58
58
|
ragaai_catalyst/tracers/utils/rag_extraction_logic_final.py,sha256=3ygkRT__lLDRflRttjzPu28tIA8cTCiGQVMQjqMItqQ,11309
|
59
|
-
ragaai_catalyst/tracers/utils/trace_json_converter.py,sha256
|
59
|
+
ragaai_catalyst/tracers/utils/trace_json_converter.py,sha256=NPsxU04u6MCOMqisrgiAIv1bXFjWNwlrUn-LScC8f-s,12109
|
60
60
|
ragaai_catalyst/tracers/utils/utils.py,sha256=o-p9n2ZuophdrV0wrixu-BqRHCkovup_klc3mS8mU8g,2374
|
61
|
-
ragaai_catalyst-2.2.
|
62
|
-
ragaai_catalyst-2.2.
|
63
|
-
ragaai_catalyst-2.2.
|
64
|
-
ragaai_catalyst-2.2.
|
65
|
-
ragaai_catalyst-2.2.
|
61
|
+
ragaai_catalyst-2.2.6b1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
62
|
+
ragaai_catalyst-2.2.6b1.dist-info/METADATA,sha256=qNKQxUD_sI5zPNeZFouH9xRsPdo1Wb0IxrLwAKB-ldg,17735
|
63
|
+
ragaai_catalyst-2.2.6b1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
64
|
+
ragaai_catalyst-2.2.6b1.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
|
65
|
+
ragaai_catalyst-2.2.6b1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|