M-Rique commited on
Commit
43aad2c
·
0 Parent(s):

First commit

Browse files
Files changed (2) hide show
  1. app.py +278 -0
  2. requirements.txt +6 -0
app.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import textwrap
3
+ from datetime import date, datetime, timedelta
4
+
5
+ import gradio as gr
6
+ import pandas as pd
7
+ from apscheduler.schedulers.background import BackgroundScheduler
8
+ from datasets import Dataset
9
+ from dotenv import load_dotenv
10
+ from huggingface_hub import HfApi
11
+ from predibench.agent.agent import run_smolagent
12
+ from predibench.polymarket_api import (
13
+ MarketRequest,
14
+ filter_interesting_questions,
15
+ filter_out_resolved_markets,
16
+ get_open_markets,
17
+ )
18
+
19
+ load_dotenv()
20
+
21
+ # Configuration
22
+ WEEKLY_MARKETS_REPO = "m-ric/predibench-weekly-markets"
23
+ AGENT_CHOICES_REPO = "m-ric/predibench-agent-choices"
24
+ N_MARKETS = 10
25
+
26
+
27
+ def restart_space():
28
+ """Restart the HuggingFace space"""
29
+ try:
30
+ HfApi(token=os.getenv("HF_TOKEN", None)).restart_space(
31
+ repo_id="m-ric/predibench-backend" # Update with your actual space repo
32
+ )
33
+ print(f"Space restarted on {datetime.now()}")
34
+ except Exception as e:
35
+ print(f"Failed to restart space: {e}")
36
+
37
+
38
+ def get_top_polymarket_questions(n_markets: int = 10) -> list:
39
+ """Fetch top questions from Polymarket API"""
40
+ end_date = date.today() + timedelta(days=7)
41
+
42
+ request = MarketRequest(
43
+ limit=n_markets * 10,
44
+ active=True,
45
+ closed=False,
46
+ order="volumeNum",
47
+ ascending=False,
48
+ end_date_min=end_date,
49
+ end_date_max=end_date + timedelta(days=21),
50
+ )
51
+
52
+ markets = get_open_markets(request)
53
+ markets = filter_out_resolved_markets(markets)
54
+
55
+ # Filter for interesting questions
56
+ interesting_questions = filter_interesting_questions(
57
+ [market.question for market in markets]
58
+ )
59
+ markets = [market for market in markets if market.question in interesting_questions]
60
+
61
+ return markets[:n_markets]
62
+
63
+
64
+ def upload_weekly_markets(markets: list):
65
+ """Upload weekly markets to HuggingFace dataset"""
66
+ markets_data = []
67
+ for market in markets:
68
+ markets_data.append(
69
+ {
70
+ "id": market.id,
71
+ "question": market.question,
72
+ "slug": market.slug,
73
+ "description": market.description,
74
+ "end_date": market.end_date,
75
+ "active": market.active,
76
+ "closed": market.closed,
77
+ "volume": market.volume,
78
+ "liquidity": market.liquidity,
79
+ "week_selected": date.today().strftime("%Y-%m-%d"),
80
+ "timestamp": datetime.now(),
81
+ }
82
+ )
83
+
84
+ df = pd.DataFrame(markets_data)
85
+ dataset = Dataset.from_pandas(df)
86
+
87
+ try:
88
+ # Try to load existing dataset and append
89
+ existing_dataset = Dataset.from_parquet(f"hf://datasets/{WEEKLY_MARKETS_REPO}")
90
+ combined_dataset = existing_dataset.concatenate(dataset)
91
+ combined_dataset.push_to_hub(WEEKLY_MARKETS_REPO, private=False)
92
+ except:
93
+ # If no existing dataset, create new one
94
+ dataset.push_to_hub(WEEKLY_MARKETS_REPO, private=False)
95
+
96
+ print(f"Uploaded {len(markets_data)} markets to {WEEKLY_MARKETS_REPO}")
97
+
98
+
99
+ def run_agent_decisions(markets: list, model_ids: list = None):
100
+ """Run agent decision-making logic on the selected markets"""
101
+ if model_ids is None:
102
+ model_ids = [
103
+ "gpt-4o",
104
+ "gpt-4.1",
105
+ "anthropic/claude-sonnet-4-20250514",
106
+ "huggingface/Qwen/Qwen3-30B-A3B-Instruct-2507",
107
+ ]
108
+
109
+ today = date.today()
110
+ decisions = []
111
+
112
+ for model_id in model_ids:
113
+ for market in markets:
114
+ # Create the investment decision prompt
115
+ full_question = textwrap.dedent(
116
+ f"""Let's say we are the {today.strftime("%B %d, %Y")}.
117
+ Please answer the below question by yes or no. But first, run a detailed analysis.
118
+ Here is the question:
119
+ {market.question}
120
+ More details:
121
+ {market.description}
122
+
123
+ Invest in yes only if you think the yes is underrated, and invest in no only if you think that the yes is overrated.
124
+ What would you decide: buy yes, buy no, or do nothing?
125
+ """
126
+ )
127
+
128
+ try:
129
+ response = run_smolagent(model_id, full_question, cutoff_date=today)
130
+ choice = response.output.lower()
131
+
132
+ # Standardize choice format
133
+ if "yes" in choice:
134
+ choice_standardized = 1
135
+ choice_raw = "yes"
136
+ elif "no" in choice:
137
+ choice_standardized = -1
138
+ choice_raw = "no"
139
+ else:
140
+ choice_standardized = 0
141
+ choice_raw = "nothing"
142
+
143
+ decisions.append(
144
+ {
145
+ "agent_name": f"smolagent_{model_id}".replace("/", "--"),
146
+ "date": today,
147
+ "question": market.question,
148
+ "question_id": market.id,
149
+ "choice": choice_standardized,
150
+ "choice_raw": choice_raw,
151
+ "messages_count": len(response.messages),
152
+ "has_reasoning": len(response.messages) > 0,
153
+ "timestamp": datetime.now(),
154
+ }
155
+ )
156
+
157
+ print(f"Completed decision for {model_id} on {market.question[:50]}...")
158
+
159
+ except Exception as e:
160
+ print(f"Error processing {model_id} on {market.question[:50]}: {e}")
161
+ continue
162
+
163
+ return decisions
164
+
165
+
166
+ def upload_agent_choices(decisions: list):
167
+ """Upload agent choices to HuggingFace dataset"""
168
+ df = pd.DataFrame(decisions)
169
+ dataset = Dataset.from_pandas(df)
170
+
171
+ try:
172
+ # Try to load existing dataset and append
173
+ existing_dataset = Dataset.from_parquet(f"hf://datasets/{AGENT_CHOICES_REPO}")
174
+ combined_dataset = existing_dataset.concatenate(dataset)
175
+ combined_dataset.push_to_hub(AGENT_CHOICES_REPO, private=False)
176
+ except:
177
+ # If no existing dataset, create new one
178
+ dataset.push_to_hub(AGENT_CHOICES_REPO, private=False)
179
+
180
+ print(f"Uploaded {len(decisions)} agent decisions to {AGENT_CHOICES_REPO}")
181
+
182
+
183
+ def weekly_pipeline():
184
+ """Main weekly pipeline that runs every Sunday"""
185
+ print(f"Starting weekly pipeline at {datetime.now()}")
186
+
187
+ try:
188
+ # 1. Get top 10 questions from Polymarket
189
+ markets = get_top_polymarket_questions(N_MARKETS)
190
+ print(f"Retrieved {len(markets)} markets from Polymarket")
191
+
192
+ # 2. Upload to weekly markets dataset
193
+ upload_weekly_markets(markets)
194
+
195
+ # 3. Run agent decision-making
196
+ decisions = run_agent_decisions(markets)
197
+ print(f"Generated {len(decisions)} agent decisions")
198
+
199
+ # 4. Upload agent choices
200
+ upload_agent_choices(decisions)
201
+
202
+ print("Weekly pipeline completed successfully")
203
+
204
+ except Exception as e:
205
+ print(f"Weekly pipeline failed: {e}")
206
+
207
+
208
+ # Set up scheduler to run every Sunday at 8:30 AM
209
+ scheduler = BackgroundScheduler()
210
+ scheduler.add_job(restart_space, "cron", day_of_week="sun", hour=8, minute=0)
211
+ scheduler.add_job(weekly_pipeline, "cron", day_of_week="sun", hour=8, minute=30)
212
+ scheduler.start()
213
+
214
+
215
+ # Simple Gradio interface for monitoring
216
+ def get_status():
217
+ """Get current status of the backend"""
218
+ try:
219
+ # Check if datasets exist and get their info
220
+ api = HfApi()
221
+
222
+ weekly_info = "Not available"
223
+ choices_info = "Not available"
224
+
225
+ try:
226
+ weekly_dataset = Dataset.from_parquet(
227
+ f"hf://datasets/{WEEKLY_MARKETS_REPO}"
228
+ )
229
+ weekly_info = f"{len(weekly_dataset)} markets"
230
+ except:
231
+ pass
232
+
233
+ try:
234
+ choices_dataset = Dataset.from_parquet(
235
+ f"hf://datasets/{AGENT_CHOICES_REPO}"
236
+ )
237
+ choices_info = f"{len(choices_dataset)} decisions"
238
+ except:
239
+ pass
240
+
241
+ return f"""
242
+ Backend Status (Last updated: {datetime.now()})
243
+
244
+ Weekly Markets Dataset: {weekly_info}
245
+ Agent Choices Dataset: {choices_info}
246
+
247
+ Next scheduled run: Next Sunday at 8:30 AM UTC
248
+ """
249
+ except Exception as e:
250
+ return f"Error getting status: {e}"
251
+
252
+
253
+ def manual_run():
254
+ """Manually trigger the weekly pipeline"""
255
+ weekly_pipeline()
256
+ return "Manual pipeline run completed. Check logs for details."
257
+
258
+
259
+ # Create Gradio interface
260
+ with gr.Blocks(title="PrediBench Backend") as demo:
261
+ gr.Markdown("# PrediBench Backend Monitor")
262
+ gr.Markdown(
263
+ "This backend automatically fetches new Polymarket questions every Sunday and runs agent predictions."
264
+ )
265
+
266
+ with gr.Row():
267
+ status_text = gr.Textbox(label="Status", value=get_status(), lines=10)
268
+ refresh_btn = gr.Button("Refresh Status")
269
+ refresh_btn.click(get_status, outputs=status_text)
270
+
271
+ with gr.Row():
272
+ manual_btn = gr.Button("Run Manual Pipeline", variant="primary")
273
+ manual_output = gr.Textbox(label="Manual Run Output", lines=5)
274
+ manual_btn.click(manual_run, outputs=manual_output)
275
+
276
+ if __name__ == "__main__":
277
+ print("Starting PrediBench backend...")
278
+ demo.launch(server_name="0.0.0.0", server_port=7860)
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ gradio
2
+ datasets
3
+ huggingface_hub
4
+ apscheduler
5
+ python-dotenv
6
+ git+https://github.com/m-ric/predibench-core