Skip to content

Commit 352c3fc

Browse files
shrutipatel31facebook-github-bot
authored andcommitted
(3/6) Port helpers to OSS for the new Complexity Rating Healthcheck - format_tier_message (facebook#4650)
Summary: Pull Request resolved: facebook#4650 Reviewed By: bernardbeckerman Differential Revision: D88908448
1 parent 92e8311 commit 352c3fc

2 files changed

Lines changed: 150 additions & 1 deletion

File tree

ax/utils/common/complexity_utils.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
# pyre-strict
77

8+
from collections.abc import Iterable
89
from typing import Any
910

1011
from ax.adapter.adapter_utils import can_map_to_binary, is_unordered_choice
@@ -13,6 +14,30 @@
1314
from ax.exceptions.core import OptimizationNotConfiguredError
1415
from ax.service.orchestrator import OrchestratorOptions
1516

17+
WHEELHOUSE_TIER_MESSAGE = """This experiment is in tier 'Wheelhouse'.
18+
19+
Experiments belonging to this tier should not run into any problems! If an issue \
20+
does occur, please post to our github issues page.
21+
"""
22+
23+
ADVANCED_TIER_MESSAGE = """This experiment is in tier 'Advanced'.
24+
25+
This experiment should technically run, but uses advanced features that may not \
26+
be well-tested and/or may not be compatible with other advanced features. We \
27+
encourage users to raise issues encountered in advanced workflows just like \
28+
wheelhouse workflows but it is also possible that reducing the complexity of \
29+
your setup can solve your issue.
30+
"""
31+
32+
UNSUPPORTED_TIER_MESSAGE = """This experiment is in tier 'Unsupported'.
33+
34+
You are pushing Ax beyond its limits. Please post to our github issues page for help \
35+
in improving/simplifying your configuration to conform to a more \
36+
well-supported usage tier if possible.
37+
"""
38+
39+
WIKI_TIER_MESSAGE = "https://ax.dev/docs/why-ax"
40+
1641

1742
def summarize_ax_optimization_complexity(
1843
experiment: Experiment,
@@ -87,3 +112,46 @@ def summarize_ax_optimization_complexity(
87112
options.min_failed_trials_for_failure_rate_check
88113
),
89114
}
115+
116+
117+
def format_tier_message(
118+
tier: str,
119+
why_not_is_in_wheelhouse: Iterable[str] | None,
120+
why_not_supported: Iterable[str] | None,
121+
) -> str:
122+
"""
123+
Format the result from `check_if_in_wheelhouse` to a markdown-formatted string
124+
explaining the tier.
125+
"""
126+
127+
if tier == "Wheelhouse":
128+
msg = WHEELHOUSE_TIER_MESSAGE
129+
else:
130+
if tier == "Advanced":
131+
msg = ADVANCED_TIER_MESSAGE
132+
elif tier == "Unsupported":
133+
msg = UNSUPPORTED_TIER_MESSAGE
134+
else:
135+
raise ValueError(f'Got unexpected tier "{tier}".')
136+
137+
# Provide user-feedback
138+
if why_not_is_in_wheelhouse:
139+
why_msg = "\n".join("\t- " + s for s in why_not_is_in_wheelhouse)
140+
why_msg = (
141+
"\n\nWhy this experiment is not in the 'Wheelhouse' tier: "
142+
f"\n{why_msg}\n"
143+
)
144+
msg += why_msg
145+
if why_not_supported:
146+
why_msg = "\n".join("\t- " + s for s in why_not_supported)
147+
why_msg = (
148+
"\n\nWhy this experiment is not in the 'Advanced' tier: "
149+
f"\n{why_msg}\n"
150+
)
151+
msg += why_msg
152+
153+
msg += (
154+
"\n\nFor more information about the definition of each tier and what "
155+
f"level of support you can expect: {WIKI_TIER_MESSAGE}"
156+
)
157+
return msg

ax/utils/common/tests/test_complexity_utils.py

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88

99
from ax.exceptions.core import OptimizationNotConfiguredError
1010
from ax.service.orchestrator import OrchestratorOptions
11-
from ax.utils.common.complexity_utils import summarize_ax_optimization_complexity
11+
from ax.utils.common.complexity_utils import (
12+
ADVANCED_TIER_MESSAGE,
13+
format_tier_message,
14+
summarize_ax_optimization_complexity,
15+
UNSUPPORTED_TIER_MESSAGE,
16+
WHEELHOUSE_TIER_MESSAGE,
17+
)
1218
from ax.utils.common.testutils import TestCase
1319
from ax.utils.testing.core_stubs import (
1420
get_experiment,
@@ -160,3 +166,78 @@ def test_parameter_constraints_counted(self) -> None:
160166

161167
# THEN num_parameter_constraints should be greater than 0
162168
self.assertGreater(summary["num_parameter_constraints"], 0)
169+
170+
171+
class TestFormatTierMessage(TestCase):
172+
"""Tests for format_tier_message."""
173+
174+
def test_tier_messages(self) -> None:
175+
"""Test formatting of tier messages for all tiers."""
176+
test_cases: list[
177+
tuple[
178+
str,
179+
list[str] | None,
180+
list[str] | None,
181+
str,
182+
list[str],
183+
]
184+
] = [
185+
(
186+
"Wheelhouse",
187+
None,
188+
None,
189+
WHEELHOUSE_TIER_MESSAGE,
190+
["tier 'Wheelhouse'"],
191+
),
192+
(
193+
"Advanced",
194+
["51 tunable parameters", "Early stopping is enabled"],
195+
None,
196+
ADVANCED_TIER_MESSAGE,
197+
[
198+
"tier 'Advanced'",
199+
"Why this experiment is not in the 'Wheelhouse' tier:",
200+
"51 tunable parameters",
201+
"Early stopping is enabled",
202+
],
203+
),
204+
(
205+
"Unsupported",
206+
["51 tunable parameters"],
207+
["201 tunable parameters"],
208+
UNSUPPORTED_TIER_MESSAGE,
209+
[
210+
"tier 'Unsupported'",
211+
"Why this experiment is not in the 'Wheelhouse' tier:",
212+
"51 tunable parameters",
213+
"Why this experiment is not in the 'Advanced' tier:",
214+
"201 tunable parameters",
215+
],
216+
),
217+
]
218+
219+
for (
220+
tier,
221+
why_not_wheelhouse,
222+
why_not_supported,
223+
expected_message,
224+
expected_contents,
225+
) in test_cases:
226+
with self.subTest(tier=tier):
227+
msg = format_tier_message(
228+
tier=tier,
229+
why_not_is_in_wheelhouse=why_not_wheelhouse,
230+
why_not_supported=why_not_supported,
231+
)
232+
self.assertIn(expected_message, msg)
233+
for content in expected_contents:
234+
self.assertIn(content, msg)
235+
236+
def test_unknown_tier_raises_error(self) -> None:
237+
"""Test that unknown tier raises ValueError."""
238+
with self.assertRaisesRegex(ValueError, 'Got unexpected tier "BadTier"'):
239+
format_tier_message(
240+
tier="BadTier",
241+
why_not_is_in_wheelhouse=None,
242+
why_not_supported=None,
243+
)

0 commit comments

Comments
 (0)