Skip to content

Commit

Permalink
Merge pull request #90 from valory-xyz/feat/tool-selection
Browse files Browse the repository at this point in the history
Implement tool selection logic based on the policy
  • Loading branch information
Adamantios authored Sep 20, 2023
2 parents c50326b + 37b8153 commit a52f4c8
Show file tree
Hide file tree
Showing 22 changed files with 548 additions and 240 deletions.
17 changes: 9 additions & 8 deletions packages/packages.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
17 changes: 9 additions & 8 deletions packages/valory/agents/trader/aea-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 3 additions & 6 deletions packages/valory/contracts/agent_registry/contract.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion packages/valory/contracts/mech/contract.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 17 additions & 17 deletions 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:bafybeigoojaxpc7sz7vuswkxvpa5lp37lipuwc4qycztqk4hxdesmxqcda
agent: valory/trader:0.1.0:bafybeiba5eqawktwkpziiazxm5u6ftm7o3zytcbafqsjwt7zrr63o2yis4
number_of_agents: 4
deployment: {}
---
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
)
from packages.valory.skills.decision_maker_abci.models import (
DecisionMakerParams,
EGreedyPolicy,
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -60,4 +63,5 @@ class AgentDecisionMakerRoundBehaviour(AbstractRoundBehaviour):
BetPlacementBehaviour, # type: ignore
RedeemBehaviour, # type: ignore
HandleFailedTxBehaviour, # type: ignore
ToolSelectionBehaviour, # type: ignore
}
Original file line number Diff line number Diff line change
@@ -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)
Loading

0 comments on commit a52f4c8

Please sign in to comment.