rnow 0.2.4__py3-none-any.whl
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.
- rnow/__init__.py +5 -0
- rnow/__main__.py +7 -0
- rnow/cli/__init__.py +6 -0
- rnow/cli/auth.py +67 -0
- rnow/cli/blob.py +98 -0
- rnow/cli/commands.py +2311 -0
- rnow/cli/common.py +28 -0
- rnow/cli/cube.py +255 -0
- rnow/cli/main.py +49 -0
- rnow/cli/test.py +728 -0
- rnow/cli/token_count.py +295 -0
- rnow/core/__init__.py +33 -0
- rnow/core/reward.py +333 -0
- rnow/core/tool.py +494 -0
- rnow/models.py +295 -0
- rnow/templates/deepseek-aha/config.yml +26 -0
- rnow/templates/deepseek-aha/rewards.py +36 -0
- rnow/templates/deepseek-aha/train.jsonl +1000 -0
- rnow/templates/mcp-tavily/config.yml +29 -0
- rnow/templates/mcp-tavily/requirements.txt +1 -0
- rnow/templates/mcp-tavily/rewards.py +25 -0
- rnow/templates/mcp-tavily/train.jsonl +500 -0
- rnow/templates/new/config.yml +26 -0
- rnow/templates/new/requirements.txt +1 -0
- rnow/templates/new/rewards.py +0 -0
- rnow/templates/new/train.jsonl +0 -0
- rnow/templates/rl-nextjs/config.yml +27 -0
- rnow/templates/rl-nextjs/requirements.txt +2 -0
- rnow/templates/rl-nextjs/rewards.py +446 -0
- rnow/templates/rl-nextjs/train.jsonl +1000 -0
- rnow/templates/rl-single/config.yml +27 -0
- rnow/templates/rl-single/requirements.txt +1 -0
- rnow/templates/rl-single/rewards.py +14 -0
- rnow/templates/rl-single/train.jsonl +1000 -0
- rnow/templates/rl-tools/config.yml +27 -0
- rnow/templates/rl-tools/env.py +38 -0
- rnow/templates/rl-tools/requirements.txt +3 -0
- rnow/templates/rl-tools/rewards.py +25 -0
- rnow/templates/rl-tools/train.jsonl +500 -0
- rnow/templates/sft/config.yml +20 -0
- rnow/templates/sft/train.jsonl +100 -0
- rnow/templates/tutorial-reward/config.yml +27 -0
- rnow/templates/tutorial-reward/requirements.txt +1 -0
- rnow/templates/tutorial-reward/rewards.py +15 -0
- rnow/templates/tutorial-reward/train.jsonl +1000 -0
- rnow/templates/tutorial-tool/config.yml +27 -0
- rnow/templates/tutorial-tool/env.py +7 -0
- rnow/templates/tutorial-tool/requirements.txt +3 -0
- rnow/templates/tutorial-tool/rewards.py +7 -0
- rnow/templates/tutorial-tool/train.jsonl +1266 -0
- rnow-0.2.4.dist-info/METADATA +135 -0
- rnow-0.2.4.dist-info/RECORD +56 -0
- rnow-0.2.4.dist-info/WHEEL +5 -0
- rnow-0.2.4.dist-info/entry_points.txt +2 -0
- rnow-0.2.4.dist-info/licenses/LICENSE +21 -0
- rnow-0.2.4.dist-info/top_level.txt +1 -0
rnow/cli/common.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# reinforcenow/cli/common.py
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from rnow.cli import auth
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_active_organization():
|
|
11
|
+
"""Get active organization ID (config > credentials)."""
|
|
12
|
+
# First check config
|
|
13
|
+
org_id = auth.get_active_org_from_config()
|
|
14
|
+
if org_id:
|
|
15
|
+
return org_id
|
|
16
|
+
|
|
17
|
+
# Fall back to credentials
|
|
18
|
+
try:
|
|
19
|
+
with open(auth.CREDS_FILE) as f:
|
|
20
|
+
return json.load(f).get("organization_id")
|
|
21
|
+
except (FileNotFoundError, json.JSONDecodeError, KeyError):
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def require_auth():
|
|
26
|
+
"""Ensure authenticated."""
|
|
27
|
+
if not auth.is_authenticated():
|
|
28
|
+
raise click.ClickException("Not authenticated. Run 'reinforcenow login'")
|
rnow/cli/cube.py
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# reinforcenow/cli/cube.py
|
|
2
|
+
"""ASCII 3D rotating cube animation for loading states.
|
|
3
|
+
|
|
4
|
+
Inspired by https://github.com/leonmavr/retrovoxel
|
|
5
|
+
Voxel-style cube rendering with depth-based shading.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import contextlib
|
|
9
|
+
import math
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
import threading
|
|
13
|
+
import time
|
|
14
|
+
|
|
15
|
+
# Display settings
|
|
16
|
+
WIDTH = 50
|
|
17
|
+
HEIGHT = 18
|
|
18
|
+
FRAME_DELAY = 0.04
|
|
19
|
+
|
|
20
|
+
# ReinforceNow teal: #14B8A6
|
|
21
|
+
TEAL_RGB = (20, 184, 166)
|
|
22
|
+
TEAL = "\033[38;2;20;184;166m"
|
|
23
|
+
RESET = "\033[0m"
|
|
24
|
+
|
|
25
|
+
# Cube faces with shading characters (front to back)
|
|
26
|
+
CHARS = ".,-~:;=!*#$@"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class VoxelCube:
|
|
30
|
+
"""Voxel-style 3D cube renderer."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, width=WIDTH, height=HEIGHT):
|
|
33
|
+
self.width = width
|
|
34
|
+
self.height = height
|
|
35
|
+
self.A = 0 # Rotation angle X
|
|
36
|
+
self.B = 0 # Rotation angle Y
|
|
37
|
+
self.C = 0 # Rotation angle Z
|
|
38
|
+
self.cube_size = 8
|
|
39
|
+
self.distance = 40
|
|
40
|
+
self.k1 = 20 # Projection constant
|
|
41
|
+
|
|
42
|
+
def calculate_x(self, i, j, k):
|
|
43
|
+
"""Calculate rotated X coordinate."""
|
|
44
|
+
return (
|
|
45
|
+
j * math.sin(self.A) * math.sin(self.B) * math.cos(self.C)
|
|
46
|
+
- k * math.cos(self.A) * math.sin(self.B) * math.cos(self.C)
|
|
47
|
+
+ j * math.cos(self.A) * math.sin(self.C)
|
|
48
|
+
+ k * math.sin(self.A) * math.sin(self.C)
|
|
49
|
+
+ i * math.cos(self.B) * math.cos(self.C)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def calculate_y(self, i, j, k):
|
|
53
|
+
"""Calculate rotated Y coordinate."""
|
|
54
|
+
return (
|
|
55
|
+
j * math.cos(self.A) * math.cos(self.C)
|
|
56
|
+
+ k * math.sin(self.A) * math.cos(self.C)
|
|
57
|
+
- j * math.sin(self.A) * math.sin(self.B) * math.sin(self.C)
|
|
58
|
+
+ k * math.cos(self.A) * math.sin(self.B) * math.sin(self.C)
|
|
59
|
+
- i * math.cos(self.B) * math.sin(self.C)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def calculate_z(self, i, j, k):
|
|
63
|
+
"""Calculate rotated Z coordinate."""
|
|
64
|
+
return (
|
|
65
|
+
k * math.cos(self.A) * math.cos(self.B)
|
|
66
|
+
- j * math.sin(self.A) * math.cos(self.B)
|
|
67
|
+
+ i * math.sin(self.B)
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def render_frame(self):
|
|
71
|
+
"""Render a single frame of the rotating cube."""
|
|
72
|
+
output = [[" " for _ in range(self.width)] for _ in range(self.height)]
|
|
73
|
+
z_buffer = [[0 for _ in range(self.width)] for _ in range(self.height)]
|
|
74
|
+
|
|
75
|
+
# Render each face of the cube
|
|
76
|
+
cube_size = self.cube_size
|
|
77
|
+
increment = 0.6
|
|
78
|
+
|
|
79
|
+
for face in range(6):
|
|
80
|
+
# Generate points for each face
|
|
81
|
+
if face == 0: # Front
|
|
82
|
+
points = [
|
|
83
|
+
(i, j, -cube_size)
|
|
84
|
+
for i in self._frange(-cube_size, cube_size, increment)
|
|
85
|
+
for j in self._frange(-cube_size, cube_size, increment)
|
|
86
|
+
]
|
|
87
|
+
char_idx = 0
|
|
88
|
+
elif face == 1: # Back
|
|
89
|
+
points = [
|
|
90
|
+
(i, j, cube_size)
|
|
91
|
+
for i in self._frange(-cube_size, cube_size, increment)
|
|
92
|
+
for j in self._frange(-cube_size, cube_size, increment)
|
|
93
|
+
]
|
|
94
|
+
char_idx = 2
|
|
95
|
+
elif face == 2: # Left
|
|
96
|
+
points = [
|
|
97
|
+
(-cube_size, j, k)
|
|
98
|
+
for j in self._frange(-cube_size, cube_size, increment)
|
|
99
|
+
for k in self._frange(-cube_size, cube_size, increment)
|
|
100
|
+
]
|
|
101
|
+
char_idx = 4
|
|
102
|
+
elif face == 3: # Right
|
|
103
|
+
points = [
|
|
104
|
+
(cube_size, j, k)
|
|
105
|
+
for j in self._frange(-cube_size, cube_size, increment)
|
|
106
|
+
for k in self._frange(-cube_size, cube_size, increment)
|
|
107
|
+
]
|
|
108
|
+
char_idx = 6
|
|
109
|
+
elif face == 4: # Top
|
|
110
|
+
points = [
|
|
111
|
+
(i, -cube_size, k)
|
|
112
|
+
for i in self._frange(-cube_size, cube_size, increment)
|
|
113
|
+
for k in self._frange(-cube_size, cube_size, increment)
|
|
114
|
+
]
|
|
115
|
+
char_idx = 8
|
|
116
|
+
else: # Bottom
|
|
117
|
+
points = [
|
|
118
|
+
(i, cube_size, k)
|
|
119
|
+
for i in self._frange(-cube_size, cube_size, increment)
|
|
120
|
+
for k in self._frange(-cube_size, cube_size, increment)
|
|
121
|
+
]
|
|
122
|
+
char_idx = 10
|
|
123
|
+
|
|
124
|
+
for i, j, k in points:
|
|
125
|
+
x = self.calculate_x(i, j, k)
|
|
126
|
+
y = self.calculate_y(i, j, k)
|
|
127
|
+
z = self.calculate_z(i, j, k) + self.distance
|
|
128
|
+
|
|
129
|
+
ooz = 1 / z if z != 0 else 0
|
|
130
|
+
|
|
131
|
+
xp = int(self.width / 2 + self.k1 * ooz * x * 2)
|
|
132
|
+
yp = int(self.height / 2 + self.k1 * ooz * y)
|
|
133
|
+
|
|
134
|
+
if 0 <= xp < self.width and 0 <= yp < self.height and ooz > z_buffer[yp][xp]:
|
|
135
|
+
z_buffer[yp][xp] = ooz
|
|
136
|
+
output[yp][xp] = CHARS[char_idx % len(CHARS)]
|
|
137
|
+
|
|
138
|
+
return "\n".join("".join(row) for row in output)
|
|
139
|
+
|
|
140
|
+
def _frange(self, start, stop, step):
|
|
141
|
+
"""Float range generator."""
|
|
142
|
+
vals = []
|
|
143
|
+
val = start
|
|
144
|
+
while val < stop:
|
|
145
|
+
vals.append(val)
|
|
146
|
+
val += step
|
|
147
|
+
return vals
|
|
148
|
+
|
|
149
|
+
def rotate(self, da=0.04, db=0.02, dc=0.01):
|
|
150
|
+
"""Update rotation angles."""
|
|
151
|
+
self.A += da
|
|
152
|
+
self.B += db
|
|
153
|
+
self.C += dc
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class CubeSpinner:
|
|
157
|
+
"""Animated ASCII 3D rotating cube spinner."""
|
|
158
|
+
|
|
159
|
+
def __init__(self):
|
|
160
|
+
self.cube = VoxelCube()
|
|
161
|
+
self.running = False
|
|
162
|
+
self.thread = None
|
|
163
|
+
self.message = ""
|
|
164
|
+
self.lines_printed = 0
|
|
165
|
+
|
|
166
|
+
# Enable Windows ANSI support
|
|
167
|
+
if os.name == "nt":
|
|
168
|
+
os.system("")
|
|
169
|
+
|
|
170
|
+
def _animation_loop(self):
|
|
171
|
+
"""Main animation loop."""
|
|
172
|
+
first_frame = True
|
|
173
|
+
while self.running:
|
|
174
|
+
frame = self.cube.render_frame()
|
|
175
|
+
self.cube.rotate()
|
|
176
|
+
|
|
177
|
+
# Strip trailing newlines to get accurate line count
|
|
178
|
+
frame = frame.rstrip("\n")
|
|
179
|
+
colored_frame = f"{TEAL}{frame}{RESET}"
|
|
180
|
+
|
|
181
|
+
# Count actual lines in this frame
|
|
182
|
+
lines_this_frame = frame.count("\n") + 1
|
|
183
|
+
|
|
184
|
+
# Move back to top of previous frame (no clearing - new frame overwrites old)
|
|
185
|
+
if not first_frame and self.lines_printed > 0:
|
|
186
|
+
sys.stdout.write(f"\033[{self.lines_printed}A")
|
|
187
|
+
sys.stdout.write("\r")
|
|
188
|
+
|
|
189
|
+
# Print the new frame with newline so cursor ends below
|
|
190
|
+
sys.stdout.write(colored_frame + "\n")
|
|
191
|
+
sys.stdout.flush()
|
|
192
|
+
|
|
193
|
+
self.lines_printed = lines_this_frame
|
|
194
|
+
first_frame = False
|
|
195
|
+
time.sleep(FRAME_DELAY)
|
|
196
|
+
|
|
197
|
+
def start(self, message=""):
|
|
198
|
+
"""Start the animation."""
|
|
199
|
+
self.message = message
|
|
200
|
+
self.running = True
|
|
201
|
+
self.lines_printed = 0
|
|
202
|
+
self.thread = threading.Thread(target=self._animation_loop, daemon=True)
|
|
203
|
+
self.thread.start()
|
|
204
|
+
|
|
205
|
+
def update_message(self, message):
|
|
206
|
+
"""Update the message."""
|
|
207
|
+
self.message = message
|
|
208
|
+
|
|
209
|
+
def stop(self, keep_visible=False):
|
|
210
|
+
"""Stop the animation.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
keep_visible: If True, leave the cube frozen in place.
|
|
214
|
+
If False (default), clear the cube from output.
|
|
215
|
+
"""
|
|
216
|
+
self.running = False
|
|
217
|
+
if self.thread:
|
|
218
|
+
self.thread.join(timeout=0.1)
|
|
219
|
+
|
|
220
|
+
if keep_visible:
|
|
221
|
+
# Leave the cube visible, just move cursor below it
|
|
222
|
+
sys.stdout.write("\n")
|
|
223
|
+
sys.stdout.flush()
|
|
224
|
+
elif self.lines_printed > 0:
|
|
225
|
+
# Cursor is currently one line below the cube
|
|
226
|
+
# Move back up to the first line of the cube
|
|
227
|
+
sys.stdout.write(f"\033[{self.lines_printed}A")
|
|
228
|
+
sys.stdout.write("\r")
|
|
229
|
+
|
|
230
|
+
# Clear exactly self.lines_printed lines (not the whole screen)
|
|
231
|
+
for i in range(self.lines_printed):
|
|
232
|
+
sys.stdout.write("\033[2K") # Clear current line only
|
|
233
|
+
if i < self.lines_printed - 1:
|
|
234
|
+
sys.stdout.write("\n")
|
|
235
|
+
|
|
236
|
+
# Move cursor back up to where the first line was
|
|
237
|
+
if self.lines_printed > 1:
|
|
238
|
+
sys.stdout.write(f"\033[{self.lines_printed - 1}A")
|
|
239
|
+
sys.stdout.write("\r")
|
|
240
|
+
sys.stdout.flush()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
if __name__ == "__main__":
|
|
244
|
+
spinner = CubeSpinner()
|
|
245
|
+
spinner.start("Uploading...")
|
|
246
|
+
with contextlib.suppress(KeyboardInterrupt):
|
|
247
|
+
time.sleep(3)
|
|
248
|
+
spinner.stop(keep_visible=True)
|
|
249
|
+
print(f"Run started successfully {TEAL}✅{RESET}")
|
|
250
|
+
print(" Project: My Project")
|
|
251
|
+
print(" Model: Qwen/Qwen3-8B")
|
|
252
|
+
print(" Dataset: train.jsonl")
|
|
253
|
+
print()
|
|
254
|
+
print("View your experiment here:")
|
|
255
|
+
print(f"{TEAL}https://reinforcenow.ai/run/abc123{RESET}")
|
rnow/cli/main.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# reinforcenow/cli/main.py
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from rnow.cli.commands import download, init, login, logout, orgs, run, status, stop
|
|
6
|
+
from rnow.cli.test import test
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from importlib.metadata import version as get_version
|
|
10
|
+
|
|
11
|
+
__version__ = get_version("rnow")
|
|
12
|
+
except Exception:
|
|
13
|
+
__version__ = "unknown"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.group(context_settings={"help_option_names": ["-h", "--help"]})
|
|
17
|
+
@click.option("--api-url", default="https://www.reinforcenow.ai/api", hidden=True)
|
|
18
|
+
@click.option("--debug", is_flag=True, hidden=True)
|
|
19
|
+
@click.version_option(version=__version__, prog_name="rnow")
|
|
20
|
+
@click.pass_context
|
|
21
|
+
def cli(ctx, api_url, debug):
|
|
22
|
+
"""
|
|
23
|
+
\b
|
|
24
|
+
\033[1m\033[38;2;20;184;166mTrain language models with reinforcement learning.\033[0m
|
|
25
|
+
"""
|
|
26
|
+
ctx.ensure_object(dict)
|
|
27
|
+
ctx.obj["api_url"] = api_url
|
|
28
|
+
ctx.obj["debug"] = debug
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Add commands
|
|
32
|
+
cli.add_command(login)
|
|
33
|
+
cli.add_command(logout)
|
|
34
|
+
cli.add_command(status)
|
|
35
|
+
cli.add_command(orgs)
|
|
36
|
+
cli.add_command(init)
|
|
37
|
+
cli.add_command(run)
|
|
38
|
+
cli.add_command(stop)
|
|
39
|
+
cli.add_command(download)
|
|
40
|
+
cli.add_command(test)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def main():
|
|
44
|
+
"""Entry point."""
|
|
45
|
+
cli(auto_envvar_prefix="REINFORCE")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
main()
|