simonbb 0.0.7__tar.gz → 0.0.9__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.7 → simonbb-0.0.9}/PKG-INFO +12 -19
- {simonbb-0.0.7 → simonbb-0.0.9}/pyproject.toml +12 -19
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/experience.py +2 -4
- simonbb-0.0.9/src/simonbb/cis433/math500.py +105 -0
- simonbb-0.0.9/src/simonbb/cis433/qwen3.py +639 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/utils.py +139 -0
- simonbb-0.0.9/src/simonbb/cis438/rag.py +455 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/utils.py +213 -0
- simonbb-0.0.7/src/simonbb/cis438/agentic.py +0 -260
- {simonbb-0.0.7 → simonbb-0.0.9}/LICENSE +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/README.md +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/__init__.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/__init__.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/actions.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/agent.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/bert.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/dqn.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/gpt.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/ignite.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/transformer.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis433/wrappers.py +0 -0
- {simonbb-0.0.7 → simonbb-0.0.9}/src/simonbb/cis438/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: simonbb
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.9
|
|
4
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>
|
|
@@ -9,24 +9,17 @@ License-File: LICENSE
|
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Requires-Python: >=3.9
|
|
12
|
-
Requires-Dist: gymnasium
|
|
13
|
-
Requires-Dist:
|
|
14
|
-
Requires-Dist:
|
|
15
|
-
Requires-Dist:
|
|
16
|
-
Requires-Dist:
|
|
17
|
-
Requires-Dist:
|
|
18
|
-
Requires-Dist:
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist: pyyaml~=6.0.3
|
|
24
|
-
Requires-Dist: ray~=2.56.0
|
|
25
|
-
Requires-Dist: sentence-transformers~=5.3.0
|
|
26
|
-
Requires-Dist: stable-baselines3~=2.9.0
|
|
27
|
-
Requires-Dist: torchvision~=0.24.1
|
|
28
|
-
Requires-Dist: torch~=2.9.1
|
|
29
|
-
Requires-Dist: transformers~=4.57.3
|
|
12
|
+
Requires-Dist: gymnasium>=1.3.0
|
|
13
|
+
Requires-Dist: matplotlib>=3.10.8
|
|
14
|
+
Requires-Dist: numpy>=2.4.0
|
|
15
|
+
Requires-Dist: opencv-python>=5.0.0.93
|
|
16
|
+
Requires-Dist: pytorch-ignite>=0.5.4
|
|
17
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
18
|
+
Requires-Dist: ray>=2.56.0
|
|
19
|
+
Requires-Dist: stable-baselines3>=2.9.0
|
|
20
|
+
Requires-Dist: torch>=2.9.1
|
|
21
|
+
Requires-Dist: torchvision>=0.24.1
|
|
22
|
+
Requires-Dist: transformers>=4.57.3
|
|
30
23
|
Description-Content-Type: text/markdown
|
|
31
24
|
|
|
32
25
|
# Background
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "simonbb"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.9"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Huaxia Rui", email="huaxia.rui@simon.rochester.edu" },
|
|
10
10
|
]
|
|
@@ -18,24 +18,17 @@ classifiers = [
|
|
|
18
18
|
license = "MIT"
|
|
19
19
|
license-files = ["LICEN[CS]E*"]
|
|
20
20
|
dependencies = [
|
|
21
|
-
"matplotlib
|
|
22
|
-
"torch
|
|
23
|
-
"torchvision
|
|
24
|
-
"numpy
|
|
25
|
-
"transformers
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"sentence-transformers~=5.3.0",
|
|
33
|
-
"gymnasium~=1.3.0",
|
|
34
|
-
"pytorch-ignite~=0.5.4",
|
|
35
|
-
"stable_baselines3~=2.9.0",
|
|
36
|
-
"ray~=2.56.0",
|
|
37
|
-
"opencv-python~=5.0.0.93",
|
|
38
|
-
"pyyaml~=6.0.3"
|
|
21
|
+
"matplotlib >= 3.10.8",
|
|
22
|
+
"torch >= 2.9.1",
|
|
23
|
+
"torchvision >=0.24.1",
|
|
24
|
+
"numpy >=2.4.0",
|
|
25
|
+
"transformers >= 4.57.3",
|
|
26
|
+
"gymnasium >= 1.3.0",
|
|
27
|
+
"pytorch-ignite >= 0.5.4",
|
|
28
|
+
"stable_baselines3 >= 2.9.0",
|
|
29
|
+
"ray >= 2.56.0",
|
|
30
|
+
"opencv-python >= 5.0.0.93",
|
|
31
|
+
"pyyaml >= 6.0.3"
|
|
39
32
|
]
|
|
40
33
|
[project.urls]
|
|
41
34
|
Homepage = "https://simonbb.com"
|
|
@@ -31,9 +31,7 @@ class ExperienceSource:
|
|
|
31
31
|
"""
|
|
32
32
|
Item = tt.Tuple[Experience, ...]
|
|
33
33
|
|
|
34
|
-
def __init__(self, env: gym.Env | tt.Collection[gym.Env], agent: BaseAgent,
|
|
35
|
-
steps_count: int = 2, steps_delta: int = 1,
|
|
36
|
-
env_seed: tt.Optional[int] = None):
|
|
34
|
+
def __init__(self, env: gym.Env | tt.Collection[gym.Env], agent: BaseAgent, steps_count: int = 2, steps_delta: int = 1, env_seed: tt.Optional[int] = None):
|
|
37
35
|
"""
|
|
38
36
|
Create simple experience source
|
|
39
37
|
:param env: environment or list of environments to be used
|
|
@@ -46,7 +44,7 @@ class ExperienceSource:
|
|
|
46
44
|
if isinstance(env, (list, tuple)):
|
|
47
45
|
self.pool = env
|
|
48
46
|
# do the check for the multiple copies passed
|
|
49
|
-
ids = set(id(e) for e in env)
|
|
47
|
+
ids = set(id(e) for e in env) # id() returns a unique, constant integer identifier for a specified object during its lifetime
|
|
50
48
|
if len(ids) < len(env):
|
|
51
49
|
raise ValueError("You passed single environment instance multiple times")
|
|
52
50
|
else:
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import re
|
|
5
|
+
import time
|
|
6
|
+
import json
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from ..utils import grade_math_answer, eta_progress_message
|
|
9
|
+
|
|
10
|
+
RE_NUMBER = re.compile( r"-?(?:\d+/\d+|\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)" )
|
|
11
|
+
def get_last_boxed(text):
|
|
12
|
+
# Find the last occurrence of "\boxed"
|
|
13
|
+
boxed_start_idx = text.rfind(r"\boxed")
|
|
14
|
+
if boxed_start_idx == -1:
|
|
15
|
+
return None
|
|
16
|
+
# Get position after "\boxed"
|
|
17
|
+
current_idx = boxed_start_idx + len(r"\boxed")
|
|
18
|
+
# Skip any whitespace after "\boxed"
|
|
19
|
+
while current_idx < len(text) and text[current_idx].isspace():
|
|
20
|
+
current_idx += 1
|
|
21
|
+
# Expect an opening brace "{"
|
|
22
|
+
if current_idx >= len(text) or text[current_idx] != "{":
|
|
23
|
+
return None
|
|
24
|
+
# Parse the braces with nesting
|
|
25
|
+
current_idx += 1
|
|
26
|
+
brace_depth = 1
|
|
27
|
+
content_start_idx = current_idx
|
|
28
|
+
while current_idx < len(text) and brace_depth > 0:
|
|
29
|
+
char = text[current_idx]
|
|
30
|
+
if char == "{":
|
|
31
|
+
brace_depth += 1
|
|
32
|
+
elif char == "}":
|
|
33
|
+
brace_depth -= 1
|
|
34
|
+
current_idx += 1
|
|
35
|
+
# Account for unbalanced braces
|
|
36
|
+
if brace_depth != 0:
|
|
37
|
+
return None
|
|
38
|
+
# Extract content inside the outermost braces
|
|
39
|
+
return text[content_start_idx:current_idx-1]
|
|
40
|
+
|
|
41
|
+
def extract_final_candidate(text, fallback="number_then_full"):
|
|
42
|
+
# Default return value if nothing matches
|
|
43
|
+
result = ""
|
|
44
|
+
if text:
|
|
45
|
+
boxed = get_last_boxed(text.strip()) # Prefer the last boxed expression if present
|
|
46
|
+
if boxed:
|
|
47
|
+
result = boxed.strip().strip("$ ")
|
|
48
|
+
# If no boxed expression, try fallback
|
|
49
|
+
elif fallback in ("number_then_full", "number_only"):
|
|
50
|
+
m = RE_NUMBER.findall(text)
|
|
51
|
+
if m: # Use last number
|
|
52
|
+
result = m[-1]
|
|
53
|
+
elif fallback == "number_then_full":
|
|
54
|
+
# Else return full text if no number found
|
|
55
|
+
result = text
|
|
56
|
+
return result
|
|
57
|
+
|
|
58
|
+
def render_prompt(prompt):
|
|
59
|
+
template = (
|
|
60
|
+
"You are a helpful math assistant.\n"
|
|
61
|
+
"Answer the question and write the final result on a new line as:\n"
|
|
62
|
+
"\\boxed{ANSWER}\n\n"
|
|
63
|
+
f"Question:\n{prompt}\n\nAnswer:"
|
|
64
|
+
)
|
|
65
|
+
return template
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def evaluate_math500_stream( model, tokenizer, device, generate_func, math_data, out_path=None, max_new_tokens=512, verbose=False ):
|
|
69
|
+
num_examples = len(math_data)
|
|
70
|
+
num_correct = 0
|
|
71
|
+
start_time = time.time()
|
|
72
|
+
with open(Path( out_path ), "w", encoding="utf-8") as f: # Save results for inspection
|
|
73
|
+
for i, row in enumerate(math_data, start=1):
|
|
74
|
+
prompt = render_prompt(row["problem"]) # 1. Apply prompt template
|
|
75
|
+
gen_text = generate_func( model=model, tokenizer=tokenizer, prompt=prompt, device=device, max_new_tokens=max_new_tokens, verbose=verbose )
|
|
76
|
+
extracted = extract_final_candidate( gen_text )
|
|
77
|
+
is_correct = grade_math_answer( extracted, row["answer"] )
|
|
78
|
+
num_correct += int(is_correct)
|
|
79
|
+
record = { # Record to be saved for inspection
|
|
80
|
+
"index": i,
|
|
81
|
+
"problem": row["problem"],
|
|
82
|
+
"gtruth_answer": row["answer"],
|
|
83
|
+
"generated_text": gen_text,
|
|
84
|
+
"extracted": extracted,
|
|
85
|
+
"correct": bool(is_correct),
|
|
86
|
+
}
|
|
87
|
+
f.write(json.dumps(record, ensure_ascii=False) + "\n")
|
|
88
|
+
|
|
89
|
+
progress_msg = eta_progress_message( processed=i, total=num_examples, start_time=start_time, show_eta=True, label="MATH-500" )
|
|
90
|
+
print(progress_msg, end="\r", flush=True)
|
|
91
|
+
if verbose: # Print responses during the generation process
|
|
92
|
+
print(
|
|
93
|
+
f"\n\n{'='*50}\n{progress_msg}\n"
|
|
94
|
+
f"{'='*50}\nExtracted: {extracted}\n"
|
|
95
|
+
f"Expected: {row['answer']}\n"
|
|
96
|
+
f"Correct so far: {num_correct}\n{'-'*50}"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Print summary information
|
|
100
|
+
seconds_elapsed = time.time() - start_time
|
|
101
|
+
acc = num_correct / num_examples if num_examples else 0.0
|
|
102
|
+
print(f"\nAccuracy: {acc*100:.1f}% ({num_correct}/{num_examples})")
|
|
103
|
+
print(f"Total time: {seconds_elapsed/60:.1f} min")
|
|
104
|
+
print(f"Logs written to: {out_path}")
|
|
105
|
+
return num_correct, num_examples, acc
|