prediction-market-agent-tooling 0.65.4__py3-none-any.whl → 0.65.6__py3-none-any.whl
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/config.py +8 -0
- prediction_market_agent_tooling/deploy/agent.py +2 -1
- prediction_market_agent_tooling/logprobs_parser.py +2 -1
- prediction_market_agent_tooling/tools/perplexity/perplexity_client.py +86 -0
- prediction_market_agent_tooling/tools/perplexity/perplexity_models.py +26 -0
- prediction_market_agent_tooling/tools/perplexity/perplexity_search.py +73 -0
- {prediction_market_agent_tooling-0.65.4.dist-info → prediction_market_agent_tooling-0.65.6.dist-info}/METADATA +1 -1
- {prediction_market_agent_tooling-0.65.4.dist-info → prediction_market_agent_tooling-0.65.6.dist-info}/RECORD +11 -8
- {prediction_market_agent_tooling-0.65.4.dist-info → prediction_market_agent_tooling-0.65.6.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.65.4.dist-info → prediction_market_agent_tooling-0.65.6.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.65.4.dist-info → prediction_market_agent_tooling-0.65.6.dist-info}/entry_points.txt +0 -0
@@ -65,6 +65,8 @@ class APIKeys(BaseSettings):
|
|
65
65
|
|
66
66
|
SQLALCHEMY_DB_URL: t.Optional[SecretStr] = None
|
67
67
|
|
68
|
+
PERPLEXITY_API_KEY: t.Optional[SecretStr] = None
|
69
|
+
|
68
70
|
ENABLE_CACHE: bool = False
|
69
71
|
CACHE_DIR: str = "./.cache"
|
70
72
|
|
@@ -259,6 +261,12 @@ class APIKeys(BaseSettings):
|
|
259
261
|
if self.model_fields[k].annotation not in SECRET_TYPES and v is not None
|
260
262
|
}
|
261
263
|
|
264
|
+
@property
|
265
|
+
def perplexity_api_key(self) -> SecretStr:
|
266
|
+
return check_not_none(
|
267
|
+
self.PERPLEXITY_API_KEY, "PERPLEXITY_API_KEY missing in the environment."
|
268
|
+
)
|
269
|
+
|
262
270
|
def model_dump_secrets(self) -> dict[str, t.Any]:
|
263
271
|
return {
|
264
272
|
k: v.get_secret_value() if isinstance(v, SecretStr) else v
|
@@ -222,6 +222,7 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
222
222
|
self.have_bet_on_market_since = observe()(self.have_bet_on_market_since) # type: ignore[method-assign]
|
223
223
|
self.verify_market = observe()(self.verify_market) # type: ignore[method-assign]
|
224
224
|
self.answer_binary_market = observe()(self.answer_binary_market) # type: ignore[method-assign]
|
225
|
+
self.answer_categorical_market = observe()(self.answer_categorical_market) # type: ignore[method-assign]
|
225
226
|
self.process_market = observe()(self.process_market) # type: ignore[method-assign]
|
226
227
|
|
227
228
|
def update_langfuse_trace_by_market(
|
@@ -321,7 +322,7 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
321
322
|
def fetch_categorical_markets(self) -> bool:
|
322
323
|
# Check if the subclass has implemented the answer_categorical_market method, if yes, fetch categorical markets as well.
|
323
324
|
if (
|
324
|
-
self.answer_categorical_market.__func__ # type: ignore[attr-defined] # This works just fine, but mypy doesn't know about it for some reason.
|
325
|
+
self.answer_categorical_market.__wrapped__.__func__ # type: ignore[attr-defined] # This works just fine, but mypy doesn't know about it for some reason.
|
325
326
|
is not DeployablePredictionAgent.answer_categorical_market
|
326
327
|
):
|
327
328
|
return True
|
@@ -61,7 +61,8 @@ class LogprobsParser:
|
|
61
61
|
(
|
62
62
|
i
|
63
63
|
for i in range(result_start_index, len(logprobs))
|
64
|
-
if logprobs[i]["token"]
|
64
|
+
if logprobs[i]["token"]
|
65
|
+
in {",", '"', ",\n", "\",\n'", '",\n', '"\n', "\n"}
|
65
66
|
),
|
66
67
|
len(logprobs) - 1,
|
67
68
|
)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
2
|
+
|
3
|
+
import httpx
|
4
|
+
from pydantic import SecretStr
|
5
|
+
|
6
|
+
from prediction_market_agent_tooling.tools.perplexity.perplexity_models import (
|
7
|
+
PerplexityModelSettings,
|
8
|
+
PerplexityRequestParameters,
|
9
|
+
PerplexityResponse,
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
class PerplexityModel:
|
14
|
+
def __init__(
|
15
|
+
self,
|
16
|
+
model_name: str,
|
17
|
+
*,
|
18
|
+
api_key: SecretStr,
|
19
|
+
completition_endpoint: str = "https://api.perplexity.ai/chat/completions",
|
20
|
+
) -> None:
|
21
|
+
self.model_name = model_name
|
22
|
+
self.api_key = api_key
|
23
|
+
self.completition_endpoint = completition_endpoint
|
24
|
+
|
25
|
+
async def request(
|
26
|
+
self,
|
27
|
+
messages: List[dict[str, str]],
|
28
|
+
model_settings: Optional[PerplexityModelSettings],
|
29
|
+
model_request_parameters: PerplexityRequestParameters,
|
30
|
+
) -> PerplexityResponse:
|
31
|
+
payload: Dict[str, Any] = {"model": self.model_name, "messages": messages}
|
32
|
+
|
33
|
+
if model_settings:
|
34
|
+
model_settings_dict = model_settings.model_dump()
|
35
|
+
model_settings_dict = {
|
36
|
+
k: v for k, v in model_settings_dict.items() if v is not None
|
37
|
+
}
|
38
|
+
payload.update(model_settings_dict)
|
39
|
+
|
40
|
+
params_dict = model_request_parameters.model_dump()
|
41
|
+
params_dict = {k: v for k, v in params_dict.items() if v is not None}
|
42
|
+
|
43
|
+
# Extract and handle search_context_size specially
|
44
|
+
if "search_context_size" in params_dict:
|
45
|
+
search_context_size = params_dict.pop("search_context_size")
|
46
|
+
payload["web_search_options"] = {"search_context_size": search_context_size}
|
47
|
+
|
48
|
+
# Add remaining Perplexity parameters to payload
|
49
|
+
payload.update(params_dict)
|
50
|
+
|
51
|
+
try:
|
52
|
+
async with httpx.AsyncClient(timeout=180) as client:
|
53
|
+
response = await client.post(
|
54
|
+
self.completition_endpoint,
|
55
|
+
headers={
|
56
|
+
"Authorization": f"Bearer {self.api_key.get_secret_value()}",
|
57
|
+
"Content-Type": "application/json",
|
58
|
+
},
|
59
|
+
json=payload,
|
60
|
+
)
|
61
|
+
response.raise_for_status()
|
62
|
+
result: dict[str, Any] = response.json()
|
63
|
+
|
64
|
+
choices = result.get("choices", [])
|
65
|
+
if not choices:
|
66
|
+
raise ValueError("Invalid response: no choices")
|
67
|
+
|
68
|
+
content = choices[0].get("message", {}).get("content")
|
69
|
+
if not content:
|
70
|
+
raise ValueError("Invalid response: no content")
|
71
|
+
|
72
|
+
return PerplexityResponse(
|
73
|
+
content=content,
|
74
|
+
citations=result.get("citations", []),
|
75
|
+
usage=result.get("usage", {}),
|
76
|
+
)
|
77
|
+
except httpx.HTTPStatusError as e:
|
78
|
+
raise ValueError(
|
79
|
+
f"HTTP error from Perplexity API: {e.response.status_code} - {e.response.text}"
|
80
|
+
) from e
|
81
|
+
except httpx.RequestError as e:
|
82
|
+
raise ValueError(f"Request error to Perplexity API: {str(e)}") from e
|
83
|
+
except Exception as e:
|
84
|
+
raise ValueError(
|
85
|
+
f"Unexpected error in Perplexity API request: {str(e)}"
|
86
|
+
) from e
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from typing import Any, List, Literal, Optional
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
|
5
|
+
|
6
|
+
class PerplexityRequestParameters(BaseModel):
|
7
|
+
search_context_size: Optional[Literal["low", "medium", "high"]]
|
8
|
+
search_recency_filter: Optional[Literal["any", "day", "week", "month", "year"]]
|
9
|
+
search_return_related_questions: Optional[bool]
|
10
|
+
search_domain_filter: Optional[List[str]]
|
11
|
+
search_after_date_filter: Optional[str]
|
12
|
+
search_before_date_filter: Optional[str]
|
13
|
+
|
14
|
+
|
15
|
+
class PerplexityResponse(BaseModel):
|
16
|
+
content: str
|
17
|
+
citations: list[str]
|
18
|
+
usage: dict[str, Any]
|
19
|
+
|
20
|
+
|
21
|
+
class PerplexityModelSettings(BaseModel):
|
22
|
+
max_tokens: Optional[int] = None
|
23
|
+
temperature: Optional[float] = None
|
24
|
+
top_p: Optional[float] = None
|
25
|
+
frequency_penalty: Optional[float] = None
|
26
|
+
presence_penalty: Optional[float] = None
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import asyncio
|
2
|
+
import typing as t
|
3
|
+
from datetime import date, timedelta
|
4
|
+
|
5
|
+
import tenacity
|
6
|
+
|
7
|
+
from prediction_market_agent_tooling.config import APIKeys
|
8
|
+
from prediction_market_agent_tooling.tools.caches.db_cache import db_cache
|
9
|
+
from prediction_market_agent_tooling.tools.perplexity.perplexity_client import (
|
10
|
+
PerplexityModel,
|
11
|
+
)
|
12
|
+
from prediction_market_agent_tooling.tools.perplexity.perplexity_models import (
|
13
|
+
PerplexityModelSettings,
|
14
|
+
PerplexityRequestParameters,
|
15
|
+
PerplexityResponse,
|
16
|
+
)
|
17
|
+
|
18
|
+
SYSTEM_PROMPT = "You are a helpful search assistant. Your task is to provide accurate information based on web searches."
|
19
|
+
|
20
|
+
|
21
|
+
@tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(1))
|
22
|
+
@db_cache(
|
23
|
+
max_age=timedelta(days=1),
|
24
|
+
ignore_args=["api_keys"],
|
25
|
+
log_error_on_unsavable_data=False,
|
26
|
+
)
|
27
|
+
def perplexity_search(
|
28
|
+
query: str,
|
29
|
+
api_keys: APIKeys,
|
30
|
+
search_context_size: t.Literal["low", "medium", "high"] = "medium",
|
31
|
+
search_recency_filter: t.Literal["any", "day", "week", "month", "year"]
|
32
|
+
| None = None,
|
33
|
+
search_filter_before_date: date | None = None,
|
34
|
+
search_filter_after_date: date | None = None,
|
35
|
+
search_return_related_questions: bool | None = None,
|
36
|
+
include_domains: list[str] | None = None,
|
37
|
+
temperature: float = 0,
|
38
|
+
model_name: str = "sonar-pro",
|
39
|
+
max_tokens: int = 2048,
|
40
|
+
) -> PerplexityResponse:
|
41
|
+
# Create messages in ModelMessage format
|
42
|
+
messages = [
|
43
|
+
{"role": "system", "content": SYSTEM_PROMPT},
|
44
|
+
{"role": "user", "content": query},
|
45
|
+
]
|
46
|
+
|
47
|
+
# Define special parameters for the request and create the settings
|
48
|
+
model_settings = PerplexityModelSettings(
|
49
|
+
max_tokens=max_tokens, temperature=temperature
|
50
|
+
)
|
51
|
+
|
52
|
+
# Create a basic request parameters object with required base parameters
|
53
|
+
request_params = PerplexityRequestParameters(
|
54
|
+
search_domain_filter=include_domains,
|
55
|
+
search_after_date_filter=search_filter_after_date.strftime("%Y-%m-%d")
|
56
|
+
if search_filter_after_date
|
57
|
+
else None,
|
58
|
+
search_before_date_filter=search_filter_before_date.strftime("%Y-%m-%d")
|
59
|
+
if search_filter_before_date
|
60
|
+
else None,
|
61
|
+
search_recency_filter=search_recency_filter,
|
62
|
+
search_context_size=search_context_size,
|
63
|
+
search_return_related_questions=search_return_related_questions,
|
64
|
+
)
|
65
|
+
|
66
|
+
model = PerplexityModel(model_name=model_name, api_key=api_keys.perplexity_api_key)
|
67
|
+
return asyncio.run(
|
68
|
+
model.request(
|
69
|
+
messages=messages,
|
70
|
+
model_settings=model_settings,
|
71
|
+
model_request_parameters=request_params,
|
72
|
+
)
|
73
|
+
)
|
@@ -23,8 +23,8 @@ prediction_market_agent_tooling/benchmark/agents.py,sha256=zC5tUM6pPTWtqSddOOSYV
|
|
23
23
|
prediction_market_agent_tooling/benchmark/benchmark.py,sha256=KwMZzwise3sgmhdjw7xCgHMmjKHdHqQC-zc9untOLWg,17832
|
24
24
|
prediction_market_agent_tooling/benchmark/utils.py,sha256=xQd7p9H08-OtN3iC4QT2i9bkUTmrXa6rxGXeg9yMhgU,2986
|
25
25
|
prediction_market_agent_tooling/chains.py,sha256=1qQstoqXMwqwM7k-KH7MjMz8Ei-D83KZByvDbCZpAxs,116
|
26
|
-
prediction_market_agent_tooling/config.py,sha256
|
27
|
-
prediction_market_agent_tooling/deploy/agent.py,sha256=
|
26
|
+
prediction_market_agent_tooling/config.py,sha256=-kJfdDr-m0R-tGZ1KRI-hJJk0mXDt142CAlvwaJ2N2I,11778
|
27
|
+
prediction_market_agent_tooling/deploy/agent.py,sha256=ddFvBUhB_WVWtuUGkiZNKBME4Hd3AdquVv588c1rpu0,25602
|
28
28
|
prediction_market_agent_tooling/deploy/agent_example.py,sha256=yS1fWkHynr9MYGNOM2WsCnRWLPaffY4bOc6bIudrdd4,1377
|
29
29
|
prediction_market_agent_tooling/deploy/betting_strategy.py,sha256=YYayGjTKW02d3BUavJ8M3NmFk41oldEM3FHbwppZGRM,17184
|
30
30
|
prediction_market_agent_tooling/deploy/constants.py,sha256=Qe9cllgsGMkecfmbhXoFkPxuJyG6ATsrT87RF9SmPWM,249
|
@@ -37,7 +37,7 @@ prediction_market_agent_tooling/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeu
|
|
37
37
|
prediction_market_agent_tooling/jobs/jobs_models.py,sha256=DoZ9dlvVhpNrnINiR1uy6YUOsuzI_L-avBt362y5xXM,2467
|
38
38
|
prediction_market_agent_tooling/jobs/omen/omen_jobs.py,sha256=qbTZ9HVvu_iP4dDxuvOZxAp6JsRKejvEW2YDYCnRmd4,5039
|
39
39
|
prediction_market_agent_tooling/loggers.py,sha256=kFZ1BrI8hvWgZO1vzptFnYiOEDx9Ozs86DA9yF3bSgY,5212
|
40
|
-
prediction_market_agent_tooling/logprobs_parser.py,sha256=
|
40
|
+
prediction_market_agent_tooling/logprobs_parser.py,sha256=DBlBQtWX8_URXhzTU3YWIPa76Zx3QDHlx1ARqbgJsVI,5008
|
41
41
|
prediction_market_agent_tooling/markets/agent_market.py,sha256=smKuMaP1zyTtw31Robbj3ospF03xptWX0EDKPJbHH9I,19070
|
42
42
|
prediction_market_agent_tooling/markets/base_subgraph_handler.py,sha256=7RaYO_4qAmQ6ZGM8oPK2-CkiJfKmV9MxM-rJlduaecU,1971
|
43
43
|
prediction_market_agent_tooling/markets/blockchain_utils.py,sha256=gZMwCTO-1d2ALXeY7-LP6U4kCpotJ6GMPZwN11kFOfE,2604
|
@@ -100,6 +100,9 @@ prediction_market_agent_tooling/tools/langfuse_client_utils.py,sha256=6IvsqqNNfB
|
|
100
100
|
prediction_market_agent_tooling/tools/omen/reality_accuracy.py,sha256=M1SF7iSW1gVlQSTskdVFTn09uPLST23YeipVIWj54io,2236
|
101
101
|
prediction_market_agent_tooling/tools/omen/sell_positions.py,sha256=Q4oI7_QI3AkyxlH10VvxDahYVrphQa1Wnox2Ce_cf_k,2452
|
102
102
|
prediction_market_agent_tooling/tools/parallelism.py,sha256=6Gou0hbjtMZrYvxjTDFUDZuxmE2nqZVbb6hkg1hF82A,1022
|
103
|
+
prediction_market_agent_tooling/tools/perplexity/perplexity_client.py,sha256=Oi5a_uaCAPtpTAEEVwD0SXWTsKkhCXOQjCBfa1eAuC0,3215
|
104
|
+
prediction_market_agent_tooling/tools/perplexity/perplexity_models.py,sha256=SfeR5FGQ2PqaxG4f4ij50LEnS9f2aeLplVwD7IZQh1s,820
|
105
|
+
prediction_market_agent_tooling/tools/perplexity/perplexity_search.py,sha256=Ii-5bqk6DygOCK1G78PDdz2sRTNvFYHVYVl2sajUbY4,2616
|
103
106
|
prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py,sha256=95l84aztFaxcRLLcRQ46yKJbIlOEuDAbIGLouyliDzA,1316
|
104
107
|
prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py,sha256=r4MdP5uEMlaCwoa2XQZzGq3oZEqnoo9S4dg8uzXfSOY,5473
|
105
108
|
prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py,sha256=kNWq92T11Knb9mYBZlMiZUzOpKgCd-5adanylQUMRJA,3085
|
@@ -116,8 +119,8 @@ prediction_market_agent_tooling/tools/tokens/usd.py,sha256=yuW8iPPtcpP4eLH2nORMD
|
|
116
119
|
prediction_market_agent_tooling/tools/transaction_cache.py,sha256=K5YKNL2_tR10Iw2TD9fuP-CTGpBbZtNdgbd0B_R7pjg,1814
|
117
120
|
prediction_market_agent_tooling/tools/utils.py,sha256=Jzpck3_QwShhejhgbAhmNxPSOPQJssBQep0eVemVjZ4,7064
|
118
121
|
prediction_market_agent_tooling/tools/web3_utils.py,sha256=zRq-eeBGWt8uUGN9G_WfjmJ0eVvO8aWE9S0Pz_Y6AOA,12342
|
119
|
-
prediction_market_agent_tooling-0.65.
|
120
|
-
prediction_market_agent_tooling-0.65.
|
121
|
-
prediction_market_agent_tooling-0.65.
|
122
|
-
prediction_market_agent_tooling-0.65.
|
123
|
-
prediction_market_agent_tooling-0.65.
|
122
|
+
prediction_market_agent_tooling-0.65.6.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
|
123
|
+
prediction_market_agent_tooling-0.65.6.dist-info/METADATA,sha256=XT7Kp9vv8HBSZjedQV7VgRp7H4Awv4GQdjrzz1F7Z-E,8734
|
124
|
+
prediction_market_agent_tooling-0.65.6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
125
|
+
prediction_market_agent_tooling-0.65.6.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
|
126
|
+
prediction_market_agent_tooling-0.65.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|