enkryptai-sdk 1.0.3__tar.gz → 1.0.5__tar.gz

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 (42) hide show
  1. {enkryptai_sdk-1.0.3/src/enkryptai_sdk.egg-info → enkryptai_sdk-1.0.5}/PKG-INFO +84 -21
  2. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/README.md +83 -20
  3. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/setup.py +1 -1
  4. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/datasets.py +14 -0
  5. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/dto/__init__.py +3 -0
  6. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/dto/datasets.py +22 -4
  7. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/dto/deployments.py +9 -0
  8. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/dto/guardrails.py +195 -0
  9. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/dto/models.py +83 -31
  10. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/dto/red_team.py +60 -11
  11. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/evals.py +3 -3
  12. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/guardrails.py +39 -0
  13. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/models.py +32 -14
  14. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/red_team.py +9 -3
  15. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5/src/enkryptai_sdk.egg-info}/PKG-INFO +84 -21
  16. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk.egg-info/SOURCES.txt +1 -0
  17. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_all.py +3 -4
  18. enkryptai_sdk-1.0.5/tests/test_all_v2.py +1129 -0
  19. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_datasets.py +9 -4
  20. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_deployments.py +2 -0
  21. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_guardrails.py +32 -0
  22. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_model.py +14 -6
  23. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_redteam.py +11 -10
  24. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/LICENSE +0 -0
  25. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/setup.cfg +0 -0
  26. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/__init__.py +0 -0
  27. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/ai_proxy.py +0 -0
  28. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/base.py +0 -0
  29. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/config.py +0 -0
  30. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/deployments.py +0 -0
  31. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/dto/ai_proxy.py +0 -0
  32. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/dto/base.py +0 -0
  33. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/guardrails_old.py +0 -0
  34. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk/response.py +0 -0
  35. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk.egg-info/dependency_links.txt +0 -0
  36. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/src/enkryptai_sdk.egg-info/top_level.txt +0 -0
  37. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_ai_proxy.py +0 -0
  38. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_basic.py +0 -0
  39. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_detect_policy.py +0 -0
  40. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_injection_attack.py +0 -0
  41. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_openai.py +0 -0
  42. {enkryptai_sdk-1.0.3 → enkryptai_sdk-1.0.5}/tests/test_policy_violation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: enkryptai-sdk
3
- Version: 1.0.3
3
+ Version: 1.0.5
4
4
  Summary: A Python SDK with guardrails and red teaming functionality for API interactions
5
5
  Home-page: https://github.com/enkryptai/enkryptai-sdk
6
6
  Author: Enkrypt AI Team
@@ -21,9 +21,10 @@ Dynamic: license-file
21
21
  Dynamic: requires-python
22
22
  Dynamic: summary
23
23
 
24
- ![Python SDK test](https://github.com/enkryptai/enkryptai-sdk/actions/workflows/test.yaml/badge.svg)
25
24
  # Enkrypt AI Python SDK
26
25
 
26
+ ![Python SDK test](https://github.com/enkryptai/enkryptai-sdk/actions/workflows/test.yaml/badge.svg)
27
+
27
28
  A Python SDK with Guardrails, Models, Deployments, AI Proxy, Datasets and Red Team functionality for API interactions.
28
29
 
29
30
  See [https://pypi.org/project/enkryptai-sdk](https://pypi.org/project/enkryptai-sdk)
@@ -55,6 +56,7 @@ Also see the API documentation at [https://docs.enkryptai.com](https://docs.enkr
55
56
  - [Guardrails Quickstart](#guardrails-quickstart)
56
57
  - [Guardrails Response Objects](#guardrails-response-objects)
57
58
  - [GuardrailsDetectResponse](#guardrailsdetectresponse)
59
+ - [GuardrailsBatchDetectResponse](#guardrailsbatchdetectresponse)
58
60
  - [Available Guardrails Detectors](#available-guardrails-detectors)
59
61
  - [Guardrails Configs](#guardrails-configs)
60
62
  - [Injection Attack](#injection-attack)
@@ -181,6 +183,7 @@ redteam_client = RedTeamClient(api_key=ENKRYPT_API_KEY, base_url=ENKRYPT_BASE_UR
181
183
  ```python Python
182
184
  test_policy_name = "Test Policy"
183
185
  test_model_saved_name = "Test Model"
186
+ test_model_version = "v1"
184
187
  test_deployment_name = "test-deployment"
185
188
 
186
189
  pii_original_text = "My email is example@example.com. My phone number is 123-456-7890."
@@ -257,14 +260,15 @@ sample_detectors = {
257
260
  ```python Python
258
261
  sample_model_config = {
259
262
  "model_saved_name": test_model_saved_name,
260
- "testing_for": "LLM",
263
+ "model_version": test_model_version,
264
+ "testing_for": "foundationModels",
261
265
  "model_name": model_name,
262
- "modality": "text",
263
266
  "model_config": {
264
- "model_version": "",
265
267
  "model_provider": model_provider,
266
268
  "endpoint_url": model_endpoint_url,
267
269
  "apikey": OPENAI_API_KEY,
270
+ "input_modalities": ["text"],
271
+ "output_modalities": ["text"],
268
272
  },
269
273
  }
270
274
  ```
@@ -275,6 +279,7 @@ sample_model_config = {
275
279
  sample_deployment_config = {
276
280
  "name": test_deployment_name,
277
281
  "model_saved_name": test_model_saved_name,
282
+ "model_version": test_model_version,
278
283
  "input_guardrails_policy": {
279
284
  "policy_name": test_policy_name,
280
285
  "enabled": True,
@@ -308,8 +313,16 @@ sample_dataset_config = {
308
313
  "dataset_name": dataset_name,
309
314
  "system_description": "- **Voter Eligibility**: To vote in U.S. elections, individuals must be U.S. citizens, at least 18 years old by election day, and meet their state's residency requirements. - **Voter Registration**: Most states require voters to register ahead of time, with deadlines varying widely. North Dakota is an exception, as it does not require voter registration. - **Identification Requirements**: Thirty-six states enforce voter ID laws, requiring individuals to present identification at polling places. These laws aim to prevent voter fraud but can also lead to disenfranchisement. - **Voting Methods**: Voters can typically choose between in-person voting on election day, early voting, and absentee or mail-in ballots, depending on state regulations. - **Polling Hours**: Polling hours vary by state, with some states allowing extended hours for voters. Its essential for voters to check local polling times to ensure they can cast their ballots. - **Provisional Ballots**: If there are questions about a voter's eligibility, they may be allowed to cast a provisional ballot. This ballot is counted once eligibility is confirmed. - **Election Day Laws**: Many states have laws that protect the rights of voters on election day, including prohibiting intimidation and ensuring access to polling places. - **Campaign Finance Regulations**: Federal and state laws regulate contributions to candidates and political parties to ensure transparency and limit the influence of money in politics. - **Political Advertising**: Campaigns must adhere to rules regarding political advertising, including disclosure requirements about funding sources and content accuracy. - **Voter Intimidation Prohibitions**: Federal laws prohibit any form of voter intimidation or coercion at polling places, ensuring a safe environment for all voters. - **Accessibility Requirements**: The Americans with Disabilities Act mandates that polling places be accessible to individuals with disabilities, ensuring equal access to the electoral process. - **Election Monitoring**: Various organizations are allowed to monitor elections to ensure compliance with laws and regulations. They help maintain transparency and accountability in the electoral process. - **Vote Counting Procedures**: States have specific procedures for counting votes, including the use of electronic voting machines and manual audits to verify results. - **Ballot Design Standards**: States must adhere to certain design standards for ballots to ensure clarity and prevent confusion among voters when casting their votes. - **Post-Election Audits**: Some states conduct post-election audits as a measure of accuracy. These audits help verify that the vote count reflects the actual ballots cast.",
310
315
  "policy_description": "",
311
- "tools": [],
316
+ "tools": [
317
+ {
318
+ "name": "web_search",
319
+ "description": "The tool web search is used to search the web for information related to finance."
320
+ }
321
+ ],
312
322
  "info_pdf_url": "",
323
+ "scenarios": 1,
324
+ "categories": 1,
325
+ "depth": 1,
313
326
  "max_prompts": 100,
314
327
  }
315
328
  ```
@@ -320,16 +333,16 @@ sample_dataset_config = {
320
333
  sample_redteam_model_health_config = {
321
334
  "target_model_configuration": {
322
335
  "model_name": model_name,
323
- "testing_for": "LLM",
324
- "model_type": "text_2_text",
325
- "model_version": "v1",
336
+ "testing_for": "foundationModels",
337
+ "model_version": test_model_version,
326
338
  "model_source": "https://openai.com",
327
339
  "model_provider": model_provider,
328
340
  "model_endpoint_url": model_endpoint_url,
329
341
  "model_api_key": OPENAI_API_KEY,
330
342
  "system_prompt": "",
331
- "conversation_template": "",
332
- "rate_per_min": 20
343
+ "rate_per_min": 20,
344
+ "input_modalities": ["text"],
345
+ "output_modalities": ["text"]
333
346
  },
334
347
  }
335
348
  ```
@@ -364,16 +377,16 @@ sample_redteam_target_config = {
364
377
  },
365
378
  "target_model_configuration": {
366
379
  "model_name": model_name,
367
- "testing_for": "LLM",
368
- "model_type": "text_2_text",
369
- "model_version": "v1",
380
+ "testing_for": "foundationModels",
381
+ "model_version": test_model_version,
370
382
  "model_source": "https://openai.com",
371
383
  "model_provider": model_provider,
372
384
  "model_endpoint_url": model_endpoint_url,
373
385
  "model_api_key": OPENAI_API_KEY,
374
386
  "system_prompt": "",
375
- "conversation_template": "",
376
- "rate_per_min": 20
387
+ "rate_per_min": 20,
388
+ "input_modalities": ["text"],
389
+ "output_modalities": ["text"]
377
390
  },
378
391
  }
379
392
  ```
@@ -539,6 +552,43 @@ print(detect_response)
539
552
  print(detect_response.to_dict())
540
553
  ```
541
554
 
555
+ ### GuardrailsBatchDetectResponse
556
+
557
+ The `GuardrailsBatchDetectResponse` class wraps `batch_detect` response:
558
+
559
+ ```python Python
560
+ # Example usage of batch_detect with multiple texts
561
+ batch_detect_response = guardrails_client.batch_detect(
562
+ texts=[safe_prompt, bomb_prompt],
563
+ config=copy.deepcopy(sample_detectors)
564
+ )
565
+
566
+ # Batch checks
567
+ print(f"Batch Response Is Safe: {batch_detect_response.is_safe()}")
568
+ print(f"Batch Response Is Attack: {batch_detect_response.is_attack()}")
569
+ print(f"Batch Response Has Violations: {batch_detect_response.has_violations()}")
570
+ print(f"Batch Response All Violations: {batch_detect_response.get_violations()}")
571
+
572
+ # Access results for individual texts
573
+ for idx, detection in enumerate(batch_detect_response.batch_detections):
574
+ print(f"\nResults for text #{idx + 1}:")
575
+
576
+ # Access specific detector results
577
+ if detection.details.injection_attack:
578
+ print(f"Injection Attack Safe: {detection.details.injection_attack.safe}")
579
+ print(f"Injection Attack Score: {detection.details.injection_attack.attack}")
580
+
581
+ # Check safety status for this text
582
+ print(f"Is Safe: {detection.is_safe()}")
583
+ print(f"Is Attack: {detection.is_attack()}")
584
+ print(f"Has Violations: {detection.has_violations()}")
585
+ print(f"Violations: {detection.get_violations()}")
586
+
587
+ # Convert entire batch response to dictionary
588
+ print("\nComplete Batch Response Dictionary:")
589
+ print(batch_detect_response.to_dict())
590
+ ```
591
+
542
592
  ## Available Guardrails Detectors
543
593
 
544
594
  - `injection_attack`: Detect prompt injection attempts
@@ -890,7 +940,7 @@ print(add_model_response.to_dict())
890
940
 
891
941
  ```python Python
892
942
  # Check Model Health
893
- check_saved_model_health = redteam_client.check_saved_model_health(model_saved_name=test_model_saved_name)
943
+ check_saved_model_health = redteam_client.check_saved_model_health(model_saved_name=test_model_saved_name, model_version=test_model_version)
894
944
 
895
945
  print(check_saved_model_health)
896
946
 
@@ -901,11 +951,13 @@ assert check_saved_model_health.status == "healthy"
901
951
 
902
952
  ```python Python
903
953
  # Retrieve model details
904
- model_details = model_client.get_model(model_saved_name=test_model_saved_name)
954
+ model_details = model_client.get_model(model_saved_name=test_model_saved_name, model_version=test_model_version)
905
955
 
906
956
  print(model_details)
907
957
 
908
958
  # Get other fields
959
+ print(model_details.model_saved_name)
960
+ print(model_details.model_version)
909
961
  print(model_details.model_name)
910
962
  print(model_details.model_config)
911
963
  print(model_details.model_config.model_provider)
@@ -940,13 +992,23 @@ new_model_config = copy.deepcopy(sample_model_config)
940
992
  new_model_config["model_name"] = "gpt-4o-mini"
941
993
 
942
994
  # Update the model_saved_name if needed
995
+ # ---------------------------------------------------
996
+ # NOTE:
997
+ # To ensure current stuff does not break, please try creating a new model instead of modifying the existing one.
998
+ # Later, you can delete the old model when changes are made to use the new model.
999
+ # ---------------------------------------------------
943
1000
  # new_model_config["model_saved_name"] = "New Model Name"
1001
+ # new_model_config["model_version"] = "v2"
944
1002
 
945
1003
  old_model_saved_name = None
946
1004
  if new_model_config["model_saved_name"] != test_model_saved_name:
947
1005
  old_model_saved_name = test_model_saved_name
948
1006
 
949
- modify_response = model_client.modify_model(old_model_saved_name=old_model_saved_name, config=new_model_config)
1007
+ old_model_version = None
1008
+ if new_model_config["model_version"] != test_model_version:
1009
+ old_model_version = test_model_version
1010
+
1011
+ modify_response = model_client.modify_model(old_model_saved_name=old_model_saved_name, old_model_version=old_model_version, config=new_model_config)
950
1012
 
951
1013
  print(modify_response)
952
1014
 
@@ -960,7 +1022,7 @@ print(modify_response.to_dict())
960
1022
 
961
1023
  ```python Python
962
1024
  # Remove a model
963
- delete_response = model_client.delete_model(model_saved_name=test_model_saved_name)
1025
+ delete_response = model_client.delete_model(model_saved_name=test_model_saved_name, model_version=test_model_version)
964
1026
 
965
1027
  print(delete_response)
966
1028
 
@@ -996,6 +1058,7 @@ print(deployment_details)
996
1058
 
997
1059
  # Get other fields
998
1060
  print(deployment_details.model_saved_name)
1061
+ print(deployment_details.model_version)
999
1062
  print(deployment_details.input_guardrails_policy)
1000
1063
  print(deployment_details.input_guardrails_policy.policy_name)
1001
1064
 
@@ -1219,7 +1282,7 @@ print(add_redteam_target_response.to_dict())
1219
1282
 
1220
1283
  ```python Python
1221
1284
  # Use a dictionary to configure a redteam task
1222
- add_redteam_model_response = redteam_client.add_task_with_saved_model(config=copy.deepcopy(sample_redteam_model_config),model_saved_name=test_model_saved_name)
1285
+ add_redteam_model_response = redteam_client.add_task_with_saved_model(config=copy.deepcopy(sample_redteam_model_config),model_saved_name=test_model_saved_name, model_version=test_model_version)
1223
1286
 
1224
1287
  print(add_redteam_model_response)
1225
1288
 
@@ -1,6 +1,7 @@
1
- ![Python SDK test](https://github.com/enkryptai/enkryptai-sdk/actions/workflows/test.yaml/badge.svg)
2
1
  # Enkrypt AI Python SDK
3
2
 
3
+ ![Python SDK test](https://github.com/enkryptai/enkryptai-sdk/actions/workflows/test.yaml/badge.svg)
4
+
4
5
  A Python SDK with Guardrails, Models, Deployments, AI Proxy, Datasets and Red Team functionality for API interactions.
5
6
 
6
7
  See [https://pypi.org/project/enkryptai-sdk](https://pypi.org/project/enkryptai-sdk)
@@ -32,6 +33,7 @@ Also see the API documentation at [https://docs.enkryptai.com](https://docs.enkr
32
33
  - [Guardrails Quickstart](#guardrails-quickstart)
33
34
  - [Guardrails Response Objects](#guardrails-response-objects)
34
35
  - [GuardrailsDetectResponse](#guardrailsdetectresponse)
36
+ - [GuardrailsBatchDetectResponse](#guardrailsbatchdetectresponse)
35
37
  - [Available Guardrails Detectors](#available-guardrails-detectors)
36
38
  - [Guardrails Configs](#guardrails-configs)
37
39
  - [Injection Attack](#injection-attack)
@@ -158,6 +160,7 @@ redteam_client = RedTeamClient(api_key=ENKRYPT_API_KEY, base_url=ENKRYPT_BASE_UR
158
160
  ```python Python
159
161
  test_policy_name = "Test Policy"
160
162
  test_model_saved_name = "Test Model"
163
+ test_model_version = "v1"
161
164
  test_deployment_name = "test-deployment"
162
165
 
163
166
  pii_original_text = "My email is example@example.com. My phone number is 123-456-7890."
@@ -234,14 +237,15 @@ sample_detectors = {
234
237
  ```python Python
235
238
  sample_model_config = {
236
239
  "model_saved_name": test_model_saved_name,
237
- "testing_for": "LLM",
240
+ "model_version": test_model_version,
241
+ "testing_for": "foundationModels",
238
242
  "model_name": model_name,
239
- "modality": "text",
240
243
  "model_config": {
241
- "model_version": "",
242
244
  "model_provider": model_provider,
243
245
  "endpoint_url": model_endpoint_url,
244
246
  "apikey": OPENAI_API_KEY,
247
+ "input_modalities": ["text"],
248
+ "output_modalities": ["text"],
245
249
  },
246
250
  }
247
251
  ```
@@ -252,6 +256,7 @@ sample_model_config = {
252
256
  sample_deployment_config = {
253
257
  "name": test_deployment_name,
254
258
  "model_saved_name": test_model_saved_name,
259
+ "model_version": test_model_version,
255
260
  "input_guardrails_policy": {
256
261
  "policy_name": test_policy_name,
257
262
  "enabled": True,
@@ -285,8 +290,16 @@ sample_dataset_config = {
285
290
  "dataset_name": dataset_name,
286
291
  "system_description": "- **Voter Eligibility**: To vote in U.S. elections, individuals must be U.S. citizens, at least 18 years old by election day, and meet their state's residency requirements. - **Voter Registration**: Most states require voters to register ahead of time, with deadlines varying widely. North Dakota is an exception, as it does not require voter registration. - **Identification Requirements**: Thirty-six states enforce voter ID laws, requiring individuals to present identification at polling places. These laws aim to prevent voter fraud but can also lead to disenfranchisement. - **Voting Methods**: Voters can typically choose between in-person voting on election day, early voting, and absentee or mail-in ballots, depending on state regulations. - **Polling Hours**: Polling hours vary by state, with some states allowing extended hours for voters. Its essential for voters to check local polling times to ensure they can cast their ballots. - **Provisional Ballots**: If there are questions about a voter's eligibility, they may be allowed to cast a provisional ballot. This ballot is counted once eligibility is confirmed. - **Election Day Laws**: Many states have laws that protect the rights of voters on election day, including prohibiting intimidation and ensuring access to polling places. - **Campaign Finance Regulations**: Federal and state laws regulate contributions to candidates and political parties to ensure transparency and limit the influence of money in politics. - **Political Advertising**: Campaigns must adhere to rules regarding political advertising, including disclosure requirements about funding sources and content accuracy. - **Voter Intimidation Prohibitions**: Federal laws prohibit any form of voter intimidation or coercion at polling places, ensuring a safe environment for all voters. - **Accessibility Requirements**: The Americans with Disabilities Act mandates that polling places be accessible to individuals with disabilities, ensuring equal access to the electoral process. - **Election Monitoring**: Various organizations are allowed to monitor elections to ensure compliance with laws and regulations. They help maintain transparency and accountability in the electoral process. - **Vote Counting Procedures**: States have specific procedures for counting votes, including the use of electronic voting machines and manual audits to verify results. - **Ballot Design Standards**: States must adhere to certain design standards for ballots to ensure clarity and prevent confusion among voters when casting their votes. - **Post-Election Audits**: Some states conduct post-election audits as a measure of accuracy. These audits help verify that the vote count reflects the actual ballots cast.",
287
292
  "policy_description": "",
288
- "tools": [],
293
+ "tools": [
294
+ {
295
+ "name": "web_search",
296
+ "description": "The tool web search is used to search the web for information related to finance."
297
+ }
298
+ ],
289
299
  "info_pdf_url": "",
300
+ "scenarios": 1,
301
+ "categories": 1,
302
+ "depth": 1,
290
303
  "max_prompts": 100,
291
304
  }
292
305
  ```
@@ -297,16 +310,16 @@ sample_dataset_config = {
297
310
  sample_redteam_model_health_config = {
298
311
  "target_model_configuration": {
299
312
  "model_name": model_name,
300
- "testing_for": "LLM",
301
- "model_type": "text_2_text",
302
- "model_version": "v1",
313
+ "testing_for": "foundationModels",
314
+ "model_version": test_model_version,
303
315
  "model_source": "https://openai.com",
304
316
  "model_provider": model_provider,
305
317
  "model_endpoint_url": model_endpoint_url,
306
318
  "model_api_key": OPENAI_API_KEY,
307
319
  "system_prompt": "",
308
- "conversation_template": "",
309
- "rate_per_min": 20
320
+ "rate_per_min": 20,
321
+ "input_modalities": ["text"],
322
+ "output_modalities": ["text"]
310
323
  },
311
324
  }
312
325
  ```
@@ -341,16 +354,16 @@ sample_redteam_target_config = {
341
354
  },
342
355
  "target_model_configuration": {
343
356
  "model_name": model_name,
344
- "testing_for": "LLM",
345
- "model_type": "text_2_text",
346
- "model_version": "v1",
357
+ "testing_for": "foundationModels",
358
+ "model_version": test_model_version,
347
359
  "model_source": "https://openai.com",
348
360
  "model_provider": model_provider,
349
361
  "model_endpoint_url": model_endpoint_url,
350
362
  "model_api_key": OPENAI_API_KEY,
351
363
  "system_prompt": "",
352
- "conversation_template": "",
353
- "rate_per_min": 20
364
+ "rate_per_min": 20,
365
+ "input_modalities": ["text"],
366
+ "output_modalities": ["text"]
354
367
  },
355
368
  }
356
369
  ```
@@ -516,6 +529,43 @@ print(detect_response)
516
529
  print(detect_response.to_dict())
517
530
  ```
518
531
 
532
+ ### GuardrailsBatchDetectResponse
533
+
534
+ The `GuardrailsBatchDetectResponse` class wraps `batch_detect` response:
535
+
536
+ ```python Python
537
+ # Example usage of batch_detect with multiple texts
538
+ batch_detect_response = guardrails_client.batch_detect(
539
+ texts=[safe_prompt, bomb_prompt],
540
+ config=copy.deepcopy(sample_detectors)
541
+ )
542
+
543
+ # Batch checks
544
+ print(f"Batch Response Is Safe: {batch_detect_response.is_safe()}")
545
+ print(f"Batch Response Is Attack: {batch_detect_response.is_attack()}")
546
+ print(f"Batch Response Has Violations: {batch_detect_response.has_violations()}")
547
+ print(f"Batch Response All Violations: {batch_detect_response.get_violations()}")
548
+
549
+ # Access results for individual texts
550
+ for idx, detection in enumerate(batch_detect_response.batch_detections):
551
+ print(f"\nResults for text #{idx + 1}:")
552
+
553
+ # Access specific detector results
554
+ if detection.details.injection_attack:
555
+ print(f"Injection Attack Safe: {detection.details.injection_attack.safe}")
556
+ print(f"Injection Attack Score: {detection.details.injection_attack.attack}")
557
+
558
+ # Check safety status for this text
559
+ print(f"Is Safe: {detection.is_safe()}")
560
+ print(f"Is Attack: {detection.is_attack()}")
561
+ print(f"Has Violations: {detection.has_violations()}")
562
+ print(f"Violations: {detection.get_violations()}")
563
+
564
+ # Convert entire batch response to dictionary
565
+ print("\nComplete Batch Response Dictionary:")
566
+ print(batch_detect_response.to_dict())
567
+ ```
568
+
519
569
  ## Available Guardrails Detectors
520
570
 
521
571
  - `injection_attack`: Detect prompt injection attempts
@@ -867,7 +917,7 @@ print(add_model_response.to_dict())
867
917
 
868
918
  ```python Python
869
919
  # Check Model Health
870
- check_saved_model_health = redteam_client.check_saved_model_health(model_saved_name=test_model_saved_name)
920
+ check_saved_model_health = redteam_client.check_saved_model_health(model_saved_name=test_model_saved_name, model_version=test_model_version)
871
921
 
872
922
  print(check_saved_model_health)
873
923
 
@@ -878,11 +928,13 @@ assert check_saved_model_health.status == "healthy"
878
928
 
879
929
  ```python Python
880
930
  # Retrieve model details
881
- model_details = model_client.get_model(model_saved_name=test_model_saved_name)
931
+ model_details = model_client.get_model(model_saved_name=test_model_saved_name, model_version=test_model_version)
882
932
 
883
933
  print(model_details)
884
934
 
885
935
  # Get other fields
936
+ print(model_details.model_saved_name)
937
+ print(model_details.model_version)
886
938
  print(model_details.model_name)
887
939
  print(model_details.model_config)
888
940
  print(model_details.model_config.model_provider)
@@ -917,13 +969,23 @@ new_model_config = copy.deepcopy(sample_model_config)
917
969
  new_model_config["model_name"] = "gpt-4o-mini"
918
970
 
919
971
  # Update the model_saved_name if needed
972
+ # ---------------------------------------------------
973
+ # NOTE:
974
+ # To ensure current stuff does not break, please try creating a new model instead of modifying the existing one.
975
+ # Later, you can delete the old model when changes are made to use the new model.
976
+ # ---------------------------------------------------
920
977
  # new_model_config["model_saved_name"] = "New Model Name"
978
+ # new_model_config["model_version"] = "v2"
921
979
 
922
980
  old_model_saved_name = None
923
981
  if new_model_config["model_saved_name"] != test_model_saved_name:
924
982
  old_model_saved_name = test_model_saved_name
925
983
 
926
- modify_response = model_client.modify_model(old_model_saved_name=old_model_saved_name, config=new_model_config)
984
+ old_model_version = None
985
+ if new_model_config["model_version"] != test_model_version:
986
+ old_model_version = test_model_version
987
+
988
+ modify_response = model_client.modify_model(old_model_saved_name=old_model_saved_name, old_model_version=old_model_version, config=new_model_config)
927
989
 
928
990
  print(modify_response)
929
991
 
@@ -937,7 +999,7 @@ print(modify_response.to_dict())
937
999
 
938
1000
  ```python Python
939
1001
  # Remove a model
940
- delete_response = model_client.delete_model(model_saved_name=test_model_saved_name)
1002
+ delete_response = model_client.delete_model(model_saved_name=test_model_saved_name, model_version=test_model_version)
941
1003
 
942
1004
  print(delete_response)
943
1005
 
@@ -973,6 +1035,7 @@ print(deployment_details)
973
1035
 
974
1036
  # Get other fields
975
1037
  print(deployment_details.model_saved_name)
1038
+ print(deployment_details.model_version)
976
1039
  print(deployment_details.input_guardrails_policy)
977
1040
  print(deployment_details.input_guardrails_policy.policy_name)
978
1041
 
@@ -1196,7 +1259,7 @@ print(add_redteam_target_response.to_dict())
1196
1259
 
1197
1260
  ```python Python
1198
1261
  # Use a dictionary to configure a redteam task
1199
- add_redteam_model_response = redteam_client.add_task_with_saved_model(config=copy.deepcopy(sample_redteam_model_config),model_saved_name=test_model_saved_name)
1262
+ add_redteam_model_response = redteam_client.add_task_with_saved_model(config=copy.deepcopy(sample_redteam_model_config),model_saved_name=test_model_saved_name, model_version=test_model_version)
1200
1263
 
1201
1264
  print(add_redteam_model_response)
1202
1265
 
@@ -8,7 +8,7 @@ with open(os.path.join(here, "README.md"), encoding="utf-8") as fh:
8
8
 
9
9
  setup(
10
10
  name="enkryptai-sdk", # This is the name of your package on PyPI
11
- version="1.0.3", # Update this for new versions
11
+ version="1.0.5", # Update this for new versions
12
12
  description="A Python SDK with guardrails and red teaming functionality for API interactions",
13
13
  long_description=long_description,
14
14
  long_description_content_type="text/markdown",
@@ -36,9 +36,23 @@ class DatasetClient(BaseClient):
36
36
 
37
37
  payload = config.to_dict()
38
38
 
39
+ # If payload["tools"] is None or is an empty list [] or [{}], remove it from the payload
40
+ if (payload.get("tools") is None or
41
+ payload["tools"] == [] or
42
+ payload["tools"] == [{}] or
43
+ payload["tools"] == [{"name": "", "description": ""}]):
44
+ del payload["tools"]
45
+
46
+ # Print payload
47
+ # print(f"\nAdd Dataset Payload: {payload}")
48
+
39
49
  response = self._request(
40
50
  "POST", "/datasets/add-task", headers=headers, json=payload
41
51
  )
52
+
53
+ # Print response
54
+ # print(f"\nAdd Dataset Response: {response}")
55
+
42
56
  if response.get("error"):
43
57
  raise DatasetClientError(response["error"])
44
58
  return DatasetAddTaskResponse.from_dict(response)
@@ -62,10 +62,13 @@ __all__ = [
62
62
  "GuardrailsModelsResponse",
63
63
  "GuardrailDetectors",
64
64
  "GuardrailsDetectRequest",
65
+ "GuardrailsBatchDetectRequest",
65
66
  "GuardrailsPolicyDetectRequest",
66
67
  "DetectResponseSummary",
67
68
  "DetectResponseDetails",
68
69
  "GuardrailsDetectResponse",
70
+ "BatchDetectResponseItem",
71
+ "GuardrailsBatchDetectResponse",
69
72
  "GuardrailsPIIRequest",
70
73
  "GuardrailsPIIResponse",
71
74
  "GuardrailsHallucinationRequest",
@@ -3,17 +3,35 @@ from dataclasses import dataclass, field
3
3
  from typing import Dict, List, Optional, Any
4
4
 
5
5
 
6
+ @dataclass
7
+ class Tool(BaseDTO):
8
+ name: str
9
+ description: str
10
+
11
+ @classmethod
12
+ def from_dict(cls, data: Dict[str, Any]) -> "Tool":
13
+ return cls(
14
+ name=data.get("name", ""),
15
+ description=data.get("description", "")
16
+ )
17
+
18
+ def to_dict(self) -> Dict[str, Any]:
19
+ return {
20
+ "name": self.name,
21
+ "description": self.description
22
+ }
23
+
6
24
  @dataclass
7
25
  class DatasetConfig(BaseDTO):
8
26
  dataset_name: str
9
27
  system_description: str
10
28
  policy_description: str = ""
11
- tools: List[str] = field(default_factory=list)
29
+ tools: List[Tool] = field(default_factory=list)
12
30
  info_pdf_url: str = ""
13
31
  max_prompts: int = 100
14
- # scenarios: int = 2
15
- # categories: int = 2
16
- # depth: int = 2
32
+ scenarios: int = 2
33
+ categories: int = 2
34
+ depth: int = 2
17
35
 
18
36
 
19
37
  @dataclass
@@ -141,6 +141,7 @@ class OutputGuardrailsPolicy(BaseDTO):
141
141
  class DeploymentInput(BaseDTO):
142
142
  name: str
143
143
  model_saved_name: str
144
+ model_version: str
144
145
  input_guardrails_policy: InputGuardrailsPolicy
145
146
  output_guardrails_policy: OutputGuardrailsPolicy
146
147
  _extra_fields: Dict[str, Any] = field(default_factory=dict)
@@ -153,6 +154,7 @@ class DeploymentInput(BaseDTO):
153
154
  return cls(
154
155
  name=data.get("name", ""),
155
156
  model_saved_name=data.get("model_saved_name", ""),
157
+ model_version=data.get("model_version", ""),
156
158
  input_guardrails_policy=InputGuardrailsPolicy.from_dict(input_policy_data),
157
159
  output_guardrails_policy=OutputGuardrailsPolicy.from_dict(output_policy_data)
158
160
  )
@@ -161,6 +163,7 @@ class DeploymentInput(BaseDTO):
161
163
  result = {
162
164
  "name": self.name,
163
165
  "model_saved_name": self.model_saved_name,
166
+ "model_version": self.model_version,
164
167
  "input_guardrails_policy": self.input_guardrails_policy.to_dict(),
165
168
  "output_guardrails_policy": self.output_guardrails_policy.to_dict()
166
169
  }
@@ -172,6 +175,7 @@ class DeploymentInput(BaseDTO):
172
175
  class GetDeploymentResponse(BaseDTO):
173
176
  name: str
174
177
  model_saved_name: str
178
+ model_version: str
175
179
  input_guardrails_policy: InputGuardrailsPolicy
176
180
  output_guardrails_policy: OutputGuardrailsPolicy
177
181
  created_at: str
@@ -186,6 +190,7 @@ class GetDeploymentResponse(BaseDTO):
186
190
  return cls(
187
191
  name=data.get("name", ""),
188
192
  model_saved_name=data.get("model_saved_name", ""),
193
+ model_version=data.get("model_version", ""),
189
194
  input_guardrails_policy=InputGuardrailsPolicy.from_dict(input_policy_data),
190
195
  output_guardrails_policy=OutputGuardrailsPolicy.from_dict(output_policy_data),
191
196
  updated_at=data.get("updated_at", ""),
@@ -197,6 +202,7 @@ class GetDeploymentResponse(BaseDTO):
197
202
  return {
198
203
  "name": self.name,
199
204
  "model_saved_name": self.model_saved_name,
205
+ "model_version": self.model_version,
200
206
  "input_guardrails_policy": self.input_guardrails_policy.to_dict(),
201
207
  "output_guardrails_policy": self.output_guardrails_policy.to_dict(),
202
208
  "updated_at": self.updated_at,
@@ -293,6 +299,7 @@ class DeploymentSummary(BaseDTO):
293
299
  created_at: str
294
300
  updated_at: str
295
301
  model_saved_name: str
302
+ model_version: str
296
303
  project_name: str
297
304
 
298
305
  @classmethod
@@ -303,6 +310,7 @@ class DeploymentSummary(BaseDTO):
303
310
  created_at=data.get("created_at", ""),
304
311
  updated_at=data.get("updated_at", ""),
305
312
  model_saved_name=data.get("model_saved_name", ""),
313
+ model_version=data.get("model_version", ""),
306
314
  project_name=data.get("project_name", "")
307
315
  )
308
316
 
@@ -313,6 +321,7 @@ class DeploymentSummary(BaseDTO):
313
321
  "created_at": self.created_at,
314
322
  "updated_at": self.updated_at,
315
323
  "model_saved_name": self.model_saved_name,
324
+ "model_version": self.model_version,
316
325
  "project_name": self.project_name
317
326
  }
318
327