From 10af4a81e8eaac94aaf675eeed331d9ab96b494e Mon Sep 17 00:00:00 2001 From: gabrielfior Date: Mon, 21 Oct 2024 14:50:24 +0200 Subject: [PATCH 1/7] Adding agent model to IPFS upload --- prediction_market_agent_tooling/deploy/agent.py | 6 +++++- prediction_market_agent_tooling/markets/omen/data_models.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/prediction_market_agent_tooling/deploy/agent.py b/prediction_market_agent_tooling/deploy/agent.py index 76f0bf20..2a2f1404 100644 --- a/prediction_market_agent_tooling/deploy/agent.py +++ b/prediction_market_agent_tooling/deploy/agent.py @@ -353,6 +353,10 @@ def update_langfuse_trace_by_processed_market( ] ) + @property + def model(self) -> str | None: + return None + def check_min_required_balance_to_operate( self, market_type: MarketType, @@ -533,7 +537,7 @@ def store_prediction( if keys.enable_ipfs_upload: logger.info("Storing prediction on IPFS.") ipfs_hash = IPFSHandler(keys).store_agent_result( - IPFSAgentResult(reasoning=reasoning) + IPFSAgentResult(reasoning=reasoning, model=self.model) ) ipfs_hash_decoded = ipfscidv0_to_byte32(ipfs_hash) diff --git a/prediction_market_agent_tooling/markets/omen/data_models.py b/prediction_market_agent_tooling/markets/omen/data_models.py index d5613877..b3fcf451 100644 --- a/prediction_market_agent_tooling/markets/omen/data_models.py +++ b/prediction_market_agent_tooling/markets/omen/data_models.py @@ -798,7 +798,7 @@ def from_tuple(values: tuple[t.Any]) -> "ContractPrediction": class IPFSAgentResult(BaseModel): reasoning: str - + model: str | None model_config = ConfigDict( extra="forbid", ) From 1ed438989a53efc832bfb2d3e03cd5633595eca8 Mon Sep 17 00:00:00 2001 From: gabrielfior Date: Mon, 21 Oct 2024 17:48:16 +0200 Subject: [PATCH 2/7] Added agent name as property to DeployableTraderAgent --- prediction_market_agent_tooling/deploy/agent.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prediction_market_agent_tooling/deploy/agent.py b/prediction_market_agent_tooling/deploy/agent.py index 2a2f1404..9d8c0391 100644 --- a/prediction_market_agent_tooling/deploy/agent.py +++ b/prediction_market_agent_tooling/deploy/agent.py @@ -354,8 +354,8 @@ def update_langfuse_trace_by_processed_market( ) @property - def model(self) -> str | None: - return None + def agent_name(self) -> str: + return self.__class__.__name__ def check_min_required_balance_to_operate( self, From bcd2682d26474964d3edeb2ff46a1807cd72d0e2 Mon Sep 17 00:00:00 2001 From: gabrielfior Date: Mon, 21 Oct 2024 17:57:21 +0200 Subject: [PATCH 3/7] Added agent name as property to DeployableTraderAgent --- prediction_market_agent_tooling/deploy/agent.py | 11 ++++++++++- .../markets/agent_market.py | 6 +++++- .../markets/omen/data_models.py | 2 +- .../markets/omen/omen.py | 15 +++++---------- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/prediction_market_agent_tooling/deploy/agent.py b/prediction_market_agent_tooling/deploy/agent.py index ea60d89f..f668b1c0 100644 --- a/prediction_market_agent_tooling/deploy/agent.py +++ b/prediction_market_agent_tooling/deploy/agent.py @@ -48,6 +48,7 @@ MarketType, have_bet_on_market_since, ) +from prediction_market_agent_tooling.markets.omen.data_models import IPFSAgentResult from prediction_market_agent_tooling.markets.omen.omen import ( withdraw_wxdai_to_xdai_to_keep_balance, ) @@ -496,7 +497,15 @@ def after_process_market( processed_market: ProcessedMarket, ) -> None: keys = APIKeys() - market.store_prediction(processed_market=processed_market, keys=keys) + reasoning = ( + processed_market.answer.reasoning + if processed_market.answer.reasoning + else "" + ) + agent_result = IPFSAgentResult(reasoning=reasoning, agent_name=self.agent_name) + market.store_prediction( + processed_market=processed_market, keys=keys, agent_result=agent_result + ) def before_process_markets(self, market_type: MarketType) -> None: """ diff --git a/prediction_market_agent_tooling/markets/agent_market.py b/prediction_market_agent_tooling/markets/agent_market.py index 713057de..1198aab0 100644 --- a/prediction_market_agent_tooling/markets/agent_market.py +++ b/prediction_market_agent_tooling/markets/agent_market.py @@ -19,6 +19,7 @@ TokenAmount, ) from prediction_market_agent_tooling.markets.market_fees import MarketFees +from prediction_market_agent_tooling.markets.omen.data_models import IPFSAgentResult from prediction_market_agent_tooling.tools.utils import ( DatetimeUTC, check_not_none, @@ -228,7 +229,10 @@ def verify_operational_balance(api_keys: APIKeys) -> bool: raise NotImplementedError("Subclasses must implement this method") def store_prediction( - self, processed_market: ProcessedMarket, keys: APIKeys + self, + processed_market: ProcessedMarket, + keys: APIKeys, + agent_result: IPFSAgentResult, ) -> None: """ If market allows to upload predictions somewhere, implement it in this method. diff --git a/prediction_market_agent_tooling/markets/omen/data_models.py b/prediction_market_agent_tooling/markets/omen/data_models.py index b3fcf451..1a1e0b75 100644 --- a/prediction_market_agent_tooling/markets/omen/data_models.py +++ b/prediction_market_agent_tooling/markets/omen/data_models.py @@ -798,7 +798,7 @@ def from_tuple(values: tuple[t.Any]) -> "ContractPrediction": class IPFSAgentResult(BaseModel): reasoning: str - model: str | None + agent_name: str | None model_config = ConfigDict( extra="forbid", ) diff --git a/prediction_market_agent_tooling/markets/omen/omen.py b/prediction_market_agent_tooling/markets/omen/omen.py index c4685c2c..8a210ecb 100644 --- a/prediction_market_agent_tooling/markets/omen/omen.py +++ b/prediction_market_agent_tooling/markets/omen/omen.py @@ -417,20 +417,15 @@ def verify_operational_balance(api_keys: APIKeys) -> bool: ) > xdai_type(0.001) def store_prediction( - self, processed_market: ProcessedMarket, keys: APIKeys + self, + processed_market: ProcessedMarket, + keys: APIKeys, + agent_result: IPFSAgentResult, ) -> None: - reasoning = ( - processed_market.answer.reasoning - if processed_market.answer.reasoning - else "" - ) - ipfs_hash_decoded = HexBytes(HASH_ZERO) if keys.enable_ipfs_upload: logger.info("Storing prediction on IPFS.") - ipfs_hash = IPFSHandler(keys).store_agent_result( - IPFSAgentResult(reasoning=reasoning) - ) + ipfs_hash = IPFSHandler(keys).store_agent_result(agent_result) ipfs_hash_decoded = ipfscidv0_to_byte32(ipfs_hash) tx_hashes = [ From f353ff32732204d3353664861b1ab64702878753 Mon Sep 17 00:00:00 2001 From: Gabriel Fior Date: Tue, 22 Oct 2024 10:43:33 +0200 Subject: [PATCH 4/7] Update prediction_market_agent_tooling/markets/omen/data_models.py Co-authored-by: Peter Jung --- prediction_market_agent_tooling/markets/omen/data_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prediction_market_agent_tooling/markets/omen/data_models.py b/prediction_market_agent_tooling/markets/omen/data_models.py index 1a1e0b75..a43ce387 100644 --- a/prediction_market_agent_tooling/markets/omen/data_models.py +++ b/prediction_market_agent_tooling/markets/omen/data_models.py @@ -798,7 +798,7 @@ def from_tuple(values: tuple[t.Any]) -> "ContractPrediction": class IPFSAgentResult(BaseModel): reasoning: str - agent_name: str | None + agent_name: str model_config = ConfigDict( extra="forbid", ) From 75228f6638f9aee69b32e90766347f35431ecfbd Mon Sep 17 00:00:00 2001 From: gabrielfior Date: Tue, 22 Oct 2024 10:48:53 +0200 Subject: [PATCH 5/7] Passing agent_name --- prediction_market_agent_tooling/deploy/agent.py | 9 +-------- .../markets/agent_market.py | 3 +-- prediction_market_agent_tooling/markets/omen/omen.py | 12 ++++++++++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/prediction_market_agent_tooling/deploy/agent.py b/prediction_market_agent_tooling/deploy/agent.py index f668b1c0..c7860b55 100644 --- a/prediction_market_agent_tooling/deploy/agent.py +++ b/prediction_market_agent_tooling/deploy/agent.py @@ -48,7 +48,6 @@ MarketType, have_bet_on_market_since, ) -from prediction_market_agent_tooling.markets.omen.data_models import IPFSAgentResult from prediction_market_agent_tooling.markets.omen.omen import ( withdraw_wxdai_to_xdai_to_keep_balance, ) @@ -497,14 +496,8 @@ def after_process_market( processed_market: ProcessedMarket, ) -> None: keys = APIKeys() - reasoning = ( - processed_market.answer.reasoning - if processed_market.answer.reasoning - else "" - ) - agent_result = IPFSAgentResult(reasoning=reasoning, agent_name=self.agent_name) market.store_prediction( - processed_market=processed_market, keys=keys, agent_result=agent_result + processed_market=processed_market, keys=keys, agent_name=self.agent_name ) def before_process_markets(self, market_type: MarketType) -> None: diff --git a/prediction_market_agent_tooling/markets/agent_market.py b/prediction_market_agent_tooling/markets/agent_market.py index 1198aab0..9b969766 100644 --- a/prediction_market_agent_tooling/markets/agent_market.py +++ b/prediction_market_agent_tooling/markets/agent_market.py @@ -19,7 +19,6 @@ TokenAmount, ) from prediction_market_agent_tooling.markets.market_fees import MarketFees -from prediction_market_agent_tooling.markets.omen.data_models import IPFSAgentResult from prediction_market_agent_tooling.tools.utils import ( DatetimeUTC, check_not_none, @@ -232,7 +231,7 @@ def store_prediction( self, processed_market: ProcessedMarket, keys: APIKeys, - agent_result: IPFSAgentResult, + agent_name: str, ) -> None: """ If market allows to upload predictions somewhere, implement it in this method. diff --git a/prediction_market_agent_tooling/markets/omen/omen.py b/prediction_market_agent_tooling/markets/omen/omen.py index 8a210ecb..51831eee 100644 --- a/prediction_market_agent_tooling/markets/omen/omen.py +++ b/prediction_market_agent_tooling/markets/omen/omen.py @@ -43,12 +43,12 @@ ConditionPreparationEvent, ContractPrediction, CreatedMarket, - IPFSAgentResult, OmenBet, OmenMarket, OmenUserPosition, get_bet_outcome, get_boolean_outcome, + IPFSAgentResult, ) from prediction_market_agent_tooling.markets.omen.omen_contracts import ( OMEN_DEFAULT_MARKET_FEE_PERC, @@ -420,11 +420,19 @@ def store_prediction( self, processed_market: ProcessedMarket, keys: APIKeys, - agent_result: IPFSAgentResult, + agent_name: str, ) -> None: ipfs_hash_decoded = HexBytes(HASH_ZERO) if keys.enable_ipfs_upload: logger.info("Storing prediction on IPFS.") + reasoning = ( + processed_market.answer.reasoning + if processed_market.answer.reasoning + else "" + ) + agent_result = IPFSAgentResult( + reasoning=reasoning, agent_name=self.agent_name + ) ipfs_hash = IPFSHandler(keys).store_agent_result(agent_result) ipfs_hash_decoded = ipfscidv0_to_byte32(ipfs_hash) From 979407751f48381c900a76cee322897cba5a75f7 Mon Sep 17 00:00:00 2001 From: gabrielfior Date: Fri, 1 Nov 2024 11:13:43 -0300 Subject: [PATCH 6/7] Passing agent_names everywhere --- .../deploy/agent.py | 24 ++++++++++++------- .../markets/agent_market.py | 5 +++- .../markets/metaculus/metaculus.py | 2 +- .../markets/omen/omen.py | 22 ++++++++++------- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/prediction_market_agent_tooling/deploy/agent.py b/prediction_market_agent_tooling/deploy/agent.py index 9a26b5da..729f7201 100644 --- a/prediction_market_agent_tooling/deploy/agent.py +++ b/prediction_market_agent_tooling/deploy/agent.py @@ -153,10 +153,10 @@ def langfuse_update_current_trace( input=input, output=output, user_id=user_id or getpass.getuser(), - session_id=session_id - or self.session_id, # All traces within a single run execution will be grouped under a single session. - version=version - or APIKeys().LANGFUSE_DEPLOYMENT_VERSION, # Optionally, mark the current deployment with version (e.g. add git commit hash during docker building). + session_id=session_id or self.session_id, + # All traces within a single run execution will be grouped under a single session. + version=version or APIKeys().LANGFUSE_DEPLOYMENT_VERSION, + # Optionally, mark the current deployment with version (e.g. add git commit hash during docker building). release=release, metadata=metadata, tags=tags, @@ -445,12 +445,13 @@ def after_process_market( market_type: MarketType, market: AgentMarket, processed_market: ProcessedMarket | None, + agent_name: str, ) -> None: keys = APIKeys() if self.store_prediction: market.store_prediction( - processed_market=processed_market, keys=keys, agent_name=self.agent_name - ) + processed_market=processed_market, keys=keys, agent_name=self.agent_name + ) else: logger.info( f"Prediction {processed_market} not stored because {self.store_prediction=}." @@ -478,7 +479,9 @@ def process_markets(self, market_type: MarketType) -> None: for market in available_markets: self.before_process_market(market_type, market) processed_market = self.process_market(market_type, market) - self.after_process_market(market_type, market, processed_market) + self.after_process_market( + market_type, market, processed_market, self.agent_name + ) if processed_market is not None: processed += 1 @@ -618,12 +621,15 @@ def after_process_market( market_type: MarketType, market: AgentMarket, processed_market: ProcessedMarket | None, + agent_name: str, ) -> None: api_keys = APIKeys() - super().after_process_market(market_type, market, processed_market) + super().after_process_market( + market_type, market, processed_market, self.agent_name + ) if isinstance(processed_market, ProcessedTradedMarket): if self.store_trades: - market.store_trades(processed_market, api_keys) + market.store_trades(processed_market, api_keys, self.agent_name) else: logger.info( f"Trades {processed_market.trades} not stored because {self.store_trades=}." diff --git a/prediction_market_agent_tooling/markets/agent_market.py b/prediction_market_agent_tooling/markets/agent_market.py index a9db365a..40afe29c 100644 --- a/prediction_market_agent_tooling/markets/agent_market.py +++ b/prediction_market_agent_tooling/markets/agent_market.py @@ -242,7 +242,10 @@ def store_prediction( raise NotImplementedError("Subclasses must implement this method") def store_trades( - self, traded_market: ProcessedTradedMarket | None, keys: APIKeys + self, + traded_market: ProcessedTradedMarket | None, + keys: APIKeys, + agent_name: str, ) -> None: """ If market allows to upload trades somewhere, implement it in this method. diff --git a/prediction_market_agent_tooling/markets/metaculus/metaculus.py b/prediction_market_agent_tooling/markets/metaculus/metaculus.py index 64efc75e..5a9daf97 100644 --- a/prediction_market_agent_tooling/markets/metaculus/metaculus.py +++ b/prediction_market_agent_tooling/markets/metaculus/metaculus.py @@ -107,7 +107,7 @@ def get_binary_markets( return [MetaculusAgentMarket.from_data_model(q) for q in all_questions[:limit]] def store_prediction( - self, processed_market: ProcessedMarket | None, keys: APIKeys + self, processed_market: ProcessedMarket | None, keys: APIKeys, agent_name: str ) -> None: if processed_market is not None: make_prediction(self.id, processed_market.answer.p_yes) diff --git a/prediction_market_agent_tooling/markets/omen/omen.py b/prediction_market_agent_tooling/markets/omen/omen.py index ff127cf3..dfbf9868 100644 --- a/prediction_market_agent_tooling/markets/omen/omen.py +++ b/prediction_market_agent_tooling/markets/omen/omen.py @@ -413,17 +413,21 @@ def get_trade_balance(api_keys: APIKeys, web3: Web3 | None = None) -> xDai: @staticmethod def verify_operational_balance(api_keys: APIKeys) -> bool: return get_total_balance( - api_keys.public_key, # Use `public_key`, not `bet_from_address` because transaction costs are paid from the EOA wallet. + api_keys.public_key, + # Use `public_key`, not `bet_from_address` because transaction costs are paid from the EOA wallet. sum_wxdai=False, ) > xdai_type(0.001) def store_prediction( - self, processed_market: ProcessedMarket | None, keys: APIKeys + self, processed_market: ProcessedMarket | None, keys: APIKeys, agent_name: str ) -> None: """On Omen, we have to store predictions along with trades, see `store_trades`.""" def store_trades( - self, traded_market: ProcessedTradedMarket | None, keys: APIKeys + self, + traded_market: ProcessedTradedMarket | None, + keys: APIKeys, + agent_name: str, ) -> None: if traded_market is None: logger.warning(f"No prediction for market {self.id}, not storing anything.") @@ -437,7 +441,7 @@ def store_trades( if keys.enable_ipfs_upload: logger.info("Storing prediction on IPFS.") ipfs_hash = IPFSHandler(keys).store_agent_result( - IPFSAgentResult(reasoning=reasoning) + IPFSAgentResult(reasoning=reasoning, agent_name=agent_name) ) ipfs_hash_decoded = ipfscidv0_to_byte32(ipfs_hash) @@ -1237,12 +1241,12 @@ def redeem_from_all_user_positions( if not conditional_token_contract.is_condition_resolved(condition_id): logger.info( - f"[{index+1} / {len(user_positions)}] Skipping redeem, {user_position.id=} isn't resolved yet." + f"[{index + 1} / {len(user_positions)}] Skipping redeem, {user_position.id=} isn't resolved yet." ) continue logger.info( - f"[{index+1} / {len(user_positions)}] Processing redeem from {user_position.id=}." + f"[{index + 1} / {len(user_positions)}] Processing redeem from {user_position.id=}." ) original_balances = get_balances(public_key, web3) @@ -1263,9 +1267,11 @@ def redeem_from_all_user_positions( def get_binary_market_p_yes_history(market: OmenAgentMarket) -> list[Probability]: history: list[Probability] = [] trades = sorted( - OmenSubgraphHandler().get_trades( # We need to look at price both after buying or selling, so get trades, not bets. + OmenSubgraphHandler().get_trades( + # We need to look at price both after buying or selling, so get trades, not bets. market_id=market.market_maker_contract_address_checksummed, - end_time=market.close_time, # Even after market is closed, there can be many `Sell` trades which will converge the probability to the true one. + end_time=market.close_time, + # Even after market is closed, there can be many `Sell` trades which will converge the probability to the true one. ), key=lambda x: x.creation_datetime, ) From fac753815ee4e3db45b819afff9de02e7d5556f8 Mon Sep 17 00:00:00 2001 From: gabrielfior Date: Fri, 1 Nov 2024 15:25:48 -0300 Subject: [PATCH 7/7] Removing agent names not needed as params --- prediction_market_agent_tooling/deploy/agent.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/prediction_market_agent_tooling/deploy/agent.py b/prediction_market_agent_tooling/deploy/agent.py index f3e9613a..ae413968 100644 --- a/prediction_market_agent_tooling/deploy/agent.py +++ b/prediction_market_agent_tooling/deploy/agent.py @@ -445,7 +445,6 @@ def after_process_market( market_type: MarketType, market: AgentMarket, processed_market: ProcessedMarket | None, - agent_name: str, ) -> None: keys = APIKeys() if self.store_prediction: @@ -479,9 +478,7 @@ def process_markets(self, market_type: MarketType) -> None: for market in available_markets: self.before_process_market(market_type, market) processed_market = self.process_market(market_type, market) - self.after_process_market( - market_type, market, processed_market, self.agent_name - ) + self.after_process_market(market_type, market, processed_market) if processed_market is not None: processed += 1 @@ -620,11 +617,12 @@ def after_process_market( market_type: MarketType, market: AgentMarket, processed_market: ProcessedMarket | None, - agent_name: str, ) -> None: api_keys = APIKeys() super().after_process_market( - market_type, market, processed_market, self.agent_name + market_type, + market, + processed_market, ) if isinstance(processed_market, ProcessedTradedMarket): if self.store_trades: