Skip to content

Commit 3402c15

Browse files
committed
Allows setting hyperparams arbitrarily, as long as they exist in the AdminUtils pallet.
1 parent 1778f62 commit 3402c15

File tree

4 files changed

+94
-46
lines changed

4 files changed

+94
-46
lines changed

bittensor_cli/src/commands/stake/add.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,7 @@ async def safe_stake_extrinsic(
107107
)
108108
return
109109
else:
110-
err_out(
111-
f"\n{failure_prelude} with error: {format_error_message(e)}"
112-
)
110+
err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
113111
return
114112
else:
115113
await response.process_events()
@@ -180,9 +178,7 @@ async def stake_extrinsic(
180178
extrinsic, wait_for_inclusion=True, wait_for_finalization=False
181179
)
182180
except SubstrateRequestException as e:
183-
err_out(
184-
f"\n{failure_prelude} with error: {format_error_message(e)}"
185-
)
181+
err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
186182
return
187183
else:
188184
await response.process_events()

bittensor_cli/src/commands/stake/remove.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -666,9 +666,7 @@ async def _safe_unstake_extrinsic(
666666
)
667667
return
668668
else:
669-
err_out(
670-
f"\n{failure_prelude} with error: {format_error_message(e)}"
671-
)
669+
err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
672670
return
673671

674672
await response.process_events()

bittensor_cli/src/commands/subnets/subnets.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -889,8 +889,8 @@ async def show_root():
889889
total_emission_per_block = 0
890890
for netuid_ in range(len(all_subnets)):
891891
subnet = all_subnets[netuid_]
892-
emission_on_subnet = (
893-
root_state.emission_history[netuid_][idx] / subnet.tempo
892+
emission_on_subnet = root_state.emission_history[netuid_][idx] / (
893+
subnet.tempo or 1
894894
)
895895
total_emission_per_block += subnet.alpha_to_tao(
896896
Balance.from_rao(emission_on_subnet)
@@ -2135,9 +2135,7 @@ async def get_identity(subtensor: "SubtensorInterface", netuid: int, title: str
21352135
title = "Subnet Identity"
21362136

21372137
if not await subtensor.subnet_exists(netuid):
2138-
print_error(
2139-
f"Subnet {netuid} does not exist."
2140-
)
2138+
print_error(f"Subnet {netuid} does not exist.")
21412139
raise typer.Exit()
21422140

21432141
with console.status(

bittensor_cli/src/commands/sudo.py

Lines changed: 88 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
normalize_hyperparameters,
1919
unlock_key,
2020
blocks_to_duration,
21+
float_to_u64,
22+
float_to_u16,
2123
)
2224

2325
if TYPE_CHECKING:
@@ -70,6 +72,44 @@ def allowed_value(
7072
return True, value
7173

7274

75+
def search_metadata(
76+
param_name: str, netuid: int, metadata
77+
) -> tuple[bool, Optional[dict]]:
78+
"""
79+
Searches the substrate metadata AdminUtils pallet for a given parameter name. Crafts a response dict to be used
80+
as call parameters for setting this hyperparameter.
81+
82+
Args:
83+
param_name: the name of the hyperparameter
84+
netuid: the specified netuid
85+
metadata: the subtensor.substrate.metadata
86+
87+
Returns:
88+
(success, dict of call params)
89+
90+
"""
91+
arg_types = {"bool": bool, "u16": float_to_u16, "u64": float_to_u64}
92+
93+
call_crafter = {"netuid": netuid}
94+
95+
for pallet in metadata.pallets:
96+
if pallet.name == "AdminUtils":
97+
for call in pallet.calls:
98+
if call.name == param_name:
99+
if "netuid" not in [x.name for x in call.args]:
100+
return False, None
101+
for arg in call.args:
102+
if arg.name == "netuid":
103+
continue
104+
raw_val = input(
105+
f"Enter a value for field '{arg.name}' with type '{arg.typeName}'"
106+
)
107+
call_crafter[arg.name] = arg_types[arg.typeName](raw_val)
108+
return True, call_crafter
109+
else:
110+
return False, None
111+
112+
73113
async def set_hyperparameter_extrinsic(
74114
subtensor: "SubtensorInterface",
75115
wallet: "Wallet",
@@ -110,44 +150,53 @@ async def set_hyperparameter_extrinsic(
110150
if not unlock_key(wallet).success:
111151
return False
112152

153+
arbitrary_extrinsic = False
154+
113155
extrinsic, sudo_ = HYPERPARAMS.get(parameter, ("", False))
114156
if extrinsic is None:
115-
err_console.print(":cross_mark: [red]Invalid hyperparameter specified.[/red]")
116-
return False
157+
arbitrary_extrinsic, call_params = search_metadata(
158+
parameter, netuid, subtensor.substrate.metadata
159+
)
160+
if not arbitrary_extrinsic:
161+
err_console.print(
162+
":cross_mark: [red]Invalid hyperparameter specified.[/red]"
163+
)
164+
return False
117165

118166
with console.status(
119167
f":satellite: Setting hyperparameter [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{parameter}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] to [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{value}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] on subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{netuid}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] ...",
120168
spinner="earth",
121169
):
122-
substrate = subtensor.substrate
123-
extrinsic_params = await substrate.get_metadata_call_function(
124-
"AdminUtils", extrinsic
125-
)
126-
call_params: dict[str, Union[str, bool, float]] = {"netuid": netuid}
127-
128-
# if input value is a list, iterate through the list and assign values
129-
if isinstance(value, list):
130-
# Ensure that there are enough values for all non-netuid parameters
131-
non_netuid_fields = [
132-
param["name"]
133-
for param in extrinsic_params["fields"]
134-
if "netuid" not in param["name"]
135-
]
136-
137-
if len(value) < len(non_netuid_fields):
138-
raise ValueError(
139-
"Not enough values provided in the list for all parameters"
140-
)
141-
142-
call_params.update(
143-
{str(name): val for name, val in zip(non_netuid_fields, value)}
170+
if not arbitrary_extrinsic:
171+
substrate = subtensor.substrate
172+
extrinsic_params = await substrate.get_metadata_call_function(
173+
"AdminUtils", extrinsic
144174
)
175+
call_params = {"netuid": netuid}
176+
177+
# if input value is a list, iterate through the list and assign values
178+
if isinstance(value, list):
179+
# Ensure that there are enough values for all non-netuid parameters
180+
non_netuid_fields = [
181+
param["name"]
182+
for param in extrinsic_params["fields"]
183+
if "netuid" not in param["name"]
184+
]
185+
186+
if len(value) < len(non_netuid_fields):
187+
raise ValueError(
188+
"Not enough values provided in the list for all parameters"
189+
)
145190

146-
else:
147-
value_argument = extrinsic_params["fields"][
148-
len(extrinsic_params["fields"]) - 1
149-
]
150-
call_params[str(value_argument["name"])] = value
191+
call_params.update(
192+
{str(name): val for name, val in zip(non_netuid_fields, value)}
193+
)
194+
195+
else:
196+
value_argument = extrinsic_params["fields"][
197+
len(extrinsic_params["fields"]) - 1
198+
]
199+
call_params[str(value_argument["name"])] = value
151200

152201
# create extrinsic call
153202
call_ = await substrate.compose_call(
@@ -167,11 +216,16 @@ async def set_hyperparameter_extrinsic(
167216
if not success:
168217
err_console.print(f":cross_mark: [red]Failed[/red]: {err_msg}")
169218
await asyncio.sleep(0.5)
170-
219+
elif arbitrary_extrinsic:
220+
console.print(
221+
f":white_heavy_check_mark: "
222+
f"[dark_sea_green3]Hyperparameter {parameter} values changed to {call_params}[/dark_sea_green3]"
223+
)
171224
# Successful registration, final check for membership
172225
else:
173226
console.print(
174-
f":white_heavy_check_mark: [dark_sea_green3]Hyperparameter {parameter} changed to {value}[/dark_sea_green3]"
227+
f":white_heavy_check_mark: "
228+
f"[dark_sea_green3]Hyperparameter {parameter} changed to {value}[/dark_sea_green3]"
175229
)
176230
return True
177231

@@ -481,7 +535,9 @@ async def sudo_set_hyperparameter(
481535
"commit_reveal_weights_enabled",
482536
"liquid_alpha_enabled",
483537
]:
484-
normalized_value = param_value.lower() in ["true", "True", "1"]
538+
normalized_value = param_value.lower() in ["true", "1"]
539+
elif param_value in ("True", "False"):
540+
normalized_value = bool(param_value)
485541
else:
486542
normalized_value = param_value
487543

0 commit comments

Comments
 (0)