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

Implement PredictProbabilityForQuestion function for microchain agent #75

Merged
merged 27 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
641c796
Implement BuyTokens and SellTokens microchain Functions
evangriffiths Apr 11, 2024
28629bc
Add Buy/SellTokens test
evangriffiths Apr 11, 2024
023bd64
Merge main
evangriffiths Apr 11, 2024
2aebc66
Tidy
evangriffiths Apr 11, 2024
1c64ab8
Remove incorrect error message
evangriffiths Apr 11, 2024
448c1e5
Change test assertion
evangriffiths Apr 11, 2024
c5d5153
Implement PredictPropabilityForQuestion function for microchain agent
evangriffiths Apr 11, 2024
319d10d
Fix json parsing, add comments
evangriffiths Apr 12, 2024
e933009
Merge main
evangriffiths Apr 12, 2024
4bfb58b
Merge branch 'main' into evan/implement-PredictPropabilityForQuestion
evangriffiths Apr 12, 2024
8e6c232
Fix PredictPropabilityForQuestion example arg
evangriffiths Apr 12, 2024
074b7b0
Add min balance check to PredictPropabilityForQuestion
evangriffiths Apr 15, 2024
2b480cf
mypy
evangriffiths Apr 15, 2024
509ffa7
Remove duplicate bet_from_private_key
evangriffiths Apr 15, 2024
19b9348
Fix dependencies
evangriffiths Apr 15, 2024
331d8e5
Add setuptools dep
evangriffiths Apr 15, 2024
6f809e0
Add 'local' mech calling Function
evangriffiths Apr 15, 2024
f336af8
Add prediction mech as a git submodule
evangriffiths Apr 15, 2024
b10fbd6
Use submodules in CI
evangriffiths Apr 15, 2024
fc569d4
Fix ci
evangriffiths Apr 15, 2024
8ab4431
Fix ci
evangriffiths Apr 15, 2024
98cc683
Fix deps
evangriffiths Apr 15, 2024
e3ad0c7
Add comment
evangriffiths Apr 15, 2024
816c698
PredictPropabilityForQuestion -> PredictProbabilityForQuestion
evangriffiths Apr 16, 2024
55ad3d7
Update deps
evangriffiths Apr 16, 2024
3fcc7ea
Review comment
evangriffiths Apr 16, 2024
59604f8
Use latest PMAT release
evangriffiths Apr 16, 2024
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ __pycache__
logs
.mypy_cache
.pytest_cache

# Created on mech-client `interact` call
acn_cert.txt
3,198 changes: 768 additions & 2,430 deletions poetry.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import json
import typing as t
from datetime import datetime
from enum import Enum

Expand All @@ -12,6 +10,7 @@
from prediction_market_agent.tools.web_scrape.basic_summary import _summary
from prediction_market_agent.tools.web_scrape.markdown import web_scrape
from prediction_market_agent.tools.web_search.tavily import web_search
from prediction_market_agent.utils import completion_str_to_json


class Result(str, Enum):
Expand Down Expand Up @@ -141,26 +140,6 @@ def has_known_result(self) -> bool:
"""


def completion_str_to_json(completion: str) -> dict[str, t.Any]:
"""
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to prediction_market_agent/utils.py

Cleans completion JSON in form of a string:

```json
{
...
}
```

into just { ... }
```
"""
start_index = completion.find("{")
end_index = completion.rfind("}")
completion = completion[start_index : end_index + 1]
completion_dict: dict[str, t.Any] = json.loads(completion)
return completion_dict


def summarize_if_required(content: str, model: str, question: str) -> str:
"""
If the content is too long to fit in the model's context, summarize it.
Expand Down
77 changes: 68 additions & 9 deletions prediction_market_agent/agents/microchain_agent/functions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import json
import typing as t
from decimal import Decimal

from eth_utils import to_checksum_address
from mech_client.interact import interact
from microchain import Function
from prediction_market_agent_tooling.markets.agent_market import AgentMarket
from prediction_market_agent_tooling.markets.data_models import Currency, TokenAmount
Expand All @@ -11,16 +13,21 @@
OmenSubgraphHandler,
)

from prediction_market_agent.agents.microchain_agent.mech import (
prediction_with_research_report,
)
from prediction_market_agent.agents.microchain_agent.utils import (
MechResult,
MicroMarket,
get_balance,
get_binary_markets,
get_boolean_outcome,
get_example_market_id,
get_no_outcome,
get_yes_outcome,
saved_str_to_tmpfile,
)
from prediction_market_agent.utils import APIKeys
from prediction_market_agent.utils import APIKeys, completion_str_to_json


class Sum(Function):
Expand Down Expand Up @@ -101,19 +108,71 @@ def __call__(self, market_id: str) -> list[str]:
class PredictPropabilityForQuestion(MarketFunction):
@property
def description(self) -> str:
return "Use this function to research the probability of an event occuring"
return (
"Use this function to research perform research and predict the "
"probability of an event occuring. Returns the probability. The "
"one parameter is the market id of the prediction market you want "
"to predict the probability of. Note, this costs money to run."
)
evangriffiths marked this conversation as resolved.
Show resolved Hide resolved

@property
def example_args(self) -> list[str]:
return ["Will Joe Biden get reelected in 2024?"]
return [get_example_market_id(self.market_type)]

def __call__(self, question: str) -> str:
private_key = APIKeys().bet_from_private_key.get_secret_value()
Copy link
Contributor

Choose a reason for hiding this comment

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

Storing private keys temporarily in files can be risky. Consider using more secure methods to handle private keys, such as using environment variables or secure vault solutions.

# 0.01 xDai is hardcoded cost for an interaction with the mech-client
MECH_CALL_XDAI_LIMIT = 0.011
account_balance = float(get_balance(market_type=self.market_type).amount)
if account_balance < MECH_CALL_XDAI_LIMIT:
return (
f"Your balance of {self.currency} ({account_balance}) is not "
f"large enough to make a mech call (min required "
f"{MECH_CALL_XDAI_LIMIT})."
)
with saved_str_to_tmpfile(private_key) as tmpfile_path:
response = interact(
Copy link
Contributor

Choose a reason for hiding this comment

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

This costs money to run. Should we do some kind of balance check here to see if the agent has enough funds? Otherwise this will throw an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added. I don't think there's a way to query the cost of a mech call, so I've hard-coded it here.

I tried playing around with the value here that sets the cost of the mech call, and it fails for anything <0.01xDai, and works for anything >=.

Uploading Screenshot 2024-04-15 at 11.37.29.png…

prompt=question,
# Taken from https://github.com/valory-xyz/mech?tab=readme-ov-file#examples-of-deployed-mechs
agent_id=3,
private_key_path=tmpfile_path,
# To see a list of available tools, comment out the tool parameter
# and run the function. You will be prompted to select a tool.
tool="claude-prediction-online",
)
result = json.loads(response["result"])
return str(MechResult.model_validate(result).p_yes)

def __call__(self, a: str) -> float:
if a == "Will Joe Biden get reelected in 2024?":
return 0.41
if a == "Will Bitcoin hit 100k in 2024?":
return 0.22

return 0.0
class PredictPropabilityForQuestionLocal(MarketFunction):
@property
def description(self) -> str:
return (
"Use this function to research perform research and predict the "
"probability of an event occuring. Returns the probability. The "
"one parameter is the market id of the prediction market you want "
"to predict the probability of."
)

@property
def example_args(self) -> list[str]:
return [get_example_market_id(self.market_type)]

def __call__(self, question: str) -> str:
keys = APIKeys()
openai_api_key = keys.openai_api_key.get_secret_value()
tavily_api_key = keys.tavily_api_key.get_secret_value()
kwargs = {
"tool": "prediction-with-research-conservative",
"prompt": question,
"api_keys": {
"openai": openai_api_key,
"tavily": tavily_api_key,
},
}
response = prediction_with_research_report.run(**kwargs) # type: ignore
result = completion_str_to_json(str(response[0]))
return str(MechResult.model_validate(result).p_yes)


class BuyTokens(MarketFunction):
Expand Down
Empty file.
Loading
Loading