Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

More NFT game mods #681

Merged
merged 9 commits into from
Feb 10, 2025
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import time
from enum import Enum

from microchain.functions import Reasoning
from prediction_market_agent_tooling.gtypes import ChecksumAddress
from prediction_market_agent_tooling.loggers import logger
from prediction_market_agent_tooling.tools.contract import SimpleTreasuryContract
from prediction_market_agent_tooling.tools.contract import (
ContractOwnableERC721OnGnosisChain,
SimpleTreasuryContract,
)
from prediction_market_agent_tooling.tools.utils import check_not_none
from web3 import Web3

Expand Down Expand Up @@ -37,6 +41,11 @@
from prediction_market_agent.db.agent_communication import get_treasury_tax_ratio


class Role(Enum):
buyer = "buyer"
seller = "seller"


class DeployableAgentNFTGameAbstract(DeployableMicrochainAgentAbstract):
# Agent configuration
sleep_between_iterations = 15
Expand All @@ -54,6 +63,7 @@ class DeployableAgentNFTGameAbstract(DeployableMicrochainAgentAbstract):
# Setup per-nft-agent class.
name: str
wallet_address: ChecksumAddress
role: Role

# Game status
game_finished_already_detected: bool = False
Expand Down Expand Up @@ -84,17 +94,34 @@ def load(self) -> None:

super().load()

@classmethod
def get_initial_system_prompt(cls) -> str:
system_prompt = nft_treasury_game_base_prompt(wallet_address=cls.wallet_address)
if cls.role == Role.buyer:
system_prompt += nft_treasury_game_buyer_prompt()
elif cls.role == Role.seller:
system_prompt += nft_treasury_game_seller_prompt()
return system_prompt

def get_holding_n_nft_keys(self) -> int:
contract = ContractOwnableERC721OnGnosisChain(address=NFT_TOKEN_FACTORY)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
contract = ContractOwnableERC721OnGnosisChain(address=NFT_TOKEN_FACTORY)
contract = ContractERC721BaseClass(address=NFT_TOKEN_FACTORY)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggesting the above because no need for it to be ownable - just the ERC721 component has balanceOf functionality

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it is ownable https://github.com/gnosis/labs-contracts/blob/dd748a506c9ee0cdc90778417b2743cc82e26aeb/src/NFT/AgentNFT.sol#L8. The idea for these classes is to be 1:1 with an underlying contract.

return contract.balanceOf(Web3.to_checksum_address(self.wallet_address))
kongzii marked this conversation as resolved.
Show resolved Hide resolved

def before_iteration_callback(self) -> CallbackReturn:
"""
In following if statements, we hard-code a few special cases about the game status, to make it a bit easier on the agent logic.
"""
system_prompt = self.agent.history[0] if self.agent.history else None
is_seller_without_keys = (
self.role == Role.seller and not self.get_holding_n_nft_keys()
)

# First, if the agent just started, but the game is not ready yet, make him sleep and stop -- until the game is ready.
# Otherwise, he would try to learn from past games (until he realise there are none!), he'd try to communicate, but without any money it would fail, etc.
if (
len(self.agent.history) <= 1 # One optional system message doesn't count.
and get_nft_game_status() == NFTGameStatus.finished
if len(
self.agent.history
) <= 1 and ( # One optional system message doesn't count.
is_seller_without_keys or get_nft_game_status() == NFTGameStatus.finished
):
logger.info(
"The game is not ready yet and agent didn't have any previous interactions, sleeping and stopping."
Expand All @@ -103,9 +130,8 @@ def before_iteration_callback(self) -> CallbackReturn:
return CallbackReturn.STOP

# Second, if this is the agent's first iteration after the game finished, force him to reflect on the past game.
elif (
not self.game_finished_already_detected
and get_nft_game_status() == NFTGameStatus.finished
elif not self.game_finished_already_detected and (
is_seller_without_keys or get_nft_game_status() == NFTGameStatus.finished
):
logger.info("Game is finished, forcing agent to reflect on the past game.")
# Switch to more capable (but a lot more expensive) model so that the reflections are worth it.
Expand Down Expand Up @@ -135,7 +161,10 @@ def before_iteration_callback(self) -> CallbackReturn:
self.agent.history[-1]
):
# Either do nothing wait for the game to start again.
if get_nft_game_status() == NFTGameStatus.finished:
if (
is_seller_without_keys
or get_nft_game_status() == NFTGameStatus.finished
):
# Just sleep if the last thing the agent did was being done with this game and the game is still finished.
# That way he won't be doing anything until the game is reset.
logger.info("Agent is done with the game, sleeping and stopping.")
Expand Down Expand Up @@ -164,6 +193,7 @@ class DeployableAgentNFTGame1(DeployableAgentNFTGameAbstract):
wallet_address = Web3.to_checksum_address(
"0x2A537F3403a3F5F463996c36D31e94227c9833CE"
)
role = Role.seller

@classmethod
def get_initial_system_prompt(cls) -> str:
Expand All @@ -174,8 +204,7 @@ def get_initial_system_prompt(cls) -> str:
You are a gossiper, you like to talk to other agents, but also to broadcast public messages.

"""
+ nft_treasury_game_base_prompt(wallet_address=cls.wallet_address)
+ nft_treasury_game_seller_prompt()
+ super().get_initial_system_prompt()
)


Expand All @@ -185,6 +214,7 @@ class DeployableAgentNFTGame2(DeployableAgentNFTGameAbstract):
wallet_address = Web3.to_checksum_address(
"0x485D096b4c0413dA1B09Ed9261B8e91eCCD7ffb9"
)
role = Role.seller

@classmethod
def get_initial_system_prompt(cls) -> str:
Expand All @@ -194,8 +224,7 @@ def get_initial_system_prompt(cls) -> str:
You respond in the style of characters from historical Bridgeton movie and you are very protective of your resources.

"""
+ nft_treasury_game_base_prompt(wallet_address=cls.wallet_address)
+ nft_treasury_game_seller_prompt()
+ super().get_initial_system_prompt()
)


Expand All @@ -205,6 +234,7 @@ class DeployableAgentNFTGame3(DeployableAgentNFTGameAbstract):
wallet_address = Web3.to_checksum_address(
"0xA87BD78f4a2312469119AFD88142c71Ca075C30A"
)
role = Role.seller

@classmethod
def get_initial_system_prompt(cls) -> str:
Expand All @@ -217,8 +247,7 @@ def get_initial_system_prompt(cls) -> str:
Try to trick people and other agents to send you more money in exchange for the NFT key -- but don't transfer the NFT key in the end.

"""
+ nft_treasury_game_base_prompt(wallet_address=cls.wallet_address)
+ nft_treasury_game_seller_prompt()
+ super().get_initial_system_prompt()
)


Expand All @@ -228,6 +257,7 @@ class DeployableAgentNFTGame4(DeployableAgentNFTGameAbstract):
wallet_address = Web3.to_checksum_address(
"0xd4fC4305DC1226c38356024c26cdE985817f137F"
)
role = Role.seller

@classmethod
def get_initial_system_prompt(cls) -> str:
Expand All @@ -237,8 +267,7 @@ def get_initial_system_prompt(cls) -> str:
You respond in the style of Sheldon Cooper from Big Bang Theory and you are very protective of your resources.

"""
+ nft_treasury_game_base_prompt(wallet_address=cls.wallet_address)
+ nft_treasury_game_seller_prompt()
+ super().get_initial_system_prompt()
)


Expand All @@ -248,6 +277,7 @@ class DeployableAgentNFTGame5(DeployableAgentNFTGameAbstract):
wallet_address = Web3.to_checksum_address(
"0x1C7AbbBef500620A68ed2F94b816221A61d72F33"
)
role = Role.seller

@classmethod
def get_initial_system_prompt(cls) -> str:
Expand All @@ -258,8 +288,7 @@ def get_initial_system_prompt(cls) -> str:
Always write in Klingon, but add also English translation.

"""
+ nft_treasury_game_base_prompt(wallet_address=cls.wallet_address)
+ nft_treasury_game_seller_prompt()
+ super().get_initial_system_prompt()
)


Expand All @@ -269,6 +298,7 @@ class DeployableAgentNFTGame6(DeployableAgentNFTGameAbstract):
wallet_address = Web3.to_checksum_address(
"0x64D94C8621128E1C813F8AdcD62c4ED7F89B1Fd6"
)
role = Role.buyer

@classmethod
def get_initial_system_prompt(cls) -> str:
Expand All @@ -280,8 +310,7 @@ def get_initial_system_prompt(cls) -> str:
You are a bit of a mystery, but you are also a bit of a trickster.

"""
+ nft_treasury_game_base_prompt(wallet_address=cls.wallet_address)
+ nft_treasury_game_buyer_prompt()
+ super().get_initial_system_prompt()
)


Expand All @@ -291,6 +320,7 @@ class DeployableAgentNFTGame7(DeployableAgentNFTGameAbstract):
wallet_address = Web3.to_checksum_address(
"0x469Bc26531800068f306D304Ced56641F63ae140"
)
role = Role.buyer

@classmethod
def get_initial_system_prompt(cls) -> str:
Expand All @@ -302,8 +332,7 @@ def get_initial_system_prompt(cls) -> str:
You are also very patient and able to wait for the right moment to strike.
You are also very good at making people believe that you are on their side, even if you are not.
"""
+ nft_treasury_game_base_prompt(wallet_address=cls.wallet_address)
+ nft_treasury_game_buyer_prompt()
+ super().get_initial_system_prompt()
)


Expand Down