Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: miner response times #162

Closed
wants to merge 8 commits into from
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ fund-validator-wallet:
fund-miner-wallet:
btcli wallet faucet --wallet.name miner --subtensor.$(SUBTENSOR_ENVIRONMENT)

## Send TAO
send:
btcli w transfer --subtensor.$(SUBTENSOR_ENVIRONMENT)

## Subnet creation
create-subnet:
btcli subnet create --wallet.name owner --subtensor.$(SUBTENSOR_ENVIRONMENT)
Expand Down
5 changes: 5 additions & 0 deletions masa/utils/uids.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ async def get_random_uids(self, k: int, exclude: List[int] = None) -> torch.Long
candidate_uids = remove_excluded_uids(avail_uids, exclude)

healthy_uids, _ = await ping_uids(dendrite, self.metagraph, candidate_uids)

# guard against deployed validators not finding any healthy ids via ping...
if (len(healthy_uids) == 0):
healthy_uids = candidate_uids

# filtered_uids = filter_duplicated_axon_ips_for_uids(
# healthy_uids, self.metagraph
# )
Expand Down
46 changes: 20 additions & 26 deletions masa/validator/forwarder.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,51 +20,48 @@
from masa.utils.uids import get_random_uids
import bittensor as bt


# this forwarder needs to able to handle multiple requests, driven off of an API request
class Forwarder:
def __init__(self, validator):
self.validator = validator

async def forward(
self, request, get_rewards, parser_object=None, parser_method=None, timeout=5
):
# TODO: This should live inside each endpoint to enable us to filter miners by different parameters in the future
# like blacklisting miners only on a specific endpoint like profiles or followers
miner_uids = await get_random_uids(
self.validator, k=self.validator.config.neuron.sample_size
)



async def forward(self, request, get_rewards, parser_object = None, parser_method = None, timeout = 20):
miner_uids = await get_random_uids(self.validator, k=self.validator.config.neuron.sample_size)
if miner_uids is None:
return []

responses = await self.validator.dendrite(
synapses = await self.validator.dendrite(
axons=[self.validator.metagraph.axons[uid] for uid in miner_uids],
synapse=request,
deserialize=True,
timeout=timeout,
deserialize=False,
timeout=timeout
)

responses = [synapse.response for synapse in synapses]

# Filter and parse valid responses
valid_responses, valid_miner_uids = self.sanitize_responses_and_uids(
responses, miner_uids=miner_uids
)
parsed_responses = responses

if parser_object:
parsed_responses = [
parser_object(**response) for response in valid_responses
]
elif parser_method:
parsed_responses = parser_method(valid_responses)


process_times = [synapse.dendrite.process_time for synapse, uid in zip(synapses, miner_uids) if uid in valid_miner_uids]

# Score responses
rewards = get_rewards(
self.validator, query=request.query, responses=parsed_responses
)

# Update the scores based on the rewards

if len(valid_miner_uids) > 0:
self.validator.update_scores(rewards, valid_miner_uids)
if self.validator.should_set_weights():
Expand All @@ -73,18 +70,15 @@ async def forward(
except Exception as e:
bt.logging.error(f"Failed to set weights: {e}")


# Add corresponding uid to each response
response_with_uids = [
{"response": response, "uid": int(uid.item()), "score": score.item()}
for response, uid, score in zip(parsed_responses, valid_miner_uids, rewards)
responses_with_metadata = [
{"response": response, "uid": int(uid.item()), "score": score.item(), "latency": latency}
for response, latency, uid, score in zip(parsed_responses, process_times, valid_miner_uids, rewards)
]

response_with_uids.sort(key=lambda x: x["score"], reverse=True)

print("FINAL RESPONSES ------------------------------------------------")
print(response_with_uids)

return response_with_uids
responses_with_metadata.sort(key=lambda x: (-x["score"], x["latency"]))
return responses_with_metadata

def sanitize_responses_and_uids(self, responses, miner_uids):
valid_responses = [response for response in responses if response is not None]
Expand Down
Loading