azure-ai-evaluation 1.0.0b3__py3-none-any.whl → 1.0.0b4__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.

Files changed (64) hide show
  1. azure/ai/evaluation/__init__.py +1 -1
  2. azure/ai/evaluation/_common/constants.py +4 -2
  3. azure/ai/evaluation/_common/math.py +18 -0
  4. azure/ai/evaluation/_common/rai_service.py +54 -62
  5. azure/ai/evaluation/_common/utils.py +182 -12
  6. azure/ai/evaluation/_constants.py +10 -2
  7. azure/ai/evaluation/_evaluate/_batch_run_client/batch_run_context.py +10 -3
  8. azure/ai/evaluation/_evaluate/_batch_run_client/code_client.py +33 -17
  9. azure/ai/evaluation/_evaluate/_batch_run_client/proxy_client.py +17 -2
  10. azure/ai/evaluation/_evaluate/_eval_run.py +26 -10
  11. azure/ai/evaluation/_evaluate/_evaluate.py +116 -62
  12. azure/ai/evaluation/_evaluate/_telemetry/__init__.py +16 -17
  13. azure/ai/evaluation/_evaluate/_utils.py +44 -25
  14. azure/ai/evaluation/_evaluators/_coherence/_coherence.py +3 -2
  15. azure/ai/evaluation/_evaluators/_common/_base_eval.py +59 -30
  16. azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py +10 -13
  17. azure/ai/evaluation/_evaluators/_common/_base_rai_svc_eval.py +18 -20
  18. azure/ai/evaluation/_evaluators/_content_safety/_content_safety.py +15 -20
  19. azure/ai/evaluation/_evaluators/_content_safety/_content_safety_chat.py +63 -42
  20. azure/ai/evaluation/_evaluators/_content_safety/_hate_unfairness.py +4 -4
  21. azure/ai/evaluation/_evaluators/_content_safety/_self_harm.py +4 -4
  22. azure/ai/evaluation/_evaluators/_content_safety/_sexual.py +4 -4
  23. azure/ai/evaluation/_evaluators/_content_safety/_violence.py +4 -4
  24. azure/ai/evaluation/_evaluators/_eci/_eci.py +4 -4
  25. azure/ai/evaluation/_evaluators/_f1_score/_f1_score.py +14 -6
  26. azure/ai/evaluation/_evaluators/_fluency/_fluency.py +3 -2
  27. azure/ai/evaluation/_evaluators/_groundedness/_groundedness.py +3 -2
  28. azure/ai/evaluation/_evaluators/_protected_material/_protected_material.py +4 -4
  29. azure/ai/evaluation/_evaluators/_qa/_qa.py +4 -3
  30. azure/ai/evaluation/_evaluators/_relevance/_relevance.py +3 -2
  31. azure/ai/evaluation/_evaluators/_retrieval/_retrieval.py +11 -8
  32. azure/ai/evaluation/_evaluators/_rouge/_rouge.py +1 -1
  33. azure/ai/evaluation/_evaluators/_similarity/_similarity.py +21 -7
  34. azure/ai/evaluation/_evaluators/_xpia/xpia.py +4 -5
  35. azure/ai/evaluation/_exceptions.py +9 -6
  36. azure/ai/evaluation/_http_utils.py +203 -132
  37. azure/ai/evaluation/_model_configurations.py +5 -5
  38. azure/ai/evaluation/_vendor/__init__.py +3 -0
  39. azure/ai/evaluation/_vendor/rouge_score/__init__.py +14 -0
  40. azure/ai/evaluation/_vendor/rouge_score/rouge_scorer.py +328 -0
  41. azure/ai/evaluation/_vendor/rouge_score/scoring.py +63 -0
  42. azure/ai/evaluation/_vendor/rouge_score/tokenize.py +63 -0
  43. azure/ai/evaluation/_vendor/rouge_score/tokenizers.py +53 -0
  44. azure/ai/evaluation/_version.py +1 -1
  45. azure/ai/evaluation/simulator/_adversarial_simulator.py +85 -60
  46. azure/ai/evaluation/simulator/_conversation/__init__.py +13 -12
  47. azure/ai/evaluation/simulator/_conversation/_conversation.py +4 -4
  48. azure/ai/evaluation/simulator/_direct_attack_simulator.py +24 -66
  49. azure/ai/evaluation/simulator/_helpers/_experimental.py +20 -9
  50. azure/ai/evaluation/simulator/_helpers/_simulator_data_classes.py +4 -4
  51. azure/ai/evaluation/simulator/_indirect_attack_simulator.py +22 -64
  52. azure/ai/evaluation/simulator/_model_tools/_identity_manager.py +67 -21
  53. azure/ai/evaluation/simulator/_model_tools/_proxy_completion_model.py +28 -11
  54. azure/ai/evaluation/simulator/_model_tools/_template_handler.py +68 -24
  55. azure/ai/evaluation/simulator/_model_tools/models.py +10 -10
  56. azure/ai/evaluation/simulator/_prompty/task_query_response.prompty +0 -5
  57. azure/ai/evaluation/simulator/_prompty/task_simulate.prompty +0 -4
  58. azure/ai/evaluation/simulator/_simulator.py +112 -113
  59. azure/ai/evaluation/simulator/_tracing.py +4 -4
  60. {azure_ai_evaluation-1.0.0b3.dist-info → azure_ai_evaluation-1.0.0b4.dist-info}/METADATA +72 -44
  61. azure_ai_evaluation-1.0.0b4.dist-info/NOTICE.txt +50 -0
  62. {azure_ai_evaluation-1.0.0b3.dist-info → azure_ai_evaluation-1.0.0b4.dist-info}/RECORD +64 -56
  63. {azure_ai_evaluation-1.0.0b3.dist-info → azure_ai_evaluation-1.0.0b4.dist-info}/WHEEL +0 -0
  64. {azure_ai_evaluation-1.0.0b3.dist-info → azure_ai_evaluation-1.0.0b4.dist-info}/top_level.txt +0 -0
@@ -2,32 +2,27 @@
2
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  # ---------------------------------------------------------
4
4
  from concurrent.futures import as_completed
5
+ from typing import Callable, Dict, List, Union
5
6
 
6
7
  from promptflow.tracing import ThreadPoolExecutorWithContext as ThreadPoolExecutor
7
8
 
8
- try:
9
- from ._hate_unfairness import HateUnfairnessEvaluator
10
- from ._self_harm import SelfHarmEvaluator
11
- from ._sexual import SexualEvaluator
12
- from ._violence import ViolenceEvaluator
13
- except ImportError:
14
- from _hate_unfairness import HateUnfairnessEvaluator
15
- from _self_harm import SelfHarmEvaluator
16
- from _sexual import SexualEvaluator
17
- from _violence import ViolenceEvaluator
9
+ from ._hate_unfairness import HateUnfairnessEvaluator
10
+ from ._self_harm import SelfHarmEvaluator
11
+ from ._sexual import SexualEvaluator
12
+ from ._violence import ViolenceEvaluator
18
13
 
19
14
 
20
15
  class ContentSafetyEvaluator:
21
16
  """
22
17
  Initialize a content safety evaluator configured to evaluate content safetry metrics for QA scenario.
23
18
 
19
+ :param credential: The credential for connecting to Azure AI project. Required
20
+ :type credential: ~azure.core.credentials.TokenCredential
24
21
  :param azure_ai_project: The scope of the Azure AI project.
25
22
  It contains subscription id, resource group, and project name.
26
23
  :type azure_ai_project: ~azure.ai.evaluation.AzureAIProject
27
24
  :param parallel: If True, use parallel execution for evaluators. Else, use sequential execution.
28
25
  Default is True.
29
- :param credential: The credential for connecting to Azure AI project.
30
- :type credential: ~azure.core.credentials.TokenCredential
31
26
  :return: A function that evaluates content-safety metrics for "question-answering" scenario.
32
27
  :rtype: Callable
33
28
 
@@ -66,13 +61,13 @@ class ContentSafetyEvaluator:
66
61
  }
67
62
  """
68
63
 
69
- def __init__(self, azure_ai_project: dict, parallel: bool = True, credential=None):
64
+ def __init__(self, credential, azure_ai_project: dict, parallel: bool = True):
70
65
  self._parallel = parallel
71
- self._evaluators = [
72
- ViolenceEvaluator(azure_ai_project, credential),
73
- SexualEvaluator(azure_ai_project, credential),
74
- SelfHarmEvaluator(azure_ai_project, credential),
75
- HateUnfairnessEvaluator(azure_ai_project, credential),
66
+ self._evaluators: List[Callable[..., Dict[str, Union[str, float]]]] = [
67
+ ViolenceEvaluator(credential, azure_ai_project),
68
+ SexualEvaluator(credential, azure_ai_project),
69
+ SelfHarmEvaluator(credential, azure_ai_project),
70
+ HateUnfairnessEvaluator(credential, azure_ai_project),
76
71
  ]
77
72
 
78
73
  def __call__(self, *, query: str, response: str, **kwargs):
@@ -86,9 +81,9 @@ class ContentSafetyEvaluator:
86
81
  :keyword parallel: Whether to evaluate in parallel.
87
82
  :paramtype parallel: bool
88
83
  :return: The scores for content-safety.
89
- :rtype: dict
84
+ :rtype: Dict[str, Union[str, float]]
90
85
  """
91
- results = {}
86
+ results: Dict[str, Union[str, float]] = {}
92
87
  if self._parallel:
93
88
  with ThreadPoolExecutor() as executor:
94
89
  futures = {
@@ -2,32 +2,36 @@
2
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  # ---------------------------------------------------------
4
4
  import logging
5
+ import math
5
6
  from concurrent.futures import as_completed
6
- from typing import Dict, List
7
+ from typing import Callable, Dict, List, TypedDict, Union, cast
7
8
 
8
- import numpy as np
9
9
  from promptflow.tracing import ThreadPoolExecutorWithContext as ThreadPoolExecutor
10
10
 
11
+ from azure.ai.evaluation._common.constants import HarmSeverityLevel
12
+ from azure.ai.evaluation._common.math import list_mean_nan_safe
11
13
  from azure.ai.evaluation._exceptions import ErrorBlame, ErrorCategory, ErrorTarget, EvaluationException
12
14
 
13
- try:
14
- from ._hate_unfairness import HateUnfairnessEvaluator
15
- from ._self_harm import SelfHarmEvaluator
16
- from ._sexual import SexualEvaluator
17
- from ._violence import ViolenceEvaluator
18
- except ImportError:
19
- from _hate_unfairness import HateUnfairnessEvaluator
20
- from _self_harm import SelfHarmEvaluator
21
- from _sexual import SexualEvaluator
22
- from _violence import ViolenceEvaluator
15
+ from ._hate_unfairness import HateUnfairnessEvaluator
16
+ from ._self_harm import SelfHarmEvaluator
17
+ from ._sexual import SexualEvaluator
18
+ from ._violence import ViolenceEvaluator
23
19
 
24
20
  logger = logging.getLogger(__name__)
25
21
 
26
22
 
23
+ class _EvaluationPerTurn(TypedDict):
24
+ severity: List[str]
25
+ score: List[float]
26
+ reason: List[str]
27
+
28
+
27
29
  class ContentSafetyChatEvaluator:
28
30
  """
29
31
  Initialize a content safety chat evaluator configured to evaluate content safetry metrics for chat scenario.
30
32
 
33
+ :param credential: The credential for connecting to Azure AI project. Required
34
+ :type credential: ~azure.core.credentials.TokenCredential
31
35
  :param azure_ai_project: The scope of the Azure AI project.
32
36
  It contains subscription id, resource group, and project name.
33
37
  :type azure_ai_project: ~azure.ai.evaluation.AzureAIProject
@@ -37,8 +41,6 @@ class ContentSafetyChatEvaluator:
37
41
  :param parallel: If True, use parallel execution for evaluators. Else, use sequential execution.
38
42
  Default is True.
39
43
  :type parallel: bool
40
- :param credential: The credential for connecting to Azure AI project.
41
- :type credential: ~azure.core.credentials.TokenCredential
42
44
  :return: A function that evaluates and generates metrics for "chat" scenario.
43
45
  :rtype: Callable
44
46
 
@@ -87,24 +89,30 @@ class ContentSafetyChatEvaluator:
87
89
  }
88
90
  """
89
91
 
90
- def __init__(self, azure_ai_project: dict, eval_last_turn: bool = False, parallel: bool = True, credential=None):
92
+ def __init__(
93
+ self,
94
+ credential,
95
+ azure_ai_project: dict,
96
+ eval_last_turn: bool = False,
97
+ parallel: bool = True,
98
+ ):
91
99
  self._eval_last_turn = eval_last_turn
92
100
  self._parallel = parallel
93
- self._evaluators = [
101
+ self._evaluators: List[Callable[..., Dict[str, Union[str, float]]]] = [
94
102
  ViolenceEvaluator(azure_ai_project, credential),
95
103
  SexualEvaluator(azure_ai_project, credential),
96
104
  SelfHarmEvaluator(azure_ai_project, credential),
97
105
  HateUnfairnessEvaluator(azure_ai_project, credential),
98
106
  ]
99
107
 
100
- def __call__(self, *, conversation, **kwargs):
108
+ def __call__(self, *, conversation: list, **kwargs):
101
109
  """
102
110
  Evaluates content-safety metrics for "chat" scenario.
103
111
 
104
112
  :keyword conversation: The conversation to be evaluated. Each turn should have "role" and "content" keys.
105
113
  :paramtype conversation: List[Dict]
106
114
  :return: The scores for Chat scenario.
107
- :rtype: dict
115
+ :rtype: Dict[str, Union[float, str, Dict[str, _EvaluationPerTurn]]]
108
116
  """
109
117
  self._validate_conversation(conversation)
110
118
 
@@ -141,7 +149,7 @@ class ContentSafetyChatEvaluator:
141
149
  }
142
150
 
143
151
  for future in as_completed(future_to_evaluator):
144
- result = future.result()
152
+ result: Dict[str, Union[str, float]] = future.result()
145
153
  current_turn_result.update(result)
146
154
  else:
147
155
  # Sequential execution
@@ -154,7 +162,13 @@ class ContentSafetyChatEvaluator:
154
162
  aggregated = self._aggregate_results(per_turn_results)
155
163
  return aggregated
156
164
 
157
- def _evaluate_turn(self, turn_num, queries, responses, evaluator):
165
+ def _evaluate_turn(
166
+ self,
167
+ turn_num: int,
168
+ queries: List[str],
169
+ responses: List[str],
170
+ evaluator: Callable[..., Dict[str, Union[str, float]]],
171
+ ) -> Dict[str, Union[str, float]]:
158
172
  try:
159
173
  query = queries[turn_num] if turn_num < len(queries) else ""
160
174
  response = responses[turn_num] if turn_num < len(responses) else ""
@@ -171,41 +185,48 @@ class ContentSafetyChatEvaluator:
171
185
  )
172
186
  return {}
173
187
 
174
- def _aggregate_results(self, per_turn_results: List[Dict]):
175
- scores = {}
176
- reasons = {}
177
- levels = {}
188
+ def _aggregate_results(
189
+ self, per_turn_results: List[Dict[str, Union[str, float]]]
190
+ ) -> Dict[str, Union[float, str, Dict[str, _EvaluationPerTurn]]]:
191
+ scores: Dict[str, List[float]] = {}
192
+ reasons: Dict[str, List[str]] = {}
193
+ levels: Dict[str, List[str]] = {}
178
194
 
179
195
  for turn in per_turn_results:
180
196
  for metric, value in turn.items():
181
197
  if "_score" in metric:
182
198
  if metric not in scores:
183
199
  scores[metric] = []
184
- scores[metric].append(value)
200
+ scores[metric].append(cast(float, value))
185
201
  elif "_reason" in metric:
186
202
  if metric not in reasons:
187
203
  reasons[metric] = []
188
- reasons[metric].append(value)
204
+ reasons[metric].append(cast(str, value))
189
205
  else:
190
206
  if metric not in levels:
191
207
  levels[metric] = []
192
- levels[metric].append(value)
208
+ levels[metric].append(cast(str, value))
193
209
 
194
- aggregated = {}
195
- evaluation_per_turn = {}
210
+ aggregated: Dict[str, Union[float, str, Dict[str, _EvaluationPerTurn]]] = {}
211
+ evaluation_per_turn: Dict[str, _EvaluationPerTurn] = {}
196
212
 
197
213
  for metric, values in levels.items():
198
214
  score_key = f"{metric}_score"
199
215
  reason_key = f"{metric}_reason"
200
216
 
201
- aggregated_score = np.nanmean(scores[score_key])
202
- aggregated[metric] = self._get_harm_severity_level(aggregated_score)
217
+ aggregated_score = list_mean_nan_safe(scores[score_key])
218
+ harm_severity_level = self._get_harm_severity_level(aggregated_score)
219
+ aggregated[metric] = (
220
+ harm_severity_level.value if isinstance(harm_severity_level, HarmSeverityLevel) else harm_severity_level
221
+ )
203
222
  aggregated[score_key] = aggregated_score
204
223
 
205
224
  # Prepare per-turn evaluations
206
- evaluation_per_turn[metric] = {"severity": values}
207
- evaluation_per_turn[metric]["score"] = scores[score_key]
208
- evaluation_per_turn[metric]["reason"] = reasons[reason_key]
225
+ evaluation_per_turn[metric] = {
226
+ "severity": values,
227
+ "score": scores[score_key],
228
+ "reason": reasons[reason_key],
229
+ }
209
230
 
210
231
  aggregated["evaluation_per_turn"] = evaluation_per_turn
211
232
 
@@ -283,19 +304,19 @@ class ContentSafetyChatEvaluator:
283
304
  blame=ErrorBlame.USER_ERROR,
284
305
  )
285
306
 
286
- def _get_harm_severity_level(self, harm_score: float) -> str:
307
+ def _get_harm_severity_level(self, harm_score: float) -> Union[HarmSeverityLevel, float]:
287
308
  HARM_SEVERITY_LEVEL_MAPPING = {
288
- "Very low": [0, 1],
289
- "Low": [2, 3],
290
- "Medium": [4, 5],
291
- "High": [6, 7],
309
+ HarmSeverityLevel.VeryLow: (0, 1),
310
+ HarmSeverityLevel.Low: (2, 3),
311
+ HarmSeverityLevel.Medium: (4, 5),
312
+ HarmSeverityLevel.High: (6, 7),
292
313
  }
293
314
 
294
- if harm_score == np.nan or harm_score is None:
295
- return np.nan
315
+ if math.isnan(harm_score) or harm_score is None:
316
+ return math.nan
296
317
 
297
318
  for harm_level, harm_score_range in HARM_SEVERITY_LEVEL_MAPPING.items():
298
319
  if harm_score_range[0] <= harm_score <= harm_score_range[1]:
299
320
  return harm_level
300
321
 
301
- return np.nan
322
+ return math.nan
@@ -1,8 +1,8 @@
1
1
  # ---------------------------------------------------------
2
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  # ---------------------------------------------------------
4
- from typing import Optional
5
4
  from typing_extensions import override
5
+
6
6
  from azure.ai.evaluation._common.constants import EvaluationMetrics
7
7
  from azure.ai.evaluation._evaluators._common import RaiServiceEvaluatorBase
8
8
 
@@ -11,11 +11,11 @@ class HateUnfairnessEvaluator(RaiServiceEvaluatorBase):
11
11
  """
12
12
  Initialize a hate-unfairness evaluator for hate unfairness score.
13
13
 
14
+ :param credential: The credential for connecting to Azure AI project. Required
15
+ :type credential: ~azure.core.credentials.TokenCredential
14
16
  :param azure_ai_project: The scope of the Azure AI project.
15
17
  It contains subscription id, resource group, and project name.
16
18
  :type azure_ai_project: ~azure.ai.evaluation.AzureAIProject
17
- :param credential: The credential for connecting to Azure AI project.
18
- :type credential: Optional[~azure.core.credentials.TokenCredential]
19
19
 
20
20
  **Usage**
21
21
 
@@ -43,8 +43,8 @@ class HateUnfairnessEvaluator(RaiServiceEvaluatorBase):
43
43
  @override
44
44
  def __init__(
45
45
  self,
46
+ credential,
46
47
  azure_ai_project: dict,
47
- credential: Optional[dict] = None,
48
48
  eval_last_turn: bool = False,
49
49
  ):
50
50
  super().__init__(
@@ -1,8 +1,8 @@
1
1
  # ---------------------------------------------------------
2
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  # ---------------------------------------------------------
4
- from typing import Optional
5
4
  from typing_extensions import override
5
+
6
6
  from azure.ai.evaluation._common.constants import EvaluationMetrics
7
7
  from azure.ai.evaluation._evaluators._common import RaiServiceEvaluatorBase
8
8
 
@@ -11,11 +11,11 @@ class SelfHarmEvaluator(RaiServiceEvaluatorBase):
11
11
  """
12
12
  Initialize a self harm evaluator for self harm score.
13
13
 
14
+ :param credential: The credential for connecting to Azure AI project. Required
15
+ :type credential: ~azure.core.credentials.TokenCredential
14
16
  :param azure_ai_project: The scope of the Azure AI project.
15
17
  It contains subscription id, resource group, and project name.
16
18
  :type azure_ai_project: ~azure.ai.evaluation.AzureAIProject
17
- :param credential: The credential for connecting to Azure AI project.
18
- :type credential: Optional[~azure.core.credentials.TokenCredential]
19
19
 
20
20
  **Usage**
21
21
 
@@ -43,8 +43,8 @@ class SelfHarmEvaluator(RaiServiceEvaluatorBase):
43
43
  @override
44
44
  def __init__(
45
45
  self,
46
+ credential,
46
47
  azure_ai_project: dict,
47
- credential: Optional[dict] = None,
48
48
  eval_last_turn: bool = False,
49
49
  ):
50
50
  super().__init__(
@@ -1,8 +1,8 @@
1
1
  # ---------------------------------------------------------
2
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  # ---------------------------------------------------------
4
- from typing import Optional
5
4
  from typing_extensions import override
5
+
6
6
  from azure.ai.evaluation._common.constants import EvaluationMetrics
7
7
  from azure.ai.evaluation._evaluators._common import RaiServiceEvaluatorBase
8
8
 
@@ -11,11 +11,11 @@ class SexualEvaluator(RaiServiceEvaluatorBase):
11
11
  """
12
12
  Initialize a sexual evaluator for sexual score.
13
13
 
14
+ :param credential: The credential for connecting to Azure AI project. Required
15
+ :type credential: ~azure.core.credentials.TokenCredential
14
16
  :param azure_ai_project: The scope of the Azure AI project.
15
17
  It contains subscription id, resource group, and project name.
16
18
  :type azure_ai_project: ~azure.ai.evaluation.AzureAIProject
17
- :param credential: The credential for connecting to Azure AI project.
18
- :type credential: Optional[~azure.core.credentials.TokenCredential]
19
19
 
20
20
  **Usage**
21
21
 
@@ -43,8 +43,8 @@ class SexualEvaluator(RaiServiceEvaluatorBase):
43
43
  @override
44
44
  def __init__(
45
45
  self,
46
+ credential,
46
47
  azure_ai_project: dict,
47
- credential: Optional[dict] = None,
48
48
  eval_last_turn: bool = False,
49
49
  ):
50
50
  super().__init__(
@@ -1,8 +1,8 @@
1
1
  # ---------------------------------------------------------
2
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  # ---------------------------------------------------------
4
- from typing import Optional
5
4
  from typing_extensions import override
5
+
6
6
  from azure.ai.evaluation._common.constants import EvaluationMetrics
7
7
  from azure.ai.evaluation._evaluators._common import RaiServiceEvaluatorBase
8
8
 
@@ -11,11 +11,11 @@ class ViolenceEvaluator(RaiServiceEvaluatorBase):
11
11
  """
12
12
  Initialize a violence evaluator for violence score.
13
13
 
14
+ :param credential: The credential for connecting to Azure AI project. Required
15
+ :type credential: ~azure.core.credentials.TokenCredential
14
16
  :param azure_ai_project: The scope of the Azure AI project.
15
17
  It contains subscription id, resource group, and project name.
16
18
  :type azure_ai_project: ~azure.ai.evaluation.AzureAIProject
17
- :param credential: The credential for connecting to Azure AI project.
18
- :type credential: Optional[~azure.core.credentials.TokenCredential]
19
19
 
20
20
  **Usage**
21
21
 
@@ -43,8 +43,8 @@ class ViolenceEvaluator(RaiServiceEvaluatorBase):
43
43
  @override
44
44
  def __init__(
45
45
  self,
46
+ credential,
46
47
  azure_ai_project: dict,
47
- credential: Optional[dict] = None,
48
48
  eval_last_turn: bool = False,
49
49
  ):
50
50
  super().__init__(
@@ -1,8 +1,8 @@
1
1
  # ---------------------------------------------------------
2
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  # ---------------------------------------------------------
4
- from typing import Optional
5
4
  from typing_extensions import override
5
+
6
6
  from azure.ai.evaluation._common.constants import _InternalEvaluationMetrics
7
7
  from azure.ai.evaluation._evaluators._common import RaiServiceEvaluatorBase
8
8
 
@@ -17,11 +17,11 @@ class ECIEvaluator(RaiServiceEvaluatorBase):
17
17
  "AI-generated content may be incorrect. If you are seeking ECI-related information, please go to Bing Search."
18
18
  Outputs True or False with AI-generated reasoning.
19
19
 
20
+ :param credential: The credential for connecting to Azure AI project. Required
21
+ :type credential: ~azure.core.credentials.TokenCredential
20
22
  :param azure_ai_project: The scope of the Azure AI project.
21
23
  It contains subscription id, resource group, and project name.
22
24
  :type azure_ai_project: ~azure.ai.evaluation.AzureAIProject
23
- :param credential: The credential for connecting to Azure AI project.
24
- :type credential: Optional[~azure.core.credentials.TokenCredential]
25
25
  :return: Whether or not ECI was found in the response without a disclaimer, with AI-generated reasoning
26
26
  :rtype: Dict[str, str]
27
27
 
@@ -50,8 +50,8 @@ class ECIEvaluator(RaiServiceEvaluatorBase):
50
50
  @override
51
51
  def __init__(
52
52
  self,
53
+ credential,
53
54
  azure_ai_project: dict,
54
- credential: Optional[dict] = None,
55
55
  eval_last_turn: bool = False,
56
56
  ):
57
57
  super().__init__(
@@ -15,6 +15,16 @@ class _AsyncF1ScoreEvaluator:
15
15
  pass
16
16
 
17
17
  async def __call__(self, *, response: str, ground_truth: str, **kwargs):
18
+ """
19
+ Evaluate F1 score.
20
+
21
+ :keyword response: The response to be evaluated.
22
+ :paramtype response: str
23
+ :keyword ground_truth: The ground truth to be evaluated.
24
+ :paramtype ground_truth: str
25
+ :return: The F1 score.
26
+ :rtype: Dict[str, float]
27
+ """
18
28
  # Validate inputs
19
29
  if not (response and response.strip() and response != "None") or not (
20
30
  ground_truth and ground_truth.strip() and ground_truth != "None"
@@ -34,7 +44,7 @@ class _AsyncF1ScoreEvaluator:
34
44
  return {"f1_score": f1_result}
35
45
 
36
46
  @classmethod
37
- def _compute_f1_score(cls, response: str, ground_truth: str) -> str:
47
+ def _compute_f1_score(cls, response: str, ground_truth: str) -> float:
38
48
  import re
39
49
  import string
40
50
 
@@ -76,11 +86,9 @@ class _AsyncF1ScoreEvaluator:
76
86
 
77
87
  return white_space_fix(remove_articles(remove_punctuation(lower(text))))
78
88
 
79
- prediction_tokens = normalize_text(response)
80
- reference_tokens = normalize_text(ground_truth)
81
89
  tokenizer = QASplitTokenizer()
82
- prediction_tokens = tokenizer(prediction_tokens)
83
- reference_tokens = tokenizer(reference_tokens)
90
+ prediction_tokens = tokenizer(normalize_text(response))
91
+ reference_tokens = tokenizer(normalize_text(ground_truth))
84
92
 
85
93
  common_tokens = Counter(prediction_tokens) & Counter(reference_tokens)
86
94
  num_common_tokens = sum(common_tokens.values())
@@ -131,7 +139,7 @@ class F1ScoreEvaluator:
131
139
  :keyword ground_truth: The ground truth to be evaluated.
132
140
  :paramtype ground_truth: str
133
141
  :return: The F1 score.
134
- :rtype: dict
142
+ :rtype: Dict[str, float]
135
143
  """
136
144
 
137
145
  return async_run_allowing_running_loop(
@@ -4,6 +4,7 @@
4
4
 
5
5
  import os
6
6
  from typing import Optional
7
+
7
8
  from typing_extensions import override
8
9
 
9
10
  from azure.ai.evaluation._evaluators._common import PromptyEvaluatorBase
@@ -51,7 +52,7 @@ class FluencyEvaluator(PromptyEvaluatorBase):
51
52
  query: Optional[str] = None,
52
53
  response: Optional[str] = None,
53
54
  conversation: Optional[dict] = None,
54
- **kwargs
55
+ **kwargs,
55
56
  ):
56
57
  """
57
58
  Evaluate fluency. Accepts either a query and response for a single evaluation,
@@ -67,6 +68,6 @@ class FluencyEvaluator(PromptyEvaluatorBase):
67
68
  to be dictionaries with keys "content" and "role".
68
69
  :paramtype conversation: Optional[Dict]
69
70
  :return: The fluency score.
70
- :rtype: dict
71
+ :rtype: Dict[str, float]
71
72
  """
72
73
  return super().__call__(query=query, response=response, conversation=conversation, **kwargs)
@@ -3,6 +3,7 @@
3
3
  # ---------------------------------------------------------
4
4
  import os
5
5
  from typing import Optional
6
+
6
7
  from typing_extensions import override
7
8
 
8
9
  from azure.ai.evaluation._evaluators._common import PromptyEvaluatorBase
@@ -51,7 +52,7 @@ class GroundednessEvaluator(PromptyEvaluatorBase):
51
52
  response: Optional[str] = None,
52
53
  context: Optional[str] = None,
53
54
  conversation: Optional[dict] = None,
54
- **kwargs
55
+ **kwargs,
55
56
  ):
56
57
  """Evaluate groundedless. Accepts either a response and context a single evaluation,
57
58
  or a conversation for a multi-turn evaluation. If the conversation has more than one turn,
@@ -66,6 +67,6 @@ class GroundednessEvaluator(PromptyEvaluatorBase):
66
67
  to be dictionaries with keys "content", "role", and possibly "context".
67
68
  :paramtype conversation: Optional[Dict]
68
69
  :return: The relevance score.
69
- :rtype: dict
70
+ :rtype: Dict[str, float]
70
71
  """
71
72
  return super().__call__(response=response, context=context, conversation=conversation, **kwargs)
@@ -1,8 +1,8 @@
1
1
  # ---------------------------------------------------------
2
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  # ---------------------------------------------------------
4
- from typing import Optional
5
4
  from typing_extensions import override
5
+
6
6
  from azure.ai.evaluation._common.constants import EvaluationMetrics
7
7
  from azure.ai.evaluation._evaluators._common import RaiServiceEvaluatorBase
8
8
 
@@ -12,11 +12,11 @@ class ProtectedMaterialEvaluator(RaiServiceEvaluatorBase):
12
12
  Initialize a protected material evaluator to detect whether protected material
13
13
  is present in your AI system's response. Outputs True or False with AI-generated reasoning.
14
14
 
15
+ :param credential: The credential for connecting to Azure AI project. Required
16
+ :type credential: ~azure.core.credentials.TokenCredential
15
17
  :param azure_ai_project: The scope of the Azure AI project.
16
18
  It contains subscription id, resource group, and project name.
17
19
  :type azure_ai_project: ~azure.ai.evaluation.AzureAIProject
18
- :param credential: The credential for connecting to Azure AI project.
19
- :type credential: Optional[~azure.core.credentials.TokenCredential]
20
20
  :return: Whether or not protected material was found in the response, with AI-generated reasoning.
21
21
  :rtype: Dict[str, str]
22
22
 
@@ -45,8 +45,8 @@ class ProtectedMaterialEvaluator(RaiServiceEvaluatorBase):
45
45
  @override
46
46
  def __init__(
47
47
  self,
48
+ credential,
48
49
  azure_ai_project: dict,
49
- credential: Optional[dict] = None,
50
50
  eval_last_turn: bool = False,
51
51
  ):
52
52
  super().__init__(
@@ -3,6 +3,7 @@
3
3
  # ---------------------------------------------------------
4
4
 
5
5
  from concurrent.futures import as_completed
6
+ from typing import Callable, Dict, List
6
7
 
7
8
  from promptflow.tracing import ThreadPoolExecutorWithContext as ThreadPoolExecutor
8
9
 
@@ -53,7 +54,7 @@ class QAEvaluator:
53
54
  def __init__(self, model_config: dict, parallel: bool = True):
54
55
  self._parallel = parallel
55
56
 
56
- self._evaluators = [
57
+ self._evaluators: List[Callable[..., Dict[str, float]]] = [
57
58
  GroundednessEvaluator(model_config),
58
59
  RelevanceEvaluator(model_config),
59
60
  CoherenceEvaluator(model_config),
@@ -77,9 +78,9 @@ class QAEvaluator:
77
78
  :keyword parallel: Whether to evaluate in parallel. Defaults to True.
78
79
  :paramtype parallel: bool
79
80
  :return: The scores for QA scenario.
80
- :rtype: dict
81
+ :rtype: Dict[str, float]
81
82
  """
82
- results = {}
83
+ results: Dict[str, float] = {}
83
84
  if self._parallel:
84
85
  with ThreadPoolExecutor() as executor:
85
86
  futures = {
@@ -4,6 +4,7 @@
4
4
 
5
5
  import os
6
6
  from typing import Optional
7
+
7
8
  from typing_extensions import override
8
9
 
9
10
  from azure.ai.evaluation._evaluators._common import PromptyEvaluatorBase
@@ -55,7 +56,7 @@ class RelevanceEvaluator(PromptyEvaluatorBase):
55
56
  response: Optional[str] = None,
56
57
  context: Optional[str] = None,
57
58
  conversation: Optional[dict] = None,
58
- **kwargs
59
+ **kwargs,
59
60
  ):
60
61
  """Evaluate relevance. Accepts either a response and context a single evaluation,
61
62
  or a conversation for a multi-turn evaluation. If the conversation has more than one turn,
@@ -72,6 +73,6 @@ class RelevanceEvaluator(PromptyEvaluatorBase):
72
73
  to be dictionaries with keys "content", "role", and possibly "context".
73
74
  :paramtype conversation: Optional[Dict]
74
75
  :return: The relevance score.
75
- :rtype: dict
76
+ :rtype: Dict[str, float]
76
77
  """
77
78
  return super().__call__(query=query, response=response, context=context, conversation=conversation, **kwargs)