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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: simonbb
3
- Version: 0.0.7
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~=1.3.0
13
- Requires-Dist: langchain-chroma~=1.1.0
14
- Requires-Dist: langchain-community~=0.4.1
15
- Requires-Dist: langchain-core~=1.2.23
16
- Requires-Dist: langchain-huggingface~=1.2.1
17
- Requires-Dist: langchain~=1.2.13
18
- Requires-Dist: langgraph~=1.1.3
19
- Requires-Dist: matplotlib~=3.10.8
20
- Requires-Dist: numpy~=2.4.0
21
- Requires-Dist: opencv-python~=5.0.0.93
22
- Requires-Dist: pytorch-ignite~=0.5.4
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"
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~=3.10.8",
22
- "torch~=2.9.1",
23
- "torchvision~=0.24.1",
24
- "numpy~=2.4.0",
25
- "transformers~=4.57.3",
26
- "langchain-core~=1.2.23",
27
- "langchain~=1.2.13",
28
- "langgraph~=1.1.3",
29
- "langchain-community~=0.4.1",
30
- "langchain-chroma~=1.1.0",
31
- "langchain-huggingface~=1.2.1",
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