hiddenlayer-sdk 3.7.0__tar.gz → 3.8.0__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.
- hiddenlayer_sdk-3.8.0/.release-please-manifest.json +3 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/CHANGELOG.md +38 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/PKG-INFO +1 -1
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/api.md +7 -2
- hiddenlayer_sdk-3.8.0/examples/red_team/README.md +68 -0
- hiddenlayer_sdk-3.8.0/examples/red_team/red_team_http_api.ipynb +245 -0
- hiddenlayer_sdk-3.8.0/examples/red_team/red_team_openai.ipynb +241 -0
- hiddenlayer_sdk-3.8.0/examples/red_team/red_team_playwright.ipynb +270 -0
- hiddenlayer_sdk-3.8.0/examples/red_team/red_team_static_prompts.ipynb +249 -0
- hiddenlayer_sdk-3.8.0/examples/red_team/red_team_template.ipynb +215 -0
- hiddenlayer_sdk-3.8.0/examples/red_team/red_team_webhook.ipynb +331 -0
- hiddenlayer_sdk-3.8.0/examples/red_team/red_team_websocket.ipynb +323 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/pyproject.toml +2 -1
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_files.py +1 -1
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_models.py +80 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_version.py +1 -1
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/_beta_endpoints.py +1 -1
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/red_team_session.py +63 -121
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/evaluations/red_team.py +87 -22
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/runtime.py +174 -1
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/__init__.py +4 -0
- hiddenlayer_sdk-3.8.0/src/hiddenlayer/types/evaluations/red_team_create_params.py +99 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/prompt_analyzer_create_response.py +7 -4
- hiddenlayer_sdk-3.8.0/src/hiddenlayer/types/runtime_evaluate_interaction_params.py +195 -0
- hiddenlayer_sdk-3.8.0/src/hiddenlayer/types/runtime_evaluate_interaction_response.py +481 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/job_list_response.py +9 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/job_request_params.py +3 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/scan_job.py +3 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/scan_report.py +34 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/evaluations/test_red_team.py +16 -16
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/test_jobs.py +2 -0
- hiddenlayer_sdk-3.8.0/tests/api_resources/test_runtime.py +615 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_models.py +57 -3
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_red_team_session.py +143 -28
- hiddenlayer_sdk-3.8.0/uv.lock +1603 -0
- hiddenlayer_sdk-3.7.0/.release-please-manifest.json +0 -3
- hiddenlayer_sdk-3.7.0/src/hiddenlayer/types/evaluations/red_team_create_params.py +0 -59
- hiddenlayer_sdk-3.7.0/tests/api_resources/test_runtime.py +0 -299
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/.gitignore +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/CODE_OF_CONDUCT.md +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/CONTRIBUTING.md +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/LICENSE +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/README.md +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/SECURITY.md +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/bin/check-release-environment +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/bin/publish-jfrog +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/bin/publish-pypi +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/examples/.keep +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/examples/demo.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/noxfile.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/release-please-config.json +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/requirements-dev.lock +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/requirements.lock +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_base_client.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_client.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_compat.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_constants.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_exceptions.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_oauth2.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_qs.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_resource.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_streaming.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_types.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_compat.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_datetime_parse.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_json.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_logs.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_path.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_proxy.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_reflection.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_resources_proxy.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_streams.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_sync.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_transform.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_typing.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/_utils/_utils.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/.keep +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/_beta.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/community_scan.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/evaluation_sessions.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/model_scan.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/red_team_exceptions.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/lib/scan_utils.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/pagination.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/py.typed +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/evaluations/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/evaluations/evaluations.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/interactions.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/models/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/models/cards.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/models/models.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/prompt_analyzer.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/jobs.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/results.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/scans.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/upload/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/upload/file.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/scans/upload/upload.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/resources/sensors.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_create_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_retrieve_evaluation_results_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_retrieve_next_action_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_retrieve_status_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_submit_target_response_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/evaluations/red_team_submit_target_response_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/interaction_analyze_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/interaction_analyze_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/model_retrieve_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/models/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/models/card_list_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/models/card_list_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/prompt_analyzer_create_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/runtime_evaluate_request_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/runtime_evaluate_request_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/runtime_evaluate_response_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/runtime_evaluate_response_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/job_list_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/job_retrieve_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/result_sarif_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload/file_add_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload/file_complete_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload_complete_all_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload_start_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/scans/upload_start_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_create_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_create_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_query_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_query_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_retrieve_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_update_params.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/src/hiddenlayer/types/sensor_update_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/evaluations/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/models/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/models/test_cards.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/test_results.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/test_upload.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/upload/__init__.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/scans/upload/test_file.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/test_interactions.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/test_models.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/test_prompt_analyzer.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/api_resources/test_sensors.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/conftest.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/sample_file.txt +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_beta.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_client.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_community_scan.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_extract_files.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_files.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_model_scan.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_qs.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_required_args.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_response.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_streaming.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_transform.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_datetime_parse.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_json.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_path.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_proxy.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/test_utils/test_typing.py +0 -0
- {hiddenlayer_sdk-3.7.0 → hiddenlayer_sdk-3.8.0}/tests/utils.py +0 -0
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.8.0 (2026-06-24)
|
|
4
|
+
|
|
5
|
+
Full Changelog: [v3.7.1...v3.8.0](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/compare/v3.7.1...v3.8.0)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* **api:** api update ([4fd0d62](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/4fd0d62737e1273a0558bf66017fa054e39d1f87))
|
|
10
|
+
* **api:** api update ([c53a283](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/c53a2836f987b7dac46aa1c5677a945f45d21c2a))
|
|
11
|
+
* **api:** api update ([67dccee](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/67dcceea5e111f16a30688efb33bc0e0f06ca12c))
|
|
12
|
+
* **api:** api update ([8f00ab1](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/8f00ab1201dcda0488ca47abcf4cd4a2d4718da7))
|
|
13
|
+
* **api:** api update ([e612915](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/e6129151ba357559bb291bfe0dc6a3d3e81f3dff))
|
|
14
|
+
* **red-team:** forward all start_session params and drop hardcoded defaults ([#206](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/206)) ([45ee409](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/45ee40985d82db175e48140c2a82b9713ea8a83c))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* **client:** add missing f-string prefix in file type error message ([3405322](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/3405322c1f1b379b50d464842607bdfa8c3c080f))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Chores
|
|
23
|
+
|
|
24
|
+
* **internal:** codegen related update ([bb8153f](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/bb8153fc39bdb5dfc962908caad4e3eaeb9fd249))
|
|
25
|
+
* regenerate beta endpoint registry [skip ci] ([89009da](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/89009dab82686744fb693a7e47de13c01ac9909e))
|
|
26
|
+
* regenerate beta endpoint registry [skip ci] ([c08dc03](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/c08dc0341664260b09dc40e021e5c4fba0a00cf7))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Documentation
|
|
30
|
+
|
|
31
|
+
* **examples:** add red team evaluation notebooks ([#205](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/205)) ([5a1229b](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/5a1229b5cf3930e3a0b1665d97fdb4ea134b83da))
|
|
32
|
+
|
|
33
|
+
## 3.7.1 (2026-05-14)
|
|
34
|
+
|
|
35
|
+
Full Changelog: [v3.7.0...v3.7.1](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/compare/v3.7.0...v3.7.1)
|
|
36
|
+
|
|
37
|
+
### Bug Fixes
|
|
38
|
+
|
|
39
|
+
* **red_team_session:** fix red team sessions failing with "invalid UUID length: 0" when prompt_set_id is not provided ([#198](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/issues/198)) ([5e3c85e](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/commit/5e3c85e57482ffeda2011b8f7c65a67efe0a084d))
|
|
40
|
+
|
|
3
41
|
## 3.7.0 (2026-05-07)
|
|
4
42
|
|
|
5
43
|
Full Changelog: [v3.6.0...v3.7.0](https://github.com/hiddenlayerai/hiddenlayer-sdk-python/compare/v3.6.0...v3.7.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: hiddenlayer-sdk
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.8.0
|
|
4
4
|
Summary: The official Python library for the hiddenlayer API
|
|
5
5
|
Project-URL: Homepage, https://github.com/hiddenlayerai/hiddenlayer-sdk-python
|
|
6
6
|
Project-URL: Repository, https://github.com/hiddenlayerai/hiddenlayer-sdk-python
|
|
@@ -79,11 +79,16 @@ Methods:
|
|
|
79
79
|
Types:
|
|
80
80
|
|
|
81
81
|
```python
|
|
82
|
-
from hiddenlayer.types import
|
|
82
|
+
from hiddenlayer.types import (
|
|
83
|
+
RuntimeEvaluateInteractionResponse,
|
|
84
|
+
RuntimeEvaluateRequestResponse,
|
|
85
|
+
RuntimeEvaluateResponseResponse,
|
|
86
|
+
)
|
|
83
87
|
```
|
|
84
88
|
|
|
85
89
|
Methods:
|
|
86
90
|
|
|
91
|
+
- <code title="post /detection/v2/interaction-evaluations">client.runtime.<a href="./src/hiddenlayer/resources/runtime.py">evaluate_interaction</a>(\*\*<a href="src/hiddenlayer/types/runtime_evaluate_interaction_params.py">params</a>) -> <a href="./src/hiddenlayer/types/runtime_evaluate_interaction_response.py">RuntimeEvaluateInteractionResponse</a></code>
|
|
87
92
|
- <code title="post /detection/v2/request-evaluations">client.runtime.<a href="./src/hiddenlayer/resources/runtime.py">evaluate_request</a>(\*\*<a href="src/hiddenlayer/types/runtime_evaluate_request_params.py">params</a>) -> <a href="./src/hiddenlayer/types/runtime_evaluate_request_response.py">RuntimeEvaluateRequestResponse</a></code>
|
|
88
93
|
- <code title="post /detection/v2/response-evaluations">client.runtime.<a href="./src/hiddenlayer/resources/runtime.py">evaluate_response</a>(\*\*<a href="src/hiddenlayer/types/runtime_evaluate_response_params.py">params</a>) -> <a href="./src/hiddenlayer/types/runtime_evaluate_response_response.py">RuntimeEvaluateResponseResponse</a></code>
|
|
89
94
|
|
|
@@ -236,7 +241,7 @@ Accessed via `client.evaluation_sessions.red_team`.
|
|
|
236
241
|
|
|
237
242
|
Methods:
|
|
238
243
|
|
|
239
|
-
- **start_session(name, target_model, target_system_prompt="", max_turns=3, execution_strategy_type="random", attacker_max_generation_attempts=2, n_random_techniques=1, max_parallel_techniques=1, prompt_set_id=
|
|
244
|
+
- **start_session(name, target_model, target_system_prompt="", objective_ids=omit, refusal_judge_model=omit, objective_judge_model=omit, attacker_model=omit, evaluation_report_model=omit, attacker_guidance=omit, severity_mapping=omit, config_id=omit, max_turns=3, execution_strategy_type="random", attacker_max_generation_attempts=2, n_random_techniques=1, max_parallel_techniques=1, prompt_set_id=omit, hiddenlayer_project_id=None, poll_interval=2.0, poll_max_wait=None, sessions_per_technique=1) -> RedTeamSession**
|
|
240
245
|
Start a new red team session. Returns a `RedTeamSession` (sync) or `AsyncRedTeamSession` (async).
|
|
241
246
|
Uses adaptive multi-objective evaluation: each session runs to `max_turns` (no short-circuit),
|
|
242
247
|
tests all objectives, and maintains cross-session state for adaptive attacks.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Red Team Integrations
|
|
2
|
+
|
|
3
|
+
Example notebooks for driving HiddenLayer red team evaluations against different
|
|
4
|
+
kinds of targets using the [HiddenLayer Python SDK](https://github.com/hiddenlayerai/hiddenlayer-sdk-python).
|
|
5
|
+
|
|
6
|
+
Every notebook follows the same pattern:
|
|
7
|
+
|
|
8
|
+
1. Configure the target and the evaluation parameters.
|
|
9
|
+
2. Implement an async `handler(prompt, history, session_id, target_system_prompt)`
|
|
10
|
+
that calls your target and returns its reply as a string.
|
|
11
|
+
3. Start a session with `client.evaluation_sessions.red_team.start_session(...)`
|
|
12
|
+
and drive it with `session.run_with_callback_parallel(handler=handler)`.
|
|
13
|
+
4. Retrieve the report with `client.evaluations.red_team.retrieve_evaluation_results(...)`.
|
|
14
|
+
|
|
15
|
+
The `handler` is the only integration point — swap it to point at any target.
|
|
16
|
+
|
|
17
|
+
`red_team_openai.ipynb` additionally shows how to **resume** an existing
|
|
18
|
+
workflow (`resume_session` + `retrieve_status`), and `red_team_http_api.ipynb`
|
|
19
|
+
shows scoping a run to a project via `hiddenlayer_project_id`.
|
|
20
|
+
|
|
21
|
+
## Notebooks
|
|
22
|
+
|
|
23
|
+
| Notebook | Target |
|
|
24
|
+
|----------|--------|
|
|
25
|
+
| [`red_team_openai.ipynb`](./red_team_openai.ipynb) | An OpenAI Chat Completions model |
|
|
26
|
+
| [`red_team_http_api.ipynb`](./red_team_http_api.ipynb) | A custom LLM app/agent behind an HTTP/REST endpoint |
|
|
27
|
+
| [`red_team_playwright.ipynb`](./red_team_playwright.ipynb) | A web chat UI driven via Playwright browser automation |
|
|
28
|
+
| [`red_team_static_prompts.ipynb`](./red_team_static_prompts.ipynb) | A target tested with a pre-written static prompt set |
|
|
29
|
+
| [`red_team_webhook.ipynb`](./red_team_webhook.ipynb) | A target that replies asynchronously via webhook callback (includes a self-contained mock target) |
|
|
30
|
+
| [`red_team_websocket.ipynb`](./red_team_websocket.ipynb) | A target reached over a persistent WebSocket connection (includes a self-contained mock target) |
|
|
31
|
+
| [`red_team_template.ipynb`](./red_team_template.ipynb) | Generic skeleton — drop in any target |
|
|
32
|
+
|
|
33
|
+
## Setup
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install hiddenlayer-sdk jupyter
|
|
37
|
+
|
|
38
|
+
# Per-notebook extras:
|
|
39
|
+
pip install openai # red_team_openai.ipynb
|
|
40
|
+
pip install aiohttp # red_team_webhook.ipynb, red_team_websocket.ipynb
|
|
41
|
+
pip install playwright # red_team_playwright.ipynb
|
|
42
|
+
playwright install chromium
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`red_team_webhook.ipynb` targets a service that replies **asynchronously** via a
|
|
46
|
+
webhook callback. It runs a small in-notebook receiver and ships with a
|
|
47
|
+
self-contained mock target so it works out of the box; for a real external
|
|
48
|
+
target, expose the receiver with a tunnel (e.g. ngrok / cloudflared) and set
|
|
49
|
+
`PUBLIC_CALLBACK_URL` accordingly.
|
|
50
|
+
|
|
51
|
+
Provide credentials via environment variables (read automatically by the SDK):
|
|
52
|
+
|
|
53
|
+
- `HIDDENLAYER_CLIENT_ID` and `HIDDENLAYER_CLIENT_SECRET` (OAuth2), **or**
|
|
54
|
+
- `HIDDENLAYER_TOKEN` (Bearer token)
|
|
55
|
+
- `OPENAI_API_KEY` for `red_team_openai.ipynb`
|
|
56
|
+
|
|
57
|
+
By default the client targets US production (`prod-us`). For EU production pass
|
|
58
|
+
`environment="prod-eu"`, and for a self-hosted deployment pass
|
|
59
|
+
`base_url="http://your-host:port"` to `AsyncHiddenLayer()`.
|
|
60
|
+
|
|
61
|
+
## Run
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
jupyter lab examples/red_team/red_team_openai.ipynb
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Run the cells top to bottom. Results are viewable in the
|
|
68
|
+
[HiddenLayer Console](https://console.hiddenlayer.ai/).
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# HiddenLayer Red Team Evaluation - HTTP/REST API Target\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"Evaluate a custom target (LLM app or agent) that is exposed behind an HTTP endpoint. Adapt `to_target_request` / `from_target_response` to match your target's request and response schema.\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"**Prerequisites:**\n",
|
|
12
|
+
"- `pip install hiddenlayer-sdk`\n",
|
|
13
|
+
"- Credentials read from the environment:\n",
|
|
14
|
+
" - `HIDDENLAYER_CLIENT_ID` and `HIDDENLAYER_CLIENT_SECRET` (OAuth2), or `HIDDENLAYER_TOKEN` (Bearer token)\n",
|
|
15
|
+
"\n",
|
|
16
|
+
"**SDK Reference:** [hiddenlayer-sdk-python](https://github.com/hiddenlayerai/hiddenlayer-sdk-python)"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"cell_type": "markdown",
|
|
21
|
+
"metadata": {},
|
|
22
|
+
"source": [
|
|
23
|
+
"## Setup"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"cell_type": "code",
|
|
28
|
+
"metadata": {},
|
|
29
|
+
"source": [
|
|
30
|
+
"import httpx\n",
|
|
31
|
+
"\n",
|
|
32
|
+
"from hiddenlayer import AsyncHiddenLayer\n",
|
|
33
|
+
"\n",
|
|
34
|
+
"# AsyncHiddenLayer() reads credentials from the environment.\n",
|
|
35
|
+
"# For EU prod pass environment=\"prod-eu\"; for self-hosted pass base_url=\"http://your-host:port\".\n",
|
|
36
|
+
"client = AsyncHiddenLayer()"
|
|
37
|
+
],
|
|
38
|
+
"execution_count": null,
|
|
39
|
+
"outputs": []
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"cell_type": "markdown",
|
|
43
|
+
"metadata": {},
|
|
44
|
+
"source": [
|
|
45
|
+
"## Configurables\n",
|
|
46
|
+
"\n",
|
|
47
|
+
"1. Configure target\n",
|
|
48
|
+
"2. Configure evaluation"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"cell_type": "code",
|
|
53
|
+
"metadata": {},
|
|
54
|
+
"source": [
|
|
55
|
+
"# Target configuration\n",
|
|
56
|
+
"TARGET_URL = \"https://api.example.com/v1/chat\"\n",
|
|
57
|
+
"TARGET_MODEL_NAME = \"gpt-4o-mini\"\n",
|
|
58
|
+
"TARGET_SYSTEM_PROMPT = \"You are a helpful AI assistant.\"\n",
|
|
59
|
+
"CUSTOM_HEADERS = {\n",
|
|
60
|
+
" # \"Authorization\": \"Bearer your-api-key\",\n",
|
|
61
|
+
"}\n",
|
|
62
|
+
"\n",
|
|
63
|
+
"# Evaluation configuration\n",
|
|
64
|
+
"EVAL_NAME = \"API Red Team Eval\" # Name of the evaluation\n",
|
|
65
|
+
"EXECUTION_STRATEGY = \"single\" # Options: \"single\", \"random\", \"static_prompt_set\"\n",
|
|
66
|
+
"MAX_TURNS = 5 # Options: 1-5\n",
|
|
67
|
+
"SESSIONS_PER_TECHNIQUE = 2 # Options: 1-5\n",
|
|
68
|
+
"PARALLEL_TECHNIQUES = 10 # Options: 1-10\n",
|
|
69
|
+
"HIDDENLAYER_PROJECT_ID = None # Options: None, \"<project_id_or_alias>\""
|
|
70
|
+
],
|
|
71
|
+
"execution_count": null,
|
|
72
|
+
"outputs": []
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"cell_type": "markdown",
|
|
76
|
+
"metadata": {},
|
|
77
|
+
"source": [
|
|
78
|
+
"## Verify payload adapters\n",
|
|
79
|
+
"\n",
|
|
80
|
+
"- `to_target_request` needs to align with the target's request payload schema\n",
|
|
81
|
+
"- `from_target_response` needs to extract the reply text from the target's response payload schema"
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"cell_type": "code",
|
|
86
|
+
"metadata": {},
|
|
87
|
+
"source": [
|
|
88
|
+
"def to_target_request(prompt, history, session_id):\n",
|
|
89
|
+
" \"\"\"Format the attack payload to match the target's request schema.\"\"\"\n",
|
|
90
|
+
" messages = [{\"role\": msg[\"role\"], \"content\": msg[\"content\"]} for msg in history]\n",
|
|
91
|
+
" messages.append({\"role\": \"user\", \"content\": prompt})\n",
|
|
92
|
+
" return {\"model\": TARGET_MODEL_NAME, \"messages\": messages}\n",
|
|
93
|
+
"\n",
|
|
94
|
+
"\n",
|
|
95
|
+
"def from_target_response(api_response):\n",
|
|
96
|
+
" \"\"\"Extract the response text from the target's response schema.\"\"\"\n",
|
|
97
|
+
" if \"choices\" in api_response:\n",
|
|
98
|
+
" return api_response[\"choices\"][0][\"message\"][\"content\"]\n",
|
|
99
|
+
" return api_response.get(\"response\", str(api_response))"
|
|
100
|
+
],
|
|
101
|
+
"execution_count": null,
|
|
102
|
+
"outputs": []
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"cell_type": "markdown",
|
|
106
|
+
"metadata": {},
|
|
107
|
+
"source": [
|
|
108
|
+
"## Create Handler\n",
|
|
109
|
+
"\n",
|
|
110
|
+
"The handler acts as a proxy between the attacker and the target: it receives an attack prompt from HiddenLayer, calls the target, and returns the target's reply."
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"cell_type": "code",
|
|
115
|
+
"metadata": {},
|
|
116
|
+
"source": [
|
|
117
|
+
"async def handler(prompt, history, session_id, target_system_prompt):\n",
|
|
118
|
+
" \"\"\"Handler acts as proxy between attacker and target.\"\"\"\n",
|
|
119
|
+
" payload = to_target_request(prompt, history, session_id)\n",
|
|
120
|
+
" headers = {\"Content-Type\": \"application/json\", **CUSTOM_HEADERS}\n",
|
|
121
|
+
"\n",
|
|
122
|
+
" async with httpx.AsyncClient(timeout=None) as http_client:\n",
|
|
123
|
+
" response = await http_client.post(TARGET_URL, json=payload, headers=headers)\n",
|
|
124
|
+
" response.raise_for_status()\n",
|
|
125
|
+
" return from_target_response(response.json())"
|
|
126
|
+
],
|
|
127
|
+
"execution_count": null,
|
|
128
|
+
"outputs": []
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"cell_type": "markdown",
|
|
132
|
+
"metadata": {},
|
|
133
|
+
"source": [
|
|
134
|
+
"## Run the Evaluation\n",
|
|
135
|
+
"\n",
|
|
136
|
+
"Open a red team session and run attack techniques in parallel against the target."
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"cell_type": "code",
|
|
141
|
+
"metadata": {},
|
|
142
|
+
"source": [
|
|
143
|
+
"session = await client.evaluation_sessions.red_team.start_session(\n",
|
|
144
|
+
" name=EVAL_NAME,\n",
|
|
145
|
+
" target_model=TARGET_MODEL_NAME,\n",
|
|
146
|
+
" target_system_prompt=TARGET_SYSTEM_PROMPT,\n",
|
|
147
|
+
" execution_strategy_type=EXECUTION_STRATEGY,\n",
|
|
148
|
+
" max_turns=MAX_TURNS,\n",
|
|
149
|
+
" sessions_per_technique=SESSIONS_PER_TECHNIQUE,\n",
|
|
150
|
+
" max_parallel_techniques=PARALLEL_TECHNIQUES,\n",
|
|
151
|
+
" hiddenlayer_project_id=HIDDENLAYER_PROJECT_ID,\n",
|
|
152
|
+
")\n",
|
|
153
|
+
"\n",
|
|
154
|
+
"print(f\"Session started: {session.workflow_id}\")\n",
|
|
155
|
+
"\n",
|
|
156
|
+
"await session.run_with_callback_parallel(handler=handler)\n",
|
|
157
|
+
"\n",
|
|
158
|
+
"print(\"Evaluation complete. View results: https://console.hiddenlayer.ai/\")"
|
|
159
|
+
],
|
|
160
|
+
"execution_count": null,
|
|
161
|
+
"outputs": []
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"cell_type": "markdown",
|
|
165
|
+
"metadata": {},
|
|
166
|
+
"source": [
|
|
167
|
+
"## Resume a Session\n",
|
|
168
|
+
"\n",
|
|
169
|
+
"Reconnect to a previously started workflow by its `workflow_id` — useful after an interruption or to monitor a long-running evaluation from another process. `resume_session` returns a session you can keep driving; `retrieve_status` reports where it is."
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"cell_type": "code",
|
|
174
|
+
"metadata": {},
|
|
175
|
+
"source": [
|
|
176
|
+
"async def resume(workflow_id):\n",
|
|
177
|
+
" \"\"\"Reconnect to an existing workflow, finish it if still running, and return results.\"\"\"\n",
|
|
178
|
+
" session = await client.evaluation_sessions.red_team.resume_session(workflow_id=workflow_id)\n",
|
|
179
|
+
" status = await client.evaluations.red_team.retrieve_status(workflow_id)\n",
|
|
180
|
+
" print(f\"Resumed {session.workflow_id} - status: {status.status}\")\n",
|
|
181
|
+
"\n",
|
|
182
|
+
" if status.status == \"RUNNING\":\n",
|
|
183
|
+
" await session.run_with_callback_parallel(handler=handler)\n",
|
|
184
|
+
"\n",
|
|
185
|
+
" return await client.evaluations.red_team.retrieve_evaluation_results(workflow_id)\n",
|
|
186
|
+
"\n",
|
|
187
|
+
"\n",
|
|
188
|
+
"# results = await resume(\"<workflow_id>\")"
|
|
189
|
+
],
|
|
190
|
+
"execution_count": null,
|
|
191
|
+
"outputs": []
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"cell_type": "markdown",
|
|
195
|
+
"metadata": {},
|
|
196
|
+
"source": [
|
|
197
|
+
"## Retrieve Results\n",
|
|
198
|
+
"\n",
|
|
199
|
+
"Fetch and summarize the evaluation report for the completed session."
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"cell_type": "code",
|
|
204
|
+
"metadata": {},
|
|
205
|
+
"source": [
|
|
206
|
+
"results = await client.evaluations.red_team.retrieve_evaluation_results(\n",
|
|
207
|
+
" session.workflow_id\n",
|
|
208
|
+
")\n",
|
|
209
|
+
"\n",
|
|
210
|
+
"report = results.result.report\n",
|
|
211
|
+
"summary = report[\"summary\"]\n",
|
|
212
|
+
"\n",
|
|
213
|
+
"print(\"=\" * 60)\n",
|
|
214
|
+
"print(\"RED TEAM EVALUATION SUMMARY\")\n",
|
|
215
|
+
"print(\"=\" * 60)\n",
|
|
216
|
+
"print(f\"Total Sessions: {summary['total_sessions']}\")\n",
|
|
217
|
+
"print(f\"Success Rate: {summary['success_rate_pct']:.1f}%\")\n",
|
|
218
|
+
"print(f\"Successful: {summary['success_total']} / {summary['attempts_total']}\")\n",
|
|
219
|
+
"print(f\"Errors: {summary['error_total']}\")\n",
|
|
220
|
+
"print()\n",
|
|
221
|
+
"\n",
|
|
222
|
+
"print(\"BY OBJECTIVE\")\n",
|
|
223
|
+
"print(\"-\" * 60)\n",
|
|
224
|
+
"for obj_id, obj in report[\"by_objective\"].items():\n",
|
|
225
|
+
" status = \"PASS\" if obj[\"success\"] == 0 else \"FAIL\"\n",
|
|
226
|
+
" pct = obj[\"success\"] / obj[\"attempts\"] * 100 if obj[\"attempts\"] else 0\n",
|
|
227
|
+
" print(f\" {obj_id}: {obj['success']}/{obj['attempts']} succeeded ({pct:.0f}%) [{status}]\")"
|
|
228
|
+
],
|
|
229
|
+
"execution_count": null,
|
|
230
|
+
"outputs": []
|
|
231
|
+
}
|
|
232
|
+
],
|
|
233
|
+
"metadata": {
|
|
234
|
+
"kernelspec": {
|
|
235
|
+
"display_name": "Python 3",
|
|
236
|
+
"language": "python",
|
|
237
|
+
"name": "python3"
|
|
238
|
+
},
|
|
239
|
+
"language_info": {
|
|
240
|
+
"name": "python"
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
"nbformat": 4,
|
|
244
|
+
"nbformat_minor": 4
|
|
245
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# HiddenLayer Red Team Evaluation - OpenAI Target\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"Run adversarial red team attack techniques against an OpenAI chat model.\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"The handler is the integration point: HiddenLayer generates attack prompts, your handler forwards each prompt to the target and returns the target's reply.\n",
|
|
12
|
+
"\n",
|
|
13
|
+
"**Prerequisites:**\n",
|
|
14
|
+
"- `pip install hiddenlayer-sdk openai`\n",
|
|
15
|
+
"- Credentials read from the environment:\n",
|
|
16
|
+
" - `HIDDENLAYER_CLIENT_ID` and `HIDDENLAYER_CLIENT_SECRET` (OAuth2), or `HIDDENLAYER_TOKEN` (Bearer token)\n",
|
|
17
|
+
" - `OPENAI_API_KEY` (used to call the target model)\n",
|
|
18
|
+
"\n",
|
|
19
|
+
"**SDK Reference:** [hiddenlayer-sdk-python](https://github.com/hiddenlayerai/hiddenlayer-sdk-python)"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"cell_type": "markdown",
|
|
24
|
+
"metadata": {},
|
|
25
|
+
"source": [
|
|
26
|
+
"## Setup"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"cell_type": "code",
|
|
31
|
+
"metadata": {},
|
|
32
|
+
"source": [
|
|
33
|
+
"import os\n",
|
|
34
|
+
"\n",
|
|
35
|
+
"from openai import AsyncOpenAI\n",
|
|
36
|
+
"\n",
|
|
37
|
+
"from hiddenlayer import AsyncHiddenLayer\n",
|
|
38
|
+
"\n",
|
|
39
|
+
"# AsyncHiddenLayer() reads credentials from the environment.\n",
|
|
40
|
+
"# For EU prod pass environment=\"prod-eu\"; for self-hosted pass base_url=\"http://your-host:port\".\n",
|
|
41
|
+
"client = AsyncHiddenLayer()\n",
|
|
42
|
+
"\n",
|
|
43
|
+
"openai_client = AsyncOpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"))"
|
|
44
|
+
],
|
|
45
|
+
"execution_count": null,
|
|
46
|
+
"outputs": []
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"cell_type": "markdown",
|
|
50
|
+
"metadata": {},
|
|
51
|
+
"source": [
|
|
52
|
+
"## Configurables\n",
|
|
53
|
+
"\n",
|
|
54
|
+
"1. Configure target\n",
|
|
55
|
+
"2. Configure evaluation"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"cell_type": "code",
|
|
60
|
+
"metadata": {},
|
|
61
|
+
"source": [
|
|
62
|
+
"# Target configuration\n",
|
|
63
|
+
"TARGET_MODEL = \"gpt-4o-mini\"\n",
|
|
64
|
+
"TARGET_SYSTEM_PROMPT = \"You are a helpful AI assistant.\"\n",
|
|
65
|
+
"\n",
|
|
66
|
+
"# Evaluation configuration\n",
|
|
67
|
+
"EVAL_NAME = \"OpenAI Red Team Eval\" # Name of the evaluation\n",
|
|
68
|
+
"EXECUTION_STRATEGY = \"single\" # Options: \"single\", \"random\", \"static_prompt_set\"\n",
|
|
69
|
+
"MAX_TURNS = 5 # Options: 1-5\n",
|
|
70
|
+
"SESSIONS_PER_TECHNIQUE = 1 # Options: 1-5\n",
|
|
71
|
+
"PARALLEL_TECHNIQUES = 5 # Options: 1-10"
|
|
72
|
+
],
|
|
73
|
+
"execution_count": null,
|
|
74
|
+
"outputs": []
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"cell_type": "markdown",
|
|
78
|
+
"metadata": {},
|
|
79
|
+
"source": [
|
|
80
|
+
"## Verify payload adapters\n",
|
|
81
|
+
"\n",
|
|
82
|
+
"- `to_target_request` builds the OpenAI Chat Completions payload from the attack prompt and history\n",
|
|
83
|
+
"- `from_target_response` extracts the assistant's reply text from the target response"
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"cell_type": "code",
|
|
88
|
+
"metadata": {},
|
|
89
|
+
"source": [
|
|
90
|
+
"def to_target_request(prompt, history, session_id):\n",
|
|
91
|
+
" \"\"\"Build the target request payload from the attack prompt and history.\"\"\"\n",
|
|
92
|
+
" messages = [{\"role\": \"system\", \"content\": TARGET_SYSTEM_PROMPT}]\n",
|
|
93
|
+
" messages.extend(history)\n",
|
|
94
|
+
" messages.append({\"role\": \"user\", \"content\": prompt})\n",
|
|
95
|
+
" return {\"model\": TARGET_MODEL, \"messages\": messages}\n",
|
|
96
|
+
"\n",
|
|
97
|
+
"\n",
|
|
98
|
+
"def from_target_response(response):\n",
|
|
99
|
+
" \"\"\"Extract the assistant reply text from the target response.\"\"\"\n",
|
|
100
|
+
" return response.choices[0].message.content or \" \""
|
|
101
|
+
],
|
|
102
|
+
"execution_count": null,
|
|
103
|
+
"outputs": []
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"cell_type": "markdown",
|
|
107
|
+
"metadata": {},
|
|
108
|
+
"source": [
|
|
109
|
+
"## Create Handler\n",
|
|
110
|
+
"\n",
|
|
111
|
+
"The handler acts as a proxy between the attacker and the target: it receives an attack prompt from HiddenLayer, calls the target, and returns the target's reply."
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"cell_type": "code",
|
|
116
|
+
"metadata": {},
|
|
117
|
+
"source": [
|
|
118
|
+
"async def handler(prompt, history, session_id, target_system_prompt):\n",
|
|
119
|
+
" \"\"\"Handler acts as proxy between attacker and target.\"\"\"\n",
|
|
120
|
+
" payload = to_target_request(prompt, history, session_id)\n",
|
|
121
|
+
" response = await openai_client.chat.completions.create(**payload)\n",
|
|
122
|
+
" return from_target_response(response)"
|
|
123
|
+
],
|
|
124
|
+
"execution_count": null,
|
|
125
|
+
"outputs": []
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"cell_type": "markdown",
|
|
129
|
+
"metadata": {},
|
|
130
|
+
"source": [
|
|
131
|
+
"## Run the Evaluation\n",
|
|
132
|
+
"\n",
|
|
133
|
+
"Open a red team session and run attack techniques in parallel against the target."
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"cell_type": "code",
|
|
138
|
+
"metadata": {},
|
|
139
|
+
"source": [
|
|
140
|
+
"session = await client.evaluation_sessions.red_team.start_session(\n",
|
|
141
|
+
" name=EVAL_NAME,\n",
|
|
142
|
+
" target_model=TARGET_MODEL,\n",
|
|
143
|
+
" target_system_prompt=TARGET_SYSTEM_PROMPT,\n",
|
|
144
|
+
" execution_strategy_type=EXECUTION_STRATEGY,\n",
|
|
145
|
+
" max_turns=MAX_TURNS,\n",
|
|
146
|
+
" sessions_per_technique=SESSIONS_PER_TECHNIQUE,\n",
|
|
147
|
+
" max_parallel_techniques=PARALLEL_TECHNIQUES,\n",
|
|
148
|
+
")\n",
|
|
149
|
+
"\n",
|
|
150
|
+
"print(f\"Session started: {session.workflow_id}\")\n",
|
|
151
|
+
"\n",
|
|
152
|
+
"await session.run_with_callback_parallel(handler=handler)\n",
|
|
153
|
+
"\n",
|
|
154
|
+
"print(\"Evaluation complete. View results: https://console.hiddenlayer.ai/\")"
|
|
155
|
+
],
|
|
156
|
+
"execution_count": null,
|
|
157
|
+
"outputs": []
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"cell_type": "markdown",
|
|
161
|
+
"metadata": {},
|
|
162
|
+
"source": [
|
|
163
|
+
"## Resume a Session\n",
|
|
164
|
+
"\n",
|
|
165
|
+
"Reconnect to a previously started workflow by its `workflow_id` — useful after an interruption or to monitor a long-running evaluation from another process. `resume_session` returns a session you can keep driving; `retrieve_status` reports where it is."
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"cell_type": "code",
|
|
170
|
+
"metadata": {},
|
|
171
|
+
"source": [
|
|
172
|
+
"async def resume(workflow_id):\n",
|
|
173
|
+
" \"\"\"Reconnect to an existing workflow, finish it if still running, and return results.\"\"\"\n",
|
|
174
|
+
" session = await client.evaluation_sessions.red_team.resume_session(workflow_id=workflow_id)\n",
|
|
175
|
+
" status = await client.evaluations.red_team.retrieve_status(workflow_id)\n",
|
|
176
|
+
" print(f\"Resumed {session.workflow_id} - status: {status.status}\")\n",
|
|
177
|
+
"\n",
|
|
178
|
+
" if status.status == \"RUNNING\":\n",
|
|
179
|
+
" await session.run_with_callback_parallel(handler=handler)\n",
|
|
180
|
+
"\n",
|
|
181
|
+
" return await client.evaluations.red_team.retrieve_evaluation_results(workflow_id)\n",
|
|
182
|
+
"\n",
|
|
183
|
+
"\n",
|
|
184
|
+
"# results = await resume(\"<workflow_id>\")"
|
|
185
|
+
],
|
|
186
|
+
"execution_count": null,
|
|
187
|
+
"outputs": []
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"cell_type": "markdown",
|
|
191
|
+
"metadata": {},
|
|
192
|
+
"source": [
|
|
193
|
+
"## Retrieve Results\n",
|
|
194
|
+
"\n",
|
|
195
|
+
"Fetch and summarize the evaluation report for the completed session."
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"cell_type": "code",
|
|
200
|
+
"metadata": {},
|
|
201
|
+
"source": [
|
|
202
|
+
"results = await client.evaluations.red_team.retrieve_evaluation_results(\n",
|
|
203
|
+
" session.workflow_id\n",
|
|
204
|
+
")\n",
|
|
205
|
+
"\n",
|
|
206
|
+
"report = results.result.report\n",
|
|
207
|
+
"summary = report[\"summary\"]\n",
|
|
208
|
+
"\n",
|
|
209
|
+
"print(\"=\" * 60)\n",
|
|
210
|
+
"print(\"RED TEAM EVALUATION SUMMARY\")\n",
|
|
211
|
+
"print(\"=\" * 60)\n",
|
|
212
|
+
"print(f\"Total Sessions: {summary['total_sessions']}\")\n",
|
|
213
|
+
"print(f\"Success Rate: {summary['success_rate_pct']:.1f}%\")\n",
|
|
214
|
+
"print(f\"Successful: {summary['success_total']} / {summary['attempts_total']}\")\n",
|
|
215
|
+
"print(f\"Errors: {summary['error_total']}\")\n",
|
|
216
|
+
"print()\n",
|
|
217
|
+
"\n",
|
|
218
|
+
"print(\"BY OBJECTIVE\")\n",
|
|
219
|
+
"print(\"-\" * 60)\n",
|
|
220
|
+
"for obj_id, obj in report[\"by_objective\"].items():\n",
|
|
221
|
+
" status = \"PASS\" if obj[\"success\"] == 0 else \"FAIL\"\n",
|
|
222
|
+
" pct = obj[\"success\"] / obj[\"attempts\"] * 100 if obj[\"attempts\"] else 0\n",
|
|
223
|
+
" print(f\" {obj_id}: {obj['success']}/{obj['attempts']} succeeded ({pct:.0f}%) [{status}]\")"
|
|
224
|
+
],
|
|
225
|
+
"execution_count": null,
|
|
226
|
+
"outputs": []
|
|
227
|
+
}
|
|
228
|
+
],
|
|
229
|
+
"metadata": {
|
|
230
|
+
"kernelspec": {
|
|
231
|
+
"display_name": "Python 3",
|
|
232
|
+
"language": "python",
|
|
233
|
+
"name": "python3"
|
|
234
|
+
},
|
|
235
|
+
"language_info": {
|
|
236
|
+
"name": "python"
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
"nbformat": 4,
|
|
240
|
+
"nbformat_minor": 4
|
|
241
|
+
}
|