ragaai-catalyst 2.1b0__py3-none-any.whl → 2.1b2__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.
Files changed (45) hide show
  1. ragaai_catalyst/__init__.py +1 -0
  2. ragaai_catalyst/dataset.py +1 -4
  3. ragaai_catalyst/evaluation.py +4 -5
  4. ragaai_catalyst/guard_executor.py +97 -0
  5. ragaai_catalyst/guardrails_manager.py +41 -15
  6. ragaai_catalyst/internal_api_completion.py +1 -1
  7. ragaai_catalyst/prompt_manager.py +7 -2
  8. ragaai_catalyst/ragaai_catalyst.py +1 -1
  9. ragaai_catalyst/synthetic_data_generation.py +7 -0
  10. ragaai_catalyst/tracers/__init__.py +1 -1
  11. ragaai_catalyst/tracers/agentic_tracing/__init__.py +3 -0
  12. ragaai_catalyst/tracers/agentic_tracing/agent_tracer.py +422 -0
  13. ragaai_catalyst/tracers/agentic_tracing/agentic_tracing.py +198 -0
  14. ragaai_catalyst/tracers/agentic_tracing/base.py +376 -0
  15. ragaai_catalyst/tracers/agentic_tracing/data_structure.py +248 -0
  16. ragaai_catalyst/tracers/agentic_tracing/examples/FinancialAnalysisSystem.ipynb +536 -0
  17. ragaai_catalyst/tracers/agentic_tracing/examples/GameActivityEventPlanner.ipynb +134 -0
  18. ragaai_catalyst/tracers/agentic_tracing/examples/TravelPlanner.ipynb +563 -0
  19. ragaai_catalyst/tracers/agentic_tracing/file_name_tracker.py +46 -0
  20. ragaai_catalyst/tracers/agentic_tracing/llm_tracer.py +808 -0
  21. ragaai_catalyst/tracers/agentic_tracing/network_tracer.py +286 -0
  22. ragaai_catalyst/tracers/agentic_tracing/sample.py +197 -0
  23. ragaai_catalyst/tracers/agentic_tracing/tool_tracer.py +247 -0
  24. ragaai_catalyst/tracers/agentic_tracing/unique_decorator.py +165 -0
  25. ragaai_catalyst/tracers/agentic_tracing/unique_decorator_test.py +172 -0
  26. ragaai_catalyst/tracers/agentic_tracing/upload_agentic_traces.py +187 -0
  27. ragaai_catalyst/tracers/agentic_tracing/upload_code.py +115 -0
  28. ragaai_catalyst/tracers/agentic_tracing/user_interaction_tracer.py +43 -0
  29. ragaai_catalyst/tracers/agentic_tracing/utils/__init__.py +3 -0
  30. ragaai_catalyst/tracers/agentic_tracing/utils/api_utils.py +18 -0
  31. ragaai_catalyst/tracers/agentic_tracing/utils/data_classes.py +61 -0
  32. ragaai_catalyst/tracers/agentic_tracing/utils/generic.py +32 -0
  33. ragaai_catalyst/tracers/agentic_tracing/utils/llm_utils.py +177 -0
  34. ragaai_catalyst/tracers/agentic_tracing/utils/model_costs.json +7823 -0
  35. ragaai_catalyst/tracers/agentic_tracing/utils/trace_utils.py +74 -0
  36. ragaai_catalyst/tracers/agentic_tracing/zip_list_of_unique_files.py +184 -0
  37. ragaai_catalyst/tracers/exporters/raga_exporter.py +1 -7
  38. ragaai_catalyst/tracers/tracer.py +30 -4
  39. ragaai_catalyst/tracers/upload_traces.py +127 -0
  40. ragaai_catalyst-2.1b2.dist-info/METADATA +43 -0
  41. ragaai_catalyst-2.1b2.dist-info/RECORD +56 -0
  42. {ragaai_catalyst-2.1b0.dist-info → ragaai_catalyst-2.1b2.dist-info}/WHEEL +1 -1
  43. ragaai_catalyst-2.1b0.dist-info/METADATA +0 -295
  44. ragaai_catalyst-2.1b0.dist-info/RECORD +0 -28
  45. {ragaai_catalyst-2.1b0.dist-info → ragaai_catalyst-2.1b2.dist-info}/top_level.txt +0 -0
@@ -7,6 +7,7 @@ from .prompt_manager import PromptManager
7
7
  from .evaluation import Evaluation
8
8
  from .synthetic_data_generation import SyntheticDataGeneration
9
9
  from .guardrails_manager import GuardrailsManager
10
+ from .guard_executor import GuardExecutor
10
11
 
11
12
 
12
13
  __all__ = ["Experiment", "RagaAICatalyst", "Tracer", "PromptManager", "Evaluation","SyntheticDataGeneration", "GuardrailsManager"]
@@ -5,7 +5,6 @@ from typing import Union
5
5
  import logging
6
6
  from .ragaai_catalyst import RagaAICatalyst
7
7
  import pandas as pd
8
- import pdb
9
8
  logger = logging.getLogger(__name__)
10
9
  get_token = RagaAICatalyst.get_token
11
10
 
@@ -16,7 +15,7 @@ class Dataset:
16
15
 
17
16
  def __init__(self, project_name):
18
17
  self.project_name = project_name
19
- self.num_projects = 100
18
+ self.num_projects = 99999
20
19
  Dataset.BASE_URL = (
21
20
  os.getenv("RAGAAI_CATALYST_BASE_URL")
22
21
  if os.getenv("RAGAAI_CATALYST_BASE_URL")
@@ -202,7 +201,6 @@ class Dataset:
202
201
 
203
202
  #### put csv to presigned URL
204
203
  def put_csv_to_presignedUrl(url):
205
- # pdb.set_trace()
206
204
  headers = {
207
205
  'Content-Type': 'text/csv',
208
206
  'x-ms-blob-type': 'BlockBlob',
@@ -224,7 +222,6 @@ class Dataset:
224
222
  try:
225
223
 
226
224
  put_csv_response = put_csv_to_presignedUrl(url)
227
- # pdb.set_trace()
228
225
  print(put_csv_response)
229
226
  if put_csv_response.status_code not in (200, 201):
230
227
  raise ValueError('Unable to put csv to the presignedUrl')
@@ -4,7 +4,6 @@ import pandas as pd
4
4
  import io
5
5
  from .ragaai_catalyst import RagaAICatalyst
6
6
  import logging
7
- import pdb
8
7
 
9
8
  logger = logging.getLogger(__name__)
10
9
 
@@ -16,7 +15,7 @@ class Evaluation:
16
15
  self.base_url = f"{RagaAICatalyst.BASE_URL}"
17
16
  self.timeout = 10
18
17
  self.jobId = None
19
- self.num_projects=100
18
+ self.num_projects=99999
20
19
 
21
20
  try:
22
21
  response = requests.get(
@@ -242,7 +241,7 @@ class Evaluation:
242
241
 
243
242
  def _update_base_json(self, metrics):
244
243
  metrics_schema_response = self._get_metrics_schema_response()
245
- sub_providers = ["openai","azure","gemini","groq"]
244
+ sub_providers = ["openai","azure","gemini","groq","anthropic","bedrock"]
246
245
  metricParams = []
247
246
  for metric in metrics:
248
247
  base_json = self._get_metricParams()
@@ -252,7 +251,7 @@ class Evaluation:
252
251
  for key, value in metric["config"].items():
253
252
  #checking if provider is one of the allowed providers
254
253
  if key.lower()=="provider" and value.lower() not in sub_providers:
255
- raise ValueError("Enter a valid provider name. The following Provider names are supported: OpenAI, Azure, Gemini, Groq")
254
+ raise ValueError("Enter a valid provider name. The following Provider names are supported: openai, azure, gemini, groq, anthropic, bedrock")
256
255
 
257
256
  if key.lower()=="threshold":
258
257
  if len(value)>1:
@@ -330,7 +329,7 @@ class Evaluation:
330
329
  metric_schema_mapping = self._update_base_json(metrics)
331
330
  try:
332
331
  response = requests.post(
333
- f'{self.base_url}/playground/metric-evaluation',
332
+ f'{self.base_url}/v2/llm/metric-evaluation',
334
333
  headers=headers,
335
334
  json=metric_schema_mapping,
336
335
  timeout=self.timeout
@@ -0,0 +1,97 @@
1
+ import litellm
2
+ import json
3
+ import requests
4
+ import os
5
+ import logging
6
+ logger = logging.getLogger('LiteLLM')
7
+ logger.setLevel(logging.ERROR)
8
+
9
+ class GuardExecutor:
10
+
11
+ def __init__(self,id,guard_manager,field_map={}):
12
+ self.deployment_id = id
13
+ self.field_map = field_map
14
+ self.guard_manager = guard_manager
15
+ self.deployment_details = self.guard_manager.get_deployment(id)
16
+ if not self.deployment_details:
17
+ raise ValueError('Error in getting deployment details')
18
+ self.base_url = guard_manager.base_url
19
+ for key in field_map.keys():
20
+ if key not in ['prompt','context','response','instruction']:
21
+ print('Keys in field map should be in ["prompt","context","response","instruction"]')
22
+
23
+ def execute_deployment(self,payload):
24
+ api = self.base_url + f'/guardrail/deployment/{self.deployment_id}/ingest'
25
+
26
+ payload = json.dumps(payload)
27
+ headers = {
28
+ 'x-project-id': str(self.guard_manager.project_id),
29
+ 'Content-Type': 'application/json',
30
+ 'Authorization': f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}'
31
+ }
32
+ try:
33
+ response = requests.request("POST", api, headers=headers, data=payload,timeout=self.guard_manager.timeout)
34
+ except Exception as e:
35
+ print('Failed running guardrail: ',str(e))
36
+ return None
37
+ if response.status_code!=200:
38
+ print('Error in running deployment ',response.json()['message'])
39
+ if response.json()['success']:
40
+ return response.json()
41
+ else:
42
+ print(response.json()['message'])
43
+ return None
44
+
45
+ def llm_executor(self,messages,model_params,llm_caller):
46
+ if llm_caller == 'litellm':
47
+ model_params['messages'] = messages
48
+ response = litellm.completion(**model_params)
49
+ return response
50
+ else:
51
+ print(f"{llm_caller} not supported currently, use litellm as llm caller")
52
+
53
+
54
+ def __call__(self,messages,prompt_params,model_params,llm_caller='litellm'):
55
+ for key in self.field_map:
56
+ if key not in ['prompt','response']:
57
+ if self.field_map[key] not in prompt_params:
58
+ raise ValueError(f'{key} added as field map but not passed as prompt parameter')
59
+ context_var = self.field_map.get('context',None)
60
+ prompt = None
61
+ for msg in messages:
62
+ if 'role' in msg:
63
+ if msg['role'] == 'user':
64
+ prompt = msg['content']
65
+ if not context_var:
66
+ msg['content'] += '\n' + prompt_params[context_var]
67
+ doc = dict()
68
+ doc['prompt'] = prompt
69
+ doc['context'] = prompt_params[context_var]
70
+
71
+ # inactive the guardrails that needs Response variable
72
+ #deployment_response = self.execute_deployment(doc)
73
+
74
+ # activate only guardrails that require response
75
+ try:
76
+ llm_response = self.llm_executor(messages,model_params,llm_caller)
77
+ except Exception as e:
78
+ print('Error in running llm:',str(e))
79
+ return None
80
+ doc['response'] = llm_response['choices'][0].message.content
81
+ if 'instruction' in self.field_map:
82
+ instruction = prompt_params[self.field_map['instruction']]
83
+ doc['instruction'] = instruction
84
+ response = self.execute_deployment(doc)
85
+ if response and response['data']['status'] == 'FAIL':
86
+ print('Guardrail deployment run retured failed status, replacing with alternate response')
87
+ return response['data']['alternateResponse'],llm_response,response
88
+ else:
89
+ return None,llm_response,response
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
@@ -13,7 +13,7 @@ class GuardrailsManager:
13
13
  """
14
14
  self.project_name = project_name
15
15
  self.timeout = 10
16
- self.num_projects = 100
16
+ self.num_projects = 99999
17
17
  self.deployment_name = "NA"
18
18
  self.deployment_id = "NA"
19
19
  self.base_url = f"{RagaAICatalyst.BASE_URL}"
@@ -31,7 +31,7 @@ class GuardrailsManager:
31
31
  :return: A tuple containing a list of project names and a list of dictionaries with project IDs and names.
32
32
  """
33
33
  headers = {'Authorization': f'Bearer {os.getenv("RAGAAI_CATALYST_TOKEN")}'}
34
- response = requests.request("GET", f"{self.base_url}/v2/llm/projects?size=12&page=0", headers=headers, timeout=self.timeout)
34
+ response = requests.request("GET", f"{self.base_url}/v2/llm/projects?size={self.num_projects}", headers=headers, timeout=self.timeout)
35
35
  project_content = response.json()["data"]["content"]
36
36
  list_project = [_["name"] for _ in project_content]
37
37
  project_name_with_id = [{"id": _["id"], "name": _["name"]} for _ in project_content]
@@ -68,10 +68,11 @@ class GuardrailsManager:
68
68
  'X-Project-Id': str(self.project_id)
69
69
  }
70
70
  response = requests.request("GET", f"{self.base_url}/guardrail/deployment/{deployment_id}", headers=headers, data=payload, timeout=self.timeout)
71
- deployment_id_name = response.json()["data"]["name"]
72
- deployment_id_guardrails = response.json()["data"]["guardrailsResponse"]
73
- guardrails_list_deployment_id = [{_["type"]:_["name"]} for _ in deployment_id_guardrails]
74
- return {"deployment_name":deployment_id_name, "guardrails_list":guardrails_list_deployment_id}
71
+ if response.json()['success']:
72
+ return response.json()
73
+ else:
74
+ print('Error in retrieving deployment details:',response.json()['message'])
75
+ return None
75
76
 
76
77
 
77
78
  def list_guardrails(self):
@@ -132,11 +133,12 @@ class GuardrailsManager:
132
133
  print(response.json()["message"])
133
134
  deployment_ids = self.list_deployment_ids()
134
135
  self.deployment_id = [_["id"] for _ in deployment_ids if _["name"]==self.deployment_name][0]
136
+ return self.deployment_id
135
137
  else:
136
138
  print(response)
137
139
 
138
140
 
139
- def add_guardrails(self, guardrails, guardrails_config={}):
141
+ def add_guardrails(self, deployment_id, guardrails, guardrails_config={}):
140
142
  """
141
143
  Add guardrails to the current deployment.
142
144
 
@@ -145,16 +147,21 @@ class GuardrailsManager:
145
147
  :raises ValueError: If a guardrail name or type is invalid.
146
148
  """
147
149
  # Checking if guardrails names given already exist or not
148
- _, guardrails_type_name_exists = self.get_deployment(self.deployment_id)
150
+ self.deployment_id = deployment_id
151
+ deployment_details = self.get_deployment(self.deployment_id)
152
+ if not deployment_details:
153
+ return None
154
+ deployment_id_name = deployment_details["data"]["name"]
155
+ deployment_id_guardrails = deployment_details["data"]["guardrailsResponse"]
156
+ guardrails_type_name_exists = [{_['metricSpec']["name"]:_['metricSpec']["displayName"]} for _ in deployment_id_guardrails]
149
157
  guardrails_type_name_exists = [list(d.values())[0] for d in guardrails_type_name_exists]
150
158
  user_guardrails_name_list = [_["name"] for _ in guardrails]
151
159
  for g_name in user_guardrails_name_list:
152
160
  if g_name in guardrails_type_name_exists:
153
161
  raise ValueError(f"Guardrail with '{g_name} already exists, choose a unique name'")
154
-
155
162
  # Checking if guardrails type is correct or not
156
163
  available_guardrails_list = self.list_guardrails()
157
- user_guardrails_type_list = [_["type"] for _ in guardrails]
164
+ user_guardrails_type_list = [_["name"] for _ in guardrails]
158
165
  for g_type in user_guardrails_type_list:
159
166
  if g_type not in available_guardrails_list:
160
167
  raise ValueError(f"Guardrail type '{g_type} does not exists, choose a correct type'")
@@ -170,6 +177,8 @@ class GuardrailsManager:
170
177
  response = requests.request("POST", f"{self.base_url}/guardrail/deployment/{str(self.deployment_id)}/configure", headers=headers, data=payload)
171
178
  if response.json()["success"]:
172
179
  print(response.json()["message"])
180
+ else:
181
+ print('Error updating guardrail ',response.json()['message'])
173
182
 
174
183
  def _get_guardrail_config_payload(self, guardrails_config):
175
184
  """
@@ -209,13 +218,30 @@ class GuardrailsManager:
209
218
  :param guardrail: A dictionary containing the guardrail's attributes.
210
219
  :return: A dictionary representing the guardrail's data.
211
220
  """
221
+ if 'config' in guardrail:
222
+ if 'mappings' in guardrail.get('config'):
223
+ for mapping in guardrail.get('config',{}).get('mappings',{}):
224
+ if mapping['schemaName'] not in ['Text','Prompt','Context','Response']:
225
+ raise(ValueError('Invalid schemaName in guardrail mapping schema'))
226
+ if mapping['variableName'] not in ['Instruction','Prompt','Context','Response']:
227
+ raise(ValueError('Invalid variableName in guardrail mapping schema'))
228
+ if 'model' in guardrail.get('config'):
229
+ if guardrail.get('config',{}).get('model','') not in ['gpt-4o-mini','gpt-4o','gpt-4-turbo']:
230
+ raise(ValueError('Invalid model name in guardrail model schema'))
231
+ if 'params' not in guardrail.get('config'):
232
+ guardrail['config']['params'] = {
233
+ "isActive": {"value": False},
234
+ "isHighRisk": {"value": False},
235
+ "threshold": {"lt": 1}
236
+ }
237
+
238
+
212
239
  data = {
240
+ "displayName": guardrail["displayName"],
213
241
  "name": guardrail["name"],
214
- "type": guardrail["type"],
215
- "isHighRisk": guardrail.get("isHighRisk", False),
216
- "isActive": guardrail.get("isActive", False),
217
- "threshold": {}
242
+ "config": guardrail.get("config", {})
218
243
  }
244
+ '''
219
245
  if "lte" in guardrail["threshold"]:
220
246
  data["threshold"]["lte"] = guardrail["threshold"]["lte"]
221
247
  elif "gte" in guardrail["threshold"]:
@@ -223,7 +249,7 @@ class GuardrailsManager:
223
249
  elif "eq" in guardrail["threshold"]:
224
250
  data["threshold"]["eq"] = guardrail["threshold"]["eq"]
225
251
  else:
226
- data["threshold"]["gte"] = 0.0
252
+ data["threshold"]["gte"] = 0.0'''
227
253
  return data
228
254
 
229
255
 
@@ -36,7 +36,7 @@ def api_completion(messages, model_config, kwargs):
36
36
  raise ValueError(response["error"]["message"])
37
37
  else:
38
38
  result= response["choices"][0]["message"]["content"]
39
- response1 = result.replace('\n', '')
39
+ response1 = result.replace('\n', '').replace('```json','').replace('```', '').strip()
40
40
  try:
41
41
  json_data = json.loads(response1)
42
42
  df = pd.DataFrame(json_data)
@@ -23,7 +23,7 @@ class PromptManager:
23
23
  self.project_name = project_name
24
24
  self.base_url = f"{RagaAICatalyst.BASE_URL}/playground/prompt"
25
25
  self.timeout = 10
26
- self.size = 100 #Number of projects to fetch
26
+ self.size = 99999 #Number of projects to fetch
27
27
 
28
28
  try:
29
29
  response = requests.get(
@@ -432,7 +432,12 @@ class PromptObject:
432
432
  Returns:
433
433
  dict: A dictionary of parameters found in the prompt text.
434
434
  """
435
- parameters = {param["name"]: self._convert_value(param["value"], param["type"]) for param in self.parameters}
435
+ parameters = {}
436
+ for param in self.parameters:
437
+ if "value" in param:
438
+ parameters[param["name"]] = self._convert_value(param["value"], param["type"])
439
+ else:
440
+ parameters[param["name"]] = ""
436
441
  parameters["model"] = self.model
437
442
  return parameters
438
443
 
@@ -287,7 +287,7 @@ class RagaAICatalyst:
287
287
  def get_project_id(self, project_name):
288
288
  pass
289
289
 
290
- def list_projects(self, num_projects=100):
290
+ def list_projects(self, num_projects=99999):
291
291
  """
292
292
  Retrieves a list of projects with the specified number of projects.
293
293
 
@@ -141,6 +141,9 @@ class SyntheticDataGeneration:
141
141
 
142
142
  def _initialize_client(self, provider, api_key, api_base=None, internal_llm_proxy=None):
143
143
  """Initialize the appropriate client based on provider."""
144
+ if not provider:
145
+ raise ValueError("Model configuration must be provided with a valid provider and model.")
146
+
144
147
  if provider == "groq":
145
148
  if api_key is None and os.getenv("GROQ_API_KEY") is None:
146
149
  raise ValueError("API key must be provided for Groq.")
@@ -155,6 +158,9 @@ class SyntheticDataGeneration:
155
158
  if api_key is None and os.getenv("OPENAI_API_KEY") is None and internal_llm_proxy is None:
156
159
  raise ValueError("API key must be provided for OpenAI.")
157
160
  openai.api_key = api_key or os.getenv("OPENAI_API_KEY")
161
+
162
+ else:
163
+ raise ValueError(f"Provider is not recognized.")
158
164
 
159
165
  def _generate_batch_response(self, text, system_message, provider, model_config, api_key, api_base):
160
166
  """Generate a batch of responses using the specified provider."""
@@ -283,6 +289,7 @@ class SyntheticDataGeneration:
283
289
 
284
290
  # Extract the content from the response
285
291
  content = response.choices[0].message.content
292
+ content = content.replace('\n', '').replace('```json','').replace('```', '').strip()
286
293
 
287
294
  # Clean the response if needed (remove any prefix before the JSON list)
288
295
  list_start_index = content.find('[')
@@ -1,3 +1,3 @@
1
1
  from .tracer import Tracer
2
2
 
3
- __all__ = ["Tracer"]
3
+ __all__ = ["Tracer"]
@@ -0,0 +1,3 @@
1
+ from .agentic_tracing import AgenticTracing
2
+
3
+ __all__ = ['AgenticTracing']