Skip to content

Commit

Permalink
Merge pull request #372 from valory-xyz/feat/faulty-tools
Browse files Browse the repository at this point in the history
Implement a mechanism for detecting and recovering quickly from unreliable tools
  • Loading branch information
Adamantios authored Dec 20, 2024
2 parents 6270c07 + 6fd5ca7 commit 1ce37f9
Show file tree
Hide file tree
Showing 28 changed files with 649 additions and 442 deletions.
12 changes: 6 additions & 6 deletions packages/packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
"contract/valory/staking_token/0.1.0": "bafybeiep4r6qyilbfgzdvx6t7zvpgaioxqktmxm7puwtnbpb2ftlib43gy",
"contract/valory/relayer/0.1.0": "bafybeicawmds6czx7db2lcktvexwrp245jpekgulndtos5s5zdid3ilvq4",
"skill/valory/market_manager_abci/0.1.0": "bafybeiaru2d32wpmcgqs64eepxud4idgubc3vmsbdwbia7gygipql2mmqi",
"skill/valory/decision_maker_abci/0.1.0": "bafybeiddnmcquiuznts67ridhpnaqw2y3rrt4nfau5kjm74zhk5lhjxi2q",
"skill/valory/trader_abci/0.1.0": "bafybeiemjz3ca7la7jkeqdr7hxo7fa77xe2fkfadzb53gdkji7abpl2eiu",
"skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeietwknem7iiood6pwkfup322ywwjmdrmdapllrcms6jpeev5w2qfe",
"skill/valory/decision_maker_abci/0.1.0": "bafybeig5oivc24sqhgyxfhjbl2xsoa5yssv72lcu5ezunbcpwu3xo4jglm",
"skill/valory/trader_abci/0.1.0": "bafybeicmtcs4gaabwbyr4im2ux7co73y5n6ugj4abk6dayxzew7jly2zhe",
"skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeifpf3sk5evrvwxyht7mswcml3qy4nhzo5ddvjvgklapwsjwq6mera",
"skill/valory/staking_abci/0.1.0": "bafybeicupccurmrg7qesivonlyt3nryarsmk5qf5yh6auno64wn45bybvq",
"skill/valory/check_stop_trading_abci/0.1.0": "bafybeieduekpd4zbvjztyxyooppqnmjvup6jfp74uo6hhupvtvzzscdzkq",
"agent/valory/trader/0.1.0": "bafybeihq257kwjybsvrpzhjx4wbretrsurodpckjqdhv3idlnbu4mqvfnq",
"service/valory/trader/0.1.0": "bafybeihr6m4lec5r6kuf2zikusgyqilqwhwlpyehufyndjuziylr73dlqe",
"service/valory/trader_pearl/0.1.0": "bafybeibfqhsrtekx6nvwpz2nbbjyobljcahe6wz6jikyebt7opzxlal45u"
"agent/valory/trader/0.1.0": "bafybeih3r5xefwfqfdmmwx3e5n3i4df7pv3mvhqlk7qen2i75anj27ds4u",
"service/valory/trader/0.1.0": "bafybeid2xxc5plszxy644kbhcqxjwmpc6ay6xqhewc2c6bb3dqv3llt63u",
"service/valory/trader_pearl/0.1.0": "bafybeiaihaivsiyotduxvnmecvdf23t42bwnphwmswxcpfdhi3k6w57gze"
},
"third_party": {
"protocol/open_aea/signing/1.0.0": "bafybeihv62fim3wl2bayavfcg3u5e5cxu3b7brtu4cn5xoxd6lqwachasi",
Expand Down
11 changes: 8 additions & 3 deletions packages/valory/agents/trader/aea-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ skills:
- valory/reset_pause_abci:0.1.0:bafybeigrdlxed3xlsnxtjhnsbl3cojruihxcqx4jxhgivkd5i2fkjncgba
- valory/termination_abci:0.1.0:bafybeib5l7jhew5ic6iq24dd23nidcoimzqkrk556gqywhoziatj33zvwm
- valory/transaction_settlement_abci:0.1.0:bafybeic7q7recyka272udwcupblwbkc3jkodgp74fvcdxb7urametg5dae
- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeietwknem7iiood6pwkfup322ywwjmdrmdapllrcms6jpeev5w2qfe
- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeifpf3sk5evrvwxyht7mswcml3qy4nhzo5ddvjvgklapwsjwq6mera
- valory/market_manager_abci:0.1.0:bafybeiaru2d32wpmcgqs64eepxud4idgubc3vmsbdwbia7gygipql2mmqi
- valory/decision_maker_abci:0.1.0:bafybeiddnmcquiuznts67ridhpnaqw2y3rrt4nfau5kjm74zhk5lhjxi2q
- valory/trader_abci:0.1.0:bafybeiemjz3ca7la7jkeqdr7hxo7fa77xe2fkfadzb53gdkji7abpl2eiu
- valory/decision_maker_abci:0.1.0:bafybeig5oivc24sqhgyxfhjbl2xsoa5yssv72lcu5ezunbcpwu3xo4jglm
- valory/trader_abci:0.1.0:bafybeicmtcs4gaabwbyr4im2ux7co73y5n6ugj4abk6dayxzew7jly2zhe
- valory/staking_abci:0.1.0:bafybeicupccurmrg7qesivonlyt3nryarsmk5qf5yh6auno64wn45bybvq
- valory/check_stop_trading_abci:0.1.0:bafybeieduekpd4zbvjztyxyooppqnmjvup6jfp74uo6hhupvtvzzscdzkq
- valory/mech_interact_abci:0.1.0:bafybeid6m3i5ofq7vuogqapdnoshhq7mswmudhvfcr2craw25fdwtoe3lm
Expand Down Expand Up @@ -246,6 +246,9 @@ models:
requester_staking_instance_address: ${str:0x0000000000000000000000000000000000000000}
response_timeout: ${int:300}
expected_mech_response_time: ${int:300}
mech_invalid_response: ${str:Invalid Response}
mech_consecutive_failures_threshold: ${int:2}
tool_quarantine_duration: ${int:18000}
benchmarking_mode:
args:
enabled: ${bool:false}
Expand All @@ -271,6 +274,8 @@ models:
requests: ${str:total_requests}
accuracy: ${str:tool_accuracy}
sep: ${str:,}
max: ${str:max}
datetime_format: ${str:%Y-%m-%d %H:%M:%S}
network_subgraph:
args:
headers:
Expand Down
16 changes: 15 additions & 1 deletion packages/valory/services/trader/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license: Apache-2.0
fingerprint:
README.md: bafybeigtuothskwyvrhfosps2bu6suauycolj67dpuxqvnicdrdu7yhtvq
fingerprint_ignore_patterns: []
agent: valory/trader:0.1.0:bafybeihq257kwjybsvrpzhjx4wbretrsurodpckjqdhv3idlnbu4mqvfnq
agent: valory/trader:0.1.0:bafybeih3r5xefwfqfdmmwx3e5n3i4df7pv3mvhqlk7qen2i75anj27ds4u
number_of_agents: 4
deployment:
agent:
Expand Down Expand Up @@ -146,6 +146,9 @@ type: skill
mech_interaction_sleep_time: ${MECH_INTERACTION_SLEEP_TIME:int:10}
policy_store_update_offset: ${POLICY_STORE_UPDATE_OFFSET:int:259200}
expected_mech_response_time: ${EXPECTED_MECH_RESPONSE_TIME:int:300}
mech_invalid_response: ${MECH_INVALID_RESPONSE:str:Invalid Response}
mech_consecutive_failures_threshold: ${MECH_CONSECUTIVE_FAILURES_THRESHOLD:int:2}
tool_quarantine_duration: ${TOOL_QUARANTINE_DURATION:int:18000}
benchmark_tool: &id004
args:
log_dir: ${LOG_DIR:str:/benchmarks}
Expand Down Expand Up @@ -174,6 +177,8 @@ type: skill
requests: ${ACC_INFO_FIELDS_REQUESTS:str:total_requests}
accuracy: ${ACC_INFO_FIELDS_ACCURACY:str:tool_accuracy}
sep: ${ACC_INFO_FIELDS_SEP:str:,}
max: ${ACC_INFO_FIELDS_MAX:str:max}
datetime_format: ${ACC_INFO_FIELDS_DATETIME_FORMAT:str:%Y-%m-%d %H:%M:%S}
network_subgraph: &id006
args:
headers:
Expand Down Expand Up @@ -368,6 +373,9 @@ type: skill
mech_interaction_sleep_time: ${MECH_INTERACTION_SLEEP_TIME:int:10}
policy_store_update_offset: ${POLICY_STORE_UPDATE_OFFSET:int:259200}
expected_mech_response_time: ${EXPECTED_MECH_RESPONSE_TIME:int:300}
mech_invalid_response: ${MECH_INVALID_RESPONSE:str:Invalid Response}
mech_consecutive_failures_threshold: ${MECH_CONSECUTIVE_FAILURES_THRESHOLD:int:2}
tool_quarantine_duration: ${TOOL_QUARANTINE_DURATION:int:18000}
benchmark_tool: *id004
acc_info_fields: *id005
network_subgraph: *id006
Expand Down Expand Up @@ -486,6 +494,9 @@ type: skill
mech_interaction_sleep_time: ${MECH_INTERACTION_SLEEP_TIME:int:10}
policy_store_update_offset: ${POLICY_STORE_UPDATE_OFFSET:int:259200}
expected_mech_response_time: ${EXPECTED_MECH_RESPONSE_TIME:int:300}
mech_invalid_response: ${MECH_INVALID_RESPONSE:str:Invalid Response}
mech_consecutive_failures_threshold: ${MECH_CONSECUTIVE_FAILURES_THRESHOLD:int:2}
tool_quarantine_duration: ${TOOL_QUARANTINE_DURATION:int:18000}
benchmark_tool: *id004
acc_info_fields: *id005
network_subgraph: *id006
Expand Down Expand Up @@ -604,6 +615,9 @@ type: skill
mech_interaction_sleep_time: ${MECH_INTERACTION_SLEEP_TIME:int:10}
policy_store_update_offset: ${POLICY_STORE_UPDATE_OFFSET:int:259200}
expected_mech_response_time: ${EXPECTED_MECH_RESPONSE_TIME:int:300}
mech_invalid_response: ${MECH_INVALID_RESPONSE:str:Invalid Response}
mech_consecutive_failures_threshold: ${MECH_CONSECUTIVE_FAILURES_THRESHOLD:int:2}
tool_quarantine_duration: ${TOOL_QUARANTINE_DURATION:int:18000}
benchmark_tool: *id004
acc_info_fields: *id005
network_subgraph: *id006
Expand Down
5 changes: 4 additions & 1 deletion packages/valory/services/trader_pearl/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ license: Apache-2.0
fingerprint:
README.md: bafybeibg7bdqpioh4lmvknw3ygnllfku32oca4eq5pqtvdrdsgw6buko7e
fingerprint_ignore_patterns: []
agent: valory/trader:0.1.0:bafybeihq257kwjybsvrpzhjx4wbretrsurodpckjqdhv3idlnbu4mqvfnq
agent: valory/trader:0.1.0:bafybeih3r5xefwfqfdmmwx3e5n3i4df7pv3mvhqlk7qen2i75anj27ds4u
number_of_agents: 1
deployment:
agent:
Expand Down Expand Up @@ -104,6 +104,9 @@ models:
response_timeout: ${RESPONSE_TIMEOUT:int:300}
policy_store_update_offset: ${POLICY_STORE_UPDATE_OFFSET:int:259200}
expected_mech_response_time: ${EXPECTED_MECH_RESPONSE_TIME:int:300}
mech_invalid_response: ${MECH_INVALID_RESPONSE:str:Invalid Response}
mech_consecutive_failures_threshold: ${MECH_CONSECUTIVE_FAILURES_THRESHOLD:int:2}
tool_quarantine_duration: ${TOOL_QUARANTINE_DURATION:int:18000}
benchmark_tool:
args:
log_dir: /benchmarks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
from packages.valory.skills.decision_maker_abci.states.blacklisting import (
BlacklistingRound,
)
from packages.valory.skills.decision_maker_abci.states.handle_failed_tx import (
HandleFailedTxRound,
)


class BlacklistingBehaviour(DecisionMakerBaseBehaviour):
Expand All @@ -47,7 +50,7 @@ def _blacklist(self) -> None:
sampled_bet = self.bets[sampled_bet_index]

# the question is blacklisted, i.e., we did not place a bet on it,
# therefore, we bump to the queue status to next status
# therefore, we bump the queue's status to the next one
sampled_bet.queue_status = sampled_bet.queue_status.next_status()

def setup(self) -> None:
Expand All @@ -69,6 +72,14 @@ def async_act(self) -> Generator:
bets_hash = (
None if self.benchmarking_mode.enabled else self.hash_stored_bets()
)
if (
self.synchronized_data.tx_submitter
!= HandleFailedTxRound.auto_round_id()
):
# if we are here, then the tool has responded with an error
self.policy.tool_responded(
self.synchronized_data.mech_tool, self.synced_timestamp
)
policy = self.policy.serialize()
payload = BlacklistingPayload(self.context.agent_address, bets_hash, policy)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
from typing import Any, Dict, Generator, List, Optional, Tuple, Union

from packages.valory.skills.decision_maker_abci.behaviours.base import (
DecisionMakerBaseBehaviour,
remove_fraction_wei,
)
from packages.valory.skills.decision_maker_abci.behaviours.storage_manager import (
StorageManagerBehaviour,
)
from packages.valory.skills.decision_maker_abci.io_.loader import ComponentPackageLoader
from packages.valory.skills.decision_maker_abci.models import (
BenchmarkingMockData,
Expand Down Expand Up @@ -59,7 +61,7 @@
TOKEN_PRECISION = 10**18


class DecisionReceiveBehaviour(DecisionMakerBaseBehaviour):
class DecisionReceiveBehaviour(StorageManagerBehaviour):
"""A behaviour in which the agents receive the mech response."""

matching_round = DecisionReceiveRound
Expand Down Expand Up @@ -93,6 +95,17 @@ def mech_response(self) -> MechInteractionResponse:
return MechInteractionResponse(error=error)
return self._mech_response

@property
def is_invalid_response(self) -> bool:
"""Check if the response is invalid."""
if self.mech_response.result is None:
self.context.logger.warning(
"Trying to check whether the mech's response is invalid but no response has been detected! "
"Assuming invalid response."
)
return True
return self.mech_response.result == self.params.mech_invalid_response

def _next_dataset_row(self) -> Optional[Dict[str, str]]:
"""Read the next row from the input dataset which is used during the benchmarking mode.
Expand Down Expand Up @@ -527,12 +540,17 @@ def async_act(self) -> Generator:
"""Do the action."""

with self.context.benchmark_tool.measure(self.behaviour_id).local():
success = yield from self._setup_policy_and_tools()
if not success:
return None

prediction_response = self._get_decision()
is_profitable = None
bet_amount = None
next_mock_data_row = None
bets_hash = None
decision_received_timestamp = None
policy = None
if prediction_response is not None and prediction_response.vote is not None:
is_profitable, bet_amount = yield from self._is_profitable(
prediction_response
Expand All @@ -552,6 +570,14 @@ def async_act(self) -> Generator:
bet_amount,
)

if prediction_response is not None:
self.policy.tool_responded(
self.synchronized_data.mech_tool,
self.synced_timestamp,
self.is_invalid_response,
)
policy = self.policy.serialize()

# always remove the processed trade from the benchmarking input file
# now there is one reader pointer per market
if self.benchmarking_mode.enabled:
Expand All @@ -572,7 +598,9 @@ def async_act(self) -> Generator:
prediction_response.confidence if prediction_response else None,
bet_amount,
next_mock_data_row,
policy,
decision_received_timestamp,
)

self._store_all()
yield from self.finish_behaviour(payload)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
#
# Copyright 2023 Valory AG
# Copyright 2023-2024 Valory AG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -24,11 +24,14 @@
from packages.valory.skills.decision_maker_abci.behaviours.base import (
DecisionMakerBaseBehaviour,
)
from packages.valory.skills.decision_maker_abci.payloads import VotingPayload
from packages.valory.skills.decision_maker_abci.payloads import HandleFailedTxPayload
from packages.valory.skills.decision_maker_abci.states.bet_placement import (
BetPlacementRound,
)
from packages.valory.skills.decision_maker_abci.states.handle_failed_tx import (
HandleFailedTxRound,
)
from packages.valory.skills.decision_maker_abci.states.redeem import RedeemRound
from packages.valory.skills.mech_interact_abci.states.request import MechRequestRound


class HandleFailedTxBehaviour(DecisionMakerBaseBehaviour):
Expand All @@ -40,9 +43,13 @@ def async_act(self) -> Generator:
"""Do the action."""

with self.context.benchmark_tool.measure(self.behaviour_id).local():
after_redeeming = (
self.synchronized_data.tx_submitter == RedeemRound.auto_round_id()
after_bet_attempt = self.synchronized_data.tx_submitter in (
MechRequestRound.auto_round_id(),
BetPlacementRound.auto_round_id(),
)
submitter = HandleFailedTxRound.auto_round_id()
payload = HandleFailedTxPayload(
self.context.agent_address, after_bet_attempt, submitter
)
payload = VotingPayload(self.context.agent_address, not after_redeeming)

yield from self.finish_behaviour(payload)
Loading

0 comments on commit 1ce37f9

Please sign in to comment.