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,80 @@
|
|
|
1
|
+
# ---------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# ---------------------------------------------------------
|
|
4
|
+
from typing import Any, Dict, Optional, Union
|
|
5
|
+
|
|
6
|
+
from openai.types.graders import TextSimilarityGrader
|
|
7
|
+
from typing_extensions import Literal
|
|
8
|
+
|
|
9
|
+
from azure.ai.evaluation._common._experimental import experimental
|
|
10
|
+
from azure.ai.evaluation._model_configurations import AzureOpenAIModelConfiguration, OpenAIModelConfiguration
|
|
11
|
+
from azure.core.credentials import TokenCredential
|
|
12
|
+
|
|
13
|
+
from .aoai_grader import AzureOpenAIGrader
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@experimental
|
|
17
|
+
class AzureOpenAITextSimilarityGrader(AzureOpenAIGrader):
|
|
18
|
+
"""Wrapper class for OpenAI's string check graders.
|
|
19
|
+
|
|
20
|
+
Supplying a StringCheckGrader to the `evaluate` method will cause an asynchronous request to evaluate
|
|
21
|
+
the grader via the OpenAI API. The results of the evaluation will then be merged into the standard
|
|
22
|
+
evaluation results.
|
|
23
|
+
|
|
24
|
+
:param model_config: The model configuration to use for the grader.
|
|
25
|
+
:type model_config: Union[
|
|
26
|
+
~azure.ai.evaluation.AzureOpenAIModelConfiguration,
|
|
27
|
+
~azure.ai.evaluation.OpenAIModelConfiguration]
|
|
28
|
+
:param evaluation_metric: The evaluation metric to use.
|
|
29
|
+
:type evaluation_metric: Literal["fuzzy_match", "bleu", "gleu", "meteor", "rouge_1", "rouge_2", "rouge_3",
|
|
30
|
+
"rouge_4", "rouge_5", "rouge_l", "cosine"]
|
|
31
|
+
:param input: The text being graded.
|
|
32
|
+
:type input: str
|
|
33
|
+
:param pass_threshold: A float score where a value greater than or equal indicates a passing grade.
|
|
34
|
+
:type pass_threshold: float
|
|
35
|
+
:param reference: The text being graded against.
|
|
36
|
+
:type reference: str
|
|
37
|
+
:param name: The name of the grader.
|
|
38
|
+
:type name: str
|
|
39
|
+
:param credential: The credential to use to authenticate to the model. Only applicable to AzureOpenAI models.
|
|
40
|
+
:type credential: ~azure.core.credentials.TokenCredential
|
|
41
|
+
:param kwargs: Additional keyword arguments to pass to the grader.
|
|
42
|
+
:type kwargs: Any
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
id = "azureai://built-in/evaluators/azure-openai/text_similarity_grader"
|
|
46
|
+
_type = "text_similarity"
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
*,
|
|
51
|
+
model_config: Union[AzureOpenAIModelConfiguration, OpenAIModelConfiguration],
|
|
52
|
+
evaluation_metric: Literal[
|
|
53
|
+
"fuzzy_match",
|
|
54
|
+
"bleu",
|
|
55
|
+
"gleu",
|
|
56
|
+
"meteor",
|
|
57
|
+
"rouge_1",
|
|
58
|
+
"rouge_2",
|
|
59
|
+
"rouge_3",
|
|
60
|
+
"rouge_4",
|
|
61
|
+
"rouge_5",
|
|
62
|
+
"rouge_l",
|
|
63
|
+
"cosine",
|
|
64
|
+
],
|
|
65
|
+
input: str,
|
|
66
|
+
pass_threshold: float,
|
|
67
|
+
reference: str,
|
|
68
|
+
name: str,
|
|
69
|
+
credential: Optional[TokenCredential] = None,
|
|
70
|
+
**kwargs: Any
|
|
71
|
+
):
|
|
72
|
+
grader = TextSimilarityGrader(
|
|
73
|
+
evaluation_metric=evaluation_metric,
|
|
74
|
+
input=input,
|
|
75
|
+
pass_threshold=pass_threshold,
|
|
76
|
+
name=name,
|
|
77
|
+
reference=reference,
|
|
78
|
+
type=AzureOpenAITextSimilarityGrader._type,
|
|
79
|
+
)
|
|
80
|
+
super().__init__(model_config=model_config, grader_config=grader, credential=credential, **kwargs)
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# ---------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# ---------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
from logging import Logger
|
|
6
|
+
from typing import Any, Dict, Final, Optional, Set, Union, cast
|
|
7
|
+
from threading import Lock
|
|
8
|
+
from urllib.parse import quote
|
|
9
|
+
from json.decoder import JSONDecodeError
|
|
10
|
+
|
|
11
|
+
from azure.core.credentials import TokenCredential, AzureSasCredential, AccessToken
|
|
12
|
+
from azure.core.rest import HttpResponse
|
|
13
|
+
from azure.ai.evaluation._exceptions import ErrorBlame, ErrorCategory, ErrorTarget, EvaluationException
|
|
14
|
+
from azure.ai.evaluation._http_utils import HttpPipeline, get_http_client
|
|
15
|
+
from azure.ai.evaluation._azure._token_manager import AzureMLTokenManager
|
|
16
|
+
from azure.ai.evaluation._constants import TokenScope
|
|
17
|
+
from ._models import BlobStoreInfo, Workspace
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
API_VERSION: Final[str] = "2024-07-01-preview"
|
|
21
|
+
QUERY_KEY_API_VERSION: Final[str] = "api-version"
|
|
22
|
+
PATH_ML_WORKSPACES = ("providers", "Microsoft.MachineLearningServices", "workspaces")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class LiteMLClient:
|
|
26
|
+
"""A lightweight Azure ML API client.
|
|
27
|
+
|
|
28
|
+
:param subscription_id: Azure subscription ID
|
|
29
|
+
:type subscription_id: str
|
|
30
|
+
:param resource_group: Azure resource group name
|
|
31
|
+
:type resource_group: str
|
|
32
|
+
:param logger: Logger object
|
|
33
|
+
:type logger: logging.Logger
|
|
34
|
+
:keyword credential: Azure credentials
|
|
35
|
+
:paramtype credential: TokenCredential
|
|
36
|
+
:keyword kwargs: Additional keyword arguments
|
|
37
|
+
:paramtype kwargs: Dict
|
|
38
|
+
:keyword str api_version: The API version. Default is 2024-10-01
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
subscription_id: str,
|
|
44
|
+
resource_group: str,
|
|
45
|
+
logger: Logger,
|
|
46
|
+
credential: Optional[TokenCredential] = None,
|
|
47
|
+
**kwargs: Any,
|
|
48
|
+
) -> None:
|
|
49
|
+
subscription_id = quote(subscription_id, safe="")
|
|
50
|
+
resource_group = quote(resource_group, safe="")
|
|
51
|
+
|
|
52
|
+
self._base_url: Final[str] = (
|
|
53
|
+
f"https://management.azure.com/subscriptions/{subscription_id}/resourceGroups/{resource_group}"
|
|
54
|
+
)
|
|
55
|
+
self._logger: Final[Logger] = logger
|
|
56
|
+
self._api_version: Final[str] = kwargs.get("api_version", API_VERSION)
|
|
57
|
+
self._http_client: Final[HttpPipeline] = get_http_client(**kwargs)
|
|
58
|
+
self._lock: Final[Lock] = Lock()
|
|
59
|
+
|
|
60
|
+
# things that can change under lock
|
|
61
|
+
self._token_manager: Optional[AzureMLTokenManager] = None
|
|
62
|
+
self._credential: Optional[TokenCredential] = credential
|
|
63
|
+
|
|
64
|
+
def get_token(self) -> AccessToken:
|
|
65
|
+
return self._get_token_manager().get_token()
|
|
66
|
+
|
|
67
|
+
def get_credential(self) -> TokenCredential:
|
|
68
|
+
# load the token manager to get the credential if needed
|
|
69
|
+
self._get_token_manager()
|
|
70
|
+
return cast(TokenCredential, self._credential)
|
|
71
|
+
|
|
72
|
+
def workspace_get_default_datastore(
|
|
73
|
+
self, workspace_name: str, *, include_credentials: bool = False, **kwargs: Any
|
|
74
|
+
) -> BlobStoreInfo:
|
|
75
|
+
# 1. Get the default blob store
|
|
76
|
+
# REST API documentation:
|
|
77
|
+
# https://learn.microsoft.com/rest/api/azureml/datastores/list?view=rest-azureml-2024-10-01
|
|
78
|
+
url = self._generate_path( # pylint: disable=specify-parameter-names-in-call
|
|
79
|
+
*PATH_ML_WORKSPACES, workspace_name, "datastores"
|
|
80
|
+
)
|
|
81
|
+
headers = self._get_headers()
|
|
82
|
+
|
|
83
|
+
stores_response = self._http_client.request(
|
|
84
|
+
method="GET",
|
|
85
|
+
url=url,
|
|
86
|
+
params={QUERY_KEY_API_VERSION: self._api_version, "isDefault": True, "count": 1, "orderByAsc": "false"},
|
|
87
|
+
headers=headers,
|
|
88
|
+
)
|
|
89
|
+
self._throw_on_http_error(stores_response, "list default workspace datastore")
|
|
90
|
+
|
|
91
|
+
json = stores_response.json()["value"][0]
|
|
92
|
+
props_json = json["properties"]
|
|
93
|
+
name = json["name"]
|
|
94
|
+
account_name = props_json["accountName"]
|
|
95
|
+
endpoint = props_json["endpoint"]
|
|
96
|
+
container_name = props_json["containerName"]
|
|
97
|
+
credential_type = props_json.get("credentials", {}).get("credentialsType")
|
|
98
|
+
|
|
99
|
+
# 2. Get the SAS token to use for accessing the blob store
|
|
100
|
+
# REST API documentation:
|
|
101
|
+
# https://learn.microsoft.com/rest/api/azureml/datastores/list-secrets?view=rest-azureml-2024-10-01
|
|
102
|
+
blob_store_credential: Optional[Union[AzureSasCredential, TokenCredential, str]]
|
|
103
|
+
if not include_credentials:
|
|
104
|
+
blob_store_credential = None
|
|
105
|
+
elif credential_type and credential_type.lower() == "none":
|
|
106
|
+
# If storage account key access is disabled, and only Microsoft Entra ID authentication is available,
|
|
107
|
+
# the credentialsType will be "None" and we should not attempt to get the secrets.
|
|
108
|
+
blob_store_credential = self.get_credential()
|
|
109
|
+
else:
|
|
110
|
+
url = self._generate_path(
|
|
111
|
+
*PATH_ML_WORKSPACES, workspace_name, "datastores", "workspaceblobstore", "listSecrets"
|
|
112
|
+
)
|
|
113
|
+
secrets_response = self._http_client.request(
|
|
114
|
+
method="POST",
|
|
115
|
+
url=url,
|
|
116
|
+
json={
|
|
117
|
+
"expirableSecret": True,
|
|
118
|
+
"expireAfterHours": int(kwargs.get("key_expiration_hours", 1)),
|
|
119
|
+
},
|
|
120
|
+
params={
|
|
121
|
+
QUERY_KEY_API_VERSION: self._api_version,
|
|
122
|
+
},
|
|
123
|
+
headers=headers,
|
|
124
|
+
)
|
|
125
|
+
self._throw_on_http_error(secrets_response, "workspace datastore secrets")
|
|
126
|
+
|
|
127
|
+
secrets_json = secrets_response.json()
|
|
128
|
+
secrets_type = secrets_json["secretsType"].lower()
|
|
129
|
+
|
|
130
|
+
# As per this website, only SAS tokens, access tokens, or Entra IDs are valid for accessing blob data
|
|
131
|
+
# stores:
|
|
132
|
+
# https://learn.microsoft.com/rest/api/storageservices/authorize-requests-to-azure-storage.
|
|
133
|
+
if secrets_type == "sas":
|
|
134
|
+
blob_store_credential = AzureSasCredential(secrets_json["sasToken"])
|
|
135
|
+
elif secrets_type == "accountkey":
|
|
136
|
+
# To support older versions of azure-storage-blob better, we return a string here instead of
|
|
137
|
+
# an AzureNamedKeyCredential
|
|
138
|
+
blob_store_credential = secrets_json["key"]
|
|
139
|
+
else:
|
|
140
|
+
raise EvaluationException(
|
|
141
|
+
message=f"The '{account_name}' blob store does not use a recognized credential type.",
|
|
142
|
+
internal_message=f"The credential type is '{secrets_type}'",
|
|
143
|
+
target=ErrorTarget.EVALUATE,
|
|
144
|
+
category=ErrorCategory.INVALID_VALUE,
|
|
145
|
+
blame=ErrorBlame.SYSTEM_ERROR,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
return BlobStoreInfo(name, account_name, endpoint, container_name, blob_store_credential)
|
|
149
|
+
|
|
150
|
+
def workspace_get_info(self, workspace_name: str) -> Workspace:
|
|
151
|
+
# https://learn.microsoft.com/rest/api/azureml/workspaces/get?view=rest-azureml-2024-10-01
|
|
152
|
+
workspace_response = self._http_client.request(
|
|
153
|
+
"GET",
|
|
154
|
+
self._generate_path(*PATH_ML_WORKSPACES, workspace_name),
|
|
155
|
+
params={QUERY_KEY_API_VERSION: self._api_version},
|
|
156
|
+
headers=self._get_headers(),
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
self._throw_on_http_error(workspace_response, f"get '{workspace_name}' workspace")
|
|
160
|
+
workspace = Workspace.deserialize(workspace_response)
|
|
161
|
+
return workspace
|
|
162
|
+
|
|
163
|
+
def _get_token_manager(self) -> AzureMLTokenManager:
|
|
164
|
+
# Lazy init since getting credentials in the constructor can take a long time in some situations
|
|
165
|
+
if self._token_manager is None:
|
|
166
|
+
with self._lock:
|
|
167
|
+
if self._token_manager is None:
|
|
168
|
+
self._token_manager = AzureMLTokenManager(
|
|
169
|
+
TokenScope.DEFAULT_AZURE_MANAGEMENT.value, self._logger, credential=self._credential
|
|
170
|
+
)
|
|
171
|
+
self._credential = self._token_manager.credential
|
|
172
|
+
|
|
173
|
+
return self._token_manager
|
|
174
|
+
|
|
175
|
+
@staticmethod
|
|
176
|
+
def _throw_on_http_error(response: HttpResponse, description: str, valid_status: Optional[Set[int]] = None) -> None:
|
|
177
|
+
if valid_status and (response.status_code in valid_status):
|
|
178
|
+
return
|
|
179
|
+
if response.status_code >= 200 and response.status_code < 300:
|
|
180
|
+
# nothing to see here, move along
|
|
181
|
+
return
|
|
182
|
+
|
|
183
|
+
message = f"The {description} request failed with HTTP {response.status_code}"
|
|
184
|
+
try:
|
|
185
|
+
error_json = response.json()["error"]
|
|
186
|
+
additional_info = f"({error_json['code']}) {error_json['message']}"
|
|
187
|
+
message += f" - {additional_info}"
|
|
188
|
+
except (JSONDecodeError, ValueError, KeyError):
|
|
189
|
+
pass
|
|
190
|
+
|
|
191
|
+
raise EvaluationException(
|
|
192
|
+
message=message,
|
|
193
|
+
target=ErrorTarget.EVALUATE,
|
|
194
|
+
category=ErrorCategory.FAILED_EXECUTION,
|
|
195
|
+
blame=ErrorBlame.SYSTEM_ERROR,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
def _generate_path(self, *paths: str) -> str:
|
|
199
|
+
sanitized_paths = [quote(path, safe="") for path in paths]
|
|
200
|
+
url = self._base_url + "/" + str.join("/", sanitized_paths)
|
|
201
|
+
return url
|
|
202
|
+
|
|
203
|
+
def _get_headers(self) -> Dict[str, str]:
|
|
204
|
+
return {"Authorization": f"Bearer {self.get_token().token}", "Content-Type": "application/json"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# ---------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# ---------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
# NOTE:
|
|
6
|
+
# This is a simplified version of the original code from azure-ai-ml:
|
|
7
|
+
# sdk\ml\azure-ai-ml\azure\ai\ml\_azure_environments.py
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from typing import Any, Dict, Final, Mapping, Optional, Sequence, TypedDict
|
|
13
|
+
|
|
14
|
+
from azure.core import AsyncPipelineClient
|
|
15
|
+
from azure.core.configuration import Configuration
|
|
16
|
+
from azure.core.rest import HttpRequest
|
|
17
|
+
from azure.core.pipeline.policies import ProxyPolicy, AsyncRetryPolicy
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AzureEnvironmentMetadata(TypedDict):
|
|
21
|
+
"""Configuration for various Azure environments. All endpoints include a trailing slash."""
|
|
22
|
+
|
|
23
|
+
portal_endpoint: str
|
|
24
|
+
"""The management portal for the Azure environment (e.g. https://portal.azure.com/)"""
|
|
25
|
+
resource_manager_endpoint: str
|
|
26
|
+
"""The API endpoint for Azure control plan (e.g. https://management.azure.com/)"""
|
|
27
|
+
active_directory_endpoint: str
|
|
28
|
+
"""The active directory endpoint used for authentication (e.g. https://login.microsoftonline.com/)"""
|
|
29
|
+
aml_resource_endpoint: str
|
|
30
|
+
"""The endpoint for Azure Machine Learning resources (e.g. https://ml.azure.com/)"""
|
|
31
|
+
storage_suffix: str
|
|
32
|
+
"""The suffix to use for storage endpoint URLs (e.g. core.windows.net)"""
|
|
33
|
+
registry_discovery_endpoint: str
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
_ENV_ARM_CLOUD_METADATA_URL: Final[str] = "ARM_CLOUD_METADATA_URL"
|
|
37
|
+
_ENV_DEFAULT_CLOUD_NAME: Final[str] = "AZUREML_CURRENT_CLOUD"
|
|
38
|
+
_ENV_REGISTRY_DISCOVERY_URL: Final[str] = "REGISTRY_DISCOVERY_ENDPOINT_URL"
|
|
39
|
+
_ENV_REGISTRY_DISCOVERY_REGION: Final[str] = "REGISTRY_DISCOVERY_ENDPOINT_REGION"
|
|
40
|
+
_DEFAULT_REGISTRY_DISCOVERY_REGION: Final[str] = "west"
|
|
41
|
+
_DEFAULT_AZURE_ENV_NAME: Final[str] = "AzureCloud"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
_ASYNC_LOCK = asyncio.Lock()
|
|
45
|
+
_KNOWN_AZURE_ENVIRONMENTS: Dict[str, AzureEnvironmentMetadata] = {
|
|
46
|
+
_DEFAULT_AZURE_ENV_NAME: {
|
|
47
|
+
"portal_endpoint": "https://portal.azure.com/",
|
|
48
|
+
"resource_manager_endpoint": "https://management.azure.com/",
|
|
49
|
+
"active_directory_endpoint": "https://login.microsoftonline.com/",
|
|
50
|
+
"aml_resource_endpoint": "https://ml.azure.com/",
|
|
51
|
+
"storage_suffix": "core.windows.net",
|
|
52
|
+
"registry_discovery_endpoint": "https://eastus.api.azureml.ms/",
|
|
53
|
+
},
|
|
54
|
+
"AzureChinaCloud": {
|
|
55
|
+
"portal_endpoint": "https://portal.azure.cn/",
|
|
56
|
+
"resource_manager_endpoint": "https://management.chinacloudapi.cn/",
|
|
57
|
+
"active_directory_endpoint": "https://login.chinacloudapi.cn/",
|
|
58
|
+
"aml_resource_endpoint": "https://ml.azure.cn/",
|
|
59
|
+
"storage_suffix": "core.chinacloudapi.cn",
|
|
60
|
+
"registry_discovery_endpoint": "https://chinaeast2.api.ml.azure.cn/",
|
|
61
|
+
},
|
|
62
|
+
"AzureUSGovernment": {
|
|
63
|
+
"portal_endpoint": "https://portal.azure.us/",
|
|
64
|
+
"resource_manager_endpoint": "https://management.usgovcloudapi.net/",
|
|
65
|
+
"active_directory_endpoint": "https://login.microsoftonline.us/",
|
|
66
|
+
"aml_resource_endpoint": "https://ml.azure.us/",
|
|
67
|
+
"storage_suffix": "core.usgovcloudapi.net",
|
|
68
|
+
"registry_discovery_endpoint": "https://usgovarizona.api.ml.azure.us/",
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class AzureEnvironmentClient:
|
|
74
|
+
DEFAULT_API_VERSION: Final[str] = "2019-05-01"
|
|
75
|
+
DEFAULT_AZURE_CLOUD_NAME: Final[str] = _DEFAULT_AZURE_ENV_NAME
|
|
76
|
+
|
|
77
|
+
def __init__(self, *, base_url: Optional[str] = None, **kwargs: Any) -> None:
|
|
78
|
+
base_url = base_url if base_url is not None else AzureEnvironmentClient.get_default_metadata_url()
|
|
79
|
+
|
|
80
|
+
config: Configuration = kwargs.pop("config", Configuration(**kwargs))
|
|
81
|
+
if config.retry_policy is None:
|
|
82
|
+
config.retry_policy = AsyncRetryPolicy(**kwargs)
|
|
83
|
+
if config.proxy_policy is None and "proxy" in kwargs:
|
|
84
|
+
config.proxy_policy = ProxyPolicy(proxies={"http": kwargs["proxy"], "https": kwargs["proxy"]})
|
|
85
|
+
|
|
86
|
+
self._async_client = AsyncPipelineClient(base_url, config=config, **kwargs)
|
|
87
|
+
|
|
88
|
+
async def get_default_cloud_name_async(self, *, update_cached: bool = True) -> str:
|
|
89
|
+
current_cloud_env = os.getenv(_ENV_DEFAULT_CLOUD_NAME)
|
|
90
|
+
if current_cloud_env is not None:
|
|
91
|
+
return current_cloud_env
|
|
92
|
+
|
|
93
|
+
arm_metadata_url = os.getenv(_ENV_ARM_CLOUD_METADATA_URL)
|
|
94
|
+
if arm_metadata_url is None:
|
|
95
|
+
return _DEFAULT_AZURE_ENV_NAME
|
|
96
|
+
|
|
97
|
+
# load clouds from metadata url
|
|
98
|
+
clouds = await self.get_clouds_async(metadata_url=arm_metadata_url, update_cached=update_cached)
|
|
99
|
+
matched = next(filter(lambda t: t[1]["resource_manager_endpoint"] in arm_metadata_url, clouds.items()), None)
|
|
100
|
+
if matched is None:
|
|
101
|
+
return _DEFAULT_AZURE_ENV_NAME
|
|
102
|
+
|
|
103
|
+
os.environ[_ENV_DEFAULT_CLOUD_NAME] = matched[0]
|
|
104
|
+
return matched[0]
|
|
105
|
+
|
|
106
|
+
async def get_cloud_async(self, name: str, *, update_cached: bool = True) -> Optional[AzureEnvironmentMetadata]:
|
|
107
|
+
default_endpoint: Optional[str]
|
|
108
|
+
|
|
109
|
+
def case_insensitive_match(d: Mapping[str, Any], key: str) -> Optional[Any]:
|
|
110
|
+
key = key.strip().lower()
|
|
111
|
+
return next((v for k, v in d.items() if k.strip().lower() == key), None)
|
|
112
|
+
|
|
113
|
+
async with _ASYNC_LOCK:
|
|
114
|
+
cloud = _KNOWN_AZURE_ENVIRONMENTS.get(name) or case_insensitive_match(_KNOWN_AZURE_ENVIRONMENTS, name)
|
|
115
|
+
if cloud:
|
|
116
|
+
return cloud
|
|
117
|
+
default_endpoint = _KNOWN_AZURE_ENVIRONMENTS.get(_DEFAULT_AZURE_ENV_NAME, {}).get(
|
|
118
|
+
"resource_manager_endpoint"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
metadata_url = self.get_default_metadata_url(default_endpoint)
|
|
122
|
+
clouds = await self.get_clouds_async(metadata_url=metadata_url, update_cached=update_cached)
|
|
123
|
+
cloud_metadata = clouds.get(name) or case_insensitive_match(clouds, name)
|
|
124
|
+
|
|
125
|
+
return cloud_metadata
|
|
126
|
+
|
|
127
|
+
async def get_clouds_async(
|
|
128
|
+
self, *, metadata_url: Optional[str] = None, update_cached: bool = True
|
|
129
|
+
) -> Mapping[str, AzureEnvironmentMetadata]:
|
|
130
|
+
metadata_url = metadata_url or self.get_default_metadata_url()
|
|
131
|
+
|
|
132
|
+
clouds: Mapping[str, AzureEnvironmentMetadata]
|
|
133
|
+
async with self._async_client.send_request(HttpRequest("GET", metadata_url)) as response: # type: ignore
|
|
134
|
+
response.raise_for_status()
|
|
135
|
+
clouds = await self._parse_cloud_endpoints_async(response.json())
|
|
136
|
+
|
|
137
|
+
if update_cached:
|
|
138
|
+
async with _ASYNC_LOCK:
|
|
139
|
+
recursive_update(_KNOWN_AZURE_ENVIRONMENTS, clouds)
|
|
140
|
+
return clouds
|
|
141
|
+
|
|
142
|
+
async def close(self) -> None:
|
|
143
|
+
await self._async_client.close()
|
|
144
|
+
|
|
145
|
+
@staticmethod
|
|
146
|
+
def get_default_metadata_url(default_endpoint: Optional[str] = None) -> str:
|
|
147
|
+
default_endpoint = default_endpoint or "https://management.azure.com/"
|
|
148
|
+
metadata_url = os.getenv(
|
|
149
|
+
_ENV_ARM_CLOUD_METADATA_URL,
|
|
150
|
+
f"{default_endpoint}metadata/endpoints?api-version={AzureEnvironmentClient.DEFAULT_API_VERSION}",
|
|
151
|
+
)
|
|
152
|
+
return metadata_url
|
|
153
|
+
|
|
154
|
+
@staticmethod
|
|
155
|
+
async def _get_registry_discovery_url_async(cloud_name: str, cloud_suffix: str) -> str:
|
|
156
|
+
async with _ASYNC_LOCK:
|
|
157
|
+
discovery_url = _KNOWN_AZURE_ENVIRONMENTS.get(cloud_name, {}).get("registry_discovery_endpoint")
|
|
158
|
+
if discovery_url:
|
|
159
|
+
return discovery_url
|
|
160
|
+
|
|
161
|
+
discovery_url = os.getenv(_ENV_REGISTRY_DISCOVERY_URL)
|
|
162
|
+
if discovery_url is not None:
|
|
163
|
+
return discovery_url
|
|
164
|
+
|
|
165
|
+
region = os.getenv(_ENV_REGISTRY_DISCOVERY_REGION, _DEFAULT_REGISTRY_DISCOVERY_REGION)
|
|
166
|
+
return f"https://{cloud_name.lower()}{region}.api.ml.azure.{cloud_suffix}/"
|
|
167
|
+
|
|
168
|
+
@staticmethod
|
|
169
|
+
async def _parse_cloud_endpoints_async(data: Any) -> Mapping[str, AzureEnvironmentMetadata]:
|
|
170
|
+
# If there is only one cloud, you will get a dict, otherwise a list of dicts
|
|
171
|
+
cloud_data: Sequence[Mapping[str, Any]] = data if not isinstance(data, dict) else [data]
|
|
172
|
+
clouds: Dict[str, AzureEnvironmentMetadata] = {}
|
|
173
|
+
|
|
174
|
+
def append_trailing_slash(url: str) -> str:
|
|
175
|
+
return url if url.endswith("/") else f"{url}/"
|
|
176
|
+
|
|
177
|
+
for cloud in cloud_data:
|
|
178
|
+
try:
|
|
179
|
+
name: str = cloud["name"]
|
|
180
|
+
portal_endpoint: str = cloud["portal"]
|
|
181
|
+
cloud_suffix = ".".join(portal_endpoint.split(".")[2:]).replace("/", "")
|
|
182
|
+
discovery_url = await AzureEnvironmentClient._get_registry_discovery_url_async(name, cloud_suffix)
|
|
183
|
+
clouds[name] = {
|
|
184
|
+
"portal_endpoint": append_trailing_slash(portal_endpoint),
|
|
185
|
+
"resource_manager_endpoint": append_trailing_slash(cloud["resourceManager"]),
|
|
186
|
+
"active_directory_endpoint": append_trailing_slash(cloud["authentication"]["loginEndpoint"]),
|
|
187
|
+
"aml_resource_endpoint": append_trailing_slash(f"https://ml.azure.{cloud_suffix}/"),
|
|
188
|
+
"storage_suffix": cloud["suffixes"]["storage"],
|
|
189
|
+
"registry_discovery_endpoint": append_trailing_slash(discovery_url),
|
|
190
|
+
}
|
|
191
|
+
except KeyError:
|
|
192
|
+
continue
|
|
193
|
+
|
|
194
|
+
return clouds
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def recursive_update(d: Dict, u: Mapping) -> None:
|
|
198
|
+
"""Recursively update a dictionary.
|
|
199
|
+
|
|
200
|
+
:param Dict d: The dictionary to update.
|
|
201
|
+
:param Mapping u: The mapping to update from.
|
|
202
|
+
"""
|
|
203
|
+
for k, v in u.items():
|
|
204
|
+
if isinstance(v, Dict) and k in d:
|
|
205
|
+
recursive_update(d[k], v)
|
|
206
|
+
else:
|
|
207
|
+
d[k] = v
|