ragaai-catalyst 1.0.7b3__py3-none-any.whl → 1.0.8b1__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 +123 -5
- ragaai_catalyst/experiment.py +143 -6
- ragaai_catalyst/prompt_manager.py +382 -0
- ragaai_catalyst/ragaai_catalyst.py +42 -46
- ragaai_catalyst/tracers/exporters/raga_exporter.py +25 -1
- ragaai_catalyst/tracers/tracer.py +28 -1
- {ragaai_catalyst-1.0.7b3.dist-info → ragaai_catalyst-1.0.8b1.dist-info}/METADATA +59 -21
- {ragaai_catalyst-1.0.7b3.dist-info → ragaai_catalyst-1.0.8b1.dist-info}/RECORD +10 -9
- {ragaai_catalyst-1.0.7b3.dist-info → ragaai_catalyst-1.0.8b1.dist-info}/WHEEL +1 -1
- {ragaai_catalyst-1.0.7b3.dist-info → ragaai_catalyst-1.0.8b1.dist-info}/top_level.txt +0 -0
ragaai_catalyst/dataset.py
CHANGED
@@ -4,6 +4,7 @@ from .utils import response_checker
|
|
4
4
|
from typing import Union
|
5
5
|
import logging
|
6
6
|
from .ragaai_catalyst import RagaAICatalyst
|
7
|
+
import pandas as pd
|
7
8
|
|
8
9
|
logger = logging.getLogger(__name__)
|
9
10
|
get_token = RagaAICatalyst.get_token
|
@@ -11,7 +12,7 @@ get_token = RagaAICatalyst.get_token
|
|
11
12
|
|
12
13
|
class Dataset:
|
13
14
|
BASE_URL = None
|
14
|
-
TIMEOUT =
|
15
|
+
TIMEOUT = 30
|
15
16
|
|
16
17
|
def __init__(self, project_name):
|
17
18
|
self.project_name = project_name
|
@@ -63,7 +64,7 @@ class Dataset:
|
|
63
64
|
sub_datasets = [dataset["name"] for dataset in datasets]
|
64
65
|
return sub_datasets
|
65
66
|
|
66
|
-
def
|
67
|
+
def create_from_trace(self, dataset_name, filter_list):
|
67
68
|
"""
|
68
69
|
Creates a new dataset with the given `dataset_name` and `filter_list`.
|
69
70
|
|
@@ -79,7 +80,7 @@ class Dataset:
|
|
79
80
|
|
80
81
|
"""
|
81
82
|
|
82
|
-
def
|
83
|
+
def request_trace_creation():
|
83
84
|
headers = {
|
84
85
|
"Content-Type": "application/json",
|
85
86
|
"Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
|
@@ -98,12 +99,129 @@ class Dataset:
|
|
98
99
|
)
|
99
100
|
return response
|
100
101
|
|
101
|
-
response =
|
102
|
+
response = request_trace_creation()
|
102
103
|
response_checker(response, "Dataset.create_dataset")
|
103
104
|
if response.status_code == 401:
|
104
105
|
get_token() # Fetch a new token and set it in the environment
|
105
|
-
response =
|
106
|
+
response = request_trace_creation() # Retry the request
|
106
107
|
if response.status_code != 200:
|
107
108
|
return response.json()["message"]
|
108
109
|
message = response.json()["message"]
|
109
110
|
return f"{message} {dataset_name}"
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
###################### CSV Upload APIs ###################
|
115
|
+
|
116
|
+
def get_csv_schema(self):
|
117
|
+
headers = {
|
118
|
+
"Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
|
119
|
+
"X-Project-Name": self.project_name,
|
120
|
+
}
|
121
|
+
response = requests.get(
|
122
|
+
f"{Dataset.BASE_URL}/v1/llm/schema-elements",
|
123
|
+
headers=headers,
|
124
|
+
timeout=Dataset.TIMEOUT,
|
125
|
+
)
|
126
|
+
|
127
|
+
response_data = response.json()
|
128
|
+
if not response_data['success']:
|
129
|
+
raise ValueError('Unable to fetch Schema Elements for the CSV')
|
130
|
+
|
131
|
+
# chema_elements = response['data']['schemaElements']
|
132
|
+
return response_data
|
133
|
+
|
134
|
+
|
135
|
+
def create_from_csv(self, csv_path, dataset_name, schema_mapping):
|
136
|
+
|
137
|
+
## check the validity of schema_mapping
|
138
|
+
df = pd.read_csv(csv_path)
|
139
|
+
keys = list(df.columns)
|
140
|
+
values = self.get_csv_schema()['data']['schemaElements']
|
141
|
+
print(type(values), values)
|
142
|
+
for k in schema_mapping.keys():
|
143
|
+
if k not in keys:
|
144
|
+
raise ValueError(f'--{k}-- column is not present in csv column but present in schema_mapping. Plase provide the right schema_mapping.')
|
145
|
+
for k in schema_mapping.values():
|
146
|
+
if k not in values:
|
147
|
+
raise ValueError(f'--{k}-- is not present in the schema_elements but present in schema_mapping. Plase provide the right schema_mapping.')
|
148
|
+
|
149
|
+
|
150
|
+
#### get presigned URL
|
151
|
+
def get_presignedUrl():
|
152
|
+
headers = {
|
153
|
+
"Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
|
154
|
+
"X-Project-Name": self.project_name,
|
155
|
+
}
|
156
|
+
response = requests.get(
|
157
|
+
f"{Dataset.BASE_URL}/v1/llm/presignedUrl/test-url",
|
158
|
+
headers=headers,
|
159
|
+
timeout=Dataset.TIMEOUT,
|
160
|
+
)
|
161
|
+
return response.json()
|
162
|
+
|
163
|
+
presignedUrl = get_presignedUrl()
|
164
|
+
if presignedUrl['success']:
|
165
|
+
url = presignedUrl['data']['presignedUrl']
|
166
|
+
filename = presignedUrl['data']['fileName']
|
167
|
+
print('-- PresignedUrl fetched Succussfuly --')
|
168
|
+
print('filename: ', filename)
|
169
|
+
else:
|
170
|
+
raise ValueError('Unable to fetch presignedUrl')
|
171
|
+
|
172
|
+
|
173
|
+
|
174
|
+
#### put csv to presigned URL
|
175
|
+
def put_csv_to_presignedUrl(url):
|
176
|
+
headers = {
|
177
|
+
'Content-Type': 'text/csv',
|
178
|
+
'x-ms-blob-type': 'BlockBlob',
|
179
|
+
}
|
180
|
+
with open(csv_path, 'rb') as file:
|
181
|
+
response = requests.put(
|
182
|
+
url,
|
183
|
+
headers=headers,
|
184
|
+
data=file,
|
185
|
+
timeout=Dataset.TIMEOUT,
|
186
|
+
)
|
187
|
+
return response
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
put_csv_response = put_csv_to_presignedUrl(url)
|
192
|
+
if put_csv_response.status_code != 201:
|
193
|
+
raise ValueError('Unable to put csv to the presignedUrl')
|
194
|
+
else:
|
195
|
+
print('-- csv put to presignedUrl Succussfuly --')
|
196
|
+
|
197
|
+
|
198
|
+
|
199
|
+
## Upload csv to elastic
|
200
|
+
def upload_csv_to_elastic(data):
|
201
|
+
header = {
|
202
|
+
'Authorization': f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
|
203
|
+
'X-Project-Name': self.project_name
|
204
|
+
}
|
205
|
+
response = requests.post(
|
206
|
+
f"{Dataset.BASE_URL}/v1/llm/csv-dataset",
|
207
|
+
headers=header,
|
208
|
+
json=data,
|
209
|
+
timeout=Dataset.TIMEOUT,
|
210
|
+
)
|
211
|
+
|
212
|
+
return response.json()
|
213
|
+
|
214
|
+
data = {
|
215
|
+
"datasetName": dataset_name,
|
216
|
+
"fileName": filename,
|
217
|
+
"schemaMapping": schema_mapping
|
218
|
+
}
|
219
|
+
print(data)
|
220
|
+
|
221
|
+
upload_csv_response = upload_csv_to_elastic(data)
|
222
|
+
print(type(upload_csv_response), upload_csv_response)
|
223
|
+
if not upload_csv_response['success']:
|
224
|
+
raise ValueError('Unable to upload csv')
|
225
|
+
else:
|
226
|
+
print(upload_csv_response['message'])
|
227
|
+
|
ragaai_catalyst/experiment.py
CHANGED
@@ -14,6 +14,7 @@ get_token = RagaAICatalyst.get_token
|
|
14
14
|
class Experiment:
|
15
15
|
BASE_URL = None
|
16
16
|
TIMEOUT = 10
|
17
|
+
NUM_PROJECTS = 100
|
17
18
|
|
18
19
|
def __init__(
|
19
20
|
self, project_name, experiment_name, experiment_description, dataset_name
|
@@ -42,6 +43,28 @@ class Experiment:
|
|
42
43
|
self.experiment_id = None
|
43
44
|
self.job_id = None
|
44
45
|
|
46
|
+
params = {
|
47
|
+
"size": str(self.NUM_PROJECTS),
|
48
|
+
"page": "0",
|
49
|
+
"type": "llm",
|
50
|
+
}
|
51
|
+
headers = {
|
52
|
+
"Content-Type": "application/json",
|
53
|
+
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
54
|
+
}
|
55
|
+
response = requests.get(
|
56
|
+
f"{RagaAICatalyst.BASE_URL}/projects",
|
57
|
+
params=params,
|
58
|
+
headers=headers,
|
59
|
+
timeout=10,
|
60
|
+
)
|
61
|
+
response.raise_for_status()
|
62
|
+
# logger.debug("Projects list retrieved successfully")
|
63
|
+
experiment_list = [exp["name"] for project in response.json()["data"]["content"] if project["name"] == self.project_name for exp in project["experiments"]]
|
64
|
+
# print(experiment_list)
|
65
|
+
if self.experiment_name in experiment_list:
|
66
|
+
raise ValueError("The experiment name already exists in the project. Enter a unique experiment name.")
|
67
|
+
|
45
68
|
self.access_key = os.getenv("RAGAAI_CATALYST_ACCESS_KEY")
|
46
69
|
self.secret_key = os.getenv("RAGAAI_CATALYST_SECRET_KEY")
|
47
70
|
|
@@ -50,8 +73,73 @@ class Experiment:
|
|
50
73
|
if os.getenv("RAGAAI_CATALYST_TOKEN") is not None
|
51
74
|
else get_token()
|
52
75
|
)
|
76
|
+
|
77
|
+
if not self._check_if_project_exists(project_name=project_name):
|
78
|
+
raise ValueError(f"Project '{project_name}' not found. Please enter a valid project name")
|
79
|
+
|
80
|
+
if not self._check_if_dataset_exists(project_name=project_name,dataset_name=dataset_name):
|
81
|
+
raise ValueError(f"dataset '{dataset_name}' not found. Please enter a valid dataset name")
|
82
|
+
|
83
|
+
|
53
84
|
self.metrics = []
|
85
|
+
def _check_if_dataset_exists(self,project_name,dataset_name):
|
86
|
+
headers = {
|
87
|
+
"X-Project-Name":project_name,
|
88
|
+
# "accept":"application/json, text/plain, */*",
|
89
|
+
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
90
|
+
}
|
91
|
+
response = requests.get(
|
92
|
+
f"{RagaAICatalyst.BASE_URL}/v1/llm/sub-datasets",
|
93
|
+
headers=headers,
|
94
|
+
timeout=self.TIMEOUT,
|
95
|
+
)
|
96
|
+
response.raise_for_status()
|
97
|
+
logger.debug("dataset list retrieved successfully")
|
98
|
+
dataset_list = [
|
99
|
+
item['name'] for item in response.json()['data']['content']
|
100
|
+
]
|
101
|
+
exists = dataset_name in dataset_list
|
102
|
+
if exists:
|
103
|
+
logger.info(f"dataset '{dataset_name}' exists.")
|
104
|
+
else:
|
105
|
+
logger.info(f"dataset '{dataset_name}' does not exist.")
|
106
|
+
return exists
|
107
|
+
|
108
|
+
|
54
109
|
|
110
|
+
|
111
|
+
def _check_if_project_exists(self,project_name,num_projects=100):
|
112
|
+
# TODO: 1. List All projects
|
113
|
+
params = {
|
114
|
+
"size": str(num_projects),
|
115
|
+
"page": "0",
|
116
|
+
"type": "llm",
|
117
|
+
}
|
118
|
+
headers = {
|
119
|
+
"Content-Type": "application/json",
|
120
|
+
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
121
|
+
}
|
122
|
+
response = requests.get(
|
123
|
+
f"{RagaAICatalyst.BASE_URL}/projects",
|
124
|
+
params=params,
|
125
|
+
headers=headers,
|
126
|
+
timeout=self.TIMEOUT,
|
127
|
+
)
|
128
|
+
response.raise_for_status()
|
129
|
+
logger.debug("Projects list retrieved successfully")
|
130
|
+
project_list = [
|
131
|
+
project["name"] for project in response.json()["data"]["content"]
|
132
|
+
]
|
133
|
+
|
134
|
+
# TODO: 2. Check if the given project_name exists
|
135
|
+
# TODO: 3. Return bool (True / False output)
|
136
|
+
exists = project_name in project_list
|
137
|
+
if exists:
|
138
|
+
logger.info(f"Project '{project_name}' exists.")
|
139
|
+
else:
|
140
|
+
logger.info(f"Project '{project_name}' does not exist.")
|
141
|
+
return exists
|
142
|
+
|
55
143
|
def list_experiments(self):
|
56
144
|
"""
|
57
145
|
Retrieves a list of experiments associated with the current project.
|
@@ -115,6 +203,15 @@ class Experiment:
|
|
115
203
|
metrics = [metrics]
|
116
204
|
else:
|
117
205
|
metrics_list = metrics
|
206
|
+
sub_providers = ["openai","azure","gemini","groq"]
|
207
|
+
sub_metrics = RagaAICatalyst.list_metrics()
|
208
|
+
for metric in metrics_list:
|
209
|
+
provider = metric.get('config', {}).get('provider', '').lower()
|
210
|
+
if provider and provider not in sub_providers:
|
211
|
+
raise ValueError("Enter a valid provider name. The following Provider names are supported: OpenAI, Azure, Gemini, Groq")
|
212
|
+
|
213
|
+
if metric['name'] not in sub_metrics:
|
214
|
+
raise ValueError("Enter a valid metric name. Refer to RagaAI Metric Library to select a valid metric")
|
118
215
|
|
119
216
|
json_data = {
|
120
217
|
"projectName": self.project_name,
|
@@ -274,14 +371,15 @@ class Experiment:
|
|
274
371
|
"projectId": self.project_id,
|
275
372
|
"filterList": [],
|
276
373
|
}
|
374
|
+
base_url_without_api = Experiment.BASE_URL.removesuffix('/api')
|
277
375
|
|
278
376
|
status_json = self.get_status(job_id_to_use)
|
279
377
|
if status_json == "Failed":
|
280
378
|
return print("Job failed. No results to fetch.")
|
281
379
|
elif status_json == "In Progress":
|
282
|
-
return print("Job in progress. Please wait while the job completes
|
380
|
+
return print(f"Job in progress. Please wait while the job completes.\n Visit Job Status: {base_url_without_api}/home/job-status to track")
|
283
381
|
elif status_json == "Completed":
|
284
|
-
print("Job completed. fetching results")
|
382
|
+
print(f"Job completed. fetching results.\n Visit Job Status: {base_url_without_api}/home/job-status to track")
|
285
383
|
|
286
384
|
response = requests.post(
|
287
385
|
f"{Experiment.BASE_URL}/v1/llm/docs",
|
@@ -339,11 +437,50 @@ class Experiment:
|
|
339
437
|
Parse the response to get the results
|
340
438
|
"""
|
341
439
|
try:
|
342
|
-
|
343
|
-
|
440
|
+
x = pd.DataFrame(response["data"]["docs"])
|
441
|
+
|
442
|
+
column_names_to_replace = [
|
443
|
+
{item["columnName"]: item["displayName"]}
|
444
|
+
for item in response["data"]["columns"]
|
445
|
+
]
|
446
|
+
|
447
|
+
if column_names_to_replace:
|
448
|
+
for item in column_names_to_replace:
|
449
|
+
x = x.rename(columns=item)
|
450
|
+
|
451
|
+
dict_cols = [
|
452
|
+
col
|
453
|
+
for col in x.columns
|
454
|
+
if x[col].dtype == "object"
|
455
|
+
and x[col].apply(lambda y: isinstance(y, dict)).any()
|
456
|
+
]
|
457
|
+
|
458
|
+
for dict_col in dict_cols:
|
459
|
+
x[f"{dict_col}_reason"] = x[dict_col].apply(
|
460
|
+
lambda y: y.get("reason") if isinstance(y, dict) else None
|
461
|
+
)
|
462
|
+
x[f"{dict_col}_metric_config"] = x[dict_col].apply(
|
463
|
+
lambda y: (
|
464
|
+
y.get("metric_config") if isinstance(y, dict) else None
|
465
|
+
)
|
466
|
+
)
|
467
|
+
x[f"{dict_col}_status"] = x[dict_col].apply(
|
468
|
+
lambda y: y.get("status") if isinstance(y, dict) else None
|
469
|
+
)
|
470
|
+
|
471
|
+
x = x.drop(columns=[dict_col])
|
472
|
+
|
473
|
+
x.columns = x.columns.str.replace("_reason_reason", "_reason")
|
474
|
+
x.columns = x.columns.str.replace("_reason_metric_config", "_metric_config")
|
475
|
+
x.columns = x.columns.str.replace("_reason_status", "_status")
|
476
|
+
|
477
|
+
x = x.drop(columns=["trace_uri"])
|
478
|
+
|
479
|
+
return True, x
|
480
|
+
|
344
481
|
except Exception as e:
|
345
|
-
logger.error(f"Failed to parse response: {e}")
|
346
|
-
return False,
|
482
|
+
logger.error(f"Failed to parse response: {e}", exc_info=True)
|
483
|
+
return False, pd.DataFrame()
|
347
484
|
|
348
485
|
|
349
486
|
class FailedToRetrieveResults(Exception):
|
@@ -0,0 +1,382 @@
|
|
1
|
+
import os
|
2
|
+
import requests
|
3
|
+
import json
|
4
|
+
import re
|
5
|
+
from .ragaai_catalyst import RagaAICatalyst
|
6
|
+
import pdb
|
7
|
+
|
8
|
+
class PromptManager:
|
9
|
+
NUM_PROJECTS = 100
|
10
|
+
TIMEOUT = 10
|
11
|
+
|
12
|
+
def __init__(self, project_name):
|
13
|
+
"""
|
14
|
+
Initialize the PromptManager with a project name.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
project_name (str): The name of the project.
|
18
|
+
|
19
|
+
Raises:
|
20
|
+
requests.RequestException: If there's an error with the API request.
|
21
|
+
ValueError: If the project is not found.
|
22
|
+
"""
|
23
|
+
self.project_name = project_name
|
24
|
+
self.headers = {
|
25
|
+
"Content-Type": "application/json",
|
26
|
+
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
27
|
+
"X-Project-Name": self.project_name
|
28
|
+
}
|
29
|
+
self.base_url = f"{RagaAICatalyst.BASE_URL}/playground/prompt"
|
30
|
+
self.timeout = 10
|
31
|
+
|
32
|
+
try:
|
33
|
+
response = requests.get(
|
34
|
+
f"{RagaAICatalyst.BASE_URL}/projects",
|
35
|
+
params={
|
36
|
+
"size": str(self.NUM_PROJECTS),
|
37
|
+
"page": "0",
|
38
|
+
"type": "llm",
|
39
|
+
},
|
40
|
+
headers={
|
41
|
+
"Content-Type": "application/json",
|
42
|
+
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
43
|
+
},
|
44
|
+
timeout=self.TIMEOUT,
|
45
|
+
)
|
46
|
+
response.raise_for_status()
|
47
|
+
except requests.RequestException as e:
|
48
|
+
raise requests.RequestException(f"Error fetching projects: {str(e)}")
|
49
|
+
|
50
|
+
try:
|
51
|
+
project_list = [
|
52
|
+
project["name"] for project in response.json()["data"]["content"]
|
53
|
+
]
|
54
|
+
except (KeyError, json.JSONDecodeError) as e:
|
55
|
+
raise ValueError(f"Error parsing project list: {str(e)}")
|
56
|
+
|
57
|
+
if self.project_name not in project_list:
|
58
|
+
raise ValueError("Project not found. Please enter a valid project name")
|
59
|
+
|
60
|
+
|
61
|
+
def list_prompts(self):
|
62
|
+
"""
|
63
|
+
List all available prompts.
|
64
|
+
|
65
|
+
Returns:
|
66
|
+
list: A list of prompt names.
|
67
|
+
|
68
|
+
Raises:
|
69
|
+
requests.RequestException: If there's an error with the API request.
|
70
|
+
"""
|
71
|
+
prompt = Prompt()
|
72
|
+
try:
|
73
|
+
prompt_list = prompt.list_prompts(self.base_url, self.headers, self.timeout)
|
74
|
+
return prompt_list
|
75
|
+
except requests.RequestException as e:
|
76
|
+
raise requests.RequestException(f"Error listing prompts: {str(e)}")
|
77
|
+
|
78
|
+
def get_prompt(self, prompt_name, version=None):
|
79
|
+
"""
|
80
|
+
Get a specific prompt.
|
81
|
+
|
82
|
+
Args:
|
83
|
+
prompt_name (str): The name of the prompt.
|
84
|
+
version (str, optional): The version of the prompt. Defaults to None.
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
PromptObject: An object representing the prompt.
|
88
|
+
|
89
|
+
Raises:
|
90
|
+
ValueError: If the prompt or version is not found.
|
91
|
+
requests.RequestException: If there's an error with the API request.
|
92
|
+
"""
|
93
|
+
try:
|
94
|
+
prompt_list = self.list_prompts()
|
95
|
+
except requests.RequestException as e:
|
96
|
+
raise requests.RequestException(f"Error fetching prompt list: {str(e)}")
|
97
|
+
|
98
|
+
if prompt_name not in prompt_list:
|
99
|
+
raise ValueError("Prompt not found. Please enter a valid prompt name")
|
100
|
+
|
101
|
+
try:
|
102
|
+
prompt_versions = self.list_prompt_versions(prompt_name)
|
103
|
+
except requests.RequestException as e:
|
104
|
+
raise requests.RequestException(f"Error fetching prompt versions: {str(e)}")
|
105
|
+
|
106
|
+
if version and version not in prompt_versions.keys():
|
107
|
+
raise ValueError("Version not found. Please enter a valid version name")
|
108
|
+
|
109
|
+
prompt = Prompt()
|
110
|
+
try:
|
111
|
+
prompt_object = prompt.get_prompt(self.base_url, self.headers, self.timeout, prompt_name, version)
|
112
|
+
return prompt_object
|
113
|
+
except requests.RequestException as e:
|
114
|
+
raise requests.RequestException(f"Error fetching prompt: {str(e)}")
|
115
|
+
|
116
|
+
def list_prompt_versions(self, prompt_name):
|
117
|
+
"""
|
118
|
+
List all versions of a specific prompt.
|
119
|
+
|
120
|
+
Args:
|
121
|
+
prompt_name (str): The name of the prompt.
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
dict: A dictionary mapping version names to prompt texts.
|
125
|
+
|
126
|
+
Raises:
|
127
|
+
ValueError: If the prompt is not found.
|
128
|
+
requests.RequestException: If there's an error with the API request.
|
129
|
+
"""
|
130
|
+
try:
|
131
|
+
prompt_list = self.list_prompts()
|
132
|
+
except requests.RequestException as e:
|
133
|
+
raise requests.RequestException(f"Error fetching prompt list: {str(e)}")
|
134
|
+
|
135
|
+
if prompt_name not in prompt_list:
|
136
|
+
raise ValueError("Prompt not found. Please enter a valid prompt name")
|
137
|
+
|
138
|
+
prompt = Prompt()
|
139
|
+
try:
|
140
|
+
prompt_versions = prompt.list_prompt_versions(self.base_url, self.headers, self.timeout, prompt_name)
|
141
|
+
return prompt_versions
|
142
|
+
except requests.RequestException as e:
|
143
|
+
raise requests.RequestException(f"Error fetching prompt versions: {str(e)}")
|
144
|
+
|
145
|
+
|
146
|
+
class Prompt:
|
147
|
+
def __init__(self):
|
148
|
+
"""
|
149
|
+
Initialize the Prompt class.
|
150
|
+
"""
|
151
|
+
pass
|
152
|
+
|
153
|
+
def list_prompts(self, url, headers, timeout):
|
154
|
+
"""
|
155
|
+
List all available prompts.
|
156
|
+
|
157
|
+
Args:
|
158
|
+
url (str): The base URL for the API.
|
159
|
+
headers (dict): The headers to be used in the request.
|
160
|
+
timeout (int): The timeout for the request.
|
161
|
+
|
162
|
+
Returns:
|
163
|
+
list: A list of prompt names.
|
164
|
+
|
165
|
+
Raises:
|
166
|
+
requests.RequestException: If there's an error with the API request.
|
167
|
+
"""
|
168
|
+
try:
|
169
|
+
response = requests.get(url, headers=headers, timeout=timeout)
|
170
|
+
response.raise_for_status()
|
171
|
+
prompt_list = [prompt["name"] for prompt in response.json()["data"]]
|
172
|
+
return prompt_list
|
173
|
+
except requests.RequestException as e:
|
174
|
+
raise requests.RequestException(f"Error listing prompts: {str(e)}")
|
175
|
+
except (KeyError, json.JSONDecodeError) as e:
|
176
|
+
raise ValueError(f"Error parsing prompt list: {str(e)}")
|
177
|
+
|
178
|
+
def get_response_by_version(self, base_url, headers, timeout, prompt_name, version):
|
179
|
+
"""
|
180
|
+
Get a specific version of a prompt.
|
181
|
+
|
182
|
+
Args:
|
183
|
+
base_url (str): The base URL for the API.
|
184
|
+
headers (dict): The headers to be used in the request.
|
185
|
+
timeout (int): The timeout for the request.
|
186
|
+
prompt_name (str): The name of the prompt.
|
187
|
+
version (str): The version of the prompt."""
|
188
|
+
try:
|
189
|
+
response = requests.get(f"{base_url}/version/{prompt_name}?version={version}",
|
190
|
+
headers=headers, timeout=timeout)
|
191
|
+
response.raise_for_status()
|
192
|
+
except requests.RequestException as e:
|
193
|
+
raise requests.RequestException(f"Error fetching prompt version: {str(e)}")
|
194
|
+
except (KeyError, json.JSONDecodeError, IndexError) as e:
|
195
|
+
raise ValueError(f"Error parsing prompt version: {str(e)}")
|
196
|
+
return response
|
197
|
+
|
198
|
+
def get_response(self, base_url, headers, timeout, prompt_name, version):
|
199
|
+
try:
|
200
|
+
response = requests.get(f"{base_url}/version/{prompt_name}",
|
201
|
+
headers=headers, timeout=timeout)
|
202
|
+
response.raise_for_status()
|
203
|
+
except requests.RequestException as e:
|
204
|
+
raise requests.RequestException(f"Error fetching prompt version: {str(e)}")
|
205
|
+
except (KeyError, json.JSONDecodeError, IndexError) as e:
|
206
|
+
raise ValueError(f"Error parsing prompt version: {str(e)}")
|
207
|
+
return response
|
208
|
+
|
209
|
+
def get_prompt_by_version(self, base_url, headers, timeout, prompt_name, version):
|
210
|
+
"""
|
211
|
+
Get a specific version of a prompt.
|
212
|
+
|
213
|
+
Args:
|
214
|
+
base_url (str): The base URL for the API.
|
215
|
+
headers (dict): The headers to be used in the request.
|
216
|
+
timeout (int): The timeout for the request.
|
217
|
+
prompt_name (str): The name of the prompt.
|
218
|
+
version (str): The version of the prompt.
|
219
|
+
|
220
|
+
Returns:
|
221
|
+
str: The text of the prompt.
|
222
|
+
|
223
|
+
Raises:
|
224
|
+
requests.RequestException: If there's an error with the API request.
|
225
|
+
"""
|
226
|
+
response = self.get_response_by_version(base_url, headers, timeout, prompt_name, version)
|
227
|
+
prompt_text = response.json()["data"]["docs"][0]["textFields"]
|
228
|
+
return prompt_text
|
229
|
+
|
230
|
+
def get_prompt(self, base_url, headers, timeout, prompt_name, version=None):
|
231
|
+
"""
|
232
|
+
Get a prompt, optionally specifying a version.
|
233
|
+
|
234
|
+
Args:
|
235
|
+
base_url (str): The base URL for the API.
|
236
|
+
headers (dict): The headers to be used in the request.
|
237
|
+
timeout (int): The timeout for the request.
|
238
|
+
prompt_name (str): The name of the prompt.
|
239
|
+
version (str, optional): The version of the prompt. Defaults to None.
|
240
|
+
|
241
|
+
Returns:
|
242
|
+
PromptObject: An object representing the prompt.
|
243
|
+
|
244
|
+
Raises:
|
245
|
+
requests.RequestException: If there's an error with the API request.
|
246
|
+
"""
|
247
|
+
if version:
|
248
|
+
response = self.get_response_by_version(base_url, headers, timeout, prompt_name, version)
|
249
|
+
prompt_text = response.json()["data"]["docs"][0]["textFields"]
|
250
|
+
prompt_parameters = response.json()["data"]["docs"][0]["modelSpecs"]["parameters"]
|
251
|
+
model = response.json()["data"]["docs"][0]["modelSpecs"]["model"]
|
252
|
+
else:
|
253
|
+
response = self.get_response(base_url, headers, timeout, prompt_name)
|
254
|
+
prompt_text = response.json()["data"]["docs"][0]["textFields"]
|
255
|
+
prompt_parameters = response.json()["data"]["docs"][0]["modelSpecs"]["parameters"]
|
256
|
+
model = response.json()["data"]["docs"][0]["modelSpecs"]["model"]
|
257
|
+
return PromptObject(prompt_text, prompt_parameters, model)
|
258
|
+
|
259
|
+
|
260
|
+
def list_prompt_versions(self, base_url, headers, timeout, prompt_name):
|
261
|
+
"""
|
262
|
+
List all versions of a specific prompt.
|
263
|
+
|
264
|
+
Args:
|
265
|
+
base_url (str): The base URL for the API.
|
266
|
+
headers (dict): The headers to be used in the request.
|
267
|
+
timeout (int): The timeout for the request.
|
268
|
+
prompt_name (str): The name of the prompt.
|
269
|
+
|
270
|
+
Returns:
|
271
|
+
dict: A dictionary mapping version names to prompt texts.
|
272
|
+
|
273
|
+
Raises:
|
274
|
+
requests.RequestException: If there's an error with the API request.
|
275
|
+
"""
|
276
|
+
try:
|
277
|
+
response = requests.get(f"{base_url}/{prompt_name}/version",
|
278
|
+
headers=headers, timeout=timeout)
|
279
|
+
response.raise_for_status()
|
280
|
+
version_names = [version["name"] for version in response.json()["data"]]
|
281
|
+
prompt_versions = {}
|
282
|
+
for version in version_names:
|
283
|
+
prompt_versions[version] = self.get_prompt_by_version(base_url, headers, timeout, prompt_name, version)
|
284
|
+
return prompt_versions
|
285
|
+
except requests.RequestException as e:
|
286
|
+
raise requests.RequestException(f"Error listing prompt versions: {str(e)}")
|
287
|
+
except (KeyError, json.JSONDecodeError) as e:
|
288
|
+
raise ValueError(f"Error parsing prompt versions: {str(e)}")
|
289
|
+
|
290
|
+
|
291
|
+
class PromptObject:
|
292
|
+
def __init__(self, text, parameters, model):
|
293
|
+
"""
|
294
|
+
Initialize a PromptObject with the given text.
|
295
|
+
|
296
|
+
Args:
|
297
|
+
text (str): The text of the prompt.
|
298
|
+
parameters (dict): The parameters of the prompt.
|
299
|
+
model (str): The model of the prompt.
|
300
|
+
"""
|
301
|
+
self.text = text
|
302
|
+
self.variables = self._extract_variables()
|
303
|
+
self.parameters = parameters
|
304
|
+
self.model = model
|
305
|
+
|
306
|
+
def _extract_variables(self):
|
307
|
+
"""
|
308
|
+
Extract variables from the prompt text.
|
309
|
+
|
310
|
+
Returns:
|
311
|
+
list: A list of variable names found in the prompt text.
|
312
|
+
"""
|
313
|
+
user_content = next(item["content"] for item in self.text if item["role"] == "user")
|
314
|
+
return [var.strip('{}') for var in user_content.split('{{')[1:]]
|
315
|
+
|
316
|
+
def compile(self, **kwargs):
|
317
|
+
"""
|
318
|
+
Compile the prompt by replacing variables with provided values.
|
319
|
+
|
320
|
+
Args:
|
321
|
+
**kwargs: Keyword arguments where keys are variable names and values are their replacements.
|
322
|
+
|
323
|
+
Returns:
|
324
|
+
str: The compiled prompt with variables replaced.
|
325
|
+
|
326
|
+
Raises:
|
327
|
+
ValueError: If there are missing or extra variables, or if a value is not a string.
|
328
|
+
"""
|
329
|
+
required_variables = set(self.get_variables())
|
330
|
+
provided_variables = set(kwargs.keys())
|
331
|
+
|
332
|
+
missing_variables = required_variables - provided_variables
|
333
|
+
extra_variables = provided_variables - required_variables
|
334
|
+
|
335
|
+
if missing_variables:
|
336
|
+
raise ValueError(f"Missing variable(s): {', '.join(missing_variables)}")
|
337
|
+
if extra_variables:
|
338
|
+
raise ValueError(f"Extra variable(s) provided: {', '.join(extra_variables)}")
|
339
|
+
# pdb.set_trace()
|
340
|
+
|
341
|
+
# compiled_prompt = self.text
|
342
|
+
user_content = next(item["content"] for item in self.text if item["role"] == "user")
|
343
|
+
|
344
|
+
for key, value in kwargs.items():
|
345
|
+
if not isinstance(value, str):
|
346
|
+
raise ValueError(f"Value for variable '{key}' must be a string, not {type(value).__name__}")
|
347
|
+
user_content = user_content.replace(f"{{{{{key}}}}}", value)
|
348
|
+
compiled_prompt = [{"content": user_content if item["role"] == "user" else item["content"], "role": item["role"]} for item in self.text]
|
349
|
+
return compiled_prompt
|
350
|
+
|
351
|
+
def get_variables(self):
|
352
|
+
"""
|
353
|
+
Get all variables in the prompt text.
|
354
|
+
|
355
|
+
Returns:
|
356
|
+
list: A list of variable names found in the prompt text.
|
357
|
+
"""
|
358
|
+
pattern = r'\{\{(.*?)\}\}'
|
359
|
+
user_content = next(item["content"] for item in self.text if item["role"] == "user")
|
360
|
+
matches = re.findall(pattern, user_content)
|
361
|
+
return [match.strip() for match in matches if '"' not in match]
|
362
|
+
|
363
|
+
# Function to convert value based on type
|
364
|
+
def convert_value(self, value, type_):
|
365
|
+
if type_ == "float":
|
366
|
+
return float(value)
|
367
|
+
elif type_ == "int":
|
368
|
+
return int(value)
|
369
|
+
return value # Default case, return as is
|
370
|
+
|
371
|
+
def get_parameters(self):
|
372
|
+
"""
|
373
|
+
Get all parameters in the prompt text.
|
374
|
+
|
375
|
+
Returns:
|
376
|
+
dict: A dictionary of parameters found in the prompt text.
|
377
|
+
"""
|
378
|
+
parameters = {param["name"]: self.convert_value(param["value"], param["type"]) for param in self.parameters}
|
379
|
+
parameters["model"] = self.model
|
380
|
+
return parameters
|
381
|
+
|
382
|
+
|
@@ -24,16 +24,15 @@ class RagaAICatalyst:
|
|
24
24
|
access_key (str): The access key for the RagaAICatalyst.
|
25
25
|
secret_key (str): The secret key for the RagaAICatalyst.
|
26
26
|
api_keys (Optional[Dict[str, str]]): A dictionary of API keys for different services. Defaults to None.
|
27
|
+
base_url (Optional[str]): The base URL for the RagaAICatalyst API. Defaults to None.
|
27
28
|
|
28
29
|
Raises:
|
29
30
|
ValueError: If the RAGAAI_CATALYST_ACCESS_KEY and RAGAAI_CATALYST_SECRET_KEY environment variables are not set.
|
31
|
+
ConnectionError: If the provided base_url is not accessible.
|
30
32
|
|
31
33
|
Returns:
|
32
34
|
None
|
33
35
|
"""
|
34
|
-
if base_url:
|
35
|
-
RagaAICatalyst.BASE_URL = base_url
|
36
|
-
os.environ["RAGAAI_CATALYST_BASE_URL"] = base_url
|
37
36
|
|
38
37
|
if not access_key or not secret_key:
|
39
38
|
logger.error(
|
@@ -46,22 +45,25 @@ class RagaAICatalyst:
|
|
46
45
|
self.access_key, self.secret_key = self._set_access_key_secret_key(
|
47
46
|
access_key, secret_key
|
48
47
|
)
|
48
|
+
|
49
49
|
RagaAICatalyst.BASE_URL = (
|
50
50
|
os.getenv("RAGAAI_CATALYST_BASE_URL")
|
51
51
|
if os.getenv("RAGAAI_CATALYST_BASE_URL")
|
52
|
-
else "https://
|
52
|
+
else "https://catalyst.raga.ai/api"
|
53
53
|
)
|
54
|
-
os.environ["RAGAAI_CATALYST_ACCESS_KEY"] = access_key
|
55
|
-
os.environ["RAGAAI_CATALYST_SECRET_KEY"] = secret_key
|
56
54
|
|
57
55
|
self.api_keys = api_keys or {}
|
58
|
-
|
56
|
+
|
59
57
|
if self.api_keys:
|
60
58
|
self._upload_keys()
|
61
59
|
|
62
60
|
if base_url:
|
63
61
|
RagaAICatalyst.BASE_URL = base_url
|
64
|
-
|
62
|
+
try:
|
63
|
+
self.get_token()
|
64
|
+
os.environ["RAGAAI_CATALYST_BASE_URL"] = base_url
|
65
|
+
except requests.exceptions.RequestException:
|
66
|
+
raise ConnectionError("The provided base_url is not accessible. Please re-check the base_url.")
|
65
67
|
|
66
68
|
def _set_access_key_secret_key(self, access_key, secret_key):
|
67
69
|
os.environ["RAGAAI_CATALYST_ACCESS_KEY"] = access_key
|
@@ -130,7 +132,7 @@ class RagaAICatalyst:
|
|
130
132
|
Raises:
|
131
133
|
- requests.exceptions.HTTPError: If there is an HTTP error while retrieving the token.
|
132
134
|
- requests.exceptions.RequestException: If there is an error while retrieving the token.
|
133
|
-
- ValueError: If there is a JSON decoding error.
|
135
|
+
- ValueError: If there is a JSON decoding error or if authentication fails.
|
134
136
|
- Exception: If there is an unexpected error while retrieving the token.
|
135
137
|
"""
|
136
138
|
access_key = os.getenv("RAGAAI_CATALYST_ACCESS_KEY")
|
@@ -145,54 +147,43 @@ class RagaAICatalyst:
|
|
145
147
|
headers = {"Content-Type": "application/json"}
|
146
148
|
json_data = {
|
147
149
|
"accessKey": access_key,
|
148
|
-
"secretKey": secret_key
|
150
|
+
"secretKey": secret_key
|
149
151
|
}
|
150
152
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
)
|
158
|
-
response.raise_for_status()
|
153
|
+
response = requests.post(
|
154
|
+
f"{ RagaAICatalyst.BASE_URL}/token",
|
155
|
+
headers=headers,
|
156
|
+
json=json_data,
|
157
|
+
timeout=RagaAICatalyst.TIMEOUT,
|
158
|
+
)
|
159
159
|
|
160
|
+
# Handle specific status codes before raising an error
|
161
|
+
if response.status_code == 400:
|
160
162
|
token_response = response.json()
|
163
|
+
if token_response.get("message") == "Please enter valid credentials":
|
164
|
+
raise Exception("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.")
|
161
165
|
|
162
|
-
|
163
|
-
logger.error(
|
164
|
-
"Token retrieval was not successful: %s",
|
165
|
-
token_response.get("message", "Unknown error"),
|
166
|
-
)
|
167
|
-
return None
|
166
|
+
response.raise_for_status()
|
168
167
|
|
169
|
-
|
170
|
-
if token:
|
171
|
-
os.environ["RAGAAI_CATALYST_TOKEN"] = token
|
172
|
-
print("Token(s) set successfully")
|
173
|
-
return token
|
174
|
-
else:
|
175
|
-
logger.error("Token(s) not set")
|
176
|
-
return None
|
168
|
+
token_response = response.json()
|
177
169
|
|
178
|
-
|
170
|
+
if not token_response.get("success", False):
|
179
171
|
logger.error(
|
180
|
-
"
|
172
|
+
"Token retrieval was not successful: %s",
|
173
|
+
token_response.get("message", "Unknown error"),
|
181
174
|
)
|
182
|
-
if response.status_code == 500:
|
183
|
-
error_message = response.json().get("message", "Unknown server error")
|
184
|
-
logger.error("Server error: %s", error_message)
|
185
|
-
return None
|
186
|
-
except requests.exceptions.RequestException as req_err:
|
187
|
-
logger.error("Error occurred while retrieving token: %s", str(req_err))
|
188
|
-
return None
|
189
|
-
except ValueError as json_err:
|
190
|
-
logger.error("JSON decoding error: %s", str(json_err))
|
191
175
|
return None
|
192
|
-
|
193
|
-
|
176
|
+
|
177
|
+
token = token_response.get("data", {}).get("token")
|
178
|
+
if token:
|
179
|
+
os.environ["RAGAAI_CATALYST_TOKEN"] = token
|
180
|
+
print("Token(s) set successfully")
|
181
|
+
return token
|
182
|
+
else:
|
183
|
+
logger.error("Token(s) not set")
|
194
184
|
return None
|
195
185
|
|
186
|
+
|
196
187
|
def create_project(self, project_name, type="llm", description=""):
|
197
188
|
"""
|
198
189
|
Creates a project with the given project_name, type, and description.
|
@@ -262,6 +253,7 @@ class RagaAICatalyst:
|
|
262
253
|
"Unexpected error while creating project: %s", str(general_err1)
|
263
254
|
)
|
264
255
|
return "An unexpected error occurred while creating the project"
|
256
|
+
|
265
257
|
|
266
258
|
def list_projects(self, num_projects=100):
|
267
259
|
"""
|
@@ -344,6 +336,10 @@ class RagaAICatalyst:
|
|
344
336
|
return "An unexpected error occurred while listing projects"
|
345
337
|
|
346
338
|
def list_metrics(self):
|
339
|
+
return RagaAICatalyst.list_metrics()
|
340
|
+
|
341
|
+
@staticmethod
|
342
|
+
def list_metrics():
|
347
343
|
headers = {
|
348
344
|
"Content-Type": "application/json",
|
349
345
|
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
@@ -352,7 +348,7 @@ class RagaAICatalyst:
|
|
352
348
|
response = requests.get(
|
353
349
|
f"{RagaAICatalyst.BASE_URL}/v1/llm/llm-metrics",
|
354
350
|
headers=headers,
|
355
|
-
timeout=
|
351
|
+
timeout=RagaAICatalyst.TIMEOUT,
|
356
352
|
)
|
357
353
|
response.raise_for_status()
|
358
354
|
logger.debug("Metrics list retrieved successfully")
|
@@ -44,7 +44,7 @@ class RagaExporter:
|
|
44
44
|
RagaExporter.BASE_URL = (
|
45
45
|
os.getenv("RAGAAI_CATALYST_BASE_URL")
|
46
46
|
if os.getenv("RAGAAI_CATALYST_BASE_URL")
|
47
|
-
else "https://
|
47
|
+
else "https://catalyst.raga.ai/api"
|
48
48
|
)
|
49
49
|
self.access_key = os.getenv("RAGAAI_CATALYST_ACCESS_KEY")
|
50
50
|
self.secret_key = os.getenv("RAGAAI_CATALYST_SECRET_KEY")
|
@@ -92,6 +92,23 @@ class RagaExporter:
|
|
92
92
|
timeout=RagaExporter.TIMEOUT,
|
93
93
|
)
|
94
94
|
return response
|
95
|
+
|
96
|
+
|
97
|
+
def compare_schemas(base_schema, project_schema):
|
98
|
+
differences = []
|
99
|
+
for key, base_value in base_schema.items():
|
100
|
+
if key not in project_schema:
|
101
|
+
differences.append(f"Key '{key}' is missing in new schema.")
|
102
|
+
else:
|
103
|
+
# Remove everything after '_' in the new schema value
|
104
|
+
new_value = project_schema[key].split('_')[0]
|
105
|
+
if base_value != new_value:
|
106
|
+
differences.append(f"Value mismatch for key '{key}': base = '{base_value}', new = '{new_value}'.")
|
107
|
+
|
108
|
+
if differences:
|
109
|
+
return False, differences
|
110
|
+
return True, []
|
111
|
+
|
95
112
|
|
96
113
|
response = make_request()
|
97
114
|
if response.status_code == 401:
|
@@ -99,6 +116,13 @@ class RagaExporter:
|
|
99
116
|
response = make_request() # Retry the request
|
100
117
|
if response.status_code != 200:
|
101
118
|
return response.status_code
|
119
|
+
if response.status_code == 200:
|
120
|
+
project_schema = response.json()["data"]
|
121
|
+
base_schema = RagaExporter.SCHEMA_MAPPING
|
122
|
+
is_same, _ = compare_schemas(base_schema, project_schema)
|
123
|
+
if not is_same:
|
124
|
+
raise Exception(f"Trace cannot be logged to this Project because of schema difference. Create a new project to log trace")
|
125
|
+
return response.status_code
|
102
126
|
return response.status_code
|
103
127
|
|
104
128
|
def _create_schema(self):
|
@@ -18,11 +18,13 @@ from .instrumentators import (
|
|
18
18
|
)
|
19
19
|
from .utils import get_unique_key
|
20
20
|
|
21
|
+
from ..ragaai_catalyst import RagaAICatalyst
|
22
|
+
|
21
23
|
logger = logging.getLogger(__name__)
|
22
24
|
|
23
25
|
|
24
26
|
class Tracer:
|
25
|
-
|
27
|
+
NUM_PROJECTS = 100
|
26
28
|
def __init__(
|
27
29
|
self,
|
28
30
|
project_name,
|
@@ -53,6 +55,31 @@ class Tracer:
|
|
53
55
|
self.description = description
|
54
56
|
self.upload_timeout = upload_timeout
|
55
57
|
|
58
|
+
params = {
|
59
|
+
"size": str(self.NUM_PROJECTS),
|
60
|
+
"page": "0",
|
61
|
+
"type": "llm",
|
62
|
+
}
|
63
|
+
headers = {
|
64
|
+
"Content-Type": "application/json",
|
65
|
+
"Authorization": f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}',
|
66
|
+
}
|
67
|
+
response = requests.get(
|
68
|
+
f"{RagaAICatalyst.BASE_URL}/projects",
|
69
|
+
params=params,
|
70
|
+
headers=headers,
|
71
|
+
timeout=10,
|
72
|
+
)
|
73
|
+
response.raise_for_status()
|
74
|
+
# logger.debug("Projects list retrieved successfully")
|
75
|
+
project_list = [
|
76
|
+
project["name"] for project in response.json()["data"]["content"]
|
77
|
+
]
|
78
|
+
|
79
|
+
if self.project_name not in project_list:
|
80
|
+
raise ValueError("Project not found. Please enter a valid project name")
|
81
|
+
|
82
|
+
|
56
83
|
self.raga_client = RagaExporter(project_name=self.project_name)
|
57
84
|
|
58
85
|
self._tracer_provider = self._setup_provider()
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ragaai_catalyst
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.8b1
|
4
4
|
Summary: RAGA AI CATALYST
|
5
|
-
Author-email: Kiran Scaria <kiran.scaria@raga.ai>, Kedar Gaikwad <kedar.gaikwad@raga.ai>, Dushyant Mahajan <dushyant.mahajan@raga.ai>
|
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>
|
6
6
|
Requires-Python: >=3.9
|
7
7
|
Description-Content-Type: text/markdown
|
8
8
|
Requires-Dist: aiohttp>=3.10.2
|
@@ -44,6 +44,7 @@ RagaAI Catalyst is a powerful tool for managing and optimizing LLM projects. It
|
|
44
44
|
- [Trace Management](#trace-management)
|
45
45
|
- [Experiment Management](#experiment-management)
|
46
46
|
- [Dataset Management](#dataset-management)
|
47
|
+
- [Prompt Management](#prompt-management)
|
47
48
|
|
48
49
|
## Installation
|
49
50
|
|
@@ -63,9 +64,11 @@ from ragaai_catalyst import RagaAICatalyst
|
|
63
64
|
catalyst = RagaAICatalyst(
|
64
65
|
access_key="YOUR_ACCESS_KEY",
|
65
66
|
secret_key="YOUR_SECRET_KEY",
|
66
|
-
|
67
|
+
base_url="BASE_URL"
|
67
68
|
)
|
68
69
|
```
|
70
|
+
**Note**: Authetication to RagaAICatalyst is necessary to perform any operations below
|
71
|
+
|
69
72
|
|
70
73
|
## Usage
|
71
74
|
|
@@ -102,12 +105,12 @@ tracer = Tracer(
|
|
102
105
|
"vector_store": "faiss",
|
103
106
|
"embed_model": "text-embedding-ada-002",
|
104
107
|
}
|
105
|
-
).
|
108
|
+
).start()
|
106
109
|
|
107
110
|
# Your code here
|
108
111
|
|
109
112
|
# Stop the trace recording
|
110
|
-
tracer.
|
113
|
+
tracer.stop()
|
111
114
|
|
112
115
|
# Alternatively, use a context manager
|
113
116
|
with tracer.trace():
|
@@ -153,34 +156,69 @@ print("Experiment Status:", status)
|
|
153
156
|
results = experiment_manager.get_results()
|
154
157
|
print("Experiment Results:", results)
|
155
158
|
```
|
156
|
-
### Dataset Management
|
157
159
|
|
158
|
-
Create and manage trace datasets for your projects.
|
159
160
|
|
160
161
|
|
161
|
-
|
162
|
+
## Dataset Management
|
163
|
+
Manage datasets efficiently for your projects:
|
164
|
+
|
165
|
+
```py
|
162
166
|
from ragaai_catalyst import Dataset
|
163
167
|
|
164
168
|
# Initialize Dataset management for a specific project
|
165
|
-
dataset_manager = Dataset(project_name="
|
169
|
+
dataset_manager = Dataset(project_name="project_name")
|
166
170
|
|
167
171
|
# List existing datasets
|
168
172
|
datasets = dataset_manager.list_datasets()
|
169
|
-
print("
|
173
|
+
print("Existing Datasets:", datasets)
|
170
174
|
|
171
|
-
# Create a
|
172
|
-
dataset_manager.
|
175
|
+
# Create a dataset from trace
|
176
|
+
dataset_manager.create_from_trace(
|
173
177
|
dataset_name='Test-dataset-1',
|
174
178
|
filter_list=[
|
175
|
-
{
|
176
|
-
|
177
|
-
"values": ["gpt-3.5-turbo", "gpt-4"]
|
178
|
-
},
|
179
|
-
{
|
180
|
-
"name": "prompt_length",
|
181
|
-
"lte": 27,
|
182
|
-
"gte": 23
|
183
|
-
}
|
179
|
+
{"name": "llm_model", "values": ["gpt-3.5-turbo", "gpt-4"]},
|
180
|
+
{"name": "prompt_length", "lte": 27, "gte": 23}
|
184
181
|
]
|
185
182
|
)
|
183
|
+
|
184
|
+
# Create a dataset from CSV
|
185
|
+
dataset_manager.create_from_csv(
|
186
|
+
csv_path='path/to/your.csv',
|
187
|
+
dataset_name='MyDataset',
|
188
|
+
schema_mapping={'column1': 'schema_element1', 'column2': 'schema_element2'}
|
189
|
+
)
|
186
190
|
```
|
191
|
+
|
192
|
+
For more detailed information on Dataset Management, including CSV schema handling and advanced usage, please refer to the [Dataset Management documentation](docs/dataset_management.md).
|
193
|
+
|
194
|
+
## Prompt Management
|
195
|
+
|
196
|
+
Manage and use prompts efficiently in your projects:
|
197
|
+
|
198
|
+
```py
|
199
|
+
from ragaai_catalyst.prompt_manager import PromptManager
|
200
|
+
|
201
|
+
# Initialize PromptManager
|
202
|
+
prompt_manager = PromptManager("your-project-name")
|
203
|
+
|
204
|
+
# List available prompts
|
205
|
+
prompts = prompt_manager.list_prompts()
|
206
|
+
print("Available prompts:", prompts)
|
207
|
+
|
208
|
+
# Get a specific prompt
|
209
|
+
prompt_name = "your_prompt_name"
|
210
|
+
prompt = prompt_manager.get_prompt(prompt_name)
|
211
|
+
|
212
|
+
# Compile a prompt with variables
|
213
|
+
compiled_prompt = prompt.compile(query="What's the weather?", context="sunny", llm_response="It's sunny today")
|
214
|
+
print("Compiled prompt:", compiled_prompt)
|
215
|
+
|
216
|
+
# Get prompt parameters
|
217
|
+
parameters = prompt.get_parameters()
|
218
|
+
print("Prompt parameters:", parameters)
|
219
|
+
```
|
220
|
+
|
221
|
+
For more detailed information on Prompt Management, please refer to the [Prompt Management documentation](docs/prompt_management.md).
|
222
|
+
|
223
|
+
|
224
|
+
|
@@ -1,21 +1,22 @@
|
|
1
1
|
ragaai_catalyst/__init__.py,sha256=0hf_H1xkhrpGnUWTbjvYOXXQta1S4JO2yud1Eqydt-I,226
|
2
2
|
ragaai_catalyst/_version.py,sha256=JKt9KaVNOMVeGs8ojO6LvIZr7ZkMzNN-gCcvryy4x8E,460
|
3
|
-
ragaai_catalyst/dataset.py,sha256=
|
4
|
-
ragaai_catalyst/experiment.py,sha256=
|
5
|
-
ragaai_catalyst/
|
3
|
+
ragaai_catalyst/dataset.py,sha256=xEun-MqTgT0JGyGB2t0BwwC6M7t1aUT7x5X12C-_4pI,7644
|
4
|
+
ragaai_catalyst/experiment.py,sha256=f2Z-UJSXPqlcH59oB1ThSzc7VMrlfyFQnzlbX-BCm4Q,18823
|
5
|
+
ragaai_catalyst/prompt_manager.py,sha256=3jEcgS0JRZzjHww_ityOkq9SMvi7DQ75PlKu-17dXW4,14729
|
6
|
+
ragaai_catalyst/ragaai_catalyst.py,sha256=LJECRdCmW8DtF3Lk4wZ6lXJgsYkh6Oome45DzONyaVU,16228
|
6
7
|
ragaai_catalyst/utils.py,sha256=TlhEFwLyRU690HvANbyoRycR3nQ67lxVUQoUOfTPYQ0,3772
|
7
8
|
ragaai_catalyst/tracers/__init__.py,sha256=NppmJhD3sQ5R1q6teaZLS7rULj08Gb6JT8XiPRIe_B0,49
|
8
|
-
ragaai_catalyst/tracers/tracer.py,sha256=
|
9
|
+
ragaai_catalyst/tracers/tracer.py,sha256=LZQNKQF6hRfzxDu_Ljs2HBxQinjihKQoH189gIsO4w4,9171
|
9
10
|
ragaai_catalyst/tracers/exporters/__init__.py,sha256=kVA8zp05h3phu4e-iHSlnznp_PzMRczB7LphSsZgUjg,138
|
10
11
|
ragaai_catalyst/tracers/exporters/file_span_exporter.py,sha256=E1uSBZ8JfUBLLtkhN3lIy_AWmPcZDCInsOFhPoWP9mU,6362
|
11
|
-
ragaai_catalyst/tracers/exporters/raga_exporter.py,sha256=
|
12
|
+
ragaai_catalyst/tracers/exporters/raga_exporter.py,sha256=yxLadWzGCTr6AMh9n0U_1xNlw80aAcLE0KthktC2xMU,17487
|
12
13
|
ragaai_catalyst/tracers/instrumentators/__init__.py,sha256=FgnMQupoRTzmVsG9YKsLQera2Pfs-AluZv8CxwavoyQ,253
|
13
14
|
ragaai_catalyst/tracers/instrumentators/langchain.py,sha256=yMN0qVF0pUVk6R5M1vJoUXezDo1ejs4klCFRlE8x4vE,574
|
14
15
|
ragaai_catalyst/tracers/instrumentators/llamaindex.py,sha256=SMrRlR4xM7k9HK43hakE8rkrWHxMlmtmWD-AX6TeByc,416
|
15
16
|
ragaai_catalyst/tracers/instrumentators/openai.py,sha256=14R4KW9wQCR1xysLfsP_nxS7cqXrTPoD8En4MBAaZUU,379
|
16
17
|
ragaai_catalyst/tracers/utils/__init__.py,sha256=KeMaZtYaTojilpLv65qH08QmpYclfpacDA0U3wg6Ybw,64
|
17
18
|
ragaai_catalyst/tracers/utils/utils.py,sha256=ViygfJ7vZ7U0CTSA1lbxVloHp4NSlmfDzBRNCJuMhis,2374
|
18
|
-
ragaai_catalyst-1.0.
|
19
|
-
ragaai_catalyst-1.0.
|
20
|
-
ragaai_catalyst-1.0.
|
21
|
-
ragaai_catalyst-1.0.
|
19
|
+
ragaai_catalyst-1.0.8b1.dist-info/METADATA,sha256=HdN7_Zxg_NAJwulu7LJZAEBHRljZsk-v83-mCRw1VeM,6499
|
20
|
+
ragaai_catalyst-1.0.8b1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
21
|
+
ragaai_catalyst-1.0.8b1.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
|
22
|
+
ragaai_catalyst-1.0.8b1.dist-info/RECORD,,
|
File without changes
|