Skip to content

Commit acc9e33

Browse files
authored
[Evaluation] Error improve for service-based evaluator/simulator (#38106)
* Error improve for service-based evaluator/simulator * update * update print summary * update * fix failed tests * fix black * update changelog * update * update version
1 parent 6ea41fe commit acc9e33

File tree

8 files changed

+71
-37
lines changed

8 files changed

+71
-37
lines changed

sdk/evaluation/azure-ai-evaluation/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
### Bugs Fixed
1010

1111
### Other Changes
12+
- Refined error messages for serviced-based evaluators and simulators.
13+
- Introduced environment variable `AI_EVALS_DISABLE_EXPERIMENTAL_WARNING` to disable the warning message for experimental features.
1214

1315
## 1.0.0b5 (2024-10-28)
1416

sdk/evaluation/azure-ai-evaluation/TROUBLESHOOTING.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This guide walks you through how to investigate failures, common errors in the `
66

77
- [Handle Evaluate API Errors](#handle-evaluate-api-errors)
88
- [Troubleshoot Remote Tracking Issues](#troubleshoot-remote-tracking-issues)
9-
- [Safety Metric Supported Regions](#safety-metric-supported-regions)
9+
- [Troubleshoot Safety Evaluator Issues](#troubleshoot-safety-evaluator-issues)
1010
- [Handle Simulation Errors](#handle-simulation-errors)
1111
- [Adversarial Simulation Supported Regions](#adversarial-simulation-supported-regions)
1212
- [Logging](#logging)
@@ -31,9 +31,10 @@ This guide walks you through how to investigate failures, common errors in the `
3131

3232
- Additionally, if you're using a virtual network or private link, and your evaluation run upload fails because of that, check out this [guide](https://docs.microsoft.com/azure/machine-learning/how-to-enable-studio-virtual-network#access-data-using-the-studio).
3333
34-
### Safety Metric Supported Regions
34+
### Troubleshoot Safety Evaluator Issues
3535
36-
Risk and safety evaluators depend on the Azure AI Studio safety evaluation backend service. For a list of supported regions, please refer to the documentation [here](https://aka.ms/azureaisafetyeval-regionsupport).
36+
- Risk and safety evaluators depend on the Azure AI Studio safety evaluation backend service. For a list of supported regions, please refer to the documentation [here](https://aka.ms/azureaisafetyeval-regionsupport).
37+
- If you encounter a 403 Unauthorized error when using safety evaluators, verify that you have the `Contributor` role assigned to your Azure AI project. `Contributor` role is currently required to run safety evaluations.
3738
3839
## Handle Simulation Errors
3940

sdk/evaluation/azure-ai-evaluation/azure/ai/evaluation/_common/_experimental.py

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Copyright (c) Microsoft Corporation. All rights reserved.
33
# ---------------------------------------------------------
44

5+
import os
56
import functools
67
import inspect
78
import logging
@@ -149,6 +150,9 @@ def _get_indentation_size(doc_string: str) -> int:
149150
def _should_skip_warning():
150151
skip_warning_msg = False
151152

153+
if os.getenv("AI_EVALS_DISABLE_EXPERIMENTAL_WARNING", "false").lower() == "true":
154+
skip_warning_msg = True
155+
152156
# Cases where we want to suppress the warning:
153157
# 1. When converting from REST object to SDK object
154158
for frame in inspect.stack():

sdk/evaluation/azure-ai-evaluation/azure/ai/evaluation/_common/rai_service.py

+32-24
Original file line numberDiff line numberDiff line change
@@ -83,27 +83,31 @@ async def ensure_service_availability(rai_svc_url: str, token: str, capability:
8383
async with get_async_http_client() as client:
8484
response = await client.get(svc_liveness_url, headers=headers)
8585

86-
if response.status_code != 200:
87-
msg = f"RAI service is not available in this region. Status Code: {response.status_code}"
88-
raise EvaluationException(
89-
message=msg,
90-
internal_message=msg,
91-
target=ErrorTarget.UNKNOWN,
92-
category=ErrorCategory.SERVICE_UNAVAILABLE,
93-
blame=ErrorBlame.USER_ERROR,
94-
)
95-
96-
capabilities = response.json()
86+
if response.status_code != 200:
87+
msg = (
88+
f"RAI service is unavailable in this region, or you lack the necessary permissions "
89+
f"to access the AI project. Status Code: {response.status_code}"
90+
)
91+
raise EvaluationException(
92+
message=msg,
93+
internal_message=msg,
94+
target=ErrorTarget.RAI_CLIENT,
95+
category=ErrorCategory.SERVICE_UNAVAILABLE,
96+
blame=ErrorBlame.USER_ERROR,
97+
tsg_link="https://aka.ms/azsdk/python/evaluation/safetyevaluator/troubleshoot",
98+
)
9799

98-
if capability and capability not in capabilities:
99-
msg = f"Capability '{capability}' is not available in this region"
100-
raise EvaluationException(
101-
message=msg,
102-
internal_message=msg,
103-
target=ErrorTarget.RAI_CLIENT,
104-
category=ErrorCategory.SERVICE_UNAVAILABLE,
105-
blame=ErrorBlame.USER_ERROR,
106-
)
100+
capabilities = response.json()
101+
if capability and capability not in capabilities:
102+
msg = f"The needed capability '{capability}' is not supported by the RAI service in this region."
103+
raise EvaluationException(
104+
message=msg,
105+
internal_message=msg,
106+
target=ErrorTarget.RAI_CLIENT,
107+
category=ErrorCategory.SERVICE_UNAVAILABLE,
108+
blame=ErrorBlame.USER_ERROR,
109+
tsg_link="https://aka.ms/azsdk/python/evaluation/safetyevaluator/troubleshoot",
110+
)
107111

108112

109113
def generate_payload(normalized_user_text: str, metric: str, annotation_task: str) -> Dict:
@@ -371,13 +375,17 @@ async def _get_service_discovery_url(azure_ai_project: AzureAIProject, token: st
371375
)
372376

373377
if response.status_code != 200:
374-
msg = "Failed to retrieve the discovery service URL."
378+
msg = (
379+
f"Failed to connect to your Azure AI project. Please check if the project scope is configured correctly, "
380+
f"and make sure you have the necessary access permissions. "
381+
f"Status code: {response.status_code}."
382+
)
375383
raise EvaluationException(
376384
message=msg,
377-
internal_message=msg,
378385
target=ErrorTarget.RAI_CLIENT,
379-
category=ErrorCategory.SERVICE_UNAVAILABLE,
380-
blame=ErrorBlame.UNKNOWN,
386+
blame=ErrorBlame.USER_ERROR,
387+
category=ErrorCategory.PROJECT_ACCESS_ERROR,
388+
tsg_link="https://aka.ms/azsdk/python/evaluation/safetyevaluator/troubleshoot",
381389
)
382390

383391
base_url = urlparse(response.json()["properties"]["discoveryUrl"])

sdk/evaluation/azure-ai-evaluation/azure/ai/evaluation/_evaluate/_batch_run/proxy_client.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,22 @@ def get_run_summary(self, proxy_run: ProxyRun) -> Dict[str, Any]:
6868
run = proxy_run.run.result()
6969

7070
# pylint: disable=protected-access
71+
completed_lines = run._properties.get("system_metrics", {}).get("__pf__.lines.completed", "NA")
72+
failed_lines = run._properties.get("system_metrics", {}).get("__pf__.lines.failed", "NA")
73+
74+
# Update status to "Completed with Errors" if the original status is "Completed" and there are failed lines
75+
if run.status == "Completed" and failed_lines != "NA" and int(failed_lines) > 0:
76+
status = "Completed with Errors"
77+
else:
78+
status = run.status
79+
80+
# Return the ordered dictionary with the updated status
7181
return OrderedDict(
7282
[
73-
("status", run.status),
83+
("status", status),
7484
("duration", str(run._end_time - run._created_on)),
75-
("completed_lines", run._properties.get("system_metrics", {}).get("__pf__.lines.completed", "NA")),
76-
("failed_lines", run._properties.get("system_metrics", {}).get("__pf__.lines.failed", "NA")),
85+
("completed_lines", completed_lines),
86+
("failed_lines", failed_lines),
7787
("log_path", str(run._output_path)),
7888
]
7989
)

sdk/evaluation/azure-ai-evaluation/azure/ai/evaluation/_exceptions.py

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class ErrorCategory(Enum):
2323
* SERVICE_UNAVAILABLE -> Service is unavailable
2424
* MISSING_PACKAGE -> Required package is missing
2525
* FAILED_REMOTE_TRACKING -> Remote tracking failed
26+
* PROJECT_ACCESS_ERROR -> Access to project failed
2627
* UNKNOWN -> Undefined placeholder. Avoid using.
2728
"""
2829

@@ -35,6 +36,7 @@ class ErrorCategory(Enum):
3536
SERVICE_UNAVAILABLE = "SERVICE UNAVAILABLE"
3637
MISSING_PACKAGE = "MISSING PACKAGE"
3738
FAILED_REMOTE_TRACKING = "FAILED REMOTE TRACKING"
39+
PROJECT_ACCESS_ERROR = "PROJECT ACCESS ERROR"
3840
UNKNOWN = "UNKNOWN"
3941

4042

sdk/evaluation/azure-ai-evaluation/azure/ai/evaluation/simulator/_model_tools/_rai_client.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,18 @@ def _get_service_discovery_url(self):
7474
timeout=5,
7575
)
7676
if response.status_code != 200:
77-
msg = "Failed to retrieve the discovery service URL."
77+
msg = (
78+
f"Failed to connect to your Azure AI project. Please check if the project scope is configured "
79+
f"correctly, and make sure you have the necessary access permissions. "
80+
f"Status code: {response.status_code}."
81+
)
7882
raise EvaluationException(
7983
message=msg,
80-
internal_message=msg,
8184
target=ErrorTarget.RAI_CLIENT,
82-
category=ErrorCategory.SERVICE_UNAVAILABLE,
83-
blame=ErrorBlame.UNKNOWN,
85+
category=ErrorCategory.PROJECT_ACCESS_ERROR,
86+
blame=ErrorBlame.USER_ERROR,
8487
)
88+
8589
base_url = urlparse(response.json()["properties"]["discoveryUrl"])
8690
return f"{base_url.scheme}://{base_url.netloc}"
8791

sdk/evaluation/azure-ai-evaluation/tests/unittests/test_content_safety_rai_script.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,18 @@ async def test_ensure_service_availability(self, client_mock):
146146
async def test_ensure_service_availability_service_unavailable(self, client_mock):
147147
with pytest.raises(Exception) as exc_info:
148148
_ = await ensure_service_availability("dummy_url", "dummy_token")
149-
assert "RAI service is not available in this region. Status Code: 9001" in str(exc_info._excinfo[1])
149+
assert "RAI service is unavailable in this region" in str(exc_info._excinfo[1])
150+
assert "Status Code: 9001" in str(exc_info._excinfo[1])
150151
assert client_mock._mock_await_count == 1
151152

152153
@pytest.mark.asyncio
153154
@patch("azure.ai.evaluation._http_utils.AsyncHttpPipeline.get", return_value=MockAsyncHttpResponse(200, json={}))
154155
async def test_ensure_service_availability_exception_capability_unavailable(self, client_mock):
155156
with pytest.raises(Exception) as exc_info:
156157
_ = await ensure_service_availability("dummy_url", "dummy_token", capability="does not exist")
157-
assert "Capability 'does not exist' is not available in this region" in str(exc_info._excinfo[1])
158+
assert "The needed capability 'does not exist' is not supported by the RAI service in this region" in str(
159+
exc_info._excinfo[1]
160+
)
158161
assert client_mock._mock_await_count == 1
159162

160163
@pytest.mark.asyncio
@@ -359,7 +362,7 @@ async def test_get_service_discovery_url_exception(self, client_mock):
359362

360363
with pytest.raises(Exception) as exc_info:
361364
_ = await _get_service_discovery_url(azure_ai_project=azure_ai_project, token=token)
362-
assert "Failed to retrieve the discovery service URL" in str(exc_info._excinfo[1])
365+
assert "Failed to connect to your Azure AI project." in str(exc_info._excinfo[1])
363366

364367
@pytest.mark.asyncio
365368
@patch(

0 commit comments

Comments
 (0)