simonbb 0.0.4__tar.gz → 0.0.5__tar.gz
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.
- {simonbb-0.0.4 → simonbb-0.0.5}/PKG-INFO +3 -2
- {simonbb-0.0.4 → simonbb-0.0.5}/pyproject.toml +3 -2
- simonbb-0.0.5/src/simonbb/cis433/wrappers.py +100 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/utils.py +112 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/LICENSE +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/README.md +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/__init__.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/__init__.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/actions.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/agent.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/bert.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/experience.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/gpt.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/ignite.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/transformer.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis433/utils.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis438/__init__.py +0 -0
- {simonbb-0.0.4 → simonbb-0.0.5}/src/simonbb/cis438/agentic.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simonbb
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary: A small package to facilitate teaching AI courses
|
|
3
|
+
Version: 0.0.5
|
|
4
|
+
Summary: A small package to facilitate teaching AI courses at business schools
|
|
5
5
|
Project-URL: Homepage, https://simonbb.com
|
|
6
6
|
Author-email: Huaxia Rui <huaxia.rui@simon.rochester.edu>
|
|
7
7
|
License-Expression: MIT
|
|
@@ -21,6 +21,7 @@ Requires-Dist: numpy~=2.4.0
|
|
|
21
21
|
Requires-Dist: pytorch-ignite~=0.5.4
|
|
22
22
|
Requires-Dist: pyyaml~=6.0.3
|
|
23
23
|
Requires-Dist: sentence-transformers~=5.3.0
|
|
24
|
+
Requires-Dist: stable-baselines3~=2.9.0
|
|
24
25
|
Requires-Dist: torchvision~=0.24.1
|
|
25
26
|
Requires-Dist: torch~=2.9.1
|
|
26
27
|
Requires-Dist: transformers~=4.57.3
|
|
@@ -4,11 +4,11 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "simonbb"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.5"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Huaxia Rui", email="huaxia.rui@simon.rochester.edu" },
|
|
10
10
|
]
|
|
11
|
-
description = "A small package to facilitate teaching AI courses"
|
|
11
|
+
description = "A small package to facilitate teaching AI courses at business schools"
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.9"
|
|
14
14
|
classifiers = [
|
|
@@ -32,6 +32,7 @@ dependencies = [
|
|
|
32
32
|
"sentence-transformers~=5.3.0",
|
|
33
33
|
"gymnasium~=1.3.0",
|
|
34
34
|
"pytorch-ignite~=0.5.4",
|
|
35
|
+
"stable_baselines3~=2.9.0",
|
|
35
36
|
"pyyaml~=6.0.3"
|
|
36
37
|
]
|
|
37
38
|
[project.urls]
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import typing as tt
|
|
2
|
+
import gymnasium as gym
|
|
3
|
+
from gymnasium import spaces
|
|
4
|
+
import collections
|
|
5
|
+
import numpy as np
|
|
6
|
+
from stable_baselines3.common import atari_wrappers
|
|
7
|
+
|
|
8
|
+
class ImageToPyTorch(gym.ObservationWrapper):
|
|
9
|
+
def __init__(self, env):
|
|
10
|
+
super(ImageToPyTorch, self).__init__(env)
|
|
11
|
+
obs = self.observation_space
|
|
12
|
+
assert isinstance(obs, gym.spaces.Box)
|
|
13
|
+
assert len(obs.shape) == 3
|
|
14
|
+
new_shape = (obs.shape[-1], obs.shape[0], obs.shape[1])
|
|
15
|
+
self.observation_space = gym.spaces.Box(
|
|
16
|
+
low=obs.low.min(), high=obs.high.max(),
|
|
17
|
+
shape=new_shape, dtype=obs.dtype)
|
|
18
|
+
|
|
19
|
+
def observation(self, observation):
|
|
20
|
+
return np.moveaxis(observation, 2, 0)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class FrameStack1D(gym.Wrapper):
|
|
24
|
+
"""
|
|
25
|
+
Stacks observations into 1D array
|
|
26
|
+
"""
|
|
27
|
+
def __init__(self, env, k):
|
|
28
|
+
assert isinstance(env, gym.Env)
|
|
29
|
+
assert isinstance(env.observation_space, gym.spaces.Box)
|
|
30
|
+
assert len(env.observation_space.shape) == 1
|
|
31
|
+
super(FrameStack1D, self).__init__(env)
|
|
32
|
+
self.k = k
|
|
33
|
+
self.frames = collections.deque(maxlen=k)
|
|
34
|
+
shp = env.observation_space.shape
|
|
35
|
+
self.observation_space = gym.spaces.Box(
|
|
36
|
+
low=np.min(env.observation_space.low),
|
|
37
|
+
high=np.max(env.observation_space.high),
|
|
38
|
+
shape=(env.observation_space.shape[0]*k,),
|
|
39
|
+
dtype=env.observation_space.dtype)
|
|
40
|
+
|
|
41
|
+
def reset(self):
|
|
42
|
+
ob, extra = self.env.reset()
|
|
43
|
+
for _ in range(self.k):
|
|
44
|
+
self.frames.append(ob)
|
|
45
|
+
return self._get_ob(), extra
|
|
46
|
+
|
|
47
|
+
def step(self, action):
|
|
48
|
+
ob, reward, done, trunc, info = self.env.step(action)
|
|
49
|
+
self.frames.append(ob)
|
|
50
|
+
return self._get_ob(), reward, done, trunc, info
|
|
51
|
+
|
|
52
|
+
def _get_ob(self):
|
|
53
|
+
assert len(self.frames) == self.k
|
|
54
|
+
return np.concatenate(self.frames)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class BufferWrapper(gym.ObservationWrapper):
|
|
59
|
+
def __init__(self, env, n_steps):
|
|
60
|
+
super(BufferWrapper, self).__init__(env)
|
|
61
|
+
obs = env.observation_space
|
|
62
|
+
assert isinstance(obs, spaces.Box)
|
|
63
|
+
new_obs = gym.spaces.Box(
|
|
64
|
+
obs.low.repeat(n_steps, axis=0),
|
|
65
|
+
obs.high.repeat(n_steps, axis=0), dtype=obs.dtype)
|
|
66
|
+
self.observation_space = new_obs
|
|
67
|
+
self.buffer = collections.deque(maxlen=n_steps)
|
|
68
|
+
|
|
69
|
+
def reset(self, *, seed: tt.Optional[int] = None,
|
|
70
|
+
options: tt.Optional[dict[str, tt.Any]] = None):
|
|
71
|
+
for _ in range(self.buffer.maxlen-1):
|
|
72
|
+
self.buffer.append(self.env.observation_space.low)
|
|
73
|
+
obs, extra = self.env.reset()
|
|
74
|
+
return self.observation(obs), extra
|
|
75
|
+
|
|
76
|
+
def observation(self, observation: np.ndarray) -> np.ndarray:
|
|
77
|
+
self.buffer.append(observation)
|
|
78
|
+
return np.concatenate(self.buffer)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def wrap_dqn(env: gym.Env, stack_frames: int = 4,
|
|
82
|
+
episodic_life: bool = True, clip_reward: bool = True,
|
|
83
|
+
noop_max: int = 0) -> gym.Env:
|
|
84
|
+
"""
|
|
85
|
+
Apply a common set of wrappers for Atari games.
|
|
86
|
+
:param env: Environment to wrap
|
|
87
|
+
:param stack_frames: count of frames to stack, default=4
|
|
88
|
+
:param episodic_life: convert life to end of episode
|
|
89
|
+
:param clip_reward: reward clipping
|
|
90
|
+
:param noop_max: how many NOOP actions to execute
|
|
91
|
+
:return: wrapped environment
|
|
92
|
+
"""
|
|
93
|
+
assert 'NoFrameskip' in env.spec.id
|
|
94
|
+
env = atari_wrappers.AtariWrapper(
|
|
95
|
+
env, clip_reward=clip_reward, noop_max=noop_max,
|
|
96
|
+
terminal_on_life_loss=episodic_life)
|
|
97
|
+
env = ImageToPyTorch(env)
|
|
98
|
+
env = BufferWrapper(env, stack_frames)
|
|
99
|
+
return env
|
|
100
|
+
|
|
@@ -1,11 +1,32 @@
|
|
|
1
|
+
import time
|
|
1
2
|
import re
|
|
3
|
+
import collections
|
|
4
|
+
import sys
|
|
2
5
|
import pickle
|
|
3
6
|
import json
|
|
4
7
|
from collections import Counter
|
|
5
8
|
import urllib.request
|
|
6
9
|
import numpy as np
|
|
10
|
+
import torch
|
|
11
|
+
import torch.nn as nn
|
|
7
12
|
|
|
13
|
+
class WeightedMSELoss(nn.Module):
|
|
14
|
+
def __init__(self, size_average=True):
|
|
15
|
+
super(WeightedMSELoss, self).__init__()
|
|
16
|
+
self.size_average = size_average
|
|
8
17
|
|
|
18
|
+
def forward(self, input, target, weights=None):
|
|
19
|
+
if weights is None:
|
|
20
|
+
return nn.MSELoss(self.size_average)(input, target)
|
|
21
|
+
|
|
22
|
+
loss_rows = (input - target) ** 2
|
|
23
|
+
if len(loss_rows.size()) != 1:
|
|
24
|
+
loss_rows = torch.sum(loss_rows, dim=1)
|
|
25
|
+
res = (weights * loss_rows).sum()
|
|
26
|
+
if self.size_average:
|
|
27
|
+
res /= len(weights)
|
|
28
|
+
return res
|
|
29
|
+
|
|
9
30
|
class TextVectorizer:
|
|
10
31
|
def __init__(self, max_tokens=20000, output_mode="int", output_sequence_length=None, ngrams=None, standardize=None):
|
|
11
32
|
self.max_tokens = max_tokens
|
|
@@ -123,6 +144,97 @@ class TextVectorizer:
|
|
|
123
144
|
return vectorizer
|
|
124
145
|
|
|
125
146
|
|
|
147
|
+
|
|
148
|
+
class TBMeanTracker:
|
|
149
|
+
"""
|
|
150
|
+
TensorBoard value tracker: allows to batch fixed amount of historical values and write their mean into TB
|
|
151
|
+
|
|
152
|
+
Designed and tested with pytorch-tensorboard in mind
|
|
153
|
+
"""
|
|
154
|
+
def __init__(self, writer, batch_size):
|
|
155
|
+
"""
|
|
156
|
+
:param writer: writer with close() and add_scalar() methods
|
|
157
|
+
:param batch_size: integer size of batch to track
|
|
158
|
+
"""
|
|
159
|
+
assert isinstance(batch_size, int)
|
|
160
|
+
assert writer is not None
|
|
161
|
+
self.writer = writer
|
|
162
|
+
self.batch_size = batch_size
|
|
163
|
+
|
|
164
|
+
def __enter__(self):
|
|
165
|
+
self._batches = collections.defaultdict(list)
|
|
166
|
+
return self
|
|
167
|
+
|
|
168
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
169
|
+
self.writer.close()
|
|
170
|
+
|
|
171
|
+
@staticmethod
|
|
172
|
+
def _as_float(value):
|
|
173
|
+
assert isinstance(value, (float, int, np.ndarray, np.generic, torch.autograd.Variable)) or torch.is_tensor(value)
|
|
174
|
+
tensor_val = None
|
|
175
|
+
if isinstance(value, torch.autograd.Variable):
|
|
176
|
+
tensor_val = value.data
|
|
177
|
+
elif torch.is_tensor(value):
|
|
178
|
+
tensor_val = value
|
|
179
|
+
|
|
180
|
+
if tensor_val is not None:
|
|
181
|
+
return tensor_val.float().mean().item()
|
|
182
|
+
elif isinstance(value, np.ndarray):
|
|
183
|
+
return float(np.mean(value))
|
|
184
|
+
else:
|
|
185
|
+
return float(value)
|
|
186
|
+
|
|
187
|
+
def track(self, param_name, value, iter_index):
|
|
188
|
+
assert isinstance(param_name, str)
|
|
189
|
+
assert isinstance(iter_index, int)
|
|
190
|
+
|
|
191
|
+
data = self._batches[param_name]
|
|
192
|
+
data.append(self._as_float(value))
|
|
193
|
+
|
|
194
|
+
if len(data) >= self.batch_size:
|
|
195
|
+
self.writer.add_scalar(param_name, np.mean(data), iter_index)
|
|
196
|
+
data.clear()
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class RewardTracker:
|
|
200
|
+
def __init__(self, writer, min_ts_diff=1.0):
|
|
201
|
+
"""
|
|
202
|
+
Constructs RewardTracker
|
|
203
|
+
:param writer: writer to use for writing stats
|
|
204
|
+
:param min_ts_diff: minimal time difference to track speed
|
|
205
|
+
"""
|
|
206
|
+
self.writer = writer
|
|
207
|
+
self.min_ts_diff = min_ts_diff
|
|
208
|
+
|
|
209
|
+
def __enter__(self):
|
|
210
|
+
self.ts = time.time()
|
|
211
|
+
self.ts_frame = 0
|
|
212
|
+
self.total_rewards = []
|
|
213
|
+
return self
|
|
214
|
+
|
|
215
|
+
def __exit__(self, *args):
|
|
216
|
+
self.writer.close()
|
|
217
|
+
|
|
218
|
+
def reward(self, reward, frame, epsilon=None):
|
|
219
|
+
self.total_rewards.append(reward)
|
|
220
|
+
mean_reward = np.mean(self.total_rewards[-100:])
|
|
221
|
+
ts_diff = time.time() - self.ts
|
|
222
|
+
if ts_diff > self.min_ts_diff:
|
|
223
|
+
speed = (frame - self.ts_frame) / ts_diff
|
|
224
|
+
self.ts_frame = frame
|
|
225
|
+
self.ts = time.time()
|
|
226
|
+
epsilon_str = "" if epsilon is None else ", eps %.2f" % epsilon
|
|
227
|
+
print("%d: done %d episodes, mean reward %.3f, speed %.2f f/s%s" % (
|
|
228
|
+
frame, len(self.total_rewards), mean_reward, speed, epsilon_str
|
|
229
|
+
))
|
|
230
|
+
sys.stdout.flush()
|
|
231
|
+
self.writer.add_scalar("speed", speed, frame)
|
|
232
|
+
if epsilon is not None:
|
|
233
|
+
self.writer.add_scalar("epsilon", epsilon, frame)
|
|
234
|
+
self.writer.add_scalar("reward_100", mean_reward, frame)
|
|
235
|
+
self.writer.add_scalar("reward", reward, frame)
|
|
236
|
+
return mean_reward if len(self.total_rewards) > 30 else None
|
|
237
|
+
|
|
126
238
|
def query_ollama(prompt, model="llama3", url="http://localhost:11434/api/chat"):
|
|
127
239
|
# Create the data payload as a dictionary
|
|
128
240
|
data = {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|