prediction-market-agent-tooling 0.48.2__tar.gz → 0.48.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/PKG-INFO +3 -2
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/config.py +11 -2
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/deploy/agent.py +199 -54
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/deploy/agent_example.py +2 -5
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/categorize.py +18 -6
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/monitor/monitor.py +1 -2
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +7 -1
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/is_predictable.py +16 -2
- prediction_market_agent_tooling-0.48.3/prediction_market_agent_tooling/tools/langfuse_.py +34 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/pyproject.toml +3 -2
- prediction_market_agent_tooling-0.48.2/prediction_market_agent_tooling/monitor/langfuse/langfuse_wrapper.py +0 -26
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/README.md +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/deploy/constants.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/gtypes.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/loggers.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/agent_market.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/data_models.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/markets.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/omen/data_models.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/omen/omen.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/monitor/markets/manifold.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/monitor/markets/metaculus.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/monitor/markets/omen.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/monitor/monitor_app.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/monitor/monitor_settings.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/py.typed +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/balances.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/cache.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/contract.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/costs.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/gnosis_rpc.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/google.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/safe.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/singleton.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/utils.py +0 -0
- {prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/prediction_market_agent_tooling/tools/web3_utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: prediction-market-agent-tooling
|
3
|
-
Version: 0.48.
|
3
|
+
Version: 0.48.3
|
4
4
|
Summary: Tools to benchmark, deploy and monitor prediction market agents.
|
5
5
|
Author: Gnosis
|
6
6
|
Requires-Python: >=3.10,<3.12
|
@@ -24,7 +24,7 @@ Requires-Dist: isort (>=5.13.2,<6.0.0)
|
|
24
24
|
Requires-Dist: langchain (>=0.2.6,<0.3.0) ; extra == "langchain"
|
25
25
|
Requires-Dist: langchain-community (>=0.0.19)
|
26
26
|
Requires-Dist: langchain-openai (>=0.1.0,<0.2.0) ; extra == "langchain"
|
27
|
-
Requires-Dist: langfuse (>=2.
|
27
|
+
Requires-Dist: langfuse (>=2.42.0,<3.0.0)
|
28
28
|
Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
29
29
|
Requires-Dist: numpy (>=1.26.4,<2.0.0)
|
30
30
|
Requires-Dist: openai (>=1.0.0,<2.0.0) ; extra == "openai"
|
@@ -32,6 +32,7 @@ Requires-Dist: prompt-toolkit (>=3.0.43,<4.0.0)
|
|
32
32
|
Requires-Dist: psycopg2-binary (>=2.9.9,<3.0.0)
|
33
33
|
Requires-Dist: pydantic (>=2.6.1,<3.0.0)
|
34
34
|
Requires-Dist: pydantic-settings (>=2.1.0,<3.0.0)
|
35
|
+
Requires-Dist: pymongo (>=4.8.0,<5.0.0)
|
35
36
|
Requires-Dist: safe-cli (>=1.0.0,<2.0.0)
|
36
37
|
Requires-Dist: safe-eth-py (>=6.0.0b14,<7.0.0)
|
37
38
|
Requires-Dist: scikit-learn (>=1.3.1,<2.0.0)
|
@@ -40,8 +40,9 @@ class APIKeys(BaseSettings):
|
|
40
40
|
GOOGLE_SEARCH_ENGINE_ID: t.Optional[SecretStr] = None
|
41
41
|
|
42
42
|
LANGFUSE_SECRET_KEY: t.Optional[SecretStr] = None
|
43
|
-
LANGFUSE_PUBLIC_KEY: t.Optional[
|
43
|
+
LANGFUSE_PUBLIC_KEY: t.Optional[str] = None
|
44
44
|
LANGFUSE_HOST: t.Optional[str] = None
|
45
|
+
LANGFUSE_DEPLOYMENT_VERSION: t.Optional[str] = None
|
45
46
|
|
46
47
|
TAVILY_API_KEY: t.Optional[SecretStr] = None
|
47
48
|
|
@@ -127,7 +128,7 @@ class APIKeys(BaseSettings):
|
|
127
128
|
)
|
128
129
|
|
129
130
|
@property
|
130
|
-
def langfuse_public_key(self) ->
|
131
|
+
def langfuse_public_key(self) -> str:
|
131
132
|
return check_not_none(
|
132
133
|
self.LANGFUSE_PUBLIC_KEY, "LANGFUSE_PUBLIC_KEY missing in the environment."
|
133
134
|
)
|
@@ -138,6 +139,14 @@ class APIKeys(BaseSettings):
|
|
138
139
|
self.LANGFUSE_HOST, "LANGFUSE_HOST missing in the environment."
|
139
140
|
)
|
140
141
|
|
142
|
+
@property
|
143
|
+
def default_enable_langfuse(self) -> bool:
|
144
|
+
return (
|
145
|
+
self.LANGFUSE_SECRET_KEY is not None
|
146
|
+
and self.LANGFUSE_PUBLIC_KEY is not None
|
147
|
+
and self.LANGFUSE_HOST is not None
|
148
|
+
)
|
149
|
+
|
141
150
|
@property
|
142
151
|
def tavily_api_key(self) -> SecretStr:
|
143
152
|
return check_not_none(
|
@@ -1,11 +1,14 @@
|
|
1
|
+
import getpass
|
1
2
|
import inspect
|
2
3
|
import os
|
3
4
|
import tempfile
|
4
5
|
import time
|
5
6
|
import typing as t
|
6
7
|
from datetime import datetime, timedelta
|
8
|
+
from enum import Enum
|
9
|
+
from functools import cached_property
|
7
10
|
|
8
|
-
from pydantic import BaseModel, BeforeValidator
|
11
|
+
from pydantic import BaseModel, BeforeValidator, computed_field
|
9
12
|
from typing_extensions import Annotated
|
10
13
|
|
11
14
|
from prediction_market_agent_tooling.config import APIKeys
|
@@ -39,16 +42,15 @@ from prediction_market_agent_tooling.markets.omen.omen import (
|
|
39
42
|
redeem_from_all_user_positions,
|
40
43
|
withdraw_wxdai_to_xdai_to_keep_balance,
|
41
44
|
)
|
42
|
-
from prediction_market_agent_tooling.monitor.langfuse.langfuse_wrapper import (
|
43
|
-
LangfuseWrapper,
|
44
|
-
)
|
45
45
|
from prediction_market_agent_tooling.monitor.monitor_app import (
|
46
46
|
MARKET_TYPE_TO_DEPLOYED_AGENT,
|
47
47
|
)
|
48
48
|
from prediction_market_agent_tooling.tools.is_predictable import is_predictable_binary
|
49
|
+
from prediction_market_agent_tooling.tools.langfuse_ import langfuse_context, observe
|
49
50
|
from prediction_market_agent_tooling.tools.utils import DatetimeWithTimezone, utcnow
|
50
51
|
|
51
52
|
MAX_AVAILABLE_MARKETS = 20
|
53
|
+
TRADER_TAG = "trader"
|
52
54
|
|
53
55
|
|
54
56
|
def to_boolean_outcome(value: str | bool) -> bool:
|
@@ -71,6 +73,21 @@ def to_boolean_outcome(value: str | bool) -> bool:
|
|
71
73
|
raise ValueError(f"Expected a boolean or a string, but got {value}")
|
72
74
|
|
73
75
|
|
76
|
+
def initialize_langfuse(enable_langfuse: bool) -> None:
|
77
|
+
# Configure Langfuse singleton with our APIKeys.
|
78
|
+
# If langfuse is disabled, it will just ignore all the calls, so no need to do if-else around the code.
|
79
|
+
keys = APIKeys()
|
80
|
+
if enable_langfuse:
|
81
|
+
langfuse_context.configure(
|
82
|
+
public_key=keys.langfuse_public_key,
|
83
|
+
secret_key=keys.langfuse_secret_key.get_secret_value(),
|
84
|
+
host=keys.langfuse_host,
|
85
|
+
enabled=enable_langfuse,
|
86
|
+
)
|
87
|
+
else:
|
88
|
+
langfuse_context.configure(enabled=enable_langfuse)
|
89
|
+
|
90
|
+
|
74
91
|
Decision = Annotated[bool, BeforeValidator(to_boolean_outcome)]
|
75
92
|
|
76
93
|
|
@@ -89,11 +106,66 @@ class Answer(BaseModel):
|
|
89
106
|
return Probability(1 - self.p_yes)
|
90
107
|
|
91
108
|
|
109
|
+
class ProcessedMarket(BaseModel):
|
110
|
+
answer: Answer
|
111
|
+
amount: BetAmount
|
112
|
+
|
113
|
+
|
114
|
+
class AnsweredEnum(str, Enum):
|
115
|
+
ANSWERED = "answered"
|
116
|
+
NOT_ANSWERED = "not_answered"
|
117
|
+
|
118
|
+
|
92
119
|
class DeployableAgent:
|
93
|
-
def __init__(
|
94
|
-
self
|
120
|
+
def __init__(
|
121
|
+
self,
|
122
|
+
enable_langfuse: bool = APIKeys().default_enable_langfuse,
|
123
|
+
) -> None:
|
124
|
+
self.start_time = utcnow()
|
125
|
+
self.enable_langfuse = enable_langfuse
|
126
|
+
self.initialize_langfuse()
|
95
127
|
self.load()
|
96
128
|
|
129
|
+
def initialize_langfuse(self) -> None:
|
130
|
+
initialize_langfuse(self.enable_langfuse)
|
131
|
+
|
132
|
+
def langfuse_update_current_trace(
|
133
|
+
self,
|
134
|
+
name: str | None = None,
|
135
|
+
input: t.Any | None = None,
|
136
|
+
output: t.Any | None = None,
|
137
|
+
user_id: str | None = None,
|
138
|
+
session_id: str | None = None,
|
139
|
+
version: str | None = None,
|
140
|
+
release: str | None = None,
|
141
|
+
metadata: t.Any | None = None,
|
142
|
+
tags: list[str] | None = None,
|
143
|
+
public: bool | None = None,
|
144
|
+
) -> None:
|
145
|
+
"""
|
146
|
+
Provide some useful default arguments when updating the current trace in our agents.
|
147
|
+
"""
|
148
|
+
langfuse_context.update_current_trace(
|
149
|
+
name=name,
|
150
|
+
input=input,
|
151
|
+
output=output,
|
152
|
+
user_id=user_id or getpass.getuser(),
|
153
|
+
session_id=session_id
|
154
|
+
or self.session_id, # All traces within a single run execution will be grouped under a single session.
|
155
|
+
version=version
|
156
|
+
or APIKeys().LANGFUSE_DEPLOYMENT_VERSION, # Optionally, mark the current deployment with version (e.g. add git commit hash during docker building).
|
157
|
+
release=release,
|
158
|
+
metadata=metadata,
|
159
|
+
tags=tags,
|
160
|
+
public=public,
|
161
|
+
)
|
162
|
+
|
163
|
+
@computed_field # type: ignore[prop-decorator] # Mypy issue: https://github.com/python/mypy/issues/14461
|
164
|
+
@cached_property
|
165
|
+
def session_id(self) -> str:
|
166
|
+
# Each agent should be an unique class.
|
167
|
+
return f"{self.__class__.__name__} - {self.start_time.strftime('%Y-%m-%d %H:%M:%S')}"
|
168
|
+
|
97
169
|
def __init_subclass__(cls, **kwargs: t.Any) -> None:
|
98
170
|
if "DeployableAgent" not in str(
|
99
171
|
cls.__init__
|
@@ -209,12 +281,50 @@ class DeployableTraderAgent(DeployableAgent):
|
|
209
281
|
min_required_balance_to_operate: xDai | None = xdai_type(1)
|
210
282
|
min_balance_to_keep_in_native_currency: xDai | None = xdai_type(0.1)
|
211
283
|
|
212
|
-
def __init__(
|
213
|
-
|
284
|
+
def __init__(
|
285
|
+
self,
|
286
|
+
enable_langfuse: bool = APIKeys().default_enable_langfuse,
|
287
|
+
place_bet: bool = True,
|
288
|
+
) -> None:
|
289
|
+
super().__init__(enable_langfuse=enable_langfuse)
|
214
290
|
self.place_bet = place_bet
|
215
291
|
|
216
|
-
def
|
217
|
-
|
292
|
+
def initialize_langfuse(self) -> None:
|
293
|
+
super().initialize_langfuse()
|
294
|
+
# Auto-observe all the methods where it makes sense, so that subclassses don't need to do it manually.
|
295
|
+
self.have_bet_on_market_since = observe()(self.have_bet_on_market_since) # type: ignore[method-assign]
|
296
|
+
self.verify_market = observe()(self.verify_market) # type: ignore[method-assign]
|
297
|
+
self.answer_binary_market = observe()(self.answer_binary_market) # type: ignore[method-assign]
|
298
|
+
self.calculate_bet_amount = observe()(self.calculate_bet_amount) # type: ignore[method-assign]
|
299
|
+
self.process_market = observe()(self.process_market) # type: ignore[method-assign]
|
300
|
+
|
301
|
+
def update_langfuse_trace_by_market(
|
302
|
+
self, market_type: MarketType, market: AgentMarket
|
303
|
+
) -> None:
|
304
|
+
self.langfuse_update_current_trace(
|
305
|
+
# UI allows to do filtering by these.
|
306
|
+
metadata={
|
307
|
+
"agent_class": self.__class__.__name__,
|
308
|
+
"market_id": market.id,
|
309
|
+
"market_question": market.question,
|
310
|
+
"market_outcomes": market.outcomes,
|
311
|
+
},
|
312
|
+
)
|
313
|
+
|
314
|
+
def update_langfuse_trace_by_processed_market(
|
315
|
+
self, market_type: MarketType, processed_market: ProcessedMarket | None
|
316
|
+
) -> None:
|
317
|
+
self.langfuse_update_current_trace(
|
318
|
+
tags=[
|
319
|
+
TRADER_TAG,
|
320
|
+
(
|
321
|
+
AnsweredEnum.ANSWERED
|
322
|
+
if processed_market is not None
|
323
|
+
else AnsweredEnum.NOT_ANSWERED
|
324
|
+
),
|
325
|
+
market_type.value,
|
326
|
+
]
|
327
|
+
)
|
218
328
|
|
219
329
|
def check_min_required_balance_to_operate(self, market_type: MarketType) -> None:
|
220
330
|
api_keys = APIKeys()
|
@@ -229,35 +339,26 @@ class DeployableTraderAgent(DeployableAgent):
|
|
229
339
|
f"for agent with address {api_keys.public_key} is not met."
|
230
340
|
)
|
231
341
|
|
232
|
-
def
|
233
|
-
|
234
|
-
|
342
|
+
def have_bet_on_market_since(self, market: AgentMarket, since: timedelta) -> bool:
|
343
|
+
return have_bet_on_market_since(keys=APIKeys(), market=market, since=since)
|
344
|
+
|
345
|
+
def verify_market(self, market_type: MarketType, market: AgentMarket) -> bool:
|
235
346
|
"""
|
236
347
|
Subclasses can implement their own logic instead of this one, or on top of this one.
|
237
|
-
By default, it
|
348
|
+
By default, it allows only markets where user didn't bet recently and it's a reasonable question.
|
238
349
|
"""
|
239
|
-
|
240
|
-
|
241
|
-
for market in markets:
|
242
|
-
if len(picked) >= self.bet_on_n_markets_per_run:
|
243
|
-
break
|
244
|
-
|
245
|
-
if self.have_bet_on_market_since(market, since=timedelta(hours=24)):
|
246
|
-
continue
|
247
|
-
|
248
|
-
# Do as a last check, as it uses paid OpenAI API.
|
249
|
-
if not is_predictable_binary(market.question):
|
250
|
-
continue
|
350
|
+
if self.have_bet_on_market_since(market, since=timedelta(hours=24)):
|
351
|
+
return False
|
251
352
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
):
|
256
|
-
continue
|
353
|
+
# Manifold allows to bet only on markets with probability between 1 and 99.
|
354
|
+
if market_type == MarketType.MANIFOLD and not (1 < market.current_p_yes < 99):
|
355
|
+
return False
|
257
356
|
|
258
|
-
|
357
|
+
# Do as a last check, as it uses paid OpenAI API.
|
358
|
+
if not is_predictable_binary(market.question):
|
359
|
+
return False
|
259
360
|
|
260
|
-
return
|
361
|
+
return True
|
261
362
|
|
262
363
|
def answer_binary_market(self, market: AgentMarket) -> Answer | None:
|
263
364
|
"""
|
@@ -285,7 +386,55 @@ class DeployableTraderAgent(DeployableAgent):
|
|
285
386
|
)
|
286
387
|
return available_markets
|
287
388
|
|
288
|
-
def
|
389
|
+
def before_process_market(
|
390
|
+
self, market_type: MarketType, market: AgentMarket
|
391
|
+
) -> None:
|
392
|
+
self.update_langfuse_trace_by_market(market_type, market)
|
393
|
+
|
394
|
+
def process_market(
|
395
|
+
self, market_type: MarketType, market: AgentMarket, verify_market: bool = True
|
396
|
+
) -> ProcessedMarket | None:
|
397
|
+
self.before_process_market(market_type, market)
|
398
|
+
|
399
|
+
if verify_market and not self.verify_market(market_type, market):
|
400
|
+
logger.info(f"Market '{market.question}' doesn't meet the criteria.")
|
401
|
+
self.update_langfuse_trace_by_processed_market(market_type, None)
|
402
|
+
return None
|
403
|
+
|
404
|
+
answer = self.answer_binary_market(market)
|
405
|
+
|
406
|
+
if answer is None:
|
407
|
+
logger.info(f"No answer for market '{market.question}'.")
|
408
|
+
self.update_langfuse_trace_by_processed_market(market_type, None)
|
409
|
+
return None
|
410
|
+
|
411
|
+
amount = self.calculate_bet_amount(answer, market)
|
412
|
+
|
413
|
+
if self.place_bet:
|
414
|
+
logger.info(
|
415
|
+
f"Placing bet on {market} with result {answer} and amount {amount}"
|
416
|
+
)
|
417
|
+
market.place_bet(
|
418
|
+
amount=amount,
|
419
|
+
outcome=answer.decision,
|
420
|
+
)
|
421
|
+
|
422
|
+
self.after_process_market(market_type, market)
|
423
|
+
|
424
|
+
processed_market = ProcessedMarket(
|
425
|
+
answer=answer,
|
426
|
+
amount=amount,
|
427
|
+
)
|
428
|
+
self.update_langfuse_trace_by_processed_market(market_type, processed_market)
|
429
|
+
|
430
|
+
return processed_market
|
431
|
+
|
432
|
+
def after_process_market(
|
433
|
+
self, market_type: MarketType, market: AgentMarket
|
434
|
+
) -> None:
|
435
|
+
pass
|
436
|
+
|
437
|
+
def before_process_markets(self, market_type: MarketType) -> None:
|
289
438
|
"""
|
290
439
|
Executes actions that occur before bets are placed.
|
291
440
|
"""
|
@@ -302,33 +451,29 @@ class DeployableTraderAgent(DeployableAgent):
|
|
302
451
|
withdraw_multiplier=2,
|
303
452
|
)
|
304
453
|
|
305
|
-
def
|
454
|
+
def process_markets(self, market_type: MarketType) -> None:
|
306
455
|
"""
|
307
456
|
Processes bets placed by agents on a given market.
|
308
457
|
"""
|
309
458
|
available_markets = self.get_markets(market_type)
|
310
|
-
|
311
|
-
|
459
|
+
processed = 0
|
460
|
+
|
461
|
+
for market in available_markets:
|
312
462
|
# We need to check it again before each market bet, as the balance might have changed.
|
313
463
|
self.check_min_required_balance_to_operate(market_type)
|
314
|
-
result = self.answer_binary_market(market)
|
315
|
-
if result is None:
|
316
|
-
logger.info(f"Skipping market {market} as no answer was provided")
|
317
|
-
continue
|
318
|
-
if self.place_bet:
|
319
|
-
amount = self.calculate_bet_amount(result, market)
|
320
|
-
logger.info(
|
321
|
-
f"Placing bet on {market} with result {result} and amount {amount}"
|
322
|
-
)
|
323
|
-
market.place_bet(
|
324
|
-
amount=amount,
|
325
|
-
outcome=result.decision,
|
326
|
-
)
|
327
464
|
|
328
|
-
|
465
|
+
processed_market = self.process_market(market_type, market)
|
466
|
+
|
467
|
+
if processed_market is not None:
|
468
|
+
processed += 1
|
469
|
+
|
470
|
+
if processed == self.bet_on_n_markets_per_run:
|
471
|
+
break
|
472
|
+
|
473
|
+
def after_process_markets(self, market_type: MarketType) -> None:
|
329
474
|
pass
|
330
475
|
|
331
476
|
def run(self, market_type: MarketType) -> None:
|
332
|
-
self.
|
333
|
-
self.
|
334
|
-
self.
|
477
|
+
self.before_process_markets(market_type)
|
478
|
+
self.process_markets(market_type)
|
479
|
+
self.after_process_markets(market_type)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import random
|
2
|
-
import typing as t
|
3
2
|
|
4
3
|
from prediction_market_agent_tooling.deploy.agent import (
|
5
4
|
Answer,
|
@@ -11,10 +10,8 @@ from prediction_market_agent_tooling.markets.markets import MarketType
|
|
11
10
|
|
12
11
|
|
13
12
|
class DeployableCoinFlipAgent(DeployableTraderAgent):
|
14
|
-
def
|
15
|
-
|
16
|
-
) -> t.Sequence[AgentMarket]:
|
17
|
-
return random.sample(markets, 1)
|
13
|
+
def verify_market(self, market_type: MarketType, market: AgentMarket) -> bool:
|
14
|
+
return True
|
18
15
|
|
19
16
|
def answer_binary_market(self, market: AgentMarket) -> Answer | None:
|
20
17
|
decision = random.choice([True, False])
|
@@ -1,13 +1,24 @@
|
|
1
|
-
from langchain.prompts import ChatPromptTemplate
|
2
|
-
from langchain.schema.output_parser import StrOutputParser
|
3
|
-
from langchain_openai import ChatOpenAI
|
4
|
-
|
5
1
|
from prediction_market_agent_tooling.config import APIKeys
|
2
|
+
from prediction_market_agent_tooling.tools.langfuse_ import (
|
3
|
+
get_langfuse_langchain_config,
|
4
|
+
observe,
|
5
|
+
)
|
6
6
|
|
7
7
|
|
8
|
+
@observe()
|
8
9
|
def infer_category(
|
9
|
-
question: str,
|
10
|
+
question: str,
|
11
|
+
categories: set[str],
|
12
|
+
model: str = "gpt-3.5-turbo-0125",
|
10
13
|
) -> str:
|
14
|
+
try:
|
15
|
+
from langchain.prompts import ChatPromptTemplate
|
16
|
+
from langchain.schema.output_parser import StrOutputParser
|
17
|
+
from langchain_openai import ChatOpenAI
|
18
|
+
except ImportError:
|
19
|
+
raise ImportError(
|
20
|
+
"openai not installed, please install extras `langchain` to use this function."
|
21
|
+
)
|
11
22
|
prompt = ChatPromptTemplate.from_template(
|
12
23
|
template="""Assign the following question: {question}
|
13
24
|
|
@@ -27,7 +38,8 @@ Write only the category itself, nothing else.
|
|
27
38
|
)
|
28
39
|
|
29
40
|
response: str = research_evaluation_chain.invoke(
|
30
|
-
{"question": question, "categories": sorted(categories)}
|
41
|
+
{"question": question, "categories": sorted(categories)},
|
42
|
+
config=get_langfuse_langchain_config(),
|
31
43
|
)
|
32
44
|
|
33
45
|
formatted = response.strip().strip("'").strip('"').strip()
|
@@ -229,8 +229,7 @@ def monitor_agent(agent: DeployedAgent) -> None:
|
|
229
229
|
)
|
230
230
|
.interactive()
|
231
231
|
)
|
232
|
-
|
233
|
-
st.altair_chart( # type: ignore
|
232
|
+
st.altair_chart( # type: ignore # Doesn't expect `LayerChart`, but `Chart`, yet it works.
|
234
233
|
per_day_accuracy_chart.mark_line()
|
235
234
|
+ per_day_accuracy_chart.transform_loess("x-axis-day", "Is Correct").mark_line(
|
236
235
|
color="red", strokeDash=[5, 5]
|
@@ -2,8 +2,13 @@ from PIL.Image import Image as ImageType
|
|
2
2
|
|
3
3
|
from prediction_market_agent_tooling.config import APIKeys
|
4
4
|
from prediction_market_agent_tooling.tools.image_gen.image_gen import generate_image
|
5
|
+
from prediction_market_agent_tooling.tools.langfuse_ import (
|
6
|
+
get_langfuse_langchain_config,
|
7
|
+
observe,
|
8
|
+
)
|
5
9
|
|
6
10
|
|
11
|
+
@observe()
|
7
12
|
def rewrite_question_into_image_generation_prompt(question: str) -> str:
|
8
13
|
try:
|
9
14
|
from langchain_openai import ChatOpenAI
|
@@ -19,7 +24,8 @@ def rewrite_question_into_image_generation_prompt(question: str) -> str:
|
|
19
24
|
rewritten = str(
|
20
25
|
llm.invoke(
|
21
26
|
f"Rewrite this prediction market question '{question}' into a form that will generate nice thumbnail with DALL-E-3."
|
22
|
-
"The thumbnail should be catchy and visually appealing. With a large object in the center of the image."
|
27
|
+
"The thumbnail should be catchy and visually appealing. With a large object in the center of the image.",
|
28
|
+
config=get_langfuse_langchain_config(),
|
23
29
|
).content
|
24
30
|
)
|
25
31
|
return rewritten
|
@@ -2,6 +2,10 @@ from loguru import logger
|
|
2
2
|
|
3
3
|
from prediction_market_agent_tooling.config import APIKeys
|
4
4
|
from prediction_market_agent_tooling.tools.cache import persistent_inmemory_cache
|
5
|
+
from prediction_market_agent_tooling.tools.langfuse_ import (
|
6
|
+
get_langfuse_langchain_config,
|
7
|
+
observe,
|
8
|
+
)
|
5
9
|
from prediction_market_agent_tooling.tools.utils import LLM_SUPER_LOW_TEMPERATURE
|
6
10
|
|
7
11
|
# I tried to make it return a JSON, but it didn't work well in combo with asking it to do chain of thought.
|
@@ -72,6 +76,7 @@ Finally, write your final decision, write `decision: ` followed by either "yes i
|
|
72
76
|
|
73
77
|
|
74
78
|
@persistent_inmemory_cache
|
79
|
+
@observe()
|
75
80
|
def is_predictable_binary(
|
76
81
|
question: str,
|
77
82
|
engine: str = "gpt-4-1106-preview",
|
@@ -96,12 +101,17 @@ def is_predictable_binary(
|
|
96
101
|
|
97
102
|
prompt = ChatPromptTemplate.from_template(template=prompt_template)
|
98
103
|
messages = prompt.format_messages(question=question)
|
99
|
-
completion = str(
|
104
|
+
completion = str(
|
105
|
+
llm.invoke(
|
106
|
+
messages, max_tokens=max_tokens, config=get_langfuse_langchain_config()
|
107
|
+
).content
|
108
|
+
)
|
100
109
|
|
101
110
|
return parse_decision_yes_no_completion(question, completion)
|
102
111
|
|
103
112
|
|
104
113
|
@persistent_inmemory_cache
|
114
|
+
@observe()
|
105
115
|
def is_predictable_without_description(
|
106
116
|
question: str,
|
107
117
|
description: str,
|
@@ -132,7 +142,11 @@ def is_predictable_without_description(
|
|
132
142
|
question=question,
|
133
143
|
description=description,
|
134
144
|
)
|
135
|
-
completion = str(
|
145
|
+
completion = str(
|
146
|
+
llm(
|
147
|
+
messages, max_tokens=max_tokens, config=get_langfuse_langchain_config()
|
148
|
+
).content
|
149
|
+
)
|
136
150
|
|
137
151
|
return parse_decision_yes_no_completion(question, completion)
|
138
152
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from typing import Any, Callable, Iterable, Literal, Optional, ParamSpec, TypeVar
|
2
|
+
|
3
|
+
from langchain_core.runnables.config import RunnableConfig
|
4
|
+
from langfuse.decorators.langfuse_decorator import ( # noqa: F401 # Import for the sake of easy importing with others from here.
|
5
|
+
langfuse_context,
|
6
|
+
)
|
7
|
+
from langfuse.decorators.langfuse_decorator import observe as original_observe
|
8
|
+
|
9
|
+
P = ParamSpec("P")
|
10
|
+
R = TypeVar("R")
|
11
|
+
|
12
|
+
|
13
|
+
def observe(
|
14
|
+
name: Optional[str] = None,
|
15
|
+
as_type: Optional[Literal["generation"]] = None,
|
16
|
+
capture_input: bool = True,
|
17
|
+
capture_output: bool = True,
|
18
|
+
transform_to_string: Optional[Callable[[Iterable[Any]], str]] = None,
|
19
|
+
) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
20
|
+
casted: Callable[[Callable[P, R]], Callable[P, R]] = original_observe(
|
21
|
+
name=name,
|
22
|
+
as_type=as_type,
|
23
|
+
capture_input=capture_input,
|
24
|
+
capture_output=capture_output,
|
25
|
+
transform_to_string=transform_to_string,
|
26
|
+
)
|
27
|
+
return casted
|
28
|
+
|
29
|
+
|
30
|
+
def get_langfuse_langchain_config() -> RunnableConfig:
|
31
|
+
config: RunnableConfig = {
|
32
|
+
"callbacks": [langfuse_context.get_current_langchain_handler()]
|
33
|
+
}
|
34
|
+
return config
|
{prediction_market_agent_tooling-0.48.2 → prediction_market_agent_tooling-0.48.3}/pyproject.toml
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "prediction-market-agent-tooling"
|
3
|
-
version = "0.48.
|
3
|
+
version = "0.48.3"
|
4
4
|
description = "Tools to benchmark, deploy and monitor prediction market agents."
|
5
5
|
authors = ["Gnosis"]
|
6
6
|
readme = "README.md"
|
@@ -40,8 +40,9 @@ safe-eth-py = "^6.0.0b14"
|
|
40
40
|
eth-account = ">=0.8.0,<0.12.0"
|
41
41
|
prompt-toolkit = "^3.0.43"
|
42
42
|
safe-cli = "^1.0.0"
|
43
|
-
langfuse = "^2.
|
43
|
+
langfuse = "^2.42.0"
|
44
44
|
openai = { version = "^1.0.0", optional = true}
|
45
|
+
pymongo = "^4.8.0"
|
45
46
|
tavily-python = "^0.3.9"
|
46
47
|
sqlmodel = "^0.0.21"
|
47
48
|
psycopg2-binary = "^2.9.9"
|
@@ -1,26 +0,0 @@
|
|
1
|
-
from functools import cached_property
|
2
|
-
|
3
|
-
from langfuse.callback import CallbackHandler
|
4
|
-
from pydantic import BaseModel, computed_field
|
5
|
-
|
6
|
-
from prediction_market_agent_tooling.config import APIKeys
|
7
|
-
from prediction_market_agent_tooling.tools.utils import utcnow
|
8
|
-
|
9
|
-
|
10
|
-
class LangfuseWrapper(BaseModel):
|
11
|
-
agent_name: str
|
12
|
-
|
13
|
-
@computed_field # type: ignore[prop-decorator] # Mypy issue: https://github.com/python/mypy/issues/14461
|
14
|
-
@cached_property
|
15
|
-
def session_id(self) -> str:
|
16
|
-
return f"{self.agent_name} - {utcnow()}"
|
17
|
-
|
18
|
-
def get_langfuse_handler(self) -> CallbackHandler:
|
19
|
-
keys = APIKeys()
|
20
|
-
langfuse_handler = CallbackHandler(
|
21
|
-
secret_key=keys.langfuse_secret_key.get_secret_value(),
|
22
|
-
public_key=keys.langfuse_public_key.get_secret_value(),
|
23
|
-
host=keys.langfuse_host,
|
24
|
-
session_id=self.session_id,
|
25
|
-
)
|
26
|
-
return langfuse_handler
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|