forked from arcprize/ARC-AGI-3-Kaggle-Starter
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild_notebook.py
More file actions
219 lines (187 loc) · 8.3 KB
/
Copy pathbuild_notebook.py
File metadata and controls
219 lines (187 loc) · 8.3 KB
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
"""Splice the current `agent/my_agent.py` into `notebooks/submission.ipynb`.
The notebook follows the exact pattern used by Kaggle's official sample
("ARC3 Sample Submission - Stochastic Goose"):
Cell 1: install the `arc-agi` wheel from the offline competition dataset.
Cell 2: write `my_agent.py` to /kaggle/working/ — its body is THIS file.
Cell 3: if running inside the Kaggle competition rerun, wait for the
gateway sidecar, copy the framework into /kaggle/working/, register
MyAgent, and run `python main.py --agent myagent`.
Cell 4: otherwise (during commit / save-and-run-all), write a dummy
submission.parquet so Kaggle accepts the commit.
You don't normally need to call this directly — `make submit` runs it for you.
"""
from __future__ import annotations
import json
from pathlib import Path
from textwrap import dedent
# ─────────────────────────────────────────────────────────────────────────────
# CHANGE THIS ONE LINE TO PICK YOUR KAGGLE ACCELERATOR
# Options:
# "cpu" — no GPU. Good for the random starter or any non-ML agent.
# "t4" — Nvidia T4 ×2 (default; matches Kaggle's sample submission).
# "p100" — Nvidia P100 (single big-memory GPU).
# "rtx6000" — Nvidia RTX 6000 (g4-standard-48). ARC-AGI-3 exclusive,
# burns GPU quota faster — use only when you're confident.
# ─────────────────────────────────────────────────────────────────────────────
ACCELERATOR = "t4"
# Internal mapping; don't edit unless Kaggle adds new options.
_ACCELERATORS = {
"cpu": {"name": "none", "gpu": False},
"t4": {"name": "nvidiaTeslaT4", "gpu": True},
"p100": {"name": "nvidiaTeslaP100", "gpu": True},
"rtx6000": {"name": "nvidiaRtx6000", "gpu": True},
}
ROOT = Path(__file__).resolve().parents[1]
AGENT_SRC = ROOT / "agent" / "my_agent.py"
NOTEBOOK_PATH = ROOT / "notebooks" / "submission.ipynb"
METADATA_PATH = ROOT / "notebooks" / "kernel-metadata.json"
def code_cell(source: str) -> dict:
return {
"cell_type": "code",
"metadata": {"trusted": True},
"outputs": [],
"execution_count": None,
"source": source,
}
def markdown_cell(source: str) -> dict:
return {"cell_type": "markdown", "metadata": {}, "source": source}
def build() -> dict:
if not AGENT_SRC.exists():
raise SystemExit(f"Could not find {AGENT_SRC}")
agent_body = AGENT_SRC.read_text()
install_cell = code_cell(
"!pip install --no-index --find-links \\\n"
" /kaggle/input/competitions/arc-prize-2026-arc-agi-3/arc_agi_3_wheels \\\n"
" arc-agi python-dotenv"
)
# We write the agent to /tmp/ (not /kaggle/working/) so it does NOT appear
# as a notebook output. Otherwise the "Submit to Competition" UI would
# offer it as a candidate submission file alongside submission.parquet,
# and an unlucky default selection rejects the submission.
write_agent_cell = code_cell(
"%%writefile /tmp/my_agent.py\n" + agent_body
)
run_cell_source = dedent(
"""\
import os
if os.getenv('KAGGLE_IS_COMPETITION_RERUN'):
# Wait for the gateway sidecar to be ready.
!curl --fail --retry 999 --retry-all-errors --retry-delay 5 \\
--retry-max-time 600 http://gateway:8001/api/games
# Copy the framework into a writable location.
!cp -r /kaggle/input/competitions/arc-prize-2026-arc-agi-3/ARC-AGI-3-Agents \\
/kaggle/working/ARC-AGI-3-Agents
# Drop our agent in as a framework template.
!cp /tmp/my_agent.py \\
/kaggle/working/ARC-AGI-3-Agents/agents/templates/my_agent.py
# Register MyAgent in the framework's agent registry. We rewrite
# __init__.py because the upstream version eagerly imports
# templates with deps we don't ship (langgraph, smolagents, etc.).
with open('/kaggle/working/ARC-AGI-3-Agents/agents/__init__.py', 'w') as f:
f.write(\"\"\"from typing import Type
from dotenv import load_dotenv
from .agent import Agent, Playback
from .swarm import Swarm
from .templates.random_agent import Random
from .templates.my_agent import MyAgent
load_dotenv()
AVAILABLE_AGENTS: dict[str, Type[Agent]] = {
'random': Random,
'myagent': MyAgent,
}
\"\"\")
# Point the framework at the gateway sidecar.
with open('/kaggle/working/ARC-AGI-3-Agents/.env', 'w') as f:
f.write(\"\"\"SCHEME=http
HOST=gateway
PORT=8001
ARC_API_KEY=test-key-123
ARC_BASE_URL=http://gateway:8001/
OPERATION_MODE=online
ENVIRONMENTS_DIR=
RECORDINGS_DIR=/kaggle/working/server_recording
\"\"\")
# Run it. The gateway records every action and emits submission.parquet.
!cd /kaggle/working/ARC-AGI-3-Agents && \\
MPLBACKEND=agg \\
python main.py --agent myagent
"""
)
run_cell = code_cell(run_cell_source)
dummy_submission_cell = code_cell(
dedent(
"""\
import os
if not os.getenv('KAGGLE_IS_COMPETITION_RERUN'):
# Save-and-run-all (commit) mode: emit a dummy submission so the
# commit succeeds. The real submission.parquet is produced by the
# gateway during competition rerun.
import pandas as pd
submission = pd.DataFrame(
data=[['1_0', '1', True, 1]],
columns=['row_id', 'game_id', 'end_of_game', 'score'])
submission.to_parquet('/kaggle/working/submission.parquet', index=False)
submission.head()
"""
)
)
if ACCELERATOR not in _ACCELERATORS:
raise SystemExit(
f"Unknown ACCELERATOR={ACCELERATOR!r}. Pick one of: "
f"{sorted(_ACCELERATORS)}"
)
accel = _ACCELERATORS[ACCELERATOR]
notebook = {
"metadata": {
"kernelspec": {
"language": "python",
"display_name": "Python 3",
"name": "python3",
},
"language_info": {
"name": "python",
"mimetype": "text/x-python",
"file_extension": ".py",
"pygments_lexer": "ipython3",
},
"kaggle": {
"accelerator": accel["name"],
"isInternetEnabled": False,
"isGpuEnabled": accel["gpu"],
"language": "python",
"sourceType": "notebook",
},
},
"nbformat_minor": 4,
"nbformat": 4,
"cells": [
markdown_cell(
"# ARC Prize 2026 — ARC-AGI-3 Submission\n\n"
"Built from `agent/my_agent.py` via `scripts/build_notebook.py`. "
"Do not edit cells directly — edit the source file and re-run "
"`make submit`."
),
install_cell,
write_agent_cell,
run_cell,
dummy_submission_cell,
],
}
return notebook
def main() -> None:
NOTEBOOK_PATH.parent.mkdir(parents=True, exist_ok=True)
NOTEBOOK_PATH.write_text(json.dumps(build(), indent=1))
print(f"[build_notebook] Wrote {NOTEBOOK_PATH.relative_to(ROOT)} "
f"(accelerator: {ACCELERATOR})")
# Keep notebooks/kernel-metadata.json in sync so the user never has to
# edit it just to flip CPU ↔ GPU.
if METADATA_PATH.exists():
meta = json.loads(METADATA_PATH.read_text())
wanted = _ACCELERATORS[ACCELERATOR]["gpu"]
if meta.get("enable_gpu") != wanted:
meta["enable_gpu"] = wanted
METADATA_PATH.write_text(json.dumps(meta, indent=2) + "\n")
print(f"[build_notebook] Synced enable_gpu={wanted} in "
f"{METADATA_PATH.relative_to(ROOT)}")
if __name__ == "__main__":
main()