File size: 9,264 Bytes
43aad2c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
import os
import textwrap
from datetime import date, datetime, timedelta

import gradio as gr
import pandas as pd
from apscheduler.schedulers.background import BackgroundScheduler
from datasets import Dataset
from dotenv import load_dotenv
from huggingface_hub import HfApi
from predibench.agent.agent import run_smolagent
from predibench.polymarket_api import (
    MarketRequest,
    filter_interesting_questions,
    filter_out_resolved_markets,
    get_open_markets,
)

load_dotenv()

# Configuration
WEEKLY_MARKETS_REPO = "m-ric/predibench-weekly-markets"
AGENT_CHOICES_REPO = "m-ric/predibench-agent-choices"
N_MARKETS = 10


def restart_space():
    """Restart the HuggingFace space"""
    try:
        HfApi(token=os.getenv("HF_TOKEN", None)).restart_space(
            repo_id="m-ric/predibench-backend"  # Update with your actual space repo
        )
        print(f"Space restarted on {datetime.now()}")
    except Exception as e:
        print(f"Failed to restart space: {e}")


def get_top_polymarket_questions(n_markets: int = 10) -> list:
    """Fetch top questions from Polymarket API"""
    end_date = date.today() + timedelta(days=7)

    request = MarketRequest(
        limit=n_markets * 10,
        active=True,
        closed=False,
        order="volumeNum",
        ascending=False,
        end_date_min=end_date,
        end_date_max=end_date + timedelta(days=21),
    )

    markets = get_open_markets(request)
    markets = filter_out_resolved_markets(markets)

    # Filter for interesting questions
    interesting_questions = filter_interesting_questions(
        [market.question for market in markets]
    )
    markets = [market for market in markets if market.question in interesting_questions]

    return markets[:n_markets]


def upload_weekly_markets(markets: list):
    """Upload weekly markets to HuggingFace dataset"""
    markets_data = []
    for market in markets:
        markets_data.append(
            {
                "id": market.id,
                "question": market.question,
                "slug": market.slug,
                "description": market.description,
                "end_date": market.end_date,
                "active": market.active,
                "closed": market.closed,
                "volume": market.volume,
                "liquidity": market.liquidity,
                "week_selected": date.today().strftime("%Y-%m-%d"),
                "timestamp": datetime.now(),
            }
        )

    df = pd.DataFrame(markets_data)
    dataset = Dataset.from_pandas(df)

    try:
        # Try to load existing dataset and append
        existing_dataset = Dataset.from_parquet(f"hf://datasets/{WEEKLY_MARKETS_REPO}")
        combined_dataset = existing_dataset.concatenate(dataset)
        combined_dataset.push_to_hub(WEEKLY_MARKETS_REPO, private=False)
    except:
        # If no existing dataset, create new one
        dataset.push_to_hub(WEEKLY_MARKETS_REPO, private=False)

    print(f"Uploaded {len(markets_data)} markets to {WEEKLY_MARKETS_REPO}")


def run_agent_decisions(markets: list, model_ids: list = None):
    """Run agent decision-making logic on the selected markets"""
    if model_ids is None:
        model_ids = [
            "gpt-4o",
            "gpt-4.1",
            "anthropic/claude-sonnet-4-20250514",
            "huggingface/Qwen/Qwen3-30B-A3B-Instruct-2507",
        ]

    today = date.today()
    decisions = []

    for model_id in model_ids:
        for market in markets:
            # Create the investment decision prompt
            full_question = textwrap.dedent(
                f"""Let's say we are the {today.strftime("%B %d, %Y")}.
                Please answer the below question by yes or no. But first, run a detailed analysis.
                Here is the question:
                {market.question}
                More details:
                {market.description}

                Invest in yes only if you think the yes is underrated, and invest in no only if you think that the yes is overrated.
                What would you decide: buy yes, buy no, or do nothing?
                """
            )

            try:
                response = run_smolagent(model_id, full_question, cutoff_date=today)
                choice = response.output.lower()

                # Standardize choice format
                if "yes" in choice:
                    choice_standardized = 1
                    choice_raw = "yes"
                elif "no" in choice:
                    choice_standardized = -1
                    choice_raw = "no"
                else:
                    choice_standardized = 0
                    choice_raw = "nothing"

                decisions.append(
                    {
                        "agent_name": f"smolagent_{model_id}".replace("/", "--"),
                        "date": today,
                        "question": market.question,
                        "question_id": market.id,
                        "choice": choice_standardized,
                        "choice_raw": choice_raw,
                        "messages_count": len(response.messages),
                        "has_reasoning": len(response.messages) > 0,
                        "timestamp": datetime.now(),
                    }
                )

                print(f"Completed decision for {model_id} on {market.question[:50]}...")

            except Exception as e:
                print(f"Error processing {model_id} on {market.question[:50]}: {e}")
                continue

    return decisions


def upload_agent_choices(decisions: list):
    """Upload agent choices to HuggingFace dataset"""
    df = pd.DataFrame(decisions)
    dataset = Dataset.from_pandas(df)

    try:
        # Try to load existing dataset and append
        existing_dataset = Dataset.from_parquet(f"hf://datasets/{AGENT_CHOICES_REPO}")
        combined_dataset = existing_dataset.concatenate(dataset)
        combined_dataset.push_to_hub(AGENT_CHOICES_REPO, private=False)
    except:
        # If no existing dataset, create new one
        dataset.push_to_hub(AGENT_CHOICES_REPO, private=False)

    print(f"Uploaded {len(decisions)} agent decisions to {AGENT_CHOICES_REPO}")


def weekly_pipeline():
    """Main weekly pipeline that runs every Sunday"""
    print(f"Starting weekly pipeline at {datetime.now()}")

    try:
        # 1. Get top 10 questions from Polymarket
        markets = get_top_polymarket_questions(N_MARKETS)
        print(f"Retrieved {len(markets)} markets from Polymarket")

        # 2. Upload to weekly markets dataset
        upload_weekly_markets(markets)

        # 3. Run agent decision-making
        decisions = run_agent_decisions(markets)
        print(f"Generated {len(decisions)} agent decisions")

        # 4. Upload agent choices
        upload_agent_choices(decisions)

        print("Weekly pipeline completed successfully")

    except Exception as e:
        print(f"Weekly pipeline failed: {e}")


# Set up scheduler to run every Sunday at 8:30 AM
scheduler = BackgroundScheduler()
scheduler.add_job(restart_space, "cron", day_of_week="sun", hour=8, minute=0)
scheduler.add_job(weekly_pipeline, "cron", day_of_week="sun", hour=8, minute=30)
scheduler.start()


# Simple Gradio interface for monitoring
def get_status():
    """Get current status of the backend"""
    try:
        # Check if datasets exist and get their info
        api = HfApi()

        weekly_info = "Not available"
        choices_info = "Not available"

        try:
            weekly_dataset = Dataset.from_parquet(
                f"hf://datasets/{WEEKLY_MARKETS_REPO}"
            )
            weekly_info = f"{len(weekly_dataset)} markets"
        except:
            pass

        try:
            choices_dataset = Dataset.from_parquet(
                f"hf://datasets/{AGENT_CHOICES_REPO}"
            )
            choices_info = f"{len(choices_dataset)} decisions"
        except:
            pass

        return f"""
        Backend Status (Last updated: {datetime.now()})
        
        Weekly Markets Dataset: {weekly_info}
        Agent Choices Dataset: {choices_info}
        
        Next scheduled run: Next Sunday at 8:30 AM UTC
        """
    except Exception as e:
        return f"Error getting status: {e}"


def manual_run():
    """Manually trigger the weekly pipeline"""
    weekly_pipeline()
    return "Manual pipeline run completed. Check logs for details."


# Create Gradio interface
with gr.Blocks(title="PrediBench Backend") as demo:
    gr.Markdown("# PrediBench Backend Monitor")
    gr.Markdown(
        "This backend automatically fetches new Polymarket questions every Sunday and runs agent predictions."
    )

    with gr.Row():
        status_text = gr.Textbox(label="Status", value=get_status(), lines=10)
        refresh_btn = gr.Button("Refresh Status")
        refresh_btn.click(get_status, outputs=status_text)

    with gr.Row():
        manual_btn = gr.Button("Run Manual Pipeline", variant="primary")
        manual_output = gr.Textbox(label="Manual Run Output", lines=5)
        manual_btn.click(manual_run, outputs=manual_output)

if __name__ == "__main__":
    print("Starting PrediBench backend...")
    demo.launch(server_name="0.0.0.0", server_port=7860)