diff --git a/packages/packages.json b/packages/packages.json index e17d14a30..c5a6e8f13 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -1,17 +1,18 @@ { "dev": { - "skill/valory/market_manager_abci/0.1.0": "bafybeicjqkzen2gvpnc3syojcf6ibr4kjaorcwktikqp2zzxec6vs64oky", - "skill/valory/decision_maker_abci/0.1.0": "bafybeic77zhxf5a53ngfzacklmm3nag4t4jeufdhoeg3ykrmvknojtwipi", - "skill/valory/trader_abci/0.1.0": "bafybeibi3rt3rdk4bvng3tlmwdxal3mk3bflq4cgq3fxyjwzpmhj3y6pmy", + "skill/valory/market_manager_abci/0.1.0": "bafybeigvw5tqei5xb272jb7retxiryhuhxxzupddmbdixgsmxzco3n2dde", + "skill/valory/decision_maker_abci/0.1.0": "bafybeihm77vt53vu3xt6x7istsvaw75juptlynpriebgeltbil5evvhtue", + "skill/valory/trader_abci/0.1.0": "bafybeiea2r67bzi5gkymu2pu2m3sg3lflke5m2finonak4uprqpbdcp2ru", "contract/valory/market_maker/0.1.0": "bafybeif6hivvhxqv4a3uqo2v3yszluzrmngsp624utdi466xwo5qbz5bsi", - "agent/valory/trader/0.1.0": "bafybeigoojaxpc7sz7vuswkxvpa5lp37lipuwc4qycztqk4hxdesmxqcda", - "service/valory/trader/0.1.0": "bafybeidyuzdmwrt66w32oppopviesvhinmwd76q73zv3dex2th7nldpbyi", + "agent/valory/trader/0.1.0": "bafybeiba5eqawktwkpziiazxm5u6ftm7o3zytcbafqsjwt7zrr63o2yis4", + "service/valory/trader/0.1.0": "bafybeifqi4yprf6ajureyqn45aa3mo7vezwsx63skc4n56grlormdzoz5i", "contract/valory/erc20/0.1.0": "bafybeiggo4u56drxusvcdruqrr7mlfzqbieg4hajalh4tkctxhh3c5lpdi", - "skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeidtrigrfjikl7tkbtowbp6mrdzxulayxnxcmviwy3gag557vnymlq", - "contract/valory/mech/0.1.0": "bafybeibfikekaruskx6ui7u4qnls57i2namfxi45zhqslziqyxg4npjzxu", + "skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeiey57caacd6d3ow25i6a2zuiinkx6kjtckdktannk7kijpd3p2zb4", + "contract/valory/mech/0.1.0": "bafybeidtezc4ubsyqdltiojvqe5eeh77ejte7vqbojspiej5quivgap3ae", "contract/valory/realitio/0.1.0": "bafybeigb722aznqhc5lsbt3dn4bpyaqe5hnl5onmnestqmzliwtvl3eaom", "contract/valory/realitio_proxy/0.1.0": "bafybeibvndq6756qck7forgeavhdbn6ykgqs2ufyg7n5g6qdfpveatxuwy", - "contract/valory/conditional_tokens/0.1.0": "bafybeicxwjdbmjajgr5rsmadtkxxwmcm42r2htef3tvng73uzib4hmb6qa" + "contract/valory/conditional_tokens/0.1.0": "bafybeicxwjdbmjajgr5rsmadtkxxwmcm42r2htef3tvng73uzib4hmb6qa", + "contract/valory/agent_registry/0.1.0": "bafybeib6odummk6qqietjekpljkmhqfxk7kv56kv6pyfsnnanews625ncy" }, "third_party": { "protocol/open_aea/signing/1.0.0": "bafybeifuxs7gdg2okbn7uofymenjlmnih2wxwkym44lsgwmklgwuckxm2m", diff --git a/packages/valory/agents/trader/aea-config.yaml b/packages/valory/agents/trader/aea-config.yaml index 2e771fc1d..fe3922d6c 100644 --- a/packages/valory/agents/trader/aea-config.yaml +++ b/packages/valory/agents/trader/aea-config.yaml @@ -21,7 +21,7 @@ contracts: - valory/market_maker:0.1.0:bafybeif6hivvhxqv4a3uqo2v3yszluzrmngsp624utdi466xwo5qbz5bsi - valory/erc20:0.1.0:bafybeiggo4u56drxusvcdruqrr7mlfzqbieg4hajalh4tkctxhh3c5lpdi - valory/multisend:0.1.0:bafybeidfktuprydtmi4umolfles5qaf7s3t26puvvs44hvkq6uwwr3ia3a -- valory/mech:0.1.0:bafybeibfikekaruskx6ui7u4qnls57i2namfxi45zhqslziqyxg4npjzxu +- valory/mech:0.1.0:bafybeidtezc4ubsyqdltiojvqe5eeh77ejte7vqbojspiej5quivgap3ae - valory/conditional_tokens:0.1.0:bafybeicxwjdbmjajgr5rsmadtkxxwmcm42r2htef3tvng73uzib4hmb6qa - valory/realitio:0.1.0:bafybeigb722aznqhc5lsbt3dn4bpyaqe5hnl5onmnestqmzliwtvl3eaom - valory/realitio_proxy:0.1.0:bafybeibvndq6756qck7forgeavhdbn6ykgqs2ufyg7n5g6qdfpveatxuwy @@ -41,10 +41,10 @@ skills: - valory/reset_pause_abci:0.1.0:bafybeiblayblhp5wuirfomwcpgydg35ve5tfq3xxetlosjn47wva5ucmzy - valory/termination_abci:0.1.0:bafybeieqfhvk6klnvxak3vo2ibslkrnnk2bfsn5l3gbaelcprd6cjngxki - valory/transaction_settlement_abci:0.1.0:bafybeicisazpyvnnzlqso3txiucxr5qhsa4ac7ius6b4mhouxr2wkadwfy -- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeidtrigrfjikl7tkbtowbp6mrdzxulayxnxcmviwy3gag557vnymlq -- valory/market_manager_abci:0.1.0:bafybeicjqkzen2gvpnc3syojcf6ibr4kjaorcwktikqp2zzxec6vs64oky -- valory/decision_maker_abci:0.1.0:bafybeic77zhxf5a53ngfzacklmm3nag4t4jeufdhoeg3ykrmvknojtwipi -- valory/trader_abci:0.1.0:bafybeibi3rt3rdk4bvng3tlmwdxal3mk3bflq4cgq3fxyjwzpmhj3y6pmy +- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeiey57caacd6d3ow25i6a2zuiinkx6kjtckdktannk7kijpd3p2zb4 +- valory/market_manager_abci:0.1.0:bafybeigvw5tqei5xb272jb7retxiryhuhxxzupddmbdixgsmxzco3n2dde +- valory/decision_maker_abci:0.1.0:bafybeihm77vt53vu3xt6x7istsvaw75juptlynpriebgeltbil5evvhtue +- valory/trader_abci:0.1.0:bafybeiea2r67bzi5gkymu2pu2m3sg3lflke5m2finonak4uprqpbdcp2ru default_ledger: ethereum required_ledgers: - ethereum @@ -188,9 +188,10 @@ models: slippage: ${float:0.01} redeem_margin_days: ${int:15} epsilon: ${float:0.1} - irrelevant_tools: ${set:{"openai-text-davinci-002", "openai-text-davinci-003", "openai-gpt-3.5-turbo", - "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", "stabilityai-stable-diffusion-xl-beta-v2-2-2", - "stabilityai-stable-diffusion-512-v2-1", "stabilityai-stable-diffusion-768-v2-1"}} + irrelevant_tools: ${list:["openai-text-davinci-002", "openai-text-davinci-003", + "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", + "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", + "stabilityai-stable-diffusion-768-v2-1"]} --- public_id: valory/p2p_libp2p_client:0.1.0 type: connection diff --git a/packages/valory/contracts/agent_registry/contract.yaml b/packages/valory/contracts/agent_registry/contract.yaml index dc9566f46..c9713347c 100644 --- a/packages/valory/contracts/agent_registry/contract.yaml +++ b/packages/valory/contracts/agent_registry/contract.yaml @@ -6,12 +6,9 @@ description: Agent Registry contract license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: - __init__.py: bafybeidey4syohls5hxmso6qsp5p4uhtzle5txv2mlbym6ktjzknich6oa - build/AgentRegistry.json: bafybeia4qi2vstrutejzrxfpbb6eift7va5cjs7bparaal2fafiiczuiyy - build/AgentRegistryL2.json: bafybeic2jylwfod4nmdtbs4izyxyi246pd3f35aoqyahnmyrvzn7j3sv4e - contract.py: bafybeibqwl52cnz64cysjd2jnjijuakdvyrffapxq65cdzx6g65gu42deq - tests/__init__.py: bafybeicl2oklx774jomlt6wwwegfdzrxh6iazjxwcyc7h4gepjljkpl4ji - tests/test_contract.py: bafybeicj535veqf35zb3ycu5iqjvqgj4a2kdmogmx5ba7fiolt5chah42a + __init__.py: bafybeid3wfzglolebuo6jrrsopswzu4lk77bm76mvw3euizlsjtnt3wmgu + build/AgentRegistry.json: bafybeicoe5elvvsv2neiirsdn4uddrilizmyib3x4mvpklr7olhj2kh4ue + contract.py: bafybeihrv6blme3v6diwci6zxxn72qbg5sanzmfq5tobhs4375ebcuyday fingerprint_ignore_patterns: [] contracts: [] class_name: AgentRegistryContract diff --git a/packages/valory/contracts/mech/contract.yaml b/packages/valory/contracts/mech/contract.yaml index 429716ec0..3e87738ff 100644 --- a/packages/valory/contracts/mech/contract.yaml +++ b/packages/valory/contracts/mech/contract.yaml @@ -9,7 +9,7 @@ fingerprint: README.md: bafybeibl4uw7rs6mwh7zuvdnqmj2o2xyr7nx5qk3w7torwx3jg6farn6ca __init__.py: bafybeicx5pxh3cxnml2biuuoebvafvu5tvy6mgkzyjzuubuoeebb5yzjsm build/mech.json: bafybeihsfz7rdnf6cpa3c4eagvs4pw6jhr6pcsikstakejrlkuwvwzhw7m - contract.py: bafybeigypn3frcjr7mcmdoe5ubgoy57owm4bfcgtrcytiu76u7khthlvei + contract.py: bafybeifbfa6p3jcwn6j7s5aiiqxb3ne4vbmvoggr5zpptmd727gpsjqjpe fingerprint_ignore_patterns: [] contracts: [] class_name: Mech diff --git a/packages/valory/services/trader/service.yaml b/packages/valory/services/trader/service.yaml index 4081035b4..d7036fbde 100644 --- a/packages/valory/services/trader/service.yaml +++ b/packages/valory/services/trader/service.yaml @@ -7,7 +7,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeigtuothskwyvrhfosps2bu6suauycolj67dpuxqvnicdrdu7yhtvq fingerprint_ignore_patterns: [] -agent: valory/trader:0.1.0:bafybeigoojaxpc7sz7vuswkxvpa5lp37lipuwc4qycztqk4hxdesmxqcda +agent: valory/trader:0.1.0:bafybeiba5eqawktwkpziiazxm5u6ftm7o3zytcbafqsjwt7zrr63o2yis4 number_of_agents: 4 deployment: {} --- @@ -105,10 +105,10 @@ type: skill slippage: ${SLIPPAGE:float:0.01} redeem_margin_days: ${REDEEM_MARGIN_DAYS:int:15} epsilon: ${EPSILON:float:0.1} - irrelevant_tools: ${IRRELEVANT_TOOLS:set:{"openai-text-davinci-002", "openai-text-davinci-003", - "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", - "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", - "stabilityai-stable-diffusion-768-v2-1"}} + irrelevant_tools: ${IRRELEVANT_TOOLS:list:["openai-text-davinci-002", "openai-text-davinci-003", + "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", + "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", + "stabilityai-stable-diffusion-768-v2-1"]} benchmark_tool: &id005 args: log_dir: ${LOG_DIR:str:/benchmarks} @@ -174,10 +174,10 @@ type: skill slippage: ${SLIPPAGE:float:0.01} redeem_margin_days: ${REDEEM_MARGIN_DAYS:int:15} epsilon: ${EPSILON:float:0.1} - irrelevant_tools: ${IRRELEVANT_TOOLS:set:{"openai-text-davinci-002", "openai-text-davinci-003", - "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", - "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", - "stabilityai-stable-diffusion-768-v2-1"}} + irrelevant_tools: ${IRRELEVANT_TOOLS:list:["openai-text-davinci-002", "openai-text-davinci-003", + "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", + "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", + "stabilityai-stable-diffusion-768-v2-1"]} benchmark_tool: *id005 2: models: @@ -241,10 +241,10 @@ type: skill slippage: ${SLIPPAGE:float:0.01} redeem_margin_days: ${REDEEM_MARGIN_DAYS:int:15} epsilon: ${EPSILON:float:0.1} - irrelevant_tools: ${IRRELEVANT_TOOLS:set:{"openai-text-davinci-002", "openai-text-davinci-003", - "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", - "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", - "stabilityai-stable-diffusion-768-v2-1"}} + irrelevant_tools: ${IRRELEVANT_TOOLS:list:["openai-text-davinci-002", "openai-text-davinci-003", + "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", + "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", + "stabilityai-stable-diffusion-768-v2-1"]} benchmark_tool: *id005 3: models: @@ -308,10 +308,10 @@ type: skill slippage: ${SLIPPAGE:float:0.01} redeem_margin_days: ${REDEEM_MARGIN_DAYS:int:15} epsilon: ${EPSILON:float:0.1} - irrelevant_tools: ${IRRELEVANT_TOOLS:set:{"openai-text-davinci-002", "openai-text-davinci-003", - "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", - "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", - "stabilityai-stable-diffusion-768-v2-1"}} + irrelevant_tools: ${IRRELEVANT_TOOLS:list:["openai-text-davinci-002", "openai-text-davinci-003", + "openai-gpt-3.5-turbo", "openai-gpt-4", "stabilityai-stable-diffusion-v1-5", + "stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1", + "stabilityai-stable-diffusion-768-v2-1"]} benchmark_tool: *id005 --- public_id: valory/ledger:0.19.0 diff --git a/packages/valory/skills/decision_maker_abci/behaviours/base.py b/packages/valory/skills/decision_maker_abci/behaviours/base.py index 889a40483..9ba4cf446 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/base.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/base.py @@ -42,6 +42,7 @@ DecisionMakerParams, MultisendBatch, ) +from packages.valory.skills.decision_maker_abci.policy import EGreedyPolicy from packages.valory.skills.decision_maker_abci.states.base import SynchronizedData from packages.valory.skills.transaction_settlement_abci.payload_tools import ( hash_payload_to_hex, @@ -56,6 +57,7 @@ # which is what we want in most cases # more info here: https://safe-docs.dev.gnosisdev.com/safe/docs/contracts_tx_execution/ SAFE_GAS = 0 +CID_PREFIX = "f01701220" def remove_fraction_wei(amount: int, fraction: float) -> int: @@ -75,6 +77,7 @@ def __init__(self, **kwargs: Any) -> None: self.multisend_batches: List[MultisendBatch] = [] self.multisend_data = b"" self._safe_tx_hash = "" + self._policy: Optional[EGreedyPolicy] = None @property def params(self) -> DecisionMakerParams: @@ -129,6 +132,15 @@ def tx_hex(self) -> Optional[str]: SafeOperation.DELEGATE_CALL.value, ) + @property + def policy(self) -> EGreedyPolicy: + """Get the policy.""" + if self._policy is None: + raise ValueError( + "Attempting to retrieve the policy before it has been established." + ) + return self._policy + @staticmethod def wei_to_native(wei: int) -> float: """Convert WEI to native token.""" diff --git a/packages/valory/skills/decision_maker_abci/behaviours/decision_receive.py b/packages/valory/skills/decision_maker_abci/behaviours/decision_receive.py index 342537407..fd3506eef 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/decision_receive.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/decision_receive.py @@ -26,6 +26,7 @@ from packages.valory.protocols.contract_api import ContractApiMessage from packages.valory.skills.abstract_round_abci.base import get_name from packages.valory.skills.decision_maker_abci.behaviours.base import ( + CID_PREFIX, DecisionMakerBaseBehaviour, WaitableConditionType, remove_fraction_wei, @@ -41,7 +42,6 @@ from packages.valory.skills.market_manager_abci.bets import BINARY_N_SLOTS -IPFS_HASH_PREFIX = "f01701220" ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" @@ -103,7 +103,7 @@ def mech_response_api(self) -> MechResponseSpecs: def set_mech_response_specs(self) -> None: """Set the mech's response specs.""" - full_ipfs_hash = IPFS_HASH_PREFIX + self.response_hex + full_ipfs_hash = CID_PREFIX + self.response_hex ipfs_link = self.params.ipfs_address + full_ipfs_hash + f"/{self.request_id}" # The url must be dynamically generated as it depends on the ipfs hash self.mech_response_api.__dict__["_frozen"] = False @@ -112,7 +112,7 @@ def set_mech_response_specs(self) -> None: @property def mech_response(self) -> MechInteractionResponse: - """Get the mech response api specs.""" + """Get the mech's response.""" if self._mech_response is None: error = "The mech's response has not been set!" return MechInteractionResponse(error=error) diff --git a/packages/valory/skills/decision_maker_abci/behaviours/decision_request.py b/packages/valory/skills/decision_maker_abci/behaviours/decision_request.py index 456702efe..13d006308 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/decision_request.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/decision_request.py @@ -120,7 +120,8 @@ def setup(self) -> None: question=sampled_bet.title, yes=sampled_bet.yes, no=sampled_bet.no ) prompt = self.params.prompt_template.substitute(prompt_params) - self._metadata = MechMetadata(prompt=prompt, tool=self.params.mech_tool) + tool = self.synchronized_data.mech_tool + self._metadata = MechMetadata(prompt, tool) msg = f"Prepared metadata {self.metadata!r} for the request." self.context.logger.info(msg) diff --git a/packages/valory/skills/decision_maker_abci/behaviours/reedem.py b/packages/valory/skills/decision_maker_abci/behaviours/reedem.py index 595083910..9df1e737c 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/reedem.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/reedem.py @@ -39,7 +39,7 @@ WaitableConditionType, ) from packages.valory.skills.decision_maker_abci.models import MultisendBatch -from packages.valory.skills.decision_maker_abci.payloads import MultisigTxPayload +from packages.valory.skills.decision_maker_abci.payloads import RedeemPayload from packages.valory.skills.decision_maker_abci.redeem_info import ( Condition, FPMM, @@ -86,6 +86,10 @@ def synced_timestamp(self) -> int: """Return the synchronized timestamp across the agents.""" return int(self.round_sequence.last_round_transition_timestamp.timestamp()) + def setup(self) -> None: + """Setup the behaviour""" + self._policy = self.synchronized_data.policy + def _set_block_number(self, trade: Trade) -> Generator: """Set the block number of the given trade's market.""" timestamp = trade.fpmm.creationTimestamp @@ -105,6 +109,24 @@ def _set_block_number(self, trade: Trade) -> Generator: f"Chose block number {self.from_block_mapping[condition_id]!r} as closest to timestamp {timestamp!r}" ) + def _update_policy(self, update: Trade) -> None: + """Update the policy.""" + claimable_xdai = self.wei_to_native(update.claimable_amount) + tool_index = self.synchronized_data.utilized_tools[update.transactionHash] + self.policy.add_reward(tool_index, claimable_xdai) + + def _stats_report(self) -> None: + """Report policy statistics.""" + stats_report = "Policy statistics so far:\n" + for i, tool in enumerate(self.synchronized_data.available_mech_tools): + stats_report += ( + f"{tool} tool:\n" + f"\tTimes used: {self.policy.counts[i]}\n" + f"\tReward rate: {self.policy.reward_rates[i]}\n" + ) + stats_report += f"Best tool so far is {self.policy.select_tool()}." + self.context.logger.info(stats_report) + def update_redeem_info(self, chunk: list) -> Generator: """Update the redeeming information using the given chunk.""" trades_updates: Iterator[Trade] = ( @@ -115,6 +137,8 @@ def update_redeem_info(self, chunk: list) -> Generator: ) for update in trades_updates: + self._update_policy(update) + # do not use the information if position is not winning if not update.is_winning: continue @@ -132,6 +156,8 @@ def update_redeem_info(self, chunk: list) -> Generator: if update == unique_obj: self.claimable_amounts[condition_id] += update.claimable_amount + self._stats_report() + class RedeemBehaviour(RedeemInfoBehaviour): """Redeem the winnings.""" @@ -523,11 +549,11 @@ def async_act(self) -> Generator: yield from self._clean_redeem_info() agent = self.context.agent_address redeem_tx_hex = yield from self._prepare_safe_tx() - tx_submitter = ( - self.matching_round.auto_round_id() - if redeem_tx_hex is not None - else None - ) - payload = MultisigTxPayload(agent, tx_submitter, redeem_tx_hex) + tx_submitter = policy = None + if redeem_tx_hex is not None: + tx_submitter = self.matching_round.auto_round_id() + policy = self.policy.serialize() + + payload = RedeemPayload(agent, tx_submitter, redeem_tx_hex, policy) yield from self.finish_behaviour(payload) diff --git a/packages/valory/skills/decision_maker_abci/behaviours/round_behaviour.py b/packages/valory/skills/decision_maker_abci/behaviours/round_behaviour.py index 49be37e88..af7643e54 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/round_behaviour.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/round_behaviour.py @@ -44,6 +44,9 @@ from packages.valory.skills.decision_maker_abci.behaviours.sampling import ( SamplingBehaviour, ) +from packages.valory.skills.decision_maker_abci.behaviours.tool_selection import ( + ToolSelectionBehaviour, +) from packages.valory.skills.decision_maker_abci.rounds import DecisionMakerAbciApp @@ -60,4 +63,5 @@ class AgentDecisionMakerRoundBehaviour(AbstractRoundBehaviour): BetPlacementBehaviour, # type: ignore RedeemBehaviour, # type: ignore HandleFailedTxBehaviour, # type: ignore + ToolSelectionBehaviour, # type: ignore } diff --git a/packages/valory/skills/decision_maker_abci/behaviours/tool_selection.py b/packages/valory/skills/decision_maker_abci/behaviours/tool_selection.py new file mode 100644 index 000000000..b5a46b609 --- /dev/null +++ b/packages/valory/skills/decision_maker_abci/behaviours/tool_selection.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2023 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""This module contains the behaviour of the skill which is responsible for selecting a mech tool.""" + +import json +from typing import Any, Generator, List, Optional + +from packages.valory.contracts.agent_registry.contract import AgentRegistryContract +from packages.valory.protocols.contract_api import ContractApiMessage +from packages.valory.skills.abstract_round_abci.base import get_name +from packages.valory.skills.decision_maker_abci.behaviours.base import ( + CID_PREFIX, + DecisionMakerBaseBehaviour, + WaitableConditionType, +) +from packages.valory.skills.decision_maker_abci.models import AgentToolsSpecs +from packages.valory.skills.decision_maker_abci.payloads import ToolSelectionPayload +from packages.valory.skills.decision_maker_abci.policy import EGreedyPolicy +from packages.valory.skills.decision_maker_abci.states.tool_selection import ( + ToolSelectionRound, +) + + +class ToolSelectionBehaviour(DecisionMakerBaseBehaviour): + """A behaviour in which the agents select a mech tool.""" + + matching_round = ToolSelectionRound + + def __init__(self, **kwargs: Any) -> None: + """Initialize Behaviour.""" + super().__init__(**kwargs) + self._mech_id: int = 0 + self._mech_hash: str = "" + self.mech_tools: Optional[List[str]] = None + + @property + def mech_id(self) -> int: + """Get the mech's id.""" + return self._mech_id + + @mech_id.setter + def mech_id(self, mech_id: int) -> None: + """Set the mech's id.""" + self._mech_id = mech_id + + @property + def mech_hash(self) -> str: + """Get the hash of the mech agent.""" + return self._mech_hash + + @mech_hash.setter + def mech_hash(self, mech_hash: str) -> None: + """Set the hash of the mech agent.""" + self._mech_hash = mech_hash + + @property + def mech_tools_api(self) -> AgentToolsSpecs: + """Get the mech agent api specs.""" + return self.context.agent_tools + + def set_mech_agent_specs(self) -> None: + """Set the mech's agent specs.""" + full_ipfs_hash = CID_PREFIX + self.mech_hash + ipfs_link = self.params.ipfs_address + full_ipfs_hash + # The url needs to be dynamically generated as it depends on the ipfs hash + self.mech_tools_api.__dict__["_frozen"] = False + self.mech_tools_api.url = ipfs_link + self.mech_tools_api.__dict__["_frozen"] = True + + def _get_mech_id(self) -> WaitableConditionType: + """Get the mech's id.""" + result = yield from self._mech_contract_interact( + contract_callable="get_mech_id", + data_key="id", + placeholder=get_name(ToolSelectionBehaviour.mech_id), + ) + + return result + + def _get_mech_hash(self) -> WaitableConditionType: + """Get the mech's hash.""" + result = yield from self.contract_interact( + performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, # type: ignore + contract_address=self.params.agent_registry_address, + contract_public_id=AgentRegistryContract.contract_id, + contract_callable="get_hash", + data_key="hash", + placeholder=get_name(ToolSelectionBehaviour.mech_hash), + agent_id=self.mech_id, + ) + return result + + def _get_mech_tools(self) -> WaitableConditionType: + """Get the mech agent's tools from IPFS.""" + specs = self.mech_tools_api.get_spec() + res_raw = yield from self.get_http_response(**specs) + res = self.mech_tools_api.process_response(res_raw) + + if self.mech_tools_api.is_retries_exceeded(): + error = "Retries were exceeded while trying to get the mech agent's data." + self.context.logger.error(error) + return True + + if res is None: + msg = f"Could not get the mech agent's tools from {self.mech_tools_api.api_id}" + self.context.logger.error(msg) + self.mech_tools_api.increment_retries() + return False + + self.context.logger.info(f"Retrieved the mech agent's tools: {res}.") + if len(res) == 0: + res = None + self.context.logger.error("The mech agent's tools are empty!") + self.mech_tools = res + self.mech_tools_api.reset_retries() + return True + + def _get_tools( + self, + ) -> Generator[None, None, None]: + """Get the Mech's tools.""" + for step in ( + self._get_mech_id, + self._get_mech_hash, + self._get_mech_tools, + ): + yield from self.wait_for_condition_with_sleep(step) + + def _adjust_policy_tools(self, tools: List[str]) -> None: + """Add or remove tools from the policy to match the remote tools.""" + # remove tools if they are not available anymore + local = set(self.synchronized_data.available_mech_tools) + remote = set(tools) + relevant_remote = remote - self.params.irrelevant_tools + removed_tools_idx = [ + idx for idx, tool in enumerate(local) if tool not in relevant_remote + ] + if len(removed_tools_idx) > 0: + self.policy.remove_tools(removed_tools_idx) + + # add tools if there are new ones available + new_tools = remote - local + n_new_tools = len(new_tools) + if n_new_tools > 0: + self.policy.add_new_tools(n_new_tools) + + def _set_policy(self, tools: List[str]) -> None: + """Set the E Greedy Policy.""" + if self.synchronized_data.period_count == 0: + self._policy = EGreedyPolicy.initial_state(self.params.epsilon, len(tools)) + else: + self._policy = self.synchronized_data.policy + self._adjust_policy_tools(tools) + + def _select_tool(self) -> Generator[None, None, Optional[int]]: + """Select a Mech tool based on an e-greedy policy and return its index.""" + yield from self._get_tools() + if self.mech_tools is None: + return None + + self._set_policy(self.mech_tools) + return self.policy.select_tool() + + def async_act(self) -> Generator: + """Do the action.""" + + with self.context.benchmark_tool.measure(self.behaviour_id).local(): + mech_tools = policy = None + selected_tool = yield from self._select_tool() + if selected_tool is not None: + mech_tools = json.dumps(self.mech_tools) + policy = self.policy.serialize() + + payload = ToolSelectionPayload( + self.context.agent_address, + mech_tools, + policy, + selected_tool, + ) + + yield from self.finish_behaviour(payload) diff --git a/packages/valory/skills/decision_maker_abci/fsm_specification.yaml b/packages/valory/skills/decision_maker_abci/fsm_specification.yaml index 9fb83b998..28ae210b7 100644 --- a/packages/valory/skills/decision_maker_abci/fsm_specification.yaml +++ b/packages/valory/skills/decision_maker_abci/fsm_specification.yaml @@ -38,6 +38,7 @@ states: - RedeemRound - RefillRequiredRound - SamplingRound +- ToolSelectionRound transition_func: (BetPlacementRound, DONE): FinishedDecisionMakerRound (BetPlacementRound, INSUFFICIENT_BALANCE): RefillRequiredRound @@ -68,7 +69,11 @@ transition_func: (RedeemRound, NO_MAJORITY): RedeemRound (RedeemRound, NO_REDEEMING): FinishedWithoutRedeemingRound (RedeemRound, ROUND_TIMEOUT): RedeemRound - (SamplingRound, DONE): DecisionRequestRound + (SamplingRound, DONE): ToolSelectionRound (SamplingRound, NONE): FinishedWithoutDecisionRound (SamplingRound, NO_MAJORITY): SamplingRound (SamplingRound, ROUND_TIMEOUT): SamplingRound + (ToolSelectionRound, DONE): DecisionRequestRound + (ToolSelectionRound, NONE): ToolSelectionRound + (ToolSelectionRound, NO_MAJORITY): ToolSelectionRound + (ToolSelectionRound, ROUND_TIMEOUT): ToolSelectionRound diff --git a/packages/valory/skills/decision_maker_abci/models.py b/packages/valory/skills/decision_maker_abci/models.py index 28f948b32..145b82cca 100644 --- a/packages/valory/skills/decision_maker_abci/models.py +++ b/packages/valory/skills/decision_maker_abci/models.py @@ -126,7 +126,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.agent_registry_address: str = self._ensure( "agent_registry_address", kwargs, str ) - self.irrelevant_tools: set = self._ensure("irrelevant_tools", kwargs, set) + self.irrelevant_tools: set = set(self._ensure("irrelevant_tools", kwargs, list)) super().__init__(*args, **kwargs) @property diff --git a/packages/valory/skills/decision_maker_abci/payloads.py b/packages/valory/skills/decision_maker_abci/payloads.py index 1aea905b7..b393544d1 100644 --- a/packages/valory/skills/decision_maker_abci/payloads.py +++ b/packages/valory/skills/decision_maker_abci/payloads.py @@ -50,6 +50,13 @@ class MultisigTxPayload(BaseTxPayload): tx_hash: Optional[str] +@dataclass(frozen=True) +class RedeemPayload(MultisigTxPayload): + """Represents a transaction payload for preparing an on-chain transaction for redeeming.""" + + policy: Optional[str] + + @dataclass(frozen=True) class RequestPayload(MultisigTxPayload): """Represents a transaction payload for preparing an on-chain transaction for a mech request.""" @@ -62,3 +69,12 @@ class VotingPayload(BaseTxPayload): """Represents a transaction payload for voting.""" vote: bool + + +@dataclass(frozen=True) +class ToolSelectionPayload(BaseTxPayload): + """Represents a transaction payload for selecting a mech tool.""" + + mech_tools: Optional[str] + policy: Optional[str] + index: Optional[int] diff --git a/packages/valory/skills/decision_maker_abci/policy.py b/packages/valory/skills/decision_maker_abci/policy.py new file mode 100644 index 000000000..fc83e1959 --- /dev/null +++ b/packages/valory/skills/decision_maker_abci/policy.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2023 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""This module contains an Epsilon Greedy Policy implementation.""" + +import json +import random +from dataclasses import asdict, dataclass, is_dataclass +from typing import Any, List, Optional + + +class DataclassEncoder(json.JSONEncoder): + """A custom JSON encoder for dataclasses.""" + + def default(self, o: Any) -> Any: + """The default JSON encoder.""" + if is_dataclass(o): + return asdict(o) + return super().default(o) + + +def argmax(li: List) -> int: + """Get the index of the max value within the provided list.""" + return li.index((max(li))) + + +@dataclass +class EGreedyPolicy: + """An e-Greedy policy for the tool selection.""" + + eps: float + n_tools: int + counts: List[int] + rewards: List[float] + + @classmethod + def initial_state(cls, eps: float, n_tools: int) -> "EGreedyPolicy": + """Return an instance on its initial state.""" + if n_tools == 0: + error = f"Cannot initialize an e Greedy Policy with {n_tools=}" + raise ValueError(error) + + return EGreedyPolicy(eps, n_tools, [0] * n_tools, [0.0] * n_tools) + + @classmethod + def deserialize(cls, policy: str) -> "EGreedyPolicy": + """Deserialize a string to an `EGreedyPolicy` object.""" + return EGreedyPolicy(**json.loads(policy)) + + @property + def random_tool(self) -> int: + """Get the index of a tool randomly.""" + return random.randrange(self.n_tools) # nosec + + @property + def reward_rates(self) -> List[float]: + """Get the reward rates.""" + return [reward / count for reward, count in zip(self.rewards, self.counts)] + + def add_new_tools(self, n_new: int) -> None: + """Add new tools to the current policy.""" + self.n_tools += n_new + self.counts.extend([0] * n_new) + self.rewards.extend([0.0] * n_new) + + def remove_tools(self, indexes: List[int]) -> None: + """Remove the knowledge for the tools corresponding to the given indexes.""" + self.n_tools -= len(indexes) + for i in indexes: + try: + del self.counts[i] + del self.rewards[i] + except IndexError as exc: + error = "Attempted to remove tools using incorrect indexes!" + raise ValueError(error) from exc + + def select_tool(self) -> Optional[int]: + """Select a Mech tool and return its index.""" + if self.n_tools == 0: + return None + + if sum(self.counts) == 0 or random.random() < self.eps: # nosec + return self.random_tool + + return argmax(self.reward_rates) + + def add_reward(self, index: int, reward: float) -> None: + """Add a reward for the tool corresponding to the given index.""" + self.counts[index] += 1 + self.rewards[index] += reward + + def serialize(self) -> str: + """Return the policy serialized.""" + return json.dumps(self, cls=DataclassEncoder, sort_keys=True) diff --git a/packages/valory/skills/decision_maker_abci/redeem_info.py b/packages/valory/skills/decision_maker_abci/redeem_info.py index 6e4a2a940..33e4d5e51 100644 --- a/packages/valory/skills/decision_maker_abci/redeem_info.py +++ b/packages/valory/skills/decision_maker_abci/redeem_info.py @@ -101,6 +101,7 @@ class Trade: outcomeIndex: int outcomeTokenMarginalPrice: float outcomeTokensTraded: int + transactionHash: str def __post_init__(self) -> None: """Post initialization to adjust the values.""" @@ -124,14 +125,17 @@ def __hash__(self) -> int: """Custom hashing operator.""" return hash(self.fpmm.condition.id) + hash(self.fpmm.question.id) - @property - def claimable_amount(self) -> int: - """Get the claimable amount of the current market.""" - return int(self.outcomeTokenMarginalPrice * self.outcomeTokensTraded) - @property def is_winning(self) -> bool: """Return whether the current position is winning.""" our_answer = self.outcomeIndex correct_answer = self.fpmm.current_answer_index return our_answer == correct_answer + + @property + def claimable_amount(self) -> int: + """Get the claimable amount of the current market.""" + amount = int(self.outcomeTokenMarginalPrice * self.outcomeTokensTraded) + if self.is_winning: + return amount + return -amount diff --git a/packages/valory/skills/decision_maker_abci/rounds.py b/packages/valory/skills/decision_maker_abci/rounds.py index ba22eace7..6d46ff17d 100644 --- a/packages/valory/skills/decision_maker_abci/rounds.py +++ b/packages/valory/skills/decision_maker_abci/rounds.py @@ -55,6 +55,9 @@ ) from packages.valory.skills.decision_maker_abci.states.redeem import RedeemRound from packages.valory.skills.decision_maker_abci.states.sampling import SamplingRound +from packages.valory.skills.decision_maker_abci.states.tool_selection import ( + ToolSelectionRound, +) from packages.valory.skills.market_manager_abci.rounds import ( Event as MarketManagerEvent, ) @@ -70,49 +73,54 @@ class DecisionMakerAbciApp(AbciApp[Event]): Transition states: 0. SamplingRound - done: 1. - - none: 8. + - none: 9. - no majority: 0. - round timeout: 0. - 1. DecisionRequestRound - - done: 7. - - slots unsupported error: 3. + 1. ToolSelectionRound + - done: 2. + - none: 1. - no majority: 1. - round timeout: 1. - - none: 11. - 2. DecisionReceiveRound - - done: 4. - - mech response error: 3. + 2. DecisionRequestRound + - done: 8. + - slots unsupported error: 4. - no majority: 2. - - tie: 3. - - unprofitable: 3. - round timeout: 2. - 3. BlacklistingRound - - done: 8. - - none: 11. + - none: 12. + 3. DecisionReceiveRound + - done: 5. + - mech response error: 4. - no majority: 3. + - tie: 4. + - unprofitable: 4. - round timeout: 3. - - fetch error: 11. - 4. BetPlacementRound - - done: 7. - - insufficient balance: 10. + 4. BlacklistingRound + - done: 9. + - none: 12. - no majority: 4. - round timeout: 4. - - none: 11. - 5. RedeemRound - - done: 7. - - no redeeming: 9. + - fetch error: 12. + 5. BetPlacementRound + - done: 8. + - insufficient balance: 11. - no majority: 5. - round timeout: 5. - - none: 11. - 6. HandleFailedTxRound - - blacklist: 3. - - no op: 5. + - none: 12. + 6. RedeemRound + - done: 8. + - no redeeming: 10. - no majority: 6. - 7. FinishedDecisionMakerRound - 8. FinishedWithoutDecisionRound - 9. FinishedWithoutRedeemingRound - 10. RefillRequiredRound - 11. ImpossibleRound + - round timeout: 6. + - none: 12. + 7. HandleFailedTxRound + - blacklist: 4. + - no op: 6. + - no majority: 7. + 8. FinishedDecisionMakerRound + 9. FinishedWithoutDecisionRound + 10. FinishedWithoutRedeemingRound + 11. RefillRequiredRound + 12. ImpossibleRound Final states: {FinishedDecisionMakerRound, FinishedWithoutDecisionRound, FinishedWithoutRedeemingRound, ImpossibleRound, RefillRequiredRound} @@ -129,11 +137,17 @@ class DecisionMakerAbciApp(AbciApp[Event]): } transition_function: AbciAppTransitionFunction = { SamplingRound: { - Event.DONE: DecisionRequestRound, + Event.DONE: ToolSelectionRound, Event.NONE: FinishedWithoutDecisionRound, Event.NO_MAJORITY: SamplingRound, Event.ROUND_TIMEOUT: SamplingRound, }, + ToolSelectionRound: { + Event.DONE: DecisionRequestRound, + Event.NONE: ToolSelectionRound, + Event.NO_MAJORITY: ToolSelectionRound, + Event.ROUND_TIMEOUT: ToolSelectionRound, + }, DecisionRequestRound: { Event.DONE: FinishedDecisionMakerRound, Event.SLOTS_UNSUPPORTED_ERROR: BlacklistingRound, diff --git a/packages/valory/skills/decision_maker_abci/skill.yaml b/packages/valory/skills/decision_maker_abci/skill.yaml index b3f99c667..512c61e56 100644 --- a/packages/valory/skills/decision_maker_abci/skill.yaml +++ b/packages/valory/skills/decision_maker_abci/skill.yaml @@ -12,32 +12,35 @@ fingerprint: README.md: bafybeia367zzdwndvlhw27rvnwodytjo3ms7gbc3q7mhrrjqjgfasnk47i __init__.py: bafybeih563ujnigeci2ldzh7hakbau6a222vsed7leg3b7lq32vcn3nm4a behaviours/__init__.py: bafybeih6ddz2ocvm6x6ytvlbcz6oi4snb5ee5xh5h65nq4w2qf7fd7zfky - behaviours/base.py: bafybeiaxgbkrrskfod55lhynd4ttkwrn6qwzugfmmwikzod4ar6pmjmcu4 + behaviours/base.py: bafybeicvex6q2murzsr7dnkueg2zsbdkcufbtarlojjuactsxnlu5eg3ii behaviours/bet_placement.py: bafybeifwwvvwh4qgf3jkyvza4wfvjv63il2xewsklsjtpyanp23y6hg2aa behaviours/blacklisting.py: bafybeicvespraci44y2dtddy4wi7cdhjuyk6crjs7ztnssm2rcrovha3hm - behaviours/decision_receive.py: bafybeifn4xuv2z3niyhgd35ufncrdpaisw7pd4qkw2vv3cte5koqe2mxqy - behaviours/decision_request.py: bafybeifjlh5cfitjd6wjcvcgoji2bhsi4r5nzpqocotwprmn26eiphlmqq + behaviours/decision_receive.py: bafybeid54jwjs4lulcl2n2w7taxne3wqgsey6ppaidwr2up6bztyf35ghm + behaviours/decision_request.py: bafybeidlyl2ojmpfs2zkewoacraya2cbampo4ynqbqaocsoq7v2nif3ahi behaviours/handle_failed_tx.py: bafybeidxpc6u575ymct5tdwutvzov6zqfdoio5irgldn3fw7q3lg36mmxm - behaviours/reedem.py: bafybeib25frcafu6iikppidwqqovwjkzkxif6m3f4crmklohpj6yixprsq - behaviours/round_behaviour.py: bafybeifk5utwuaneima4rdeow7tcpbe6hcc2utlzxcw3w7vsm5zw7zpamm + behaviours/reedem.py: bafybeif2sby2nfvvecpynbaek452pqhkl7gexno4max6wzw7ofuopfg4iu + behaviours/round_behaviour.py: bafybeig4tdktyu6hapoqymnxh2bgpds547st6a44heue657wkctwe4gjvm behaviours/sampling.py: bafybeiadikynvkaofbko72jc45xthhmmjfmlkpgramormhxwk5u47rnwdu + behaviours/tool_selection.py: bafybeib3vzj25c5hzpitznpe6jkbgbh7cdfmt3aa3zxyuftutikd67eniq dialogues.py: bafybeigpwuzku3we7axmxeamg7vn656maww6emuztau5pg3ebsoquyfdqm - fsm_specification.yaml: bafybeigrljw66oxyvn5wqecfgkcx7ozkjg7xuv75zcjmo25fft37qyed6y + fsm_specification.yaml: bafybeifnob3ceim2mj7lqagtnpwqjqqxs5eg3oiwc73gwm6x5i2dvvlcya handlers.py: bafybeihj33szgrcxnpd73s4nvluyxwwsvhjum2cuq3ilhhe6vfola3k7vy - models.py: bafybeibqou3ryuszu2vbwdp5b7fkj5oxmflgh3z3a7tuajbdxgzdolgmee - payloads.py: bafybeifbnyviargcj5w5kbuuvc3o4y5sdogtuynd2b4ca4xsfbi3cqcwlm - redeem_info.py: bafybeic7de4hrsgjmxbjht5ihasm5t7bykuonei5xxhpf3lpzq35fuxy74 - rounds.py: bafybeihpstybessozkb3hjxhf3gvf323zw4d575ihmxrsuzcyhqtbsruoq + models.py: bafybeicnnzyzdwdtedw3ihahugve6725ckkgt5po6qzxwljs67x5dzhwq4 + payloads.py: bafybeifpwwkikmsr7abxbin7jup6i4by7nzhpqfwlk4knm25z4mznpqj5u + policy.py: bafybeieu7yhgyuwexytpbmhuo2r5ky3sy7btoyw43bqhfcr3oj76e6dmb4 + redeem_info.py: bafybeigtxdyzs5gxfxadudg4n6ua5zpdijuzpm7x6732exxa6hpsczmyzy + rounds.py: bafybeieagkqbsy2da3soieelzvqnj4xkkpttfbhysfsfrb3geckqiejbx4 states/__init__.py: bafybeid23llnyp6j257dluxmrnztugo5llsrog7kua53hllyktz4dqhqoy - states/base.py: bafybeif42mqu6wu55iyjyqxto3poyta22gdsswgtus55lo4qpmv74wvlmm + states/base.py: bafybeieuw57xtki2dsrvr5hfx6iedxjmosr6kywphdzfukjejwv52iawcu states/bet_placement.py: bafybeibalhxhp2c4oljmiwqi6ds3g36fgtabmf42mb5sgq6z22znrcbhda states/blacklisting.py: bafybeiao747i4z7owk6dmwfuzdijag55m3ryj3nowfoggvczpgk3koza44 states/decision_receive.py: bafybeifm3oyq2aji7f5yag6wpe4vr3ivi74pybdsk2jvmziiidx5nt7t4a states/decision_request.py: bafybeic7otc3hjb753svbmur3yyk6szahc25yii3x4w4vcnpfz6jwvacuu states/final_states.py: bafybeidiwhuyd5zm2cq7vhv2owcrxdpm7fnvn3db6p6tql4jz5hgpalflu states/handle_failed_tx.py: bafybeihewm2vernvhktuorljdupjqcg2p5vs6wvsira2d62wkoyo5xlzjm - states/redeem.py: bafybeifl7qgs2xvm4nykloec5tq47sriqah3dzahv3gppvgtrrxzw5yyyq + states/redeem.py: bafybeiebofn2pg32iprvwuglclq6hm4x3hvx7neqqad4b77zej67vozjye states/sampling.py: bafybeidnvdogjlthjfe7jpaiuezm3xydrbxxukyoss4gx6t5fdin52rsta + states/tool_selection.py: bafybeihc7pmwxijc5tcsl2yt5n3rbwumqksa3oxjjcrj6vkesinhu5f7im fingerprint_ignore_patterns: [] connections: [] contracts: @@ -45,15 +48,16 @@ contracts: - valory/market_maker:0.1.0:bafybeif6hivvhxqv4a3uqo2v3yszluzrmngsp624utdi466xwo5qbz5bsi - valory/erc20:0.1.0:bafybeiggo4u56drxusvcdruqrr7mlfzqbieg4hajalh4tkctxhh3c5lpdi - valory/multisend:0.1.0:bafybeidfktuprydtmi4umolfles5qaf7s3t26puvvs44hvkq6uwwr3ia3a -- valory/mech:0.1.0:bafybeibfikekaruskx6ui7u4qnls57i2namfxi45zhqslziqyxg4npjzxu +- valory/mech:0.1.0:bafybeidtezc4ubsyqdltiojvqe5eeh77ejte7vqbojspiej5quivgap3ae - valory/conditional_tokens:0.1.0:bafybeicxwjdbmjajgr5rsmadtkxxwmcm42r2htef3tvng73uzib4hmb6qa - valory/realitio:0.1.0:bafybeigb722aznqhc5lsbt3dn4bpyaqe5hnl5onmnestqmzliwtvl3eaom - valory/realitio_proxy:0.1.0:bafybeibvndq6756qck7forgeavhdbn6ykgqs2ufyg7n5g6qdfpveatxuwy +- valory/agent_registry:0.1.0:bafybeib6odummk6qqietjekpljkmhqfxk7kv56kv6pyfsnnanews625ncy protocols: - valory/contract_api:1.0.0:bafybeiasywsvax45qmugus5kxogejj66c5taen27h4voriodz7rgushtqa skills: - valory/abstract_round_abci:0.1.0:bafybeicqwr73cs3vndzafrjrjpw63vvqbbjsur7ptek77hsw3lurnood5y -- valory/market_manager_abci:0.1.0:bafybeicjqkzen2gvpnc3syojcf6ibr4kjaorcwktikqp2zzxec6vs64oky +- valory/market_manager_abci:0.1.0:bafybeigvw5tqei5xb272jb7retxiryhuhxxzupddmbdixgsmxzco3n2dde - valory/transaction_settlement_abci:0.1.0:bafybeicisazpyvnnzlqso3txiucxr5qhsa4ac7ius6b4mhouxr2wkadwfy behaviours: main: @@ -183,14 +187,14 @@ models: slippage: 0.01 epsilon: 0.1 irrelevant_tools: - ? openai-text-davinci-002 - ? openai-text-davinci-003 - ? openai-gpt-3.5-turbo - ? openai-gpt-4 - ? stabilityai-stable-diffusion-v1-5 - ? stabilityai-stable-diffusion-xl-beta-v2-2-2 - ? stabilityai-stable-diffusion-512-v2-1 - ? stabilityai-stable-diffusion-768-v2-1 + - openai-text-davinci-002 + - openai-text-davinci-003 + - openai-gpt-3.5-turbo + - openai-gpt-4 + - stabilityai-stable-diffusion-v1-5 + - stabilityai-stable-diffusion-xl-beta-v2-2-2 + - stabilityai-stable-diffusion-512-v2-1 + - stabilityai-stable-diffusion-768-v2-1 class_name: DecisionMakerParams mech_response: args: @@ -210,7 +214,7 @@ models: headers: Content-Type: application/json method: GET - parameters: { } + parameters: {} response_key: tools response_type: list retries: 5 diff --git a/packages/valory/skills/decision_maker_abci/states/base.py b/packages/valory/skills/decision_maker_abci/states/base.py index bb7d3a87f..b29c24e2e 100644 --- a/packages/valory/skills/decision_maker_abci/states/base.py +++ b/packages/valory/skills/decision_maker_abci/states/base.py @@ -19,8 +19,9 @@ """This module contains the base functionality for the rounds of the decision-making abci app.""" +import json from enum import Enum -from typing import Optional, Tuple +from typing import Dict, List, Optional, Tuple from packages.valory.skills.abstract_round_abci.base import ( CollectSameUntilThresholdRound, @@ -28,6 +29,7 @@ get_name, ) from packages.valory.skills.decision_maker_abci.payloads import MultisigTxPayload +from packages.valory.skills.decision_maker_abci.policy import EGreedyPolicy from packages.valory.skills.market_manager_abci.bets import Bet from packages.valory.skills.market_manager_abci.rounds import ( SynchronizedData as MarketManagerSyncedData, @@ -75,6 +77,38 @@ def mech_price(self) -> int: """Get the mech's request price.""" return int(self.db.get_strict("mech_price")) + @property + def available_mech_tools(self) -> List[str]: + """Get all the available mech tools.""" + tools = self.db.get_strict("available_mech_tools") + return json.loads(tools) + + @property + def policy(self) -> EGreedyPolicy: + """Get the policy.""" + policy = self.db.get_strict("policy") + return EGreedyPolicy.deserialize(policy) + + @property + def mech_tool_idx(self) -> int: + """Get the mech tool's index.""" + return int(self.db.get_strict("mech_tool_idx")) + + @property + def mech_tool(self) -> str: + """Get the selected mech tool.""" + try: + return self.available_mech_tools[self.mech_tool_idx] + except IndexError as exc: + error = f"{self.mech_tool_idx=} is not available in {self.available_mech_tools=}." + raise IndexError(error) from exc + + @property + def utilized_tools(self) -> Dict[str, int]: + """Get a mapping of the utilized tools' indexes for each transaction.""" + tools = str(self.db.get("utilized_tools", "{}")) + return json.loads(tools) + @property def vote(self) -> Optional[int]: """Get the bet's vote index.""" diff --git a/packages/valory/skills/decision_maker_abci/states/redeem.py b/packages/valory/skills/decision_maker_abci/states/redeem.py index 3d7e0e651..7c40aeb73 100644 --- a/packages/valory/skills/decision_maker_abci/states/redeem.py +++ b/packages/valory/skills/decision_maker_abci/states/redeem.py @@ -19,8 +19,16 @@ """This module contains the redeem state of the decision-making abci app.""" +from typing import Type + +from packages.valory.skills.abstract_round_abci.base import get_name +from packages.valory.skills.decision_maker_abci.payloads import ( + MultisigTxPayload, + RedeemPayload, +) from packages.valory.skills.decision_maker_abci.states.base import ( Event, + SynchronizedData, TxPreparationRound, ) @@ -28,4 +36,8 @@ class RedeemRound(TxPreparationRound): """A round in which the agents prepare a tx to redeem the winnings.""" + payload_class: Type[MultisigTxPayload] = RedeemPayload + selection_key = TxPreparationRound.selection_key + ( + get_name(SynchronizedData.policy), + ) none_event = Event.NO_REDEEMING diff --git a/packages/valory/skills/decision_maker_abci/states/tool_selection.py b/packages/valory/skills/decision_maker_abci/states/tool_selection.py new file mode 100644 index 000000000..982d281de --- /dev/null +++ b/packages/valory/skills/decision_maker_abci/states/tool_selection.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2023 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""This module contains the tool selection state of the decision-making abci app.""" + +from packages.valory.skills.abstract_round_abci.base import ( + CollectSameUntilThresholdRound, + get_name, +) +from packages.valory.skills.decision_maker_abci.payloads import ToolSelectionPayload +from packages.valory.skills.decision_maker_abci.states.base import ( + Event, + SynchronizedData, +) + + +class ToolSelectionRound(CollectSameUntilThresholdRound): + """A round for selecting a Mech tool.""" + + payload_class = ToolSelectionPayload + synchronized_data_class = SynchronizedData + done_event = Event.DONE + none_event = Event.NONE + no_majority_event = Event.NO_MAJORITY + selection_key = ( + get_name(SynchronizedData.available_mech_tools), + get_name(SynchronizedData.policy), + get_name(SynchronizedData.mech_tool_idx), + ) + collection_key = get_name(SynchronizedData.participant_to_selection) diff --git a/packages/valory/skills/market_manager_abci/graph_tooling/queries/omen.py b/packages/valory/skills/market_manager_abci/graph_tooling/queries/omen.py index 65b9cccb0..974bb5910 100644 --- a/packages/valory/skills/market_manager_abci/graph_tooling/queries/omen.py +++ b/packages/valory/skills/market_manager_abci/graph_tooling/queries/omen.py @@ -94,6 +94,7 @@ outcomeIndex outcomeTokenMarginalPrice outcomeTokensTraded + transactionHash } } """ diff --git a/packages/valory/skills/market_manager_abci/skill.yaml b/packages/valory/skills/market_manager_abci/skill.yaml index f6640d746..95802d874 100644 --- a/packages/valory/skills/market_manager_abci/skill.yaml +++ b/packages/valory/skills/market_manager_abci/skill.yaml @@ -15,7 +15,7 @@ fingerprint: graph_tooling/__init__.py: bafybeigzo7nhbzafyq3fuhrlewksjvmzttiuk4vonrggtjtph4rw4ncpk4 graph_tooling/queries/__init__.py: bafybeihbybnl53i7k57ql5ujt5ru5n2eg324jfndh4lcnm4fk52mwbkjda graph_tooling/queries/network.py: bafybeigeq72ys2nrjqspj2uacaudrgljrne5a3o5jvzsktldxdq6m2xmeu - graph_tooling/queries/omen.py: bafybeiajk65gvqkxvxekywqqy2kob3vobjsealqlyxis3z6mpwhyng7hh4 + graph_tooling/queries/omen.py: bafybeigybmwaz3e33ug756v7k4lrwy5tlwimii5qywapaiww6qgslvfywi graph_tooling/requests.py: bafybeics4oueh3nemdvl366vqgnf3ltea2ab443qtfaoqgl63tmct227qa handlers.py: bafybeihot2i2yvfkz2gcowvt66wdu6tkjbmv7hsmc4jzt4reqeaiuphbtu models.py: bafybeiaplszooak63fo3i6agaoyol4tpof4q4tvoj4j6f2cr2corajnl3a diff --git a/packages/valory/skills/trader_abci/fsm_specification.yaml b/packages/valory/skills/trader_abci/fsm_specification.yaml index a9e12a68c..d550e79ea 100644 --- a/packages/valory/skills/trader_abci/fsm_specification.yaml +++ b/packages/valory/skills/trader_abci/fsm_specification.yaml @@ -60,6 +60,7 @@ states: - SelectKeeperTransactionSubmissionBAfterTimeoutRound - SelectKeeperTransactionSubmissionBRound - SynchronizeLateMessagesRound +- ToolSelectionRound - UpdateBetsRound - ValidateTransactionRound transition_func: @@ -130,7 +131,7 @@ transition_func: (ResetRound, DONE): RandomnessTransactionSubmissionRound (ResetRound, NO_MAJORITY): HandleFailedTxRound (ResetRound, RESET_TIMEOUT): HandleFailedTxRound - (SamplingRound, DONE): DecisionRequestRound + (SamplingRound, DONE): ToolSelectionRound (SamplingRound, NONE): RedeemRound (SamplingRound, NO_MAJORITY): SamplingRound (SamplingRound, ROUND_TIMEOUT): SamplingRound @@ -152,6 +153,10 @@ transition_func: (SynchronizeLateMessagesRound, NONE): SelectKeeperTransactionSubmissionBRound (SynchronizeLateMessagesRound, ROUND_TIMEOUT): SynchronizeLateMessagesRound (SynchronizeLateMessagesRound, SUSPICIOUS_ACTIVITY): HandleFailedTxRound + (ToolSelectionRound, DONE): DecisionRequestRound + (ToolSelectionRound, NONE): ToolSelectionRound + (ToolSelectionRound, NO_MAJORITY): ToolSelectionRound + (ToolSelectionRound, ROUND_TIMEOUT): ToolSelectionRound (UpdateBetsRound, DONE): SamplingRound (UpdateBetsRound, FETCH_ERROR): ResetAndPauseRound (UpdateBetsRound, NO_MAJORITY): UpdateBetsRound diff --git a/packages/valory/skills/trader_abci/models.py b/packages/valory/skills/trader_abci/models.py index 60f0405cc..373113b77 100644 --- a/packages/valory/skills/trader_abci/models.py +++ b/packages/valory/skills/trader_abci/models.py @@ -29,12 +29,12 @@ from packages.valory.skills.abstract_round_abci.models import ( SharedState as BaseSharedState, ) -from packages.valory.skills.decision_maker_abci.models import DecisionMakerParams from packages.valory.skills.decision_maker_abci.models import ( - MechResponseSpecs as DecisionMakerMechResponseSpecs, + AgentToolsSpecs as DecisionMakerAgentToolsSpecs, ) +from packages.valory.skills.decision_maker_abci.models import DecisionMakerParams from packages.valory.skills.decision_maker_abci.models import ( - AgentToolsSpecs as DecisionMakerAgentToolsSpecs, + MechResponseSpecs as DecisionMakerMechResponseSpecs, ) from packages.valory.skills.decision_maker_abci.rounds import ( Event as DecisionMakerEvent, diff --git a/packages/valory/skills/trader_abci/skill.yaml b/packages/valory/skills/trader_abci/skill.yaml index 5aa766e5f..d7fd07207 100644 --- a/packages/valory/skills/trader_abci/skill.yaml +++ b/packages/valory/skills/trader_abci/skill.yaml @@ -11,9 +11,9 @@ fingerprint: behaviours.py: bafybeigwadq27e4cnklboorhitwzzve4xkcgjdu2upplbbweuqyl52fj3q composition.py: bafybeie45dgneoggyavgdtswcygvz5o3klmtqf57zoxqnxrtneruutqevi dialogues.py: bafybeiebofyykseqp3fmif36cqmmyf3k7d2zbocpl6t6wnlpv4szghrxbm - fsm_specification.yaml: bafybeiasu522aq3xthvuyvajpvzxy33nu6l4esuyl2xmkslckldcomwfzu + fsm_specification.yaml: bafybeiaomt3gscv4pvxczc4scu6q6laza6bqhpvfi2bfiq37vksuchhqiy handlers.py: bafybeicamc6vmozij5dwvkxmbxjazsgf3sacojhstbjtq7vfggszxugvey - models.py: bafybeih26gyqv24lc2mlz3kbdsifip3zlac3owcpqlyi7hg6du6y6ojdda + models.py: bafybeifj5y7qcoac72woe53zaz2lopkqir2472bbey3ypsqmprjmljms7i fingerprint_ignore_patterns: [] connections: [] contracts: [] @@ -24,9 +24,9 @@ skills: - valory/reset_pause_abci:0.1.0:bafybeiblayblhp5wuirfomwcpgydg35ve5tfq3xxetlosjn47wva5ucmzy - valory/transaction_settlement_abci:0.1.0:bafybeicisazpyvnnzlqso3txiucxr5qhsa4ac7ius6b4mhouxr2wkadwfy - valory/termination_abci:0.1.0:bafybeieqfhvk6klnvxak3vo2ibslkrnnk2bfsn5l3gbaelcprd6cjngxki -- valory/market_manager_abci:0.1.0:bafybeicjqkzen2gvpnc3syojcf6ibr4kjaorcwktikqp2zzxec6vs64oky -- valory/decision_maker_abci:0.1.0:bafybeic77zhxf5a53ngfzacklmm3nag4t4jeufdhoeg3ykrmvknojtwipi -- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeidtrigrfjikl7tkbtowbp6mrdzxulayxnxcmviwy3gag557vnymlq +- valory/market_manager_abci:0.1.0:bafybeigvw5tqei5xb272jb7retxiryhuhxxzupddmbdixgsmxzco3n2dde +- valory/decision_maker_abci:0.1.0:bafybeihm77vt53vu3xt6x7istsvaw75juptlynpriebgeltbil5evvhtue +- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeiey57caacd6d3ow25i6a2zuiinkx6kjtckdktannk7kijpd3p2zb4 behaviours: main: args: {} @@ -171,14 +171,14 @@ models: redeem_margin_days: 15 epsilon: 0.1 irrelevant_tools: - ? openai-text-davinci-002 - ? openai-text-davinci-003 - ? openai-gpt-3.5-turbo - ? openai-gpt-4 - ? stabilityai-stable-diffusion-v1-5 - ? stabilityai-stable-diffusion-xl-beta-v2-2-2 - ? stabilityai-stable-diffusion-512-v2-1 - ? stabilityai-stable-diffusion-768-v2-1 + - openai-text-davinci-002 + - openai-text-davinci-003 + - openai-gpt-3.5-turbo + - openai-gpt-4 + - stabilityai-stable-diffusion-v1-5 + - stabilityai-stable-diffusion-xl-beta-v2-2-2 + - stabilityai-stable-diffusion-512-v2-1 + - stabilityai-stable-diffusion-768-v2-1 class_name: TraderParams network_subgraph: args: @@ -234,7 +234,7 @@ models: headers: Content-Type: application/json method: GET - parameters: { } + parameters: {} response_key: tools response_type: list retries: 5 diff --git a/packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py b/packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py index ca274730a..637dd3b29 100644 --- a/packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py +++ b/packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py @@ -74,6 +74,13 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Enum]]: synced_data = SynchronizedData(self.synchronized_data.db) event = submitter_to_event.get(synced_data.tx_submitter, Event.UNRECOGNIZED) + + # if a bet was just placed, edit the utilized tools mapping + if event == Event.BET_PLACEMENT_DONE: + utilized_tools = synced_data.utilized_tools + utilized_tools[synced_data.final_tx_hash] = synced_data.mech_tool_idx + self.synchronized_data.update(utilized_tools=utilized_tools) + return synced_data, event diff --git a/packages/valory/skills/tx_settlement_multiplexer_abci/skill.yaml b/packages/valory/skills/tx_settlement_multiplexer_abci/skill.yaml index 1e4557ff1..e80f4946e 100644 --- a/packages/valory/skills/tx_settlement_multiplexer_abci/skill.yaml +++ b/packages/valory/skills/tx_settlement_multiplexer_abci/skill.yaml @@ -13,14 +13,14 @@ fingerprint: fsm_specification.yaml: bafybeibeas5ovngfhfox4dkkwdvhogpuzkmwj6r33ez2xxvvmvmesa3xvm handlers.py: bafybeiafbqr7ojfcbwohvee7x4zzswad3ymfrrbjlfz7uuuttmn3qdfs6q models.py: bafybeiahojnn52s762zitwx6k5s4ef5qw7hwjf3orlklqwuz3zi7k2o7bi - rounds.py: bafybeifotgp5zr6vrgfhursm7dwkju74qdrruw7ui7zmbl5t34om4fnapa + rounds.py: bafybeifcqo6t7vhkclwj6lncfirglvayd7oqdwinca2ipndizgin7alm5q fingerprint_ignore_patterns: [] connections: [] contracts: [] protocols: [] skills: - valory/abstract_round_abci:0.1.0:bafybeicqwr73cs3vndzafrjrjpw63vvqbbjsur7ptek77hsw3lurnood5y -- valory/decision_maker_abci:0.1.0:bafybeic77zhxf5a53ngfzacklmm3nag4t4jeufdhoeg3ykrmvknojtwipi +- valory/decision_maker_abci:0.1.0:bafybeihm77vt53vu3xt6x7istsvaw75juptlynpriebgeltbil5evvhtue behaviours: main: args: {} diff --git a/poetry.lock b/poetry.lock index fa4f7b8ac..3b19fb7d2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -737,35 +737,35 @@ files = [ [[package]] name = "cryptography" -version = "41.0.3" +version = "41.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507"}, - {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116"}, - {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c"}, - {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae"}, - {file = "cryptography-41.0.3-cp37-abi3-win32.whl", hash = "sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306"}, - {file = "cryptography-41.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4"}, - {file = "cryptography-41.0.3.tar.gz", hash = "sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34"}, + {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839"}, + {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143"}, + {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397"}, + {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860"}, + {file = "cryptography-41.0.4-cp37-abi3-win32.whl", hash = "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd"}, + {file = "cryptography-41.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311"}, + {file = "cryptography-41.0.4.tar.gz", hash = "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a"}, ] [package.dependencies] @@ -1257,14 +1257,14 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-api-python-client" -version = "2.99.0" +version = "2.100.0" description = "Google API Client Library for Python" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "google-api-python-client-2.99.0.tar.gz", hash = "sha256:e733fd0f2c8793b1a000d5e69ac81b1b9ec0665b445b7ed83bdbbb0038973306"}, - {file = "google_api_python_client-2.99.0-py2.py3-none-any.whl", hash = "sha256:40272131d3a4a7aecab840ebcf3df51c54d49560156f3b9d54a4ef82c795985d"}, + {file = "google-api-python-client-2.100.0.tar.gz", hash = "sha256:eaed50efc2f8a4027dcca8fd0037f4b1b03b8093efc84ce3cb6c75bfc79a7e31"}, + {file = "google_api_python_client-2.100.0-py2.py3-none-any.whl", hash = "sha256:226ca35355993d6182506c51745ab5149405cdf6a92975b2725ab3e0d757dbe9"}, ] [package.dependencies] @@ -1528,14 +1528,14 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jsonschema" -version = "4.19.0" +version = "4.19.1" description = "An implementation of JSON Schema validation for Python" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.19.0-py3-none-any.whl", hash = "sha256:043dc26a3845ff09d20e4420d6012a9c91c9aa8999fa184e7efcfeccb41e32cb"}, - {file = "jsonschema-4.19.0.tar.gz", hash = "sha256:6e1e7569ac13be8139b2dd2c21a55d350066ee3f80df06c608b398cdc6f30e8f"}, + {file = "jsonschema-4.19.1-py3-none-any.whl", hash = "sha256:cd5f1f9ed9444e554b38ba003af06c0a8c2868131e56bfbef0550fb450c0330e"}, + {file = "jsonschema-4.19.1.tar.gz", hash = "sha256:ec84cc37cfa703ef7cd4928db24f9cb31428a5d0fa77747b8b51a847458e0bbf"}, ] [package.dependencies] @@ -1845,14 +1845,14 @@ files = [ [[package]] name = "netaddr" -version = "0.8.0" +version = "0.9.0" description = "A network address manipulation library for Python" category = "main" optional = false python-versions = "*" files = [ - {file = "netaddr-0.8.0-py2.py3-none-any.whl", hash = "sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac"}, - {file = "netaddr-0.8.0.tar.gz", hash = "sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243"}, + {file = "netaddr-0.9.0-py3-none-any.whl", hash = "sha256:5148b1055679d2a1ec070c521b7db82137887fabd6d7e37f5199b44f775c3bb1"}, + {file = "netaddr-0.9.0.tar.gz", hash = "sha256:7b46fa9b1a2d71fd5de9e4a3784ef339700a53a08c8040f08baf5f1194da0128"}, ] [[package]]