azure-ai-evaluation 1.0.0b2__py3-none-any.whl → 1.13.3__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.
Potentially problematic release.
This version of azure-ai-evaluation might be problematic. Click here for more details.
- azure/ai/evaluation/__init__.py +100 -5
- azure/ai/evaluation/{_evaluators/_chat → _aoai}/__init__.py +3 -2
- azure/ai/evaluation/_aoai/aoai_grader.py +140 -0
- azure/ai/evaluation/_aoai/label_grader.py +68 -0
- azure/ai/evaluation/_aoai/python_grader.py +86 -0
- azure/ai/evaluation/_aoai/score_model_grader.py +94 -0
- azure/ai/evaluation/_aoai/string_check_grader.py +66 -0
- azure/ai/evaluation/_aoai/text_similarity_grader.py +80 -0
- azure/ai/evaluation/_azure/__init__.py +3 -0
- azure/ai/evaluation/_azure/_clients.py +204 -0
- azure/ai/evaluation/_azure/_envs.py +207 -0
- azure/ai/evaluation/_azure/_models.py +227 -0
- azure/ai/evaluation/_azure/_token_manager.py +129 -0
- azure/ai/evaluation/_common/__init__.py +9 -1
- azure/ai/evaluation/{simulator/_helpers → _common}/_experimental.py +24 -9
- azure/ai/evaluation/_common/constants.py +131 -2
- azure/ai/evaluation/_common/evaluation_onedp_client.py +169 -0
- azure/ai/evaluation/_common/math.py +89 -0
- azure/ai/evaluation/_common/onedp/__init__.py +32 -0
- azure/ai/evaluation/_common/onedp/_client.py +166 -0
- azure/ai/evaluation/_common/onedp/_configuration.py +72 -0
- azure/ai/evaluation/_common/onedp/_model_base.py +1232 -0
- azure/ai/evaluation/_common/onedp/_patch.py +21 -0
- azure/ai/evaluation/_common/onedp/_serialization.py +2032 -0
- azure/ai/evaluation/_common/onedp/_types.py +21 -0
- azure/ai/evaluation/_common/onedp/_utils/__init__.py +6 -0
- azure/ai/evaluation/_common/onedp/_utils/model_base.py +1232 -0
- azure/ai/evaluation/_common/onedp/_utils/serialization.py +2032 -0
- azure/ai/evaluation/_common/onedp/_validation.py +66 -0
- azure/ai/evaluation/_common/onedp/_vendor.py +50 -0
- azure/ai/evaluation/_common/onedp/_version.py +9 -0
- azure/ai/evaluation/_common/onedp/aio/__init__.py +29 -0
- azure/ai/evaluation/_common/onedp/aio/_client.py +168 -0
- azure/ai/evaluation/_common/onedp/aio/_configuration.py +72 -0
- azure/ai/evaluation/_common/onedp/aio/_patch.py +21 -0
- azure/ai/evaluation/_common/onedp/aio/operations/__init__.py +49 -0
- azure/ai/evaluation/_common/onedp/aio/operations/_operations.py +7143 -0
- azure/ai/evaluation/_common/onedp/aio/operations/_patch.py +21 -0
- azure/ai/evaluation/_common/onedp/models/__init__.py +358 -0
- azure/ai/evaluation/_common/onedp/models/_enums.py +447 -0
- azure/ai/evaluation/_common/onedp/models/_models.py +5963 -0
- azure/ai/evaluation/_common/onedp/models/_patch.py +21 -0
- azure/ai/evaluation/_common/onedp/operations/__init__.py +49 -0
- azure/ai/evaluation/_common/onedp/operations/_operations.py +8951 -0
- azure/ai/evaluation/_common/onedp/operations/_patch.py +21 -0
- azure/ai/evaluation/_common/onedp/py.typed +1 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/__init__.py +1 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/aio/__init__.py +1 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/aio/operations/__init__.py +25 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/aio/operations/_operations.py +34 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/aio/operations/_patch.py +20 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/buildingblocks/__init__.py +1 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/buildingblocks/aio/__init__.py +1 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/buildingblocks/aio/operations/__init__.py +22 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/buildingblocks/aio/operations/_operations.py +29 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/buildingblocks/aio/operations/_patch.py +20 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/buildingblocks/operations/__init__.py +22 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/buildingblocks/operations/_operations.py +29 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/buildingblocks/operations/_patch.py +20 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/operations/__init__.py +25 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/operations/_operations.py +34 -0
- azure/ai/evaluation/_common/onedp/servicepatterns/operations/_patch.py +20 -0
- azure/ai/evaluation/_common/rai_service.py +831 -142
- azure/ai/evaluation/_common/raiclient/__init__.py +34 -0
- azure/ai/evaluation/_common/raiclient/_client.py +128 -0
- azure/ai/evaluation/_common/raiclient/_configuration.py +87 -0
- azure/ai/evaluation/_common/raiclient/_model_base.py +1235 -0
- azure/ai/evaluation/_common/raiclient/_patch.py +20 -0
- azure/ai/evaluation/_common/raiclient/_serialization.py +2050 -0
- azure/ai/evaluation/_common/raiclient/_version.py +9 -0
- azure/ai/evaluation/_common/raiclient/aio/__init__.py +29 -0
- azure/ai/evaluation/_common/raiclient/aio/_client.py +130 -0
- azure/ai/evaluation/_common/raiclient/aio/_configuration.py +87 -0
- azure/ai/evaluation/_common/raiclient/aio/_patch.py +20 -0
- azure/ai/evaluation/_common/raiclient/aio/operations/__init__.py +25 -0
- azure/ai/evaluation/_common/raiclient/aio/operations/_operations.py +981 -0
- azure/ai/evaluation/_common/raiclient/aio/operations/_patch.py +20 -0
- azure/ai/evaluation/_common/raiclient/models/__init__.py +60 -0
- azure/ai/evaluation/_common/raiclient/models/_enums.py +18 -0
- azure/ai/evaluation/_common/raiclient/models/_models.py +651 -0
- azure/ai/evaluation/_common/raiclient/models/_patch.py +20 -0
- azure/ai/evaluation/_common/raiclient/operations/__init__.py +25 -0
- azure/ai/evaluation/_common/raiclient/operations/_operations.py +1238 -0
- azure/ai/evaluation/_common/raiclient/operations/_patch.py +20 -0
- azure/ai/evaluation/_common/raiclient/py.typed +1 -0
- azure/ai/evaluation/_common/utils.py +870 -34
- azure/ai/evaluation/_constants.py +167 -6
- azure/ai/evaluation/_converters/__init__.py +3 -0
- azure/ai/evaluation/_converters/_ai_services.py +899 -0
- azure/ai/evaluation/_converters/_models.py +467 -0
- azure/ai/evaluation/_converters/_sk_services.py +495 -0
- azure/ai/evaluation/_eval_mapping.py +83 -0
- azure/ai/evaluation/_evaluate/_batch_run/__init__.py +17 -0
- azure/ai/evaluation/_evaluate/_batch_run/_run_submitter_client.py +176 -0
- azure/ai/evaluation/_evaluate/_batch_run/batch_clients.py +82 -0
- azure/ai/evaluation/_evaluate/{_batch_run_client → _batch_run}/code_client.py +47 -25
- azure/ai/evaluation/_evaluate/{_batch_run_client/batch_run_context.py → _batch_run/eval_run_context.py} +42 -13
- azure/ai/evaluation/_evaluate/_batch_run/proxy_client.py +124 -0
- azure/ai/evaluation/_evaluate/_batch_run/target_run_context.py +62 -0
- azure/ai/evaluation/_evaluate/_eval_run.py +102 -59
- azure/ai/evaluation/_evaluate/_evaluate.py +2134 -311
- azure/ai/evaluation/_evaluate/_evaluate_aoai.py +992 -0
- azure/ai/evaluation/_evaluate/_telemetry/__init__.py +14 -99
- azure/ai/evaluation/_evaluate/_utils.py +289 -40
- azure/ai/evaluation/_evaluator_definition.py +76 -0
- azure/ai/evaluation/_evaluators/_bleu/_bleu.py +93 -42
- azure/ai/evaluation/_evaluators/_code_vulnerability/__init__.py +5 -0
- azure/ai/evaluation/_evaluators/_code_vulnerability/_code_vulnerability.py +119 -0
- azure/ai/evaluation/_evaluators/_coherence/_coherence.py +117 -91
- azure/ai/evaluation/_evaluators/_coherence/coherence.prompty +76 -39
- azure/ai/evaluation/_evaluators/_common/__init__.py +15 -0
- azure/ai/evaluation/_evaluators/_common/_base_eval.py +742 -0
- azure/ai/evaluation/_evaluators/_common/_base_multi_eval.py +63 -0
- azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py +345 -0
- azure/ai/evaluation/_evaluators/_common/_base_rai_svc_eval.py +198 -0
- azure/ai/evaluation/_evaluators/_common/_conversation_aggregators.py +49 -0
- azure/ai/evaluation/_evaluators/_content_safety/__init__.py +0 -4
- azure/ai/evaluation/_evaluators/_content_safety/_content_safety.py +144 -86
- azure/ai/evaluation/_evaluators/_content_safety/_hate_unfairness.py +138 -57
- azure/ai/evaluation/_evaluators/_content_safety/_self_harm.py +123 -55
- azure/ai/evaluation/_evaluators/_content_safety/_sexual.py +133 -54
- azure/ai/evaluation/_evaluators/_content_safety/_violence.py +134 -54
- azure/ai/evaluation/_evaluators/_document_retrieval/__init__.py +7 -0
- azure/ai/evaluation/_evaluators/_document_retrieval/_document_retrieval.py +442 -0
- azure/ai/evaluation/_evaluators/_eci/_eci.py +49 -56
- azure/ai/evaluation/_evaluators/_f1_score/_f1_score.py +102 -60
- azure/ai/evaluation/_evaluators/_fluency/_fluency.py +115 -92
- azure/ai/evaluation/_evaluators/_fluency/fluency.prompty +66 -41
- azure/ai/evaluation/_evaluators/_gleu/_gleu.py +90 -37
- azure/ai/evaluation/_evaluators/_groundedness/_groundedness.py +318 -82
- azure/ai/evaluation/_evaluators/_groundedness/groundedness_with_query.prompty +114 -0
- azure/ai/evaluation/_evaluators/_groundedness/groundedness_without_query.prompty +104 -0
- azure/ai/evaluation/{_evaluate/_batch_run_client → _evaluators/_intent_resolution}/__init__.py +3 -4
- azure/ai/evaluation/_evaluators/_intent_resolution/_intent_resolution.py +196 -0
- azure/ai/evaluation/_evaluators/_intent_resolution/intent_resolution.prompty +275 -0
- azure/ai/evaluation/_evaluators/_meteor/_meteor.py +107 -61
- azure/ai/evaluation/_evaluators/_protected_material/_protected_material.py +104 -77
- azure/ai/evaluation/_evaluators/_qa/_qa.py +115 -63
- azure/ai/evaluation/_evaluators/_relevance/_relevance.py +182 -98
- azure/ai/evaluation/_evaluators/_relevance/relevance.prompty +178 -49
- azure/ai/evaluation/_evaluators/_response_completeness/__init__.py +7 -0
- azure/ai/evaluation/_evaluators/_response_completeness/_response_completeness.py +202 -0
- azure/ai/evaluation/_evaluators/_response_completeness/response_completeness.prompty +84 -0
- azure/ai/evaluation/_evaluators/{_chat/retrieval → _retrieval}/__init__.py +2 -2
- azure/ai/evaluation/_evaluators/_retrieval/_retrieval.py +148 -0
- azure/ai/evaluation/_evaluators/_retrieval/retrieval.prompty +93 -0
- azure/ai/evaluation/_evaluators/_rouge/_rouge.py +189 -50
- azure/ai/evaluation/_evaluators/_service_groundedness/__init__.py +9 -0
- azure/ai/evaluation/_evaluators/_service_groundedness/_service_groundedness.py +179 -0
- azure/ai/evaluation/_evaluators/_similarity/_similarity.py +102 -91
- azure/ai/evaluation/_evaluators/_similarity/similarity.prompty +0 -5
- azure/ai/evaluation/_evaluators/_task_adherence/__init__.py +7 -0
- azure/ai/evaluation/_evaluators/_task_adherence/_task_adherence.py +226 -0
- azure/ai/evaluation/_evaluators/_task_adherence/task_adherence.prompty +101 -0
- azure/ai/evaluation/_evaluators/_task_completion/__init__.py +7 -0
- azure/ai/evaluation/_evaluators/_task_completion/_task_completion.py +177 -0
- azure/ai/evaluation/_evaluators/_task_completion/task_completion.prompty +220 -0
- azure/ai/evaluation/_evaluators/_task_navigation_efficiency/__init__.py +7 -0
- azure/ai/evaluation/_evaluators/_task_navigation_efficiency/_task_navigation_efficiency.py +384 -0
- azure/ai/evaluation/_evaluators/_tool_call_accuracy/__init__.py +9 -0
- azure/ai/evaluation/_evaluators/_tool_call_accuracy/_tool_call_accuracy.py +298 -0
- azure/ai/evaluation/_evaluators/_tool_call_accuracy/tool_call_accuracy.prompty +166 -0
- azure/ai/evaluation/_evaluators/_tool_input_accuracy/__init__.py +9 -0
- azure/ai/evaluation/_evaluators/_tool_input_accuracy/_tool_input_accuracy.py +263 -0
- azure/ai/evaluation/_evaluators/_tool_input_accuracy/tool_input_accuracy.prompty +76 -0
- azure/ai/evaluation/_evaluators/_tool_output_utilization/__init__.py +7 -0
- azure/ai/evaluation/_evaluators/_tool_output_utilization/_tool_output_utilization.py +225 -0
- azure/ai/evaluation/_evaluators/_tool_output_utilization/tool_output_utilization.prompty +221 -0
- azure/ai/evaluation/_evaluators/_tool_selection/__init__.py +9 -0
- azure/ai/evaluation/_evaluators/_tool_selection/_tool_selection.py +266 -0
- azure/ai/evaluation/_evaluators/_tool_selection/tool_selection.prompty +104 -0
- azure/ai/evaluation/_evaluators/_tool_success/__init__.py +7 -0
- azure/ai/evaluation/_evaluators/_tool_success/_tool_success.py +301 -0
- azure/ai/evaluation/_evaluators/_tool_success/tool_success.prompty +321 -0
- azure/ai/evaluation/_evaluators/_ungrounded_attributes/__init__.py +5 -0
- azure/ai/evaluation/_evaluators/_ungrounded_attributes/_ungrounded_attributes.py +102 -0
- azure/ai/evaluation/_evaluators/_xpia/xpia.py +109 -107
- azure/ai/evaluation/_exceptions.py +51 -7
- azure/ai/evaluation/_http_utils.py +210 -137
- azure/ai/evaluation/_legacy/__init__.py +3 -0
- azure/ai/evaluation/_legacy/_adapters/__init__.py +7 -0
- azure/ai/evaluation/_legacy/_adapters/_check.py +17 -0
- azure/ai/evaluation/_legacy/_adapters/_configuration.py +45 -0
- azure/ai/evaluation/_legacy/_adapters/_constants.py +10 -0
- azure/ai/evaluation/_legacy/_adapters/_errors.py +29 -0
- azure/ai/evaluation/_legacy/_adapters/_flows.py +28 -0
- azure/ai/evaluation/_legacy/_adapters/_service.py +16 -0
- azure/ai/evaluation/_legacy/_adapters/client.py +51 -0
- azure/ai/evaluation/_legacy/_adapters/entities.py +26 -0
- azure/ai/evaluation/_legacy/_adapters/tracing.py +28 -0
- azure/ai/evaluation/_legacy/_adapters/types.py +15 -0
- azure/ai/evaluation/_legacy/_adapters/utils.py +31 -0
- azure/ai/evaluation/_legacy/_batch_engine/__init__.py +9 -0
- azure/ai/evaluation/_legacy/_batch_engine/_config.py +48 -0
- azure/ai/evaluation/_legacy/_batch_engine/_engine.py +477 -0
- azure/ai/evaluation/_legacy/_batch_engine/_exceptions.py +88 -0
- azure/ai/evaluation/_legacy/_batch_engine/_openai_injector.py +132 -0
- azure/ai/evaluation/_legacy/_batch_engine/_result.py +107 -0
- azure/ai/evaluation/_legacy/_batch_engine/_run.py +127 -0
- azure/ai/evaluation/_legacy/_batch_engine/_run_storage.py +128 -0
- azure/ai/evaluation/_legacy/_batch_engine/_run_submitter.py +262 -0
- azure/ai/evaluation/_legacy/_batch_engine/_status.py +25 -0
- azure/ai/evaluation/_legacy/_batch_engine/_trace.py +97 -0
- azure/ai/evaluation/_legacy/_batch_engine/_utils.py +97 -0
- azure/ai/evaluation/_legacy/_batch_engine/_utils_deprecated.py +131 -0
- azure/ai/evaluation/_legacy/_common/__init__.py +3 -0
- azure/ai/evaluation/_legacy/_common/_async_token_provider.py +117 -0
- azure/ai/evaluation/_legacy/_common/_logging.py +292 -0
- azure/ai/evaluation/_legacy/_common/_thread_pool_executor_with_context.py +17 -0
- azure/ai/evaluation/_legacy/prompty/__init__.py +36 -0
- azure/ai/evaluation/_legacy/prompty/_connection.py +119 -0
- azure/ai/evaluation/_legacy/prompty/_exceptions.py +139 -0
- azure/ai/evaluation/_legacy/prompty/_prompty.py +430 -0
- azure/ai/evaluation/_legacy/prompty/_utils.py +663 -0
- azure/ai/evaluation/_legacy/prompty/_yaml_utils.py +99 -0
- azure/ai/evaluation/_model_configurations.py +130 -8
- azure/ai/evaluation/_safety_evaluation/__init__.py +3 -0
- azure/ai/evaluation/_safety_evaluation/_generated_rai_client.py +0 -0
- azure/ai/evaluation/_safety_evaluation/_safety_evaluation.py +917 -0
- azure/ai/evaluation/_user_agent.py +32 -1
- azure/ai/evaluation/_vendor/__init__.py +3 -0
- azure/ai/evaluation/_vendor/rouge_score/__init__.py +14 -0
- azure/ai/evaluation/_vendor/rouge_score/rouge_scorer.py +324 -0
- azure/ai/evaluation/_vendor/rouge_score/scoring.py +59 -0
- azure/ai/evaluation/_vendor/rouge_score/tokenize.py +59 -0
- azure/ai/evaluation/_vendor/rouge_score/tokenizers.py +53 -0
- azure/ai/evaluation/_version.py +2 -1
- azure/ai/evaluation/red_team/__init__.py +22 -0
- azure/ai/evaluation/red_team/_agent/__init__.py +3 -0
- azure/ai/evaluation/red_team/_agent/_agent_functions.py +261 -0
- azure/ai/evaluation/red_team/_agent/_agent_tools.py +461 -0
- azure/ai/evaluation/red_team/_agent/_agent_utils.py +89 -0
- azure/ai/evaluation/red_team/_agent/_semantic_kernel_plugin.py +228 -0
- azure/ai/evaluation/red_team/_attack_objective_generator.py +268 -0
- azure/ai/evaluation/red_team/_attack_strategy.py +49 -0
- azure/ai/evaluation/red_team/_callback_chat_target.py +115 -0
- azure/ai/evaluation/red_team/_default_converter.py +21 -0
- azure/ai/evaluation/red_team/_evaluation_processor.py +505 -0
- azure/ai/evaluation/red_team/_mlflow_integration.py +430 -0
- azure/ai/evaluation/red_team/_orchestrator_manager.py +803 -0
- azure/ai/evaluation/red_team/_red_team.py +1717 -0
- azure/ai/evaluation/red_team/_red_team_result.py +661 -0
- azure/ai/evaluation/red_team/_result_processor.py +1708 -0
- azure/ai/evaluation/red_team/_utils/__init__.py +37 -0
- azure/ai/evaluation/red_team/_utils/_rai_service_eval_chat_target.py +128 -0
- azure/ai/evaluation/red_team/_utils/_rai_service_target.py +601 -0
- azure/ai/evaluation/red_team/_utils/_rai_service_true_false_scorer.py +114 -0
- azure/ai/evaluation/red_team/_utils/constants.py +72 -0
- azure/ai/evaluation/red_team/_utils/exception_utils.py +345 -0
- azure/ai/evaluation/red_team/_utils/file_utils.py +266 -0
- azure/ai/evaluation/red_team/_utils/formatting_utils.py +365 -0
- azure/ai/evaluation/red_team/_utils/logging_utils.py +139 -0
- azure/ai/evaluation/red_team/_utils/metric_mapping.py +73 -0
- azure/ai/evaluation/red_team/_utils/objective_utils.py +46 -0
- azure/ai/evaluation/red_team/_utils/progress_utils.py +252 -0
- azure/ai/evaluation/red_team/_utils/retry_utils.py +218 -0
- azure/ai/evaluation/red_team/_utils/strategy_utils.py +218 -0
- azure/ai/evaluation/simulator/__init__.py +2 -1
- azure/ai/evaluation/simulator/_adversarial_scenario.py +26 -1
- azure/ai/evaluation/simulator/_adversarial_simulator.py +270 -144
- azure/ai/evaluation/simulator/_constants.py +12 -1
- azure/ai/evaluation/simulator/_conversation/__init__.py +151 -23
- azure/ai/evaluation/simulator/_conversation/_conversation.py +10 -6
- azure/ai/evaluation/simulator/_conversation/constants.py +1 -1
- azure/ai/evaluation/simulator/_data_sources/__init__.py +3 -0
- azure/ai/evaluation/simulator/_data_sources/grounding.json +1150 -0
- azure/ai/evaluation/simulator/_direct_attack_simulator.py +54 -75
- azure/ai/evaluation/simulator/_helpers/__init__.py +1 -2
- azure/ai/evaluation/simulator/_helpers/_language_suffix_mapping.py +1 -0
- azure/ai/evaluation/simulator/_helpers/_simulator_data_classes.py +26 -5
- azure/ai/evaluation/simulator/_indirect_attack_simulator.py +145 -104
- azure/ai/evaluation/simulator/_model_tools/__init__.py +2 -1
- azure/ai/evaluation/simulator/_model_tools/_generated_rai_client.py +225 -0
- azure/ai/evaluation/simulator/_model_tools/_identity_manager.py +80 -30
- azure/ai/evaluation/simulator/_model_tools/_proxy_completion_model.py +117 -45
- azure/ai/evaluation/simulator/_model_tools/_rai_client.py +109 -7
- azure/ai/evaluation/simulator/_model_tools/_template_handler.py +97 -33
- azure/ai/evaluation/simulator/_model_tools/models.py +30 -27
- azure/ai/evaluation/simulator/_prompty/task_query_response.prompty +6 -10
- azure/ai/evaluation/simulator/_prompty/task_simulate.prompty +6 -5
- azure/ai/evaluation/simulator/_simulator.py +302 -208
- azure/ai/evaluation/simulator/_utils.py +31 -13
- azure_ai_evaluation-1.13.3.dist-info/METADATA +939 -0
- azure_ai_evaluation-1.13.3.dist-info/RECORD +305 -0
- {azure_ai_evaluation-1.0.0b2.dist-info → azure_ai_evaluation-1.13.3.dist-info}/WHEEL +1 -1
- azure_ai_evaluation-1.13.3.dist-info/licenses/NOTICE.txt +70 -0
- azure/ai/evaluation/_evaluate/_batch_run_client/proxy_client.py +0 -71
- azure/ai/evaluation/_evaluators/_chat/_chat.py +0 -357
- azure/ai/evaluation/_evaluators/_chat/retrieval/_retrieval.py +0 -157
- azure/ai/evaluation/_evaluators/_chat/retrieval/retrieval.prompty +0 -48
- azure/ai/evaluation/_evaluators/_content_safety/_content_safety_base.py +0 -65
- azure/ai/evaluation/_evaluators/_content_safety/_content_safety_chat.py +0 -301
- azure/ai/evaluation/_evaluators/_groundedness/groundedness.prompty +0 -54
- azure/ai/evaluation/_evaluators/_protected_materials/__init__.py +0 -5
- azure/ai/evaluation/_evaluators/_protected_materials/_protected_materials.py +0 -104
- azure/ai/evaluation/simulator/_tracing.py +0 -89
- azure_ai_evaluation-1.0.0b2.dist-info/METADATA +0 -449
- azure_ai_evaluation-1.0.0b2.dist-info/RECORD +0 -99
- {azure_ai_evaluation-1.0.0b2.dist-info → azure_ai_evaluation-1.13.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# ---------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# ---------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
from typing import Dict, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from azure.core.credentials import TokenCredential
|
|
10
|
+
from azure.core.pipeline.policies import UserAgentPolicy
|
|
11
|
+
from azure.ai.evaluation._model_configurations import AzureAIProject
|
|
12
|
+
from azure.ai.evaluation.simulator._model_tools import ManagedIdentityAPITokenManager
|
|
13
|
+
from azure.ai.evaluation._common.raiclient import MachineLearningServicesClient
|
|
14
|
+
from azure.ai.evaluation._constants import TokenScope
|
|
15
|
+
from azure.ai.evaluation._common.utils import is_onedp_project
|
|
16
|
+
from azure.ai.evaluation._common.onedp import ProjectsClient as AIProjectClient
|
|
17
|
+
from azure.ai.evaluation._common import EvaluationServiceOneDPClient
|
|
18
|
+
from azure.ai.evaluation._user_agent import UserAgentSingleton
|
|
19
|
+
import jwt
|
|
20
|
+
import time
|
|
21
|
+
import ast
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class GeneratedRAIClient:
|
|
25
|
+
"""Client for the Responsible AI Service using the auto-generated MachineLearningServicesClient.
|
|
26
|
+
|
|
27
|
+
:param azure_ai_project: The Azure AI project, which can either be a string representing the project endpoint
|
|
28
|
+
or an instance of AzureAIProject. It contains subscription id, resource group, and project name.
|
|
29
|
+
:type azure_ai_project: Union[str, ~azure.ai.evaluation.AzureAIProject]
|
|
30
|
+
:param token_manager: The token manager
|
|
31
|
+
:type token_manager: ~azure.ai.evaluation.simulator._model_tools._identity_manager.APITokenManager
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
azure_ai_project: Union[AzureAIProject, str],
|
|
37
|
+
token_manager: ManagedIdentityAPITokenManager,
|
|
38
|
+
):
|
|
39
|
+
self.azure_ai_project = azure_ai_project
|
|
40
|
+
self.token_manager = token_manager
|
|
41
|
+
self.logger = logging.getLogger(__name__)
|
|
42
|
+
|
|
43
|
+
user_agent_policy = UserAgentPolicy(base_user_agent=UserAgentSingleton().value)
|
|
44
|
+
|
|
45
|
+
if not is_onedp_project(azure_ai_project):
|
|
46
|
+
# Service URL construction
|
|
47
|
+
if "RAI_SVC_URL" in os.environ:
|
|
48
|
+
endpoint = os.environ["RAI_SVC_URL"].rstrip("/")
|
|
49
|
+
else:
|
|
50
|
+
endpoint = self._get_service_discovery_url()
|
|
51
|
+
|
|
52
|
+
# Create the autogenerated client
|
|
53
|
+
self._client = MachineLearningServicesClient(
|
|
54
|
+
endpoint=endpoint,
|
|
55
|
+
subscription_id=self.azure_ai_project["subscription_id"],
|
|
56
|
+
resource_group_name=self.azure_ai_project["resource_group_name"],
|
|
57
|
+
workspace_name=self.azure_ai_project["project_name"],
|
|
58
|
+
credential=self.token_manager,
|
|
59
|
+
).rai_svc
|
|
60
|
+
else:
|
|
61
|
+
self._client = AIProjectClient(
|
|
62
|
+
endpoint=azure_ai_project,
|
|
63
|
+
credential=token_manager,
|
|
64
|
+
user_agent_policy=user_agent_policy,
|
|
65
|
+
).red_teams
|
|
66
|
+
self._evaluation_onedp_client = EvaluationServiceOneDPClient(
|
|
67
|
+
endpoint=azure_ai_project,
|
|
68
|
+
credential=token_manager,
|
|
69
|
+
user_agent_policy=user_agent_policy,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def _get_service_discovery_url(self):
|
|
73
|
+
"""Get the service discovery URL.
|
|
74
|
+
|
|
75
|
+
:return: The service discovery URL
|
|
76
|
+
:rtype: str
|
|
77
|
+
"""
|
|
78
|
+
import requests
|
|
79
|
+
|
|
80
|
+
bearer_token = self._fetch_or_reuse_token(self.token_manager)
|
|
81
|
+
headers = {
|
|
82
|
+
"Authorization": f"Bearer {bearer_token}",
|
|
83
|
+
"Content-Type": "application/json",
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
response = requests.get(
|
|
87
|
+
f"https://management.azure.com/subscriptions/{self.azure_ai_project['subscription_id']}/"
|
|
88
|
+
f"resourceGroups/{self.azure_ai_project['resource_group_name']}/"
|
|
89
|
+
f"providers/Microsoft.MachineLearningServices/workspaces/{self.azure_ai_project['project_name']}?"
|
|
90
|
+
f"api-version=2023-08-01-preview",
|
|
91
|
+
headers=headers,
|
|
92
|
+
timeout=5,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if response.status_code != 200:
|
|
96
|
+
msg = (
|
|
97
|
+
f"Failed to connect to your Azure AI project. Please check if the project scope is configured "
|
|
98
|
+
f"correctly, and make sure you have the necessary access permissions. "
|
|
99
|
+
f"Status code: {response.status_code}."
|
|
100
|
+
)
|
|
101
|
+
raise Exception(msg)
|
|
102
|
+
|
|
103
|
+
# Parse the discovery URL
|
|
104
|
+
from urllib.parse import urlparse
|
|
105
|
+
|
|
106
|
+
base_url = urlparse(response.json()["properties"]["discoveryUrl"])
|
|
107
|
+
return f"{base_url.scheme}://{base_url.netloc}"
|
|
108
|
+
|
|
109
|
+
async def get_attack_objectives(
|
|
110
|
+
self,
|
|
111
|
+
*,
|
|
112
|
+
risk_type: Optional[str] = None,
|
|
113
|
+
risk_category: Optional[str] = None,
|
|
114
|
+
application_scenario: str = None,
|
|
115
|
+
strategy: Optional[str] = None,
|
|
116
|
+
language: str = "en",
|
|
117
|
+
scan_session_id: Optional[str] = None,
|
|
118
|
+
target: Optional[str] = None,
|
|
119
|
+
client_id: Optional[str] = None,
|
|
120
|
+
) -> Dict:
|
|
121
|
+
"""Get attack objectives using the auto-generated operations.
|
|
122
|
+
|
|
123
|
+
:param risk_type: Optional risk type to filter the attack objectives
|
|
124
|
+
:type risk_type: Optional[str]
|
|
125
|
+
:param risk_category: Optional risk category to filter the attack objectives
|
|
126
|
+
:type risk_category: Optional[str]
|
|
127
|
+
:param application_scenario: Optional description of the application scenario for context
|
|
128
|
+
:type application_scenario: str
|
|
129
|
+
:param strategy: Optional strategy to filter the attack objectives
|
|
130
|
+
:type strategy: Optional[str]
|
|
131
|
+
:param language: Language code for the attack objectives (e.g., "en", "es", "fr")
|
|
132
|
+
:type language: str
|
|
133
|
+
:param scan_session_id: Optional unique session ID for the scan
|
|
134
|
+
:type scan_session_id: Optional[str]
|
|
135
|
+
:param target: Optional target type (model/agent)
|
|
136
|
+
:type target: Optional[str]
|
|
137
|
+
:param client_id: Optional client ID for ACA token authorization
|
|
138
|
+
:type client_id: Optional[str]
|
|
139
|
+
:return: The attack objectives
|
|
140
|
+
:rtype: Dict
|
|
141
|
+
"""
|
|
142
|
+
try:
|
|
143
|
+
# Build headers dictionary
|
|
144
|
+
headers = {}
|
|
145
|
+
if scan_session_id:
|
|
146
|
+
headers["x-ms-client-request-id"] = scan_session_id
|
|
147
|
+
if client_id:
|
|
148
|
+
from azure.identity import DefaultAzureCredential
|
|
149
|
+
|
|
150
|
+
self.logger.info(f"Using client_id: {client_id} to set token in aml-aca-token header ")
|
|
151
|
+
|
|
152
|
+
# Get token using the client_id for managed identity
|
|
153
|
+
managed_identity_credential = DefaultAzureCredential(
|
|
154
|
+
managed_identity_client_id=client_id, exclude_interactive_browser_credential=True
|
|
155
|
+
)
|
|
156
|
+
token = managed_identity_credential.get_token(TokenScope.DEFAULT_AZURE_MANAGEMENT).token
|
|
157
|
+
headers["aml-aca-token"] = token
|
|
158
|
+
|
|
159
|
+
# Send the request using the autogenerated client
|
|
160
|
+
response = self._client.get_attack_objectives(
|
|
161
|
+
risk_types=[risk_type],
|
|
162
|
+
risk_category=risk_category,
|
|
163
|
+
lang=language,
|
|
164
|
+
strategy=strategy,
|
|
165
|
+
target_type=target,
|
|
166
|
+
headers=headers,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
return response
|
|
170
|
+
|
|
171
|
+
except Exception as e:
|
|
172
|
+
# Log the exception for debugging purposes
|
|
173
|
+
import logging
|
|
174
|
+
|
|
175
|
+
logging.error(f"Error in get_attack_objectives: {str(e)}")
|
|
176
|
+
raise
|
|
177
|
+
|
|
178
|
+
async def get_jailbreak_prefixes(self, scan_session_id: Optional[str] = None) -> List[str]:
|
|
179
|
+
"""Get jailbreak prefixes using the auto-generated operations.
|
|
180
|
+
|
|
181
|
+
:param scan_session_id: Optional unique session ID for the scan
|
|
182
|
+
:type scan_session_id: Optional[str]
|
|
183
|
+
:return: The jailbreak prefixes
|
|
184
|
+
:rtype: List[str]
|
|
185
|
+
"""
|
|
186
|
+
try:
|
|
187
|
+
# Send the request using the autogenerated client
|
|
188
|
+
response = self._client.get_jail_break_dataset_with_type(
|
|
189
|
+
type="upia", headers={"x-ms-client-request-id": scan_session_id}
|
|
190
|
+
)
|
|
191
|
+
if isinstance(response, list):
|
|
192
|
+
return response
|
|
193
|
+
else:
|
|
194
|
+
self.logger.error("Unexpected response format from get_jail_break_dataset_with_type")
|
|
195
|
+
raise ValueError("Unexpected response format from get_jail_break_dataset_with_type")
|
|
196
|
+
|
|
197
|
+
except Exception as e:
|
|
198
|
+
return [""]
|
|
199
|
+
|
|
200
|
+
def _fetch_or_reuse_token(self, credential: TokenCredential, token: Optional[str] = None) -> str:
|
|
201
|
+
"""Get token. Fetch a new token if the current token is near expiry
|
|
202
|
+
|
|
203
|
+
:param credential: The Azure authentication credential.
|
|
204
|
+
:type credential:
|
|
205
|
+
~azure.core.credentials.TokenCredential
|
|
206
|
+
:param token: The Azure authentication token. Defaults to None. If none, a new token will be fetched.
|
|
207
|
+
:type token: str
|
|
208
|
+
:return: The Azure authentication token.
|
|
209
|
+
"""
|
|
210
|
+
if token:
|
|
211
|
+
# Decode the token to get its expiration time
|
|
212
|
+
try:
|
|
213
|
+
decoded_token = jwt.decode(token, options={"verify_signature": False})
|
|
214
|
+
except jwt.PyJWTError:
|
|
215
|
+
pass
|
|
216
|
+
else:
|
|
217
|
+
exp_time = decoded_token["exp"]
|
|
218
|
+
current_time = time.time()
|
|
219
|
+
|
|
220
|
+
# Return current token if not near expiry
|
|
221
|
+
if (exp_time - current_time) >= 300:
|
|
222
|
+
return token
|
|
223
|
+
|
|
224
|
+
# Get token
|
|
225
|
+
return credential.get_token(TokenScope.DEFAULT_AZURE_MANAGEMENT).token
|
|
@@ -3,22 +3,20 @@
|
|
|
3
3
|
# ---------------------------------------------------------
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
+
import inspect
|
|
6
7
|
import logging
|
|
7
8
|
import os
|
|
8
9
|
import time
|
|
9
10
|
from abc import ABC, abstractmethod
|
|
10
|
-
from
|
|
11
|
-
from typing import Dict, Optional, Union
|
|
11
|
+
from typing import Optional, Union, Any
|
|
12
12
|
|
|
13
|
+
from azure.ai.evaluation._constants import TokenScope
|
|
14
|
+
from azure.core.credentials import AccessToken, TokenCredential
|
|
13
15
|
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
|
|
14
16
|
|
|
15
|
-
AZURE_TOKEN_REFRESH_INTERVAL =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class TokenScope(Enum):
|
|
19
|
-
"""Token scopes for Azure endpoints"""
|
|
20
|
-
|
|
21
|
-
DEFAULT_AZURE_MANAGEMENT = "https://management.azure.com/.default"
|
|
17
|
+
AZURE_TOKEN_REFRESH_INTERVAL = int(
|
|
18
|
+
os.getenv("AZURE_TOKEN_REFRESH_INTERVAL", "600")
|
|
19
|
+
) # token refresh interval in seconds
|
|
22
20
|
|
|
23
21
|
|
|
24
22
|
class APITokenManager(ABC):
|
|
@@ -29,24 +27,24 @@ class APITokenManager(ABC):
|
|
|
29
27
|
:param auth_header: Authorization header prefix. Defaults to "Bearer"
|
|
30
28
|
:type auth_header: str
|
|
31
29
|
:param credential: Azure credential object
|
|
32
|
-
:type credential: Optional[
|
|
30
|
+
:type credential: Optional[TokenCredential]
|
|
33
31
|
"""
|
|
34
32
|
|
|
35
33
|
def __init__(
|
|
36
34
|
self,
|
|
37
35
|
logger: logging.Logger,
|
|
38
36
|
auth_header: str = "Bearer",
|
|
39
|
-
credential: Optional[
|
|
37
|
+
credential: Optional[TokenCredential] = None,
|
|
40
38
|
) -> None:
|
|
41
39
|
self.logger = logger
|
|
42
40
|
self.auth_header = auth_header
|
|
43
|
-
self._lock = None
|
|
41
|
+
self._lock: Optional[asyncio.Lock] = None
|
|
44
42
|
if credential is not None:
|
|
45
43
|
self.credential = credential
|
|
46
44
|
else:
|
|
47
45
|
self.credential = self.get_aad_credential()
|
|
48
|
-
self.token = None
|
|
49
|
-
self.last_refresh_time = None
|
|
46
|
+
self.token: Optional[str] = None
|
|
47
|
+
self.last_refresh_time: Optional[float] = None
|
|
50
48
|
|
|
51
49
|
@property
|
|
52
50
|
def lock(self) -> asyncio.Lock:
|
|
@@ -73,39 +71,58 @@ class APITokenManager(ABC):
|
|
|
73
71
|
identity_client_id = os.environ.get("DEFAULT_IDENTITY_CLIENT_ID", None)
|
|
74
72
|
if identity_client_id is not None:
|
|
75
73
|
self.logger.info(f"Using DEFAULT_IDENTITY_CLIENT_ID: {identity_client_id}")
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return credential
|
|
74
|
+
return ManagedIdentityCredential(client_id=identity_client_id)
|
|
75
|
+
|
|
76
|
+
self.logger.info("Environment variable DEFAULT_IDENTITY_CLIENT_ID is not set, using DefaultAzureCredential")
|
|
77
|
+
return DefaultAzureCredential()
|
|
81
78
|
|
|
82
79
|
@abstractmethod
|
|
83
|
-
|
|
80
|
+
def get_token(
|
|
81
|
+
self,
|
|
82
|
+
scopes: Union[str, None] = None,
|
|
83
|
+
claims: Union[str, None] = None,
|
|
84
|
+
tenant_id: Union[str, None] = None,
|
|
85
|
+
enable_cae: bool = False,
|
|
86
|
+
**kwargs: Any,
|
|
87
|
+
) -> AccessToken:
|
|
88
|
+
"""Async method to get the API token. Subclasses should implement this method.
|
|
89
|
+
|
|
90
|
+
:return: API token
|
|
91
|
+
:rtype: str
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
@abstractmethod
|
|
95
|
+
async def get_token_async(self) -> str:
|
|
84
96
|
"""Async method to get the API token. Subclasses should implement this method.
|
|
85
97
|
|
|
86
98
|
:return: API token
|
|
87
99
|
:rtype: str
|
|
88
100
|
"""
|
|
89
|
-
pass # pylint: disable=unnecessary-pass
|
|
90
101
|
|
|
91
102
|
|
|
92
103
|
class ManagedIdentityAPITokenManager(APITokenManager):
|
|
93
104
|
"""API Token Manager for Azure Managed Identity
|
|
94
105
|
|
|
95
106
|
:param token_scope: Token scope for Azure endpoint
|
|
96
|
-
:type token_scope: ~azure.ai.evaluation.
|
|
107
|
+
:type token_scope: ~azure.ai.evaluation._constants.TokenScope
|
|
97
108
|
:param logger: Logger object
|
|
98
109
|
:type logger: logging.Logger
|
|
99
110
|
:keyword kwargs: Additional keyword arguments
|
|
100
111
|
:paramtype kwargs: Dict
|
|
101
112
|
"""
|
|
102
113
|
|
|
103
|
-
def __init__(
|
|
104
|
-
|
|
114
|
+
def __init__(
|
|
115
|
+
self,
|
|
116
|
+
token_scope: TokenScope,
|
|
117
|
+
logger: logging.Logger,
|
|
118
|
+
*,
|
|
119
|
+
auth_header: str = "Bearer",
|
|
120
|
+
credential: Optional[TokenCredential] = None,
|
|
121
|
+
):
|
|
122
|
+
super().__init__(logger, auth_header=auth_header, credential=credential)
|
|
105
123
|
self.token_scope = token_scope
|
|
106
124
|
|
|
107
|
-
|
|
108
|
-
def get_token(self) -> str: # pylint: disable=invalid-overridden-method
|
|
125
|
+
def get_token(self) -> str:
|
|
109
126
|
"""Get the API token. If the token is not available or has expired, refresh the token.
|
|
110
127
|
|
|
111
128
|
:return: API token
|
|
@@ -122,6 +139,32 @@ class ManagedIdentityAPITokenManager(APITokenManager):
|
|
|
122
139
|
|
|
123
140
|
return self.token
|
|
124
141
|
|
|
142
|
+
async def get_token_async(self) -> str:
|
|
143
|
+
"""Get the API token synchronously. If the token is not available or has expired, refresh it.
|
|
144
|
+
|
|
145
|
+
:return: API token
|
|
146
|
+
:rtype: str
|
|
147
|
+
"""
|
|
148
|
+
if (
|
|
149
|
+
self.token is None
|
|
150
|
+
or self.last_refresh_time is None
|
|
151
|
+
or time.time() - self.last_refresh_time > AZURE_TOKEN_REFRESH_INTERVAL
|
|
152
|
+
):
|
|
153
|
+
self.last_refresh_time = time.time()
|
|
154
|
+
get_token_method = self.credential.get_token(self.token_scope.value)
|
|
155
|
+
|
|
156
|
+
if inspect.isawaitable(get_token_method):
|
|
157
|
+
# If it's awaitable, await it
|
|
158
|
+
token_response: AccessToken = await get_token_method
|
|
159
|
+
else:
|
|
160
|
+
# Otherwise, call it synchronously
|
|
161
|
+
token_response = get_token_method
|
|
162
|
+
|
|
163
|
+
self.token = token_response.token
|
|
164
|
+
self.logger.info("Refreshed Azure endpoint token.")
|
|
165
|
+
|
|
166
|
+
return self.token
|
|
167
|
+
|
|
125
168
|
|
|
126
169
|
class PlainTokenManager(APITokenManager):
|
|
127
170
|
"""Plain API Token Manager
|
|
@@ -134,11 +177,18 @@ class PlainTokenManager(APITokenManager):
|
|
|
134
177
|
:paramtype kwargs: Dict
|
|
135
178
|
"""
|
|
136
179
|
|
|
137
|
-
def __init__(
|
|
138
|
-
|
|
139
|
-
|
|
180
|
+
def __init__(
|
|
181
|
+
self,
|
|
182
|
+
openapi_key: str,
|
|
183
|
+
logger: logging.Logger,
|
|
184
|
+
*,
|
|
185
|
+
auth_header: str = "Bearer",
|
|
186
|
+
credential: Optional[TokenCredential] = None,
|
|
187
|
+
) -> None:
|
|
188
|
+
super().__init__(logger, auth_header=auth_header, credential=credential)
|
|
189
|
+
self.token: str = openapi_key
|
|
140
190
|
|
|
141
|
-
|
|
191
|
+
def get_token(self) -> str:
|
|
142
192
|
"""Get the API token
|
|
143
193
|
|
|
144
194
|
:return: API token
|
|
@@ -6,13 +6,17 @@ import copy
|
|
|
6
6
|
import json
|
|
7
7
|
import time
|
|
8
8
|
import uuid
|
|
9
|
-
from typing import Dict, List
|
|
9
|
+
from typing import Any, Dict, List, Optional, cast, Union
|
|
10
10
|
|
|
11
11
|
from azure.ai.evaluation._http_utils import AsyncHttpPipeline, get_async_http_client
|
|
12
|
-
from azure.ai.evaluation._user_agent import
|
|
13
|
-
from azure.core.exceptions import HttpResponseError
|
|
12
|
+
from azure.ai.evaluation._user_agent import UserAgentSingleton
|
|
13
|
+
from azure.core.exceptions import HttpResponseError, ServiceResponseError
|
|
14
14
|
from azure.core.pipeline.policies import AsyncRetryPolicy, RetryMode
|
|
15
|
+
from azure.ai.evaluation._common.onedp._client import ProjectsClient as AIProjectClient
|
|
16
|
+
from azure.ai.evaluation._common.onedp.models import SimulationDTO
|
|
17
|
+
from azure.ai.evaluation._common.constants import RAIService
|
|
15
18
|
|
|
19
|
+
from .._model_tools._template_handler import TemplateParameters
|
|
16
20
|
from .models import OpenAIChatCompletionsModel
|
|
17
21
|
|
|
18
22
|
|
|
@@ -33,13 +37,21 @@ class SimulationRequestDTO:
|
|
|
33
37
|
:type template_parameters: Dict
|
|
34
38
|
"""
|
|
35
39
|
|
|
36
|
-
def __init__(
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
url: str,
|
|
43
|
+
headers: Dict[str, str],
|
|
44
|
+
payload: Dict[str, Any],
|
|
45
|
+
params: Dict[str, str],
|
|
46
|
+
templateKey: str,
|
|
47
|
+
templateParameters: Optional[TemplateParameters],
|
|
48
|
+
):
|
|
37
49
|
self.url = url
|
|
38
50
|
self.headers = headers
|
|
39
51
|
self.json = json.dumps(payload)
|
|
40
52
|
self.params = params
|
|
41
|
-
self.
|
|
42
|
-
self.templateParameters =
|
|
53
|
+
self.templateKey = templateKey
|
|
54
|
+
self.templateParameters = templateParameters
|
|
43
55
|
|
|
44
56
|
def to_dict(self) -> Dict:
|
|
45
57
|
"""Convert the DTO to a dictionary.
|
|
@@ -47,9 +59,12 @@ class SimulationRequestDTO:
|
|
|
47
59
|
:return: The DTO as a dictionary.
|
|
48
60
|
:rtype: Dict
|
|
49
61
|
"""
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
62
|
+
toReturn = self.__dict__.copy()
|
|
63
|
+
|
|
64
|
+
if toReturn["templateParameters"] is not None:
|
|
65
|
+
toReturn["templateParameters"] = {str(k): str(v) for k, v in toReturn["templateParameters"].items()}
|
|
66
|
+
|
|
67
|
+
return toReturn
|
|
53
68
|
|
|
54
69
|
def to_json(self):
|
|
55
70
|
"""Convert the DTO to a JSON string.
|
|
@@ -73,12 +88,13 @@ class ProxyChatCompletionsModel(OpenAIChatCompletionsModel):
|
|
|
73
88
|
:keyword kwargs: Additional keyword arguments to pass to the parent class.
|
|
74
89
|
"""
|
|
75
90
|
|
|
76
|
-
def __init__(self, name: str, template_key: str, template_parameters
|
|
91
|
+
def __init__(self, name: str, template_key: str, template_parameters: TemplateParameters, **kwargs) -> None:
|
|
77
92
|
self.tkey = template_key
|
|
78
93
|
self.tparam = template_parameters
|
|
79
|
-
self.result_url = None
|
|
94
|
+
self.result_url: Optional[str] = None
|
|
95
|
+
self.simulation_id: Optional[str] = kwargs.pop("simulation_id", "")
|
|
80
96
|
|
|
81
|
-
super().__init__(name=name,
|
|
97
|
+
super().__init__(name=name, **kwargs)
|
|
82
98
|
|
|
83
99
|
def format_request_data(self, messages: List[Dict], **request_params) -> Dict: # type: ignore[override]
|
|
84
100
|
"""Format the request data to query the model with.
|
|
@@ -98,7 +114,7 @@ class ProxyChatCompletionsModel(OpenAIChatCompletionsModel):
|
|
|
98
114
|
async def get_conversation_completion(
|
|
99
115
|
self,
|
|
100
116
|
messages: List[Dict],
|
|
101
|
-
session: AsyncHttpPipeline,
|
|
117
|
+
session: Union[AsyncHttpPipeline, AIProjectClient],
|
|
102
118
|
role: str = "assistant", # pylint: disable=unused-argument
|
|
103
119
|
**request_params,
|
|
104
120
|
) -> dict:
|
|
@@ -129,7 +145,7 @@ class ProxyChatCompletionsModel(OpenAIChatCompletionsModel):
|
|
|
129
145
|
|
|
130
146
|
async def request_api(
|
|
131
147
|
self,
|
|
132
|
-
session: AsyncHttpPipeline,
|
|
148
|
+
session: Union[AsyncHttpPipeline, AIProjectClient],
|
|
133
149
|
request_data: dict,
|
|
134
150
|
) -> dict:
|
|
135
151
|
"""
|
|
@@ -150,17 +166,17 @@ class ProxyChatCompletionsModel(OpenAIChatCompletionsModel):
|
|
|
150
166
|
proxy_headers = {
|
|
151
167
|
"Authorization": f"Bearer {token}",
|
|
152
168
|
"Content-Type": "application/json",
|
|
153
|
-
"User-Agent":
|
|
169
|
+
"User-Agent": UserAgentSingleton().value,
|
|
154
170
|
}
|
|
155
171
|
|
|
156
172
|
headers = {
|
|
157
173
|
"Content-Type": "application/json",
|
|
158
174
|
"X-CV": f"{uuid.uuid4()}",
|
|
159
175
|
"X-ModelType": self.model or "",
|
|
176
|
+
"x-ms-client-request-id": self.simulation_id,
|
|
160
177
|
}
|
|
161
178
|
# add all additional headers
|
|
162
179
|
headers.update(self.additional_headers) # type: ignore[arg-type]
|
|
163
|
-
|
|
164
180
|
params = {}
|
|
165
181
|
if self.api_version:
|
|
166
182
|
params["api-version"] = self.api_version
|
|
@@ -170,45 +186,101 @@ class ProxyChatCompletionsModel(OpenAIChatCompletionsModel):
|
|
|
170
186
|
headers=headers,
|
|
171
187
|
payload=request_data,
|
|
172
188
|
params=params,
|
|
173
|
-
|
|
174
|
-
|
|
189
|
+
templateKey=self.tkey,
|
|
190
|
+
templateParameters=self.tparam,
|
|
175
191
|
)
|
|
176
192
|
|
|
177
193
|
time_start = time.time()
|
|
178
194
|
full_response = None
|
|
179
195
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
196
|
+
if isinstance(session, AIProjectClient):
|
|
197
|
+
sim_request_dto = SimulationDTO(
|
|
198
|
+
headers=headers,
|
|
199
|
+
params=params,
|
|
200
|
+
json=json.dumps(request_data),
|
|
201
|
+
template_key=self.tkey,
|
|
202
|
+
template_parameters=self.tparam,
|
|
203
|
+
)
|
|
204
|
+
response_data = session.red_teams.submit_simulation(sim_request_dto, headers=headers, params=params)
|
|
205
|
+
operation_id = response_data["location"].split("/")[-1]
|
|
206
|
+
|
|
207
|
+
request_count = 0
|
|
208
|
+
flag = True
|
|
209
|
+
while flag:
|
|
210
|
+
try:
|
|
211
|
+
response = session.red_teams.operation_results(operation_id, headers=headers)
|
|
212
|
+
except Exception as e:
|
|
213
|
+
from types import SimpleNamespace # pylint: disable=forgotten-debug-statement
|
|
214
|
+
|
|
215
|
+
response = SimpleNamespace(status_code=202, text=str(e), json=lambda: {"error": str(e)})
|
|
216
|
+
if isinstance(response, dict):
|
|
217
|
+
response_data = response
|
|
218
|
+
flag = False
|
|
219
|
+
break
|
|
220
|
+
if not isinstance(response, SimpleNamespace) and response.get("object") == "chat.completion":
|
|
221
|
+
response_data = response
|
|
222
|
+
flag = False
|
|
223
|
+
break
|
|
224
|
+
else:
|
|
225
|
+
request_count += 1
|
|
226
|
+
sleep_time = RAIService.SLEEP_TIME**request_count
|
|
227
|
+
await asyncio.sleep(sleep_time)
|
|
228
|
+
else:
|
|
229
|
+
# Retry policy for POST request to RAI service
|
|
230
|
+
service_call_retry_policy = AsyncRetryPolicy(
|
|
231
|
+
retry_on_exceptions=[ServiceResponseError],
|
|
232
|
+
retry_total=7,
|
|
233
|
+
retry_backoff_factor=10.0,
|
|
234
|
+
retry_backoff_max=180,
|
|
235
|
+
retry_mode=RetryMode.Exponential,
|
|
185
236
|
)
|
|
186
237
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
238
|
+
response = None
|
|
239
|
+
async with get_async_http_client().with_policies(retry_policy=service_call_retry_policy) as retry_client:
|
|
240
|
+
try:
|
|
241
|
+
response = await retry_client.post(
|
|
242
|
+
url=self.endpoint_url, headers=proxy_headers, json=sim_request_dto.to_dict()
|
|
243
|
+
)
|
|
244
|
+
except ServiceResponseError as e:
|
|
245
|
+
self.logger.error("ServiceResponseError during POST request to rai svc after retries: %s", str(e))
|
|
246
|
+
raise
|
|
247
|
+
|
|
248
|
+
# response.raise_for_status()
|
|
249
|
+
if response.status_code != 202:
|
|
250
|
+
raise HttpResponseError(
|
|
251
|
+
message=f"Received unexpected HTTP status: {response.status_code} {response.text()}",
|
|
252
|
+
response=response,
|
|
253
|
+
)
|
|
254
|
+
response_data = response.json()
|
|
255
|
+
|
|
256
|
+
self.result_url = cast(str, response_data["location"])
|
|
257
|
+
retry_policy = AsyncRetryPolicy( # set up retry configuration
|
|
258
|
+
retry_on_status_codes=[202], # on which statuses to retry
|
|
259
|
+
retry_total=7,
|
|
260
|
+
retry_backoff_factor=10.0,
|
|
261
|
+
retry_backoff_max=180,
|
|
262
|
+
retry_mode=RetryMode.Exponential,
|
|
207
263
|
)
|
|
208
264
|
|
|
209
|
-
|
|
265
|
+
# initial 15 seconds wait before attempting to fetch result
|
|
266
|
+
# Need to wait both in this thread and in the async thread for some reason?
|
|
267
|
+
# Someone not under a crunch and with better async understandings should dig into this more.
|
|
268
|
+
await asyncio.sleep(15)
|
|
269
|
+
time.sleep(15)
|
|
270
|
+
|
|
271
|
+
async with get_async_http_client().with_policies(retry_policy=retry_policy) as exp_retry_client:
|
|
272
|
+
token = await self.token_manager.get_token_async()
|
|
273
|
+
proxy_headers = {
|
|
274
|
+
"Authorization": f"Bearer {token}",
|
|
275
|
+
"Content-Type": "application/json",
|
|
276
|
+
"User-Agent": UserAgentSingleton().value,
|
|
277
|
+
}
|
|
278
|
+
response = await exp_retry_client.get( # pylint: disable=too-many-function-args,unexpected-keyword-arg
|
|
279
|
+
self.result_url, headers=proxy_headers
|
|
280
|
+
)
|
|
281
|
+
response.raise_for_status()
|
|
282
|
+
response_data = response.json()
|
|
210
283
|
|
|
211
|
-
response_data = response.json()
|
|
212
284
|
self.logger.info("Response: %s", response_data)
|
|
213
285
|
|
|
214
286
|
# Copy the full response and return it to be saved in jsonl.
|