create-stylus-ide 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.MD +1515 -0
- package/cli.js +28 -0
- package/frontend/.vscode/settings.json +9 -0
- package/frontend/app/api/chat/route.ts +101 -0
- package/frontend/app/api/check-setup/route.ts +93 -0
- package/frontend/app/api/cleanup/route.ts +14 -0
- package/frontend/app/api/compile/route.ts +95 -0
- package/frontend/app/api/compile-stream/route.ts +98 -0
- package/frontend/app/api/complete/route.ts +86 -0
- package/frontend/app/api/deploy/route.ts +118 -0
- package/frontend/app/api/export-abi/route.ts +58 -0
- package/frontend/app/favicon.ico +0 -0
- package/frontend/app/globals.css +177 -0
- package/frontend/app/layout.tsx +29 -0
- package/frontend/app/ml/page.tsx +694 -0
- package/frontend/app/page.tsx +1132 -0
- package/frontend/app/providers.tsx +18 -0
- package/frontend/app/qlearning/page.tsx +188 -0
- package/frontend/app/raytracing/page.tsx +268 -0
- package/frontend/components/abi/ABIDialog.tsx +132 -0
- package/frontend/components/ai/AICompletionPopup.tsx +76 -0
- package/frontend/components/ai/ChatPanel.tsx +292 -0
- package/frontend/components/ai/QuickActions.tsx +128 -0
- package/frontend/components/blockchain/BlockchainContractBanner.tsx +64 -0
- package/frontend/components/blockchain/BlockchainLoadingDialog.tsx +188 -0
- package/frontend/components/deploy/DeployDialog.tsx +334 -0
- package/frontend/components/editor/FileTabs.tsx +181 -0
- package/frontend/components/editor/MonacoEditor.tsx +306 -0
- package/frontend/components/file-tree/ContextMenu.tsx +110 -0
- package/frontend/components/file-tree/DeleteConfirmDialog.tsx +61 -0
- package/frontend/components/file-tree/FileInputDialog.tsx +97 -0
- package/frontend/components/file-tree/FileNode.tsx +60 -0
- package/frontend/components/file-tree/FileTree.tsx +259 -0
- package/frontend/components/file-tree/FileTreeSkeleton.tsx +26 -0
- package/frontend/components/file-tree/FolderNode.tsx +105 -0
- package/frontend/components/github/GitHubLoadingDialog.tsx +201 -0
- package/frontend/components/github/GitHubMetadataBanner.tsx +61 -0
- package/frontend/components/github/LoadFromGitHubDialog.tsx +125 -0
- package/frontend/components/github/URLCopyButton.tsx +60 -0
- package/frontend/components/interact/ContractInteraction.tsx +323 -0
- package/frontend/components/interact/ContractPlaceholder.tsx +41 -0
- package/frontend/components/orbit/BenchmarkDialog.tsx +342 -0
- package/frontend/components/orbit/OrbitExplorer.tsx +273 -0
- package/frontend/components/project/ProjectActions.tsx +176 -0
- package/frontend/components/q-learning/ContractConfig.tsx +172 -0
- package/frontend/components/q-learning/MazeGrid.tsx +346 -0
- package/frontend/components/q-learning/PathAnimation.tsx +384 -0
- package/frontend/components/q-learning/QTableHeatmap.tsx +300 -0
- package/frontend/components/q-learning/TrainingForm.tsx +349 -0
- package/frontend/components/ray-tracing/ContractConfig.tsx +245 -0
- package/frontend/components/ray-tracing/MintingForm.tsx +280 -0
- package/frontend/components/ray-tracing/RenderCanvas.tsx +228 -0
- package/frontend/components/ray-tracing/RenderingPanel.tsx +259 -0
- package/frontend/components/ray-tracing/StyleControls.tsx +217 -0
- package/frontend/components/setup/SetupGuide.tsx +290 -0
- package/frontend/components/ui/KeyboardShortcutHint.tsx +74 -0
- package/frontend/components/ui/alert-dialog.tsx +157 -0
- package/frontend/components/ui/alert.tsx +66 -0
- package/frontend/components/ui/badge.tsx +46 -0
- package/frontend/components/ui/button.tsx +62 -0
- package/frontend/components/ui/card.tsx +92 -0
- package/frontend/components/ui/context-menu.tsx +252 -0
- package/frontend/components/ui/dialog.tsx +143 -0
- package/frontend/components/ui/dropdown-menu.tsx +257 -0
- package/frontend/components/ui/input.tsx +21 -0
- package/frontend/components/ui/label.tsx +24 -0
- package/frontend/components/ui/progress.tsx +31 -0
- package/frontend/components/ui/scroll-area.tsx +58 -0
- package/frontend/components/ui/select.tsx +190 -0
- package/frontend/components/ui/separator.tsx +28 -0
- package/frontend/components/ui/sheet.tsx +139 -0
- package/frontend/components/ui/skeleton.tsx +13 -0
- package/frontend/components/ui/slider.tsx +63 -0
- package/frontend/components/ui/sonner.tsx +40 -0
- package/frontend/components/ui/tabs.tsx +66 -0
- package/frontend/components/ui/textarea.tsx +18 -0
- package/frontend/components/wallet/ConnectButton.tsx +167 -0
- package/frontend/components/wallet/FaucetButton.tsx +256 -0
- package/frontend/components.json +22 -0
- package/frontend/eslint.config.mjs +18 -0
- package/frontend/hooks/useAICompletion.ts +75 -0
- package/frontend/hooks/useBlockchainLoader.ts +58 -0
- package/frontend/hooks/useChats.ts +137 -0
- package/frontend/hooks/useCompilation.ts +173 -0
- package/frontend/hooks/useFileTabs.ts +178 -0
- package/frontend/hooks/useGitHubLoader.ts +50 -0
- package/frontend/hooks/useKeyboardShortcuts.ts +47 -0
- package/frontend/hooks/usePanelState.ts +115 -0
- package/frontend/hooks/useProjectState.ts +276 -0
- package/frontend/hooks/useResponsive.ts +29 -0
- package/frontend/lib/abi-parser.ts +58 -0
- package/frontend/lib/blockchain-api.ts +374 -0
- package/frontend/lib/blockchain-explorers.ts +75 -0
- package/frontend/lib/blockchain-loader.ts +112 -0
- package/frontend/lib/cargo-template.ts +64 -0
- package/frontend/lib/compilation.ts +529 -0
- package/frontend/lib/constants.ts +31 -0
- package/frontend/lib/deployment.ts +176 -0
- package/frontend/lib/file-utils.ts +83 -0
- package/frontend/lib/github-api.ts +246 -0
- package/frontend/lib/github-loader.ts +369 -0
- package/frontend/lib/ml-contract-template.txt +900 -0
- package/frontend/lib/orbit-chains.ts +181 -0
- package/frontend/lib/output-formatter.ts +68 -0
- package/frontend/lib/project-manager.ts +632 -0
- package/frontend/lib/ray-tracing-abi.ts +206 -0
- package/frontend/lib/storage.ts +189 -0
- package/frontend/lib/templates.ts +1662 -0
- package/frontend/lib/url-parser.ts +188 -0
- package/frontend/lib/utils.ts +6 -0
- package/frontend/lib/wagmi-config.ts +24 -0
- package/frontend/next.config.ts +7 -0
- package/frontend/package-lock.json +16259 -0
- package/frontend/package.json +60 -0
- package/frontend/postcss.config.mjs +7 -0
- package/frontend/public/file.svg +1 -0
- package/frontend/public/globe.svg +1 -0
- package/frontend/public/ml-weights/.gitkeep +0 -0
- package/frontend/public/ml-weights/model.pkl +0 -0
- package/frontend/public/ml-weights/model_weights.json +27102 -0
- package/frontend/public/ml-weights/test_samples.json +7888 -0
- package/frontend/public/next.svg +1 -0
- package/frontend/public/vercel.svg +1 -0
- package/frontend/public/window.svg +1 -0
- package/frontend/scripts/check-env.js +52 -0
- package/frontend/scripts/setup.js +285 -0
- package/frontend/tailwind.config.ts +64 -0
- package/frontend/tsconfig.json +34 -0
- package/frontend/types/blockchain.ts +63 -0
- package/frontend/types/github.ts +54 -0
- package/frontend/types/project.ts +106 -0
- package/ml-training/README.md +56 -0
- package/ml-training/train_tiny_model.py +325 -0
- package/ml-training/update_template.py +59 -0
- package/package.json +30 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# ML Model Training for Stylus
|
|
2
|
+
|
|
3
|
+
This directory contains scripts to train a neural network and export weights for on-chain inference.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Create virtual environment
|
|
9
|
+
python3 -m venv venv
|
|
10
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
11
|
+
|
|
12
|
+
# Install dependencies
|
|
13
|
+
python -m pip install -U pip
|
|
14
|
+
python -m pip install numpy scikit-learn pandas
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Train Model
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python train_tiny_model.py
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This will:
|
|
24
|
+
|
|
25
|
+
1. Download MNIST dataset (28x28 digit images)
|
|
26
|
+
2. Train a simple neural network (784 ā 32 ā 10)
|
|
27
|
+
3. Convert weights to fixed-point format
|
|
28
|
+
4. Export to `frontend/public/ml-weights/model_weights.json`
|
|
29
|
+
5. Save test samples for demo
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
**Input Layer:** 784 neurons (28Ć28 pixels, normalized 0-1)
|
|
34
|
+
**Hidden Layer:** 32 neurons (ReLU activation)
|
|
35
|
+
**Output Layer:** 10 neurons (digit 0-9)
|
|
36
|
+
|
|
37
|
+
**Fixed-Point Format:**
|
|
38
|
+
|
|
39
|
+
- All weights/biases multiplied by 10,000
|
|
40
|
+
- Stored as i32 in Stylus
|
|
41
|
+
- Divided by 10,000 during inference
|
|
42
|
+
|
|
43
|
+
## Why Fixed-Point?
|
|
44
|
+
|
|
45
|
+
Stylus (like EVM) doesn't support floating-point. We use fixed-point arithmetic:
|
|
46
|
+
|
|
47
|
+
- Float: `0.1234` ā Fixed: `1234` (scale: 10000)
|
|
48
|
+
- Multiply: `(a * b) / SCALE`
|
|
49
|
+
- Accurate enough for simple ML
|
|
50
|
+
- Much cheaper than float emulation
|
|
51
|
+
|
|
52
|
+
## Model Stats
|
|
53
|
+
|
|
54
|
+
- **Parameters:** ~25,000 weights
|
|
55
|
+
- **Accuracy:** ~95% on MNIST test set
|
|
56
|
+
- **Gas Cost:** TBD (will measure on-chain)
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Train a TINY neural network that can be embedded on-chain
|
|
3
|
+
Architecture: 784 -> 10 -> 10 (only ~8K parameters)
|
|
4
|
+
Trade-off: Lower accuracy but actually deployable
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
from sklearn.datasets import fetch_openml
|
|
9
|
+
from sklearn.neural_network import MLPClassifier
|
|
10
|
+
from sklearn.model_selection import train_test_split
|
|
11
|
+
import json
|
|
12
|
+
import re
|
|
13
|
+
# TINY configuration for on-chain deployment
|
|
14
|
+
HIDDEN_LAYER_SIZE = 10 # Very small to reduce weights
|
|
15
|
+
INPUT_SIZE = 784
|
|
16
|
+
OUTPUT_SIZE = 10
|
|
17
|
+
FIXED_POINT_SCALE = 10000
|
|
18
|
+
|
|
19
|
+
print("Loading MNIST dataset...")
|
|
20
|
+
mnist = fetch_openml('mnist_784', version=1, parser='auto')
|
|
21
|
+
X, y = mnist.data, mnist.target
|
|
22
|
+
|
|
23
|
+
X = X.to_numpy() if hasattr(X, 'to_numpy') else X
|
|
24
|
+
y = y.to_numpy() if hasattr(y, 'to_numpy') else y
|
|
25
|
+
y = y.astype(int)
|
|
26
|
+
|
|
27
|
+
# Use more data for better accuracy
|
|
28
|
+
X = X[:30000]
|
|
29
|
+
y = y[:30000]
|
|
30
|
+
|
|
31
|
+
# Normalize
|
|
32
|
+
X = X / 255.0
|
|
33
|
+
|
|
34
|
+
X_train, X_test, y_train, y_test = train_test_split(
|
|
35
|
+
X, y, test_size=0.2, random_state=42
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
print(f"Training TINY model: {INPUT_SIZE} -> {HIDDEN_LAYER_SIZE} -> {OUTPUT_SIZE}")
|
|
39
|
+
print(f"Training set: {X_train.shape[0]} samples")
|
|
40
|
+
print(f"Test set: {X_test.shape[0]} samples")
|
|
41
|
+
|
|
42
|
+
# Train model
|
|
43
|
+
model = MLPClassifier(
|
|
44
|
+
hidden_layer_sizes=(HIDDEN_LAYER_SIZE,),
|
|
45
|
+
activation='relu',
|
|
46
|
+
solver='adam',
|
|
47
|
+
max_iter=100,
|
|
48
|
+
random_state=42,
|
|
49
|
+
verbose=True
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
model.fit(X_train, y_train)
|
|
53
|
+
|
|
54
|
+
train_score = model.score(X_train, y_train)
|
|
55
|
+
test_score = model.score(X_test, y_test)
|
|
56
|
+
|
|
57
|
+
print(f"\nTraining accuracy: {train_score:.4f}")
|
|
58
|
+
print(f"Test accuracy: {test_score:.4f}")
|
|
59
|
+
|
|
60
|
+
# Extract weights
|
|
61
|
+
w1 = model.coefs_[0] # (784, 10)
|
|
62
|
+
b1 = model.intercepts_[0] # (10,)
|
|
63
|
+
w2 = model.coefs_[1] # (10, 10)
|
|
64
|
+
b2 = model.intercepts_[1] # (10,)
|
|
65
|
+
|
|
66
|
+
print(f"\nTotal parameters: {w1.size + b1.size + w2.size + b2.size}")
|
|
67
|
+
|
|
68
|
+
# Convert to fixed-point
|
|
69
|
+
def to_fixed(arr):
|
|
70
|
+
return np.round(arr * FIXED_POINT_SCALE).astype(np.int32)
|
|
71
|
+
|
|
72
|
+
w1_fp = to_fixed(w1)
|
|
73
|
+
b1_fp = to_fixed(b1)
|
|
74
|
+
w2_fp = to_fixed(w2)
|
|
75
|
+
b2_fp = to_fixed(b2)
|
|
76
|
+
|
|
77
|
+
print("\nGenerating Rust contract code...")
|
|
78
|
+
|
|
79
|
+
# Generate Rust arrays as strings
|
|
80
|
+
def format_rust_array_2d(arr, name):
|
|
81
|
+
"""Format 2D array as Rust const"""
|
|
82
|
+
rows, cols = arr.shape
|
|
83
|
+
lines = [f"const {name}: [[i64; {cols}]; {rows}] = ["]
|
|
84
|
+
for row in arr:
|
|
85
|
+
row_str = " [" + ", ".join(str(int(x)) for x in row) + "],"
|
|
86
|
+
lines.append(row_str)
|
|
87
|
+
lines.append("];")
|
|
88
|
+
return "\n".join(lines)
|
|
89
|
+
|
|
90
|
+
def format_rust_array_1d(arr, name):
|
|
91
|
+
"""Format 1D array as Rust const"""
|
|
92
|
+
size = len(arr)
|
|
93
|
+
values = ", ".join(str(int(x)) for x in arr)
|
|
94
|
+
return f"const {name}: [i64; {size}] = [{values}];"
|
|
95
|
+
|
|
96
|
+
# Generate contract with embedded weights
|
|
97
|
+
contract_code = f"""// REAL ML Inference - MNIST (Tiny Model)
|
|
98
|
+
#![cfg_attr(not(feature = "export-abi"), no_main)]
|
|
99
|
+
extern crate alloc;
|
|
100
|
+
|
|
101
|
+
use stylus_sdk::{{alloy_primitives::U256, prelude::*, alloy_sol_types::sol}};
|
|
102
|
+
use alloc::vec::Vec;
|
|
103
|
+
|
|
104
|
+
const INPUT_SIZE: usize = {INPUT_SIZE};
|
|
105
|
+
const HIDDEN_SIZE: usize = {HIDDEN_LAYER_SIZE};
|
|
106
|
+
const OUTPUT_SIZE: usize = {OUTPUT_SIZE};
|
|
107
|
+
const SCALE: i64 = {FIXED_POINT_SCALE};
|
|
108
|
+
|
|
109
|
+
// TRAINED WEIGHTS (Fixed-point scaled by {FIXED_POINT_SCALE})
|
|
110
|
+
// Model accuracy: {test_score:.2%}
|
|
111
|
+
|
|
112
|
+
{format_rust_array_2d(w1_fp, "WEIGHTS_INPUT_HIDDEN")}
|
|
113
|
+
|
|
114
|
+
{format_rust_array_1d(b1_fp, "BIAS_HIDDEN")}
|
|
115
|
+
|
|
116
|
+
{format_rust_array_2d(w2_fp, "WEIGHTS_HIDDEN_OUTPUT")}
|
|
117
|
+
|
|
118
|
+
{format_rust_array_1d(b2_fp, "BIAS_OUTPUT")}
|
|
119
|
+
|
|
120
|
+
sol_storage! {{
|
|
121
|
+
#[entrypoint]
|
|
122
|
+
pub struct MNISTClassifier {{
|
|
123
|
+
bool initialized;
|
|
124
|
+
}}
|
|
125
|
+
}}
|
|
126
|
+
|
|
127
|
+
#[public]
|
|
128
|
+
impl MNISTClassifier {{
|
|
129
|
+
// Predict digit from 28x28 grayscale image (784 pixels, 0-255)
|
|
130
|
+
pub fn predict(&self, pixels: Vec<u8>) -> U256 {{
|
|
131
|
+
if pixels.len() != INPUT_SIZE {{
|
|
132
|
+
return U256::from(999); // Error code
|
|
133
|
+
}}
|
|
134
|
+
|
|
135
|
+
// Normalize pixels to fixed-point (0-10000 range)
|
|
136
|
+
let mut input: Vec<i64> = pixels.iter()
|
|
137
|
+
.map(|&p| ((p as i64) * SCALE) / 255)
|
|
138
|
+
.collect();
|
|
139
|
+
|
|
140
|
+
// Layer 1: Input -> Hidden (ReLU)
|
|
141
|
+
let mut hidden = Vec::with_capacity(HIDDEN_SIZE);
|
|
142
|
+
for i in 0..HIDDEN_SIZE {{
|
|
143
|
+
let mut sum = BIAS_HIDDEN[i];
|
|
144
|
+
|
|
145
|
+
// Dot product with input
|
|
146
|
+
for j in 0..INPUT_SIZE {{
|
|
147
|
+
let weight = WEIGHTS_INPUT_HIDDEN[j][i];
|
|
148
|
+
sum += (input[j] * weight) / SCALE;
|
|
149
|
+
}}
|
|
150
|
+
|
|
151
|
+
hidden.push(relu(sum));
|
|
152
|
+
}}
|
|
153
|
+
|
|
154
|
+
// Layer 2: Hidden -> Output
|
|
155
|
+
let mut output = Vec::with_capacity(OUTPUT_SIZE);
|
|
156
|
+
for i in 0..OUTPUT_SIZE {{
|
|
157
|
+
let mut sum = BIAS_OUTPUT[i];
|
|
158
|
+
|
|
159
|
+
// Dot product with hidden layer
|
|
160
|
+
for j in 0..HIDDEN_SIZE {{
|
|
161
|
+
let weight = WEIGHTS_HIDDEN_OUTPUT[j][i];
|
|
162
|
+
sum += (hidden[j] * weight) / SCALE;
|
|
163
|
+
}}
|
|
164
|
+
|
|
165
|
+
output.push(sum);
|
|
166
|
+
}}
|
|
167
|
+
|
|
168
|
+
// Return argmax (predicted digit)
|
|
169
|
+
let mut max_idx = 0;
|
|
170
|
+
let mut max_val = output[0];
|
|
171
|
+
|
|
172
|
+
for i in 1..OUTPUT_SIZE {{
|
|
173
|
+
if output[i] > max_val {{
|
|
174
|
+
max_val = output[i];
|
|
175
|
+
max_idx = i;
|
|
176
|
+
}}
|
|
177
|
+
}}
|
|
178
|
+
|
|
179
|
+
U256::from(max_idx)
|
|
180
|
+
}}
|
|
181
|
+
|
|
182
|
+
// Get model info
|
|
183
|
+
pub fn get_model_info(&self) -> (U256, U256, U256) {{
|
|
184
|
+
(
|
|
185
|
+
U256::from(INPUT_SIZE),
|
|
186
|
+
U256::from(HIDDEN_SIZE),
|
|
187
|
+
U256::from(OUTPUT_SIZE)
|
|
188
|
+
)
|
|
189
|
+
}}
|
|
190
|
+
|
|
191
|
+
// Always ready (weights are embedded)
|
|
192
|
+
pub fn is_ready(&self) -> bool {{
|
|
193
|
+
true
|
|
194
|
+
}}
|
|
195
|
+
}}
|
|
196
|
+
|
|
197
|
+
// ReLU activation
|
|
198
|
+
fn relu(x: i64) -> i64 {{
|
|
199
|
+
if x > 0 {{ x }} else {{ 0 }}
|
|
200
|
+
}}
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
# Save contract
|
|
204
|
+
with open('../frontend/lib/ml-contract-template.txt', 'w') as f:
|
|
205
|
+
f.write(contract_code)
|
|
206
|
+
|
|
207
|
+
print(f"\nā Contract saved to: frontend/lib/ml-contract-template.txt")
|
|
208
|
+
|
|
209
|
+
def escape_for_ts_template_literal(s: str) -> str:
|
|
210
|
+
# Safe for TypeScript template literals:
|
|
211
|
+
# - escape backslashes
|
|
212
|
+
# - escape backticks
|
|
213
|
+
# - prevent ${} interpolation
|
|
214
|
+
return s.replace('\\', '\\\\').replace('`', '\\`').replace('${', '\\${')
|
|
215
|
+
|
|
216
|
+
def find_closing_backtick(text: str, start: int) -> int:
|
|
217
|
+
"""
|
|
218
|
+
Find the next *unescaped* backtick in `text`, starting at `start`.
|
|
219
|
+
"""
|
|
220
|
+
i = start
|
|
221
|
+
while i < len(text):
|
|
222
|
+
if text[i] == '`':
|
|
223
|
+
# count preceding backslashes
|
|
224
|
+
bs = 0
|
|
225
|
+
j = i - 1
|
|
226
|
+
while j >= start and text[j] == '\\':
|
|
227
|
+
bs += 1
|
|
228
|
+
j -= 1
|
|
229
|
+
if bs % 2 == 0:
|
|
230
|
+
return i
|
|
231
|
+
i += 1
|
|
232
|
+
return -1
|
|
233
|
+
|
|
234
|
+
def update_template_code(templates_path: str, template_id: str, new_code: str) -> None:
|
|
235
|
+
src = open(templates_path, "r", encoding="utf-8").read()
|
|
236
|
+
|
|
237
|
+
# 1) Locate the template by id: "ml-inference"
|
|
238
|
+
m_id = re.search(rf'\bid\s*:\s*["\']{re.escape(template_id)}["\']', src)
|
|
239
|
+
if not m_id:
|
|
240
|
+
raise RuntimeError(f'Could not find template id "{template_id}" in {templates_path}')
|
|
241
|
+
|
|
242
|
+
# 2) From that point onward, locate: code: `
|
|
243
|
+
m_code = re.search(r'\bcode\s*:\s*`', src[m_id.end():])
|
|
244
|
+
if not m_code:
|
|
245
|
+
raise RuntimeError(f'Could not find `code: ` template literal for id "{template_id}"')
|
|
246
|
+
|
|
247
|
+
open_tick = m_id.end() + m_code.end() - 1 # index of the opening ` character
|
|
248
|
+
|
|
249
|
+
# 3) Find the matching closing backtick for that template literal
|
|
250
|
+
close_tick = find_closing_backtick(src, open_tick + 1)
|
|
251
|
+
if close_tick == -1:
|
|
252
|
+
raise RuntimeError(f'Could not find closing backtick for template id "{template_id}"')
|
|
253
|
+
|
|
254
|
+
# 4) Replace content between backticks
|
|
255
|
+
escaped = escape_for_ts_template_literal(new_code)
|
|
256
|
+
updated = src[:open_tick + 1] + escaped + src[close_tick:]
|
|
257
|
+
|
|
258
|
+
open(templates_path, "w", encoding="utf-8").write(updated)
|
|
259
|
+
|
|
260
|
+
# --- AUTO-UPDATE templates.ts ---
|
|
261
|
+
print("\nUpdating frontend/lib/templates.ts...")
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
templates_path = "../frontend/lib/templates.ts" # your existing path is fine
|
|
265
|
+
update_template_code(templates_path, "ml-inference", contract_code)
|
|
266
|
+
|
|
267
|
+
print("ā templates.ts updated successfully!")
|
|
268
|
+
print("ā ML contract template now has real trained weights")
|
|
269
|
+
print("\nš Training complete! Refresh your IDE to use the new model.")
|
|
270
|
+
except Exception as e:
|
|
271
|
+
print(f"ā ļø Error updating templates.ts: {e}")
|
|
272
|
+
print("Please manually copy from ml-contract-template.txt")
|
|
273
|
+
import traceback
|
|
274
|
+
traceback.print_exc()
|
|
275
|
+
|
|
276
|
+
print(f"\nā Model achieves {test_score:.2%} accuracy")
|
|
277
|
+
print(f"ā Total parameters: {w1.size + b1.size + w2.size + b2.size}")
|
|
278
|
+
print(f"\nNote: Accuracy is lower due to tiny model size")
|
|
279
|
+
print(f"Trade-off: {test_score:.0%} accuracy vs deployable on-chain")
|
|
280
|
+
|
|
281
|
+
# Save test samples for demo
|
|
282
|
+
print("\nSaving test samples...")
|
|
283
|
+
|
|
284
|
+
# Get 10 correctly classified samples (one per digit)
|
|
285
|
+
test_samples_by_digit = {i: [] for i in range(10)}
|
|
286
|
+
|
|
287
|
+
# Find examples of each digit
|
|
288
|
+
for i in range(len(X_test)):
|
|
289
|
+
label = y_test[i]
|
|
290
|
+
prediction = model.predict([X_test[i]])[0]
|
|
291
|
+
|
|
292
|
+
# Only save if correctly predicted
|
|
293
|
+
if prediction == label and len(test_samples_by_digit[label]) < 2:
|
|
294
|
+
test_samples_by_digit[label].append({
|
|
295
|
+
'image': X_test[i].tolist(),
|
|
296
|
+
'label': int(label),
|
|
297
|
+
'index': i
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
# Stop when we have 2 examples of each digit
|
|
301
|
+
if all(len(samples) >= 2 for samples in test_samples_by_digit.values()):
|
|
302
|
+
break
|
|
303
|
+
|
|
304
|
+
# Use the first example of each digit
|
|
305
|
+
test_samples = {
|
|
306
|
+
'images': [test_samples_by_digit[i][0]['image'] for i in range(10)],
|
|
307
|
+
'labels': [i for i in range(10)],
|
|
308
|
+
'indices': [test_samples_by_digit[i][0]['index'] for i in range(10)]
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
import os
|
|
312
|
+
os.makedirs('../frontend/public/ml-weights', exist_ok=True)
|
|
313
|
+
|
|
314
|
+
with open('../frontend/public/ml-weights/test_samples.json', 'w') as f:
|
|
315
|
+
json.dump(test_samples, f, indent=2)
|
|
316
|
+
|
|
317
|
+
print("ā Test samples saved (correctly classified examples)")
|
|
318
|
+
|
|
319
|
+
# Print verification info
|
|
320
|
+
print("\nTest sample verification:")
|
|
321
|
+
for i in range(10):
|
|
322
|
+
img = test_samples['images'][i]
|
|
323
|
+
label = test_samples['labels'][i]
|
|
324
|
+
pred = model.predict([img])[0]
|
|
325
|
+
print(f" Sample #{i}: Label={label}, Prediction={pred}, {'ā' if pred == label else 'ā'}")
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Helper script to update the ML template in templates.ts
|
|
3
|
+
Usage: python update_template.py
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
def update_ml_template():
|
|
10
|
+
try:
|
|
11
|
+
# Read the generated contract
|
|
12
|
+
with open('../frontend/lib/ml-contract-template.txt', 'r') as f:
|
|
13
|
+
contract_code = f.read()
|
|
14
|
+
|
|
15
|
+
# Read templates.ts
|
|
16
|
+
templates_path = '../frontend/lib/templates.ts'
|
|
17
|
+
with open(templates_path, 'r') as f:
|
|
18
|
+
content = f.read()
|
|
19
|
+
|
|
20
|
+
# Use regex to find and replace the ML template code
|
|
21
|
+
# Pattern: finds the ml-inference template and its code section
|
|
22
|
+
pattern = r"(id: 'ml-inference',\s+name: 'ML Inference \(MNIST\)',\s+description: '[^']+',\s+code: `)([^`]+)(`)"
|
|
23
|
+
|
|
24
|
+
# Escape backticks in contract code
|
|
25
|
+
escaped_contract = contract_code.replace('`', '\\`')
|
|
26
|
+
|
|
27
|
+
# Replace
|
|
28
|
+
new_content = re.sub(
|
|
29
|
+
pattern,
|
|
30
|
+
r'\1' + escaped_contract + r'\3',
|
|
31
|
+
content,
|
|
32
|
+
flags=re.DOTALL
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
if new_content != content:
|
|
36
|
+
# Write back
|
|
37
|
+
with open(templates_path, 'w') as f:
|
|
38
|
+
f.write(new_content)
|
|
39
|
+
|
|
40
|
+
print("ā templates.ts updated successfully!")
|
|
41
|
+
print("ā ML template now has real trained weights")
|
|
42
|
+
print("\nš Refresh your IDE to see the changes!")
|
|
43
|
+
return True
|
|
44
|
+
else:
|
|
45
|
+
print("ā ļø No changes made - pattern not found")
|
|
46
|
+
print("Check that ml-inference template exists in templates.ts")
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
except FileNotFoundError as e:
|
|
50
|
+
print(f"ā File not found: {e}")
|
|
51
|
+
print("Make sure you run this from the ml-training directory")
|
|
52
|
+
return False
|
|
53
|
+
except Exception as e:
|
|
54
|
+
print(f"ā Error: {e}")
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
if __name__ == '__main__':
|
|
58
|
+
success = update_ml_template()
|
|
59
|
+
sys.exit(0 if success else 1)
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-stylus-ide",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "The Ultimate Web-Based Development Environment for Arbitrum Stylus Smart Contracts",
|
|
5
|
+
"main": "cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"stylus-ide": "./cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"postinstall": "cd frontend && npm install",
|
|
11
|
+
"start": "node cli.js",
|
|
12
|
+
"dev": "cd frontend && npm run dev",
|
|
13
|
+
"setup": "cd frontend && npm run setup",
|
|
14
|
+
"check-env": "cd frontend && npm run check-env",
|
|
15
|
+
"ml:train": "python ml-training/train_tiny_model.py"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"frontend",
|
|
19
|
+
"ml-training",
|
|
20
|
+
"cli.js"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"ide",
|
|
24
|
+
"stylus",
|
|
25
|
+
"nextjs",
|
|
26
|
+
"ml"
|
|
27
|
+
],
|
|
28
|
+
"author": "Aaditya Srivastava",
|
|
29
|
+
"license": "ISC"
|
|
30
|
+
}
|