Skip to content

Commit 6fd58c2

Browse files
authored
fix function header (#40792)
* fix function header * new recordings * upgrade name map properties * fix name
1 parent ce36075 commit 6fd58c2

File tree

3 files changed

+88
-7
lines changed

3 files changed

+88
-7
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class EvaluationRunProperties:
6363
EVALUATION_RUN = "_azureml.evaluation_run"
6464
EVALUATION_SDK = "_azureml.evaluation_sdk_name"
6565
NAME_MAP = "_azureml.evaluation_name_map"
66+
NAME_MAP_LENGTH = "_azureml.evaluation_name_map_length"
6667

6768

6869
@experimental

sdk/evaluation/azure-ai-evaluation/azure/ai/evaluation/_evaluate/_utils.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from typing import Any, Dict, NamedTuple, Optional, Union, cast
1111
import uuid
1212
import base64
13+
import math
1314

1415
import pandas as pd
1516
from azure.ai.evaluation._legacy._adapters.entities import Run
@@ -173,9 +174,9 @@ def _log_metrics_and_instance_results_onedp(
173174
EvaluationRunProperties.RUN_TYPE: "eval_run",
174175
EvaluationRunProperties.EVALUATION_RUN: "promptflow.BatchRun",
175176
EvaluationRunProperties.EVALUATION_SDK: f"azure-ai-evaluation:{VERSION}",
176-
EvaluationRunProperties.NAME_MAP: json.dumps(name_map),
177177
"_azureml.evaluate_artifacts": json.dumps([{"path": artifact_name, "type": "table"}]),
178-
}
178+
}
179+
properties.update(_convert_name_map_into_property_entries(name_map))
179180

180181
create_evaluation_result_response = client.create_evaluation_result(
181182
name=uuid.uuid4(),
@@ -264,15 +265,14 @@ def _log_metrics_and_instance_results(
264265
# adding these properties to avoid showing traces if a dummy run is created.
265266
# We are doing that only for the pure evaluation runs.
266267
if run is None:
267-
ev_run.write_properties_to_run_history(
268-
properties={
268+
properties = {
269269
EvaluationRunProperties.RUN_TYPE: "eval_run",
270270
EvaluationRunProperties.EVALUATION_RUN: "promptflow.BatchRun",
271271
EvaluationRunProperties.EVALUATION_SDK: f"azure-ai-evaluation:{VERSION}",
272-
EvaluationRunProperties.NAME_MAP: json.dumps(name_map),
273272
"_azureml.evaluate_artifacts": json.dumps([{"path": artifact_name, "type": "table"}]),
274273
}
275-
)
274+
properties.update(_convert_name_map_into_property_entries(name_map))
275+
ev_run.write_properties_to_run_history(properties=properties)
276276
else:
277277
ev_run.write_properties_to_run_history(
278278
properties={
@@ -407,6 +407,41 @@ def set_event_loop_policy() -> None:
407407
# On Windows seems to be a problem with EventLoopPolicy, use this snippet to work around it
408408
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # type: ignore[attr-defined]
409409

410+
# textwrap.wrap tries to do fancy nonsense that we don't want
411+
def _wrap(s, w):
412+
return [s[i:i + w] for i in range(0, len(s), w)]
413+
414+
def _convert_name_map_into_property_entries(
415+
name_map: Dict[str, str], segment_length: int = 950, max_segments: int = 10
416+
) -> Dict[str, Any]:
417+
"""
418+
Convert the name map into property entries.
419+
420+
:param name_map: The name map to be converted.
421+
:type name_map: Dict[str, str]
422+
:param segment_length: The max length of each individual segment,
423+
which will each have their own dictionary entry
424+
:type segment_length: str
425+
:param max_segments: The max number of segments we can have. If the stringified
426+
name map is too long, we just return a length entry with a value
427+
of -1 to indicate that the map was too long.
428+
:type max_segments: str
429+
:return: The converted name map.
430+
:rtype: Dict[str, Any]
431+
"""
432+
name_map_string = json.dumps(name_map)
433+
num_segments = math.ceil(len(name_map_string) / segment_length)
434+
# Property map is somehow still too long to encode within the space
435+
# we allow, so give up, but make sure the service knows we gave up
436+
if (num_segments > max_segments):
437+
return {EvaluationRunProperties.NAME_MAP_LENGTH: -1}
438+
439+
result: Dict[str, Any] = {EvaluationRunProperties.NAME_MAP_LENGTH: num_segments}
440+
segments_list = _wrap(name_map_string, segment_length)
441+
for i in range(0, num_segments):
442+
segment_key = f"{EvaluationRunProperties.NAME_MAP}_{i}"
443+
result[segment_key] = segments_list[i]
444+
return result
410445

411446
class JSONLDataFileLoader:
412447
def __init__(self, filename: Union[os.PathLike, str]):

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

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pandas as pd
1010
import pytest
1111
from pandas.testing import assert_frame_equal
12+
import test
1213
from azure.ai.evaluation._legacy._adapters.client import PFClient
1314

1415
from azure.ai.evaluation._common.math import list_mean
@@ -24,12 +25,17 @@
2425
SelfHarmEvaluator,
2526
HateUnfairnessEvaluator,
2627
)
27-
from azure.ai.evaluation._constants import DEFAULT_EVALUATION_RESULTS_FILE_NAME, _AggregationType
28+
from azure.ai.evaluation._constants import (
29+
DEFAULT_EVALUATION_RESULTS_FILE_NAME,
30+
_AggregationType,
31+
EvaluationRunProperties
32+
)
2833
from azure.ai.evaluation._evaluate._evaluate import (
2934
_aggregate_metrics,
3035
_apply_target_to_data,
3136
_rename_columns_conditionally,
3237
)
38+
from azure.ai.evaluation._evaluate._utils import _convert_name_map_into_property_entries
3339
from azure.ai.evaluation._evaluate._utils import _apply_column_mapping, _trace_destination_from_project_scope
3440
from azure.ai.evaluation._evaluators._eci._eci import ECIEvaluator
3541
from azure.ai.evaluation._exceptions import EvaluationException
@@ -919,3 +925,42 @@ def test_evaluate_korean_characters_result(self, questions_answers_korean_file):
919925
assert result["rows"][0]["inputs.query"] == data_from_file["query"]
920926

921927
os.remove(output_path)
928+
929+
def test_name_map_conversion(self):
930+
test_map = {
931+
"name1": "property1",
932+
"name2": "property2",
933+
"name3": "property3",
934+
}
935+
map_dump = json.dumps(test_map)
936+
937+
# Test basic
938+
result = _convert_name_map_into_property_entries(test_map)
939+
assert result[EvaluationRunProperties.NAME_MAP_LENGTH] == 1
940+
assert result[f"{EvaluationRunProperties.NAME_MAP}_0"] == map_dump
941+
942+
# Test with splits (dump of test map is 66 characters long)
943+
result = _convert_name_map_into_property_entries(test_map, segment_length=40)
944+
assert result[EvaluationRunProperties.NAME_MAP_LENGTH] == 2
945+
combined_strings = (result[f"{EvaluationRunProperties.NAME_MAP}_0"] +
946+
result[f"{EvaluationRunProperties.NAME_MAP}_1"])
947+
#breakpoint()
948+
assert result[f"{EvaluationRunProperties.NAME_MAP}_0"] == map_dump[0:40]
949+
assert result[f"{EvaluationRunProperties.NAME_MAP}_1"] == map_dump[40:]
950+
assert combined_strings == map_dump
951+
952+
# Test with exact split
953+
result = _convert_name_map_into_property_entries(test_map, segment_length=22)
954+
assert result[EvaluationRunProperties.NAME_MAP_LENGTH] == 3
955+
combined_strings = (result[f"{EvaluationRunProperties.NAME_MAP}_0"] +
956+
result[f"{EvaluationRunProperties.NAME_MAP}_1"] +
957+
result[f"{EvaluationRunProperties.NAME_MAP}_2"])
958+
assert result[f"{EvaluationRunProperties.NAME_MAP}_0"] == map_dump[0:22]
959+
assert result[f"{EvaluationRunProperties.NAME_MAP}_1"] == map_dump[22:44]
960+
assert result[f"{EvaluationRunProperties.NAME_MAP}_2"] == map_dump[44:]
961+
assert combined_strings == map_dump
962+
963+
# Test failure case
964+
result = _convert_name_map_into_property_entries(test_map, segment_length=10, max_segments = 1)
965+
assert result[EvaluationRunProperties.NAME_MAP_LENGTH] == -1
966+
assert len(result) == 1

0 commit comments

Comments
 (0)