Skip to content

Commit 91ac581

Browse files
committed
Updated the Readme, Yaml Scripts, and tournament script
1 parent 558f4e4 commit 91ac581

File tree

5 files changed

+228
-73
lines changed

5 files changed

+228
-73
lines changed

.env.template

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
PYTHONPATH=.
22

3+
# Currently not being used as models, but might be in the future
4+
PERPLEXITY_API_KEY=
35
OPENAI_API_KEY=
46
EXA_API_KEY=
57

68
# Fill this in if using the Metaculus API
79
METACULUS_TOKEN=
810

9-
# Right now only used for free semantic similarity calculation, but defaults to OpenAI if not filled in
11+
# Right now only used for free semantic similarity calculation in Deduplicator, but defaults to OpenAI if not filled in
1012
HUGGINGFACE_API_KEY=
1113

12-
# Currently not being used as models, but might be in the future
13-
PERPLEXITY_API_KEY=
14-
ANTHROPIC_API_KEY=
15-
1614
# Only needed in Streamlit Cloud in order to save responses to a database and track usage
1715
CODA_API_KEY=
1816

.github/workflows/hourly-run.yaml

Lines changed: 0 additions & 46 deletions
This file was deleted.

README.md

Lines changed: 172 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ Demo website: https://mokoresearch.streamlit.app/
1414

1515
This repository contains forecasting and research tools built with Python and Streamlit. The project aims to assist users in making predictions, conducting research, and analyzing data related to hard to answer questions (especially those from Metaculus).
1616

17-
Key features: Tools most likely to be useful to you
17+
Here are the tools most likely to be useful to you:
1818
- 🎯 **Forecasting Bot:** General Forecaster that integrates with the Metaculus AI benchmarking competition. You can forecast with a pre-existing bot or override the class to customize your own (without redoing all the API code, etc)
19-
- 🔍 **Perplexity++ Smart Searcher:** Smart Searcher for AI-powered internet powered by Exa.ai that is configurable, more accurate, able to decide on filters, able to link to exact paragraphs, and generally better than Perplexity.ai.
19+
- 🔍 **Perplexity++ Smart Searcher:** An AI-powered internet-informed llm powered by Exa.ai. Its a better (but more expensive) alternative to Perplexity.ai that is configurable, more accurate, able to decide on filters, able to link to exact paragraphs, etc.
2020
- 🔑 **Key Factor Analysis:** Key Factors Analysis for scoring, ranking, and prioritizing important variables in forecasting questions
2121

2222

@@ -29,16 +29,174 @@ Here are some other cool components and features of the project:
2929

3030
Join the [discord](https://discord.gg/Dtq4JNdXnw) for updates and to give feedback (btw feedback is very appreciated, even just a quick 'I did/didn't decide to use the tool for reason X' is helpful to know)
3131

32-
Note: This package is still in a experimental phase, though I'm shooting to keep the API fairly stable. I'll especially try to keep the ForecastBot and TemplateBot APIs consistent.
32+
Note: This package is still in a experimental phase. The goal is to keep the API fairly stable, though no guarantees are given at this phase. There will be special effort to keep the ForecastBot and TemplateBot APIs consistent.
3333

3434
# Forecasting Bot Building
3535

36-
## Using Preexisting bot
36+
## Using the Preexisting Bots
37+
38+
The package comes with two major pre-built bots:
39+
- **MainBot**: The more sophisticated bot that uses multiple research strategies and carefully structured prompts
40+
- **TemplateBot**: A simpler bot that models the Metaculus templates that's cheaper, easier to start with, and faster to run.
41+
42+
They both have roughly the same parameters. See below on how to use the TemplateBot to make forecasts.
43+
44+
### Forecasting on a Tournament
45+
46+
```python
47+
from forecasting_tools import TemplateBot, MetaculusApi
48+
49+
# Initialize the bot
50+
bot = TemplateBot(
51+
research_reports_per_question=3, # Number of separate research attempts per question
52+
predictions_per_research_report=5, # Number of predictions to make per research report
53+
publish_reports_to_metaculus=True, # Whether to post the forecasts to Metaculus
54+
folder_to_save_reports_to="logs/forecasts/", # Where to save detailed reports
55+
skip_previously_forecasted_questions=True
56+
)
57+
58+
# Run forecasts on Q4 2024 AI Tournament
59+
TOURNAMENT_ID = MetaculusApi.AI_COMPETITION_ID_Q4
60+
reports = await bot.forecast_on_tournament(TOURNAMENT_ID)
61+
62+
# Print results
63+
for report in reports:
64+
print(f"\nQuestion: {report.question.question_text}")
65+
print(f"Prediction: {report.prediction}")
66+
```
67+
68+
### Forecasting a Single Question
69+
70+
```python
71+
from forecasting_tools import TemplateBot, BinaryQuestion, QuestionState
72+
73+
# Initialize the bot
74+
bot = TemplateBot(
75+
research_reports_per_question=3,
76+
predictions_per_research_report=5,
77+
publish_reports_to_metaculus=False,
78+
)
79+
80+
# Get and forecast a specific question
81+
question1 = MetaculusApi.get_question_by_url(
82+
"https://www.metaculus.com/questions/578/human-extinction-by-2100/"
83+
)
84+
question2 = BinaryQuestion(
85+
question_text="Will YouTube be blocked in Russia?",
86+
background_info="...", # Or 'None'
87+
resolution_criteria="...", # Or 'None'
88+
fine_print="...", # Or 'None'
89+
id_of_question=0, # The ID and state only matters if using Metaculus API calls
90+
question_state=QuestionState.OPEN
91+
)
92+
93+
reports = await bot.forecast_questions([question1, question2])
94+
95+
# Print results
96+
for report in reports:
97+
print(f"Question: {report.question.question_text}")
98+
print(f"Prediction: {report.prediction}")
99+
print("\nReasoning:")
100+
print(report.explanation)
101+
```
102+
103+
The bot will:
104+
1. Research the question
105+
2. Generate multiple independent predictions
106+
3. Combine these predictions into a final forecast
107+
4. Save detailed research and reasoning to the specified folder
108+
5. Optionally post the forecast to Metaculus (if `publish_reports_to_metaculus=True`)
109+
110+
Note: You'll need to have your environment variables set up (see the section below)
111+
112+
113+
## Running your own bot
114+
115+
### Join the tournament quick-start
116+
The quickest way to join the Metaculus Benchmarking Tournament (or any other tournament) is to fork this repo, enable Github workflow/actions, and then set repository secrets. Ideally this takes less than 15min, and then you have a bot in the tournament! Later you can develop locally and then merge in changes to your fork.
117+
118+
There is a prewritten workflow that will run the bot every 15min, pick up new questions, and forecast on them. Automation is handled in the `.github/workflows/` folder. The `hourly-run.yaml` file runs the bot every 15 min and will skip questions it has already forecasted on.
119+
120+
1) **Fork the repository**: Click 'fork' in the right hand corner of the repo.
121+
2) **Set secrets**: Go to `Settings -> Secrets and variables -> Actions -> New repository secret` and set API keys/Tokens as secrets. You will want to set your METACULUS_TOKEN. This will be used to post questions to Metaculus, and access the Metaculus OpenAI proxy (you should automatically be given some credits if you have a bot account). For additional environment variables you might want, see the section below.
122+
3) **Enable Actions**: Go to 'Actions' then click 'Enable'. Then go to the 'Hourly Run' workflow, and click 'Enable'. To test if the workflow is working, click 'Run workflow', choose the main branch, then click the green 'Run workflow' button. This will check for new questions and forecast only on ones it has not yet successfully forecast on.
123+
124+
The bot should just work as is at this point. You can disable the workflow by clicking `Actions > Hourly Run > Triple dots > disable workflow`
125+
126+
### Local Development
127+
See the 'Local Development' section later in this README.
128+
129+
### Customizing the Bot
130+
Generally all you have to do to make your own bot is inherit from the TemplateBot and override any combination of the 3 forecasting methods and the 1 research method. This saves you the headache of parsing the outputs, interacting with the Metaculus API, etc. Here is an example. It may also be helpful to look at the TemplateBot code (forecasting_tools/forecasting/forecast_bots/template_bot.py) for a more complete example.
131+
132+
```python
133+
from forecasting_tools import (
134+
TemplateBot,
135+
MetaculusQuestion,
136+
BinaryQuestion,
137+
MultipleChoiceQuestion,
138+
NumericQuestion,
139+
ReasonedPrediction,
140+
PredictedOptionList,
141+
NumericDistribution,
142+
SmartSearcher,
143+
Gpt4oMetaculusProxy
144+
)
145+
from forecasting_tools.ai_models.ai_utils.ai_misc import clean_indents
146+
147+
class MyCustomBot(TemplateBot):
148+
async def run_research(self, question: MetaculusQuestion) -> str:
149+
"""Custom research method that focuses on recent events and expert opinions"""
150+
searcher = SmartSearcher(
151+
num_searches_to_run=3,
152+
num_sites_per_search=5
153+
)
154+
155+
prompt = clean_indents(
156+
f"""
157+
Analyze this forecasting question:
158+
1. Filter for recent events in the past 6 months
159+
2. Don't include domains from youtube.com
160+
3. Look for current trends and data
161+
4. Find historical analogies and base rates
162+
163+
Question: {question.question_text}
164+
165+
Background Info: {question.background_info}
166+
Resolution Criteria: {question.resolution_criteria}
167+
"""
168+
)
169+
170+
report = await searcher.invoke(prompt)
171+
return report
172+
173+
async def _run_forecast_on_binary(
174+
self, question: BinaryQuestion, research: str
175+
) -> ReasonedPrediction[float]:
176+
prompt = f"Please make a prediction on the following question: {question.question_text}. The last thing you write is your final answer as: 'Probability: ZZ%', 0-100"
177+
reasoning = await Gpt4oMetaculusProxy.invoke(prompt)
178+
prediction = self._extract_forecast_from_binary_rationale(
179+
reasoning, max_prediction=1, min_prediction=0
180+
)
181+
return ReasonedPrediction(
182+
prediction_value=prediction, reasoning=reasoning
183+
)
184+
185+
async def _run_forecast_on_multiple_choice(
186+
self, question: MultipleChoiceQuestion, research: str
187+
) -> ReasonedPrediction[PredictedOptionList]:
188+
...
189+
190+
async def _run_forecast_on_numeric(
191+
self, question: NumericQuestion, research: str
192+
) -> ReasonedPrediction[NumericDistribution]:
193+
...
194+
```
195+
196+
197+
## Setting Environment Variables
198+
Whether running locally or through Github actions, you will need to set environment variables. All environment variables you might want are in `.env.template`. Generally you only need the METACULUS_TOKEN if running the Template. Having an EXA_API_KEY (see www.exa.ai) or PERPLEXITY_API_KEY (see www.perplexity.ai) is needed for searching the web. Make sure to put these variables in your `.env` file if running locally and in the Github actions secrets if running on Github actions.
37199

38-
## Building your own bot
39-
- forking
40-
- env variables
41-
- enabling actions
42200

43201
# Forecasting Tools Examples
44202

@@ -110,7 +268,7 @@ The schema instructions will format the Pydantic model into clear instructions f
110268

111269

112270
## Key Factors Researcher
113-
The Key Factors Researcher helps identify and analyze key factors that should be considered for a forecasting question. As of last update, this is the most reliable of the tools, and gives something useful and accurate most every time. It asks a lot of questions, turns search results into a long list of bullet points, rates each bullet point on ~8 criteria, and returns the top results.
271+
The Key Factors Researcher helps identify and analyze key factors that should be considered for a forecasting question. As of last update, this is the most reliable of the tools, and gives something useful and accurate almost every time. It asks a lot of questions, turns search results into a long list of bullet points, rates each bullet point on ~8 criteria, and returns the top results.
114272

115273
```python
116274
from forecasting_tools import KeyFactorsResearcher, BinaryQuestion, QuestionState
@@ -121,7 +279,7 @@ question = BinaryQuestion(
121279
background_info="...", # Or 'None'
122280
resolution_criteria="...", # Or 'None'
123281
fine_print="...", # Or 'None'
124-
question_id=0, # The ID and state only matters if using Metaculus API calls
282+
id_of_question=0, # The ID and state only matters if using Metaculus API calls
125283
question_state=QuestionState.OPEN
126284
)
127285

@@ -301,7 +459,7 @@ with MonetaryCostManager(max_cost) as cost_manager:
301459
The environment variables you need can be found in ```.env.template```. Copy this template as ```.env``` and fill it in. As of last update, you only strictly need OPENAI_API_KEY and EXA_API_KEY.
302460

303461
## Docker Dev Container
304-
Dev containers are reliable ways to make sure environments work on everyone's machine the first try and so you don't have to spend hours setting up your environment (especially if you have docker already installed). If you would rather just use poetry, without the dev container, you can skip to "Alternatives to Docker". Otherwise, to get your development environment up and running, you need to have Docker Engine installed and running. Once you do, you can use the VSCode dev container pop-up to automatically set up everything for you.
462+
Dev containers are reliable ways to make sure environments work on everyone's machine the first try and so you don't have to spend hours setting up your environment (especially if you have Docker already installed). If you would rather just use poetry, without the dev container, you can skip to "Alternatives to Docker". Otherwise, to get your development environment up and running, you need to have Docker Engine installed and running. Once you do, you can use the VSCode dev container pop-up to automatically set up everything for you.
305463

306464
### Install Docker
307465
For Windows and Mac, you will download Docker Desktop. For Linux, you will download Docker Engine. (NOTE: These instructions might be outdated).
@@ -315,19 +473,19 @@ First download and setup Docker Engine using the instructions at the link below
315473

316474

317475
### Starting the container
318-
Once Docker is installed, when you open up the project folder in VSCode, you will see a pop up noting that you have a setup for a dev container, and asking if you would like to open the folder in a container. You will want to click "open in container". This will automatically set up everything you need and bring you into the container. If the docker process times out in the middle of installing python packages you can run the `.devcontiner/postinstall.sh` manually. You may need to have the VSCode Docker extension and/or devcontainer extension downloaded in order for the pop up to appear.
476+
Once Docker is installed, when you open up the project folder in VSCode, you will see a pop up noting that you have a setup for a dev container, and asking if you would like to open the folder in a container. You will want to click "open in container". This will automatically set up everything you need and bring you into the container. If the Docker process times out in the middle of installing python packages you can run the `.devcontiner/postinstall.sh` manually. You may need to have the VSCode Docker extension and/or devcontainer extension downloaded in order for the pop up to appear.
319477

320478
Once you are in the container, poetry should have already installed a virtual environment. For VSCode features to use this environment, you will need to select the correct python interpreter. You can do this by pressing `Ctrl + Shift + P` and then typing `Python: Select Interpreter`. Then select the interpreter that starts with `.venv`.
321479

322480
A number of vscode extensions are installed automatically (e.g. linting). You may need to wait a little while and then reload the window after all of these extensions are installed. You can install personal vscode extensions in the dev environment.
323481

324482

325483
### Managing Docker
326-
There are many ways to manager Docker containers, but generally if you download the vscode docker extension, you will be able to stop/start/remove all containers and images.
484+
There are many ways to manager Docker containers, but generally if you download the vscode Docker extension, you will be able to stop/start/remove all containers and images.
327485

328486

329487
### Alternatives to Docker
330-
If you choose not to run docker, you can use poetry to set up a local virtual environment. If you are on Ubuntu, you should be able to just read through and then run `.devcontainer/postinstall.sh`. If you aren't on Ubuntu, check out the links in the postinstall file for where install instructions for dependencies were originally found. You may also want to take a look at VSCode extensions that would be installed (see the list in the `.devcontainer/devcontainer.json` file) so that some VSCode workplace settings work out of the box (e.g. automatic Black Formatting).
488+
If you choose not to run Docker, you can use poetry to set up a local virtual environment. If you are on Ubuntu, you should be able to just read through and then run `.devcontainer/postinstall.sh`. If you aren't on Ubuntu, check out the links in the postinstall file for where install instructions for dependencies were originally found. You may also want to take a look at VSCode extensions that would be installed (see the list in the `.devcontainer/devcontainer.json` file) so that some VSCode workplace settings work out of the box (e.g. automatic Black Formatting).
331489

332490
## Running the Front End
333491
You can run any front end folder in the front_end directory by executing `streamlit run front_end/Home.py`. This will start a development server for you that you can run.

forecasting_tools/forecasting/forecast_bots/template_bot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async def run_research(self, question: MetaculusQuestion) -> str:
6868
response = await SmartSearcher().invoke(prompt)
6969
else:
7070
logger.error(
71-
"No API keys for csearh. Skipping research and setting it blank."
71+
"No API keys for searching the web. Skipping research and setting it blank."
7272
)
7373
response = ""
7474
return response

0 commit comments

Comments
 (0)