k8math 0.1.0__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.
- k8math-0.1.0/LICENSE.md +19 -0
- k8math-0.1.0/PKG-INFO +93 -0
- k8math-0.1.0/README.md +67 -0
- k8math-0.1.0/pyproject.toml +55 -0
- k8math-0.1.0/pyproject.toml.orig +36 -0
- k8math-0.1.0/src/k8math/__init__.py +2 -0
- k8math-0.1.0/src/k8math/cli.py +67 -0
- k8math-0.1.0/src/k8math/core.py +172 -0
- k8math-0.1.0/src/k8math/py.typed +0 -0
k8math-0.1.0/LICENSE.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright © 2026 Ramiro Santa Ana Anguiano
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
+
this software and associated documentation files (the “Software”), to deal in
|
|
5
|
+
the Software without restriction, including without limitation the rights to
|
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
8
|
+
so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
k8math-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: k8math
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generate math word problems with AI
|
|
5
|
+
Keywords: k8math,ai,math,math word problem,generator
|
|
6
|
+
Author: ram
|
|
7
|
+
Author-email: ram <hi@colima.press>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE.md
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Education
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Education
|
|
17
|
+
Requires-Dist: anthropic>=1.2.0
|
|
18
|
+
Requires-Dist: simpleeval>=1.0.7
|
|
19
|
+
Maintainer: ram
|
|
20
|
+
Maintainer-email: ram <hi@colima.press>
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Project-URL: Repository, https://gitlab.com/perritotuerto/codigo/k8math
|
|
23
|
+
Project-URL: Changelog, https://gitlab.com/perritotuerto/codigo/k8math/-/blob/main/CHANGELOG.md
|
|
24
|
+
Project-URL: Releases, https://gitlab.com/perritotuerto/codigo/k8math/-/releases
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# K8Math
|
|
28
|
+
|
|
29
|
+
Generate math word problems with AI.
|
|
30
|
+
|
|
31
|
+
**NOTE**. Requires Anthropic API key.
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
Generate wit CLI:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
uv run k8math -k $ANTHROPIC_API_KEY -l english "3 + 4 = 7"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Print help:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
uv run k8math -h
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Import as a module:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
import os
|
|
51
|
+
from k8math import K8Math
|
|
52
|
+
|
|
53
|
+
k8m = K8Math(
|
|
54
|
+
expressions=["3 + 4 = 7"],
|
|
55
|
+
api_key=os.environ.get("ANTHROPIC_API_KEY"),
|
|
56
|
+
language="english",
|
|
57
|
+
)
|
|
58
|
+
k8m.generate()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Development
|
|
62
|
+
|
|
63
|
+
Clone:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
git clone TODO
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Format:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
uv run ruff format .
|
|
73
|
+
uv run isort .
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Check:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
uv run ruff check .
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Test:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
uv run python -m pytest -s --durations 0
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Tag version:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
git tag v1.0.0
|
|
92
|
+
git push origin tag v1.0.0
|
|
93
|
+
```
|
k8math-0.1.0/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# K8Math
|
|
2
|
+
|
|
3
|
+
Generate math word problems with AI.
|
|
4
|
+
|
|
5
|
+
**NOTE**. Requires Anthropic API key.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Generate wit CLI:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
uv run k8math -k $ANTHROPIC_API_KEY -l english "3 + 4 = 7"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Print help:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
uv run k8math -h
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Import as a module:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
import os
|
|
25
|
+
from k8math import K8Math
|
|
26
|
+
|
|
27
|
+
k8m = K8Math(
|
|
28
|
+
expressions=["3 + 4 = 7"],
|
|
29
|
+
api_key=os.environ.get("ANTHROPIC_API_KEY"),
|
|
30
|
+
language="english",
|
|
31
|
+
)
|
|
32
|
+
k8m.generate()
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Development
|
|
36
|
+
|
|
37
|
+
Clone:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
git clone TODO
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Format:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
uv run ruff format .
|
|
47
|
+
uv run isort .
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Check:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
uv run ruff check .
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Test:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
uv run python -m pytest -s --durations 0
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Tag version:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
git tag v1.0.0
|
|
66
|
+
git push origin tag v1.0.0
|
|
67
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "k8math"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Generate math word problems with AI"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
keywords = [
|
|
7
|
+
"k8math",
|
|
8
|
+
"ai",
|
|
9
|
+
"math",
|
|
10
|
+
"math word problem",
|
|
11
|
+
"generator",
|
|
12
|
+
]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 3 - Alpha",
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Intended Audience :: Education",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Topic :: Education",
|
|
21
|
+
]
|
|
22
|
+
license = "MIT"
|
|
23
|
+
license-files = ["LICENSE.md"]
|
|
24
|
+
requires-python = ">=3.12"
|
|
25
|
+
dependencies = [
|
|
26
|
+
"anthropic>=1.2.0",
|
|
27
|
+
"simpleeval>=1.0.7",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[[project.authors]]
|
|
31
|
+
name = "ram"
|
|
32
|
+
email = "hi@colima.press"
|
|
33
|
+
|
|
34
|
+
[[project.maintainers]]
|
|
35
|
+
name = "ram"
|
|
36
|
+
email = "hi@colima.press"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
k8math = "k8math.cli:main"
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Repository = "https://gitlab.com/perritotuerto/codigo/k8math"
|
|
43
|
+
Changelog = "https://gitlab.com/perritotuerto/codigo/k8math/-/blob/main/CHANGELOG.md"
|
|
44
|
+
Releases = "https://gitlab.com/perritotuerto/codigo/k8math/-/releases"
|
|
45
|
+
|
|
46
|
+
[dependency-groups]
|
|
47
|
+
dev = [
|
|
48
|
+
"isort>=8.0.1",
|
|
49
|
+
"pytest>=9.0.3",
|
|
50
|
+
"ruff>=0.15.11",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[build-system]
|
|
54
|
+
requires = ["uv_build>=0.11.8,<0.13"]
|
|
55
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "k8math"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Generate math word problems with AI"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "ram", email = "hi@colima.press" }]
|
|
7
|
+
maintainers = [{ name = "ram", email = "hi@colima.press" }]
|
|
8
|
+
keywords = ["k8math", "ai", "math", "math word problem", "generator"]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Development Status :: 3 - Alpha",
|
|
11
|
+
"Environment :: Console",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"Intended Audience :: Education",
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.12",
|
|
16
|
+
"Topic :: Education",
|
|
17
|
+
]
|
|
18
|
+
license = "MIT"
|
|
19
|
+
license-files = ["LICENSE.md"]
|
|
20
|
+
requires-python = ">=3.12"
|
|
21
|
+
dependencies = ["anthropic>=1.2.0", "simpleeval>=1.0.7"]
|
|
22
|
+
|
|
23
|
+
[dependency-groups]
|
|
24
|
+
dev = ["isort>=8.0.1", "pytest>=9.0.3", "ruff>=0.15.11"]
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
k8math = "k8math.cli:main"
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Repository = "https://gitlab.com/perritotuerto/codigo/k8math"
|
|
31
|
+
Changelog = "https://gitlab.com/perritotuerto/codigo/k8math/-/blob/main/CHANGELOG.md"
|
|
32
|
+
Releases = "https://gitlab.com/perritotuerto/codigo/k8math/-/releases"
|
|
33
|
+
|
|
34
|
+
[build-system]
|
|
35
|
+
requires = ["uv_build>=0.11.8,<0.13"]
|
|
36
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from k8math.core import K8Math
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def main() -> None:
|
|
8
|
+
parser = argparse.ArgumentParser(
|
|
9
|
+
prog=Path(__file__).stem,
|
|
10
|
+
description="Generate math word problems with AI",
|
|
11
|
+
epilog="hi@colima.press",
|
|
12
|
+
)
|
|
13
|
+
parser.add_argument(
|
|
14
|
+
"math_expressions",
|
|
15
|
+
help="one or more math expressions; e.g., '1 * 2 / 2 = 1'",
|
|
16
|
+
metavar="EXP",
|
|
17
|
+
nargs="+",
|
|
18
|
+
)
|
|
19
|
+
parser.add_argument(
|
|
20
|
+
"-k",
|
|
21
|
+
"--key",
|
|
22
|
+
help="Anthropic API key",
|
|
23
|
+
metavar="KEY",
|
|
24
|
+
required=True,
|
|
25
|
+
)
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"-l",
|
|
28
|
+
"--language",
|
|
29
|
+
help="problem language",
|
|
30
|
+
metavar="LANG",
|
|
31
|
+
choices=["english", "spanish"],
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"-s",
|
|
35
|
+
"--subject",
|
|
36
|
+
help="one or more subjects",
|
|
37
|
+
metavar="SUBJ",
|
|
38
|
+
action="append",
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"-o",
|
|
42
|
+
"--object",
|
|
43
|
+
help="one or more objects",
|
|
44
|
+
metavar="OBJ",
|
|
45
|
+
action="append",
|
|
46
|
+
)
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
"-v",
|
|
49
|
+
"--verb",
|
|
50
|
+
help="one or more verbs",
|
|
51
|
+
metavar="VERB",
|
|
52
|
+
action="append",
|
|
53
|
+
)
|
|
54
|
+
args = parser.parse_args()
|
|
55
|
+
k8m = K8Math(
|
|
56
|
+
expressions=args.math_expressions,
|
|
57
|
+
api_key=args.key,
|
|
58
|
+
language=args.language,
|
|
59
|
+
subjects=args.subject,
|
|
60
|
+
objects=args.object,
|
|
61
|
+
verbs=args.verb,
|
|
62
|
+
)
|
|
63
|
+
k8m.generate()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
main()
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import json
|
|
3
|
+
import tokenize
|
|
4
|
+
|
|
5
|
+
from anthropic import Anthropic
|
|
6
|
+
from simpleeval import simple_eval
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class K8Math:
|
|
10
|
+
MODEL = "claude-haiku-4-5-20251001" # cheapest with structured-output
|
|
11
|
+
SCHEMA = { # noqa: RUF012
|
|
12
|
+
"type": "array",
|
|
13
|
+
"items": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"text": {"type": "string"},
|
|
17
|
+
"index": {"type": "integer"},
|
|
18
|
+
"num": {"type": "number"},
|
|
19
|
+
"op": {"enum": ["+", "-", "*", "/"]},
|
|
20
|
+
"par": {"enum": ["(", ")"]},
|
|
21
|
+
"subject": {"type": "string"},
|
|
22
|
+
"subject_in_text": {"type": "string"},
|
|
23
|
+
"object": {"type": "string"},
|
|
24
|
+
"object_in_text": {"type": "string"},
|
|
25
|
+
"verb": {"type": "string"},
|
|
26
|
+
"verb_in_text": {"type": "string"},
|
|
27
|
+
},
|
|
28
|
+
"additionalProperties": False,
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
SYSTEM_PROMPT = """
|
|
32
|
+
You write short kinder and elementary-school (K-8) word problems encoded as a
|
|
33
|
+
JSON array.
|
|
34
|
+
|
|
35
|
+
Rules:
|
|
36
|
+
- Reproduce every given math token exactly (same num/op/par value, same index).
|
|
37
|
+
- NEVER alter, add, or remove a math token.
|
|
38
|
+
- Every object except "par" objects must have a non-empty "text".
|
|
39
|
+
- "par" objects never have "text" and never appear in the narrated sentence.
|
|
40
|
+
- "subject", "object" and "verb" objects have to appear at least once in "text"
|
|
41
|
+
- Every "*_in_text" field must be a literal substring of that same object's
|
|
42
|
+
"text".
|
|
43
|
+
- The verb may be conjugated freely in "verb_in_text" regardless of the form
|
|
44
|
+
given in "verb".
|
|
45
|
+
- If the change described is small or trivial (like going from 1 to 2), phrase
|
|
46
|
+
it the way someone would naturally say it in conversation — don't reach for
|
|
47
|
+
formal math language like 'doubles' or 'multiplies by' when a simpler phrase
|
|
48
|
+
fits better.
|
|
49
|
+
- MUST make sense in real world and it should not seem like a verbose math
|
|
50
|
+
expression.
|
|
51
|
+
- ATTACH every number to a concrete, countable noun the reader can picture.
|
|
52
|
+
- ALWAYS write naturally and for a kid.
|
|
53
|
+
- ALWAYS leave the punctuation, such as periods and commas, at the end of
|
|
54
|
+
"text".
|
|
55
|
+
- ALWAYS be clear and specific in what you ask.
|
|
56
|
+
- NEVER use the name of the operation.
|
|
57
|
+
- NEVER use dashes nor semicolons.
|
|
58
|
+
- NEVER hide a quantity behind a vague pronoun like 'it', 'them', or
|
|
59
|
+
'everything'.
|
|
60
|
+
- NEVER use the name of the math operator in the word problem.
|
|
61
|
+
- NEVER give the result and answer away.
|
|
62
|
+
- Respond with ONLY the JSON array. No explanation, no markdown, no code
|
|
63
|
+
fences.
|
|
64
|
+
|
|
65
|
+
Example 1:
|
|
66
|
+
Math tokens (reproduce exactly, with its order in "index"):
|
|
67
|
+
("9", "-", "7" "=", "2")
|
|
68
|
+
|
|
69
|
+
Output:
|
|
70
|
+
[
|
|
71
|
+
{"text":"Rosa","subject":"Rosa","subject_in_text":"Rosa"},
|
|
72
|
+
{"text":"has","verb":"have","verb_in_text":"has"},
|
|
73
|
+
{"text":"9","index":0,"num":9},
|
|
74
|
+
{"text":"apples.","object":"apple","object_in_text":"apples"},
|
|
75
|
+
{"text":"She","subject":"Rosa","subject_in_text":"She"},
|
|
76
|
+
{"text":"ate","index":1,"op":"-","verb":"eat","verb_in_text":"ate"},
|
|
77
|
+
{"text":"7.","index":2,"num":7},
|
|
78
|
+
{"text":"How many does she have left?"}
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
Example 2:
|
|
82
|
+
Math tokens (reproduce exactly, with its order in "index"):
|
|
83
|
+
("(", "3", "+", "7", ")", "/", "5", "=", "2")
|
|
84
|
+
|
|
85
|
+
Output:
|
|
86
|
+
[
|
|
87
|
+
{"text":"Tom","subject":"Tom","subject_in_text":"Tom"},
|
|
88
|
+
{"index":0,"par":"("},
|
|
89
|
+
{"text":"buys","verb":"buy","verb_in_text":"buys"},
|
|
90
|
+
{"text":"3","index":1,"num":3},
|
|
91
|
+
{"text":"boxes","object":"box","object_in_text":"boxes"},
|
|
92
|
+
{"text":"and","index":2,"op":"+"},
|
|
93
|
+
{"text":"7","index":3,"num":7},
|
|
94
|
+
{"text":"more boxes,","object":"box","object_in_text":"boxes"},
|
|
95
|
+
{"index":4,"par":")"},
|
|
96
|
+
{"text":"then splits them evenly among","index":5,"op":"/"},
|
|
97
|
+
{"text":"5","index":6,"num":5},
|
|
98
|
+
{"text":"friends. How many boxes does each friend get?"}
|
|
99
|
+
]
|
|
100
|
+
"""
|
|
101
|
+
USER_PROMPT = """
|
|
102
|
+
Math tokens (reproduce exactly, with its order in "index"): %s
|
|
103
|
+
|
|
104
|
+
Now produce the JSON array for a new, different word problem in
|
|
105
|
+
%s using these exact math tokens.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
def __init__( # noqa: PLR0913,PLR0917
|
|
109
|
+
self,
|
|
110
|
+
expressions: list[str] | tuple[str],
|
|
111
|
+
api_key: str,
|
|
112
|
+
language: str | None = None,
|
|
113
|
+
subjects: list | None = None,
|
|
114
|
+
objects: list | None = None,
|
|
115
|
+
verbs: list | None = None,
|
|
116
|
+
):
|
|
117
|
+
self.exps = [self._get_exp(exp) for exp in expressions]
|
|
118
|
+
self._key = api_key
|
|
119
|
+
self.lang = language if language else "english"
|
|
120
|
+
self.subjects = subjects
|
|
121
|
+
self.objects = objects
|
|
122
|
+
self.verbs = verbs
|
|
123
|
+
|
|
124
|
+
def _get_exp(self, raw_exp: str) -> tuple:
|
|
125
|
+
if "=" not in raw_exp:
|
|
126
|
+
raise ValueError(f"No equality symbol found in '{raw_exp}'")
|
|
127
|
+
tokens = tokenize.generate_tokens(io.StringIO(raw_exp).readline)
|
|
128
|
+
tokens = tuple(t.string for t in tokens if t.string.strip())
|
|
129
|
+
py_str = "".join(tuple("==" if t == "=" else t for t in tokens))
|
|
130
|
+
if not simple_eval(py_str):
|
|
131
|
+
raise ValueError(f"Invalid result '{raw_exp}'")
|
|
132
|
+
return tokens
|
|
133
|
+
|
|
134
|
+
def _get_prompt(self, exp: tuple, lang: str) -> str:
|
|
135
|
+
prompt = f"\n{exp}"
|
|
136
|
+
if self.subjects or self.objects or self.verbs:
|
|
137
|
+
prompt += "\n\nWith this content:"
|
|
138
|
+
if self.subjects:
|
|
139
|
+
prompt += f"\n- subjects: {self.subjects}"
|
|
140
|
+
if self.objects:
|
|
141
|
+
prompt += f"\n- objects: {self.objects}"
|
|
142
|
+
if self.verbs:
|
|
143
|
+
prompt += f"\n- verbs: {self.verbs}"
|
|
144
|
+
return self.USER_PROMPT % (prompt, lang)
|
|
145
|
+
|
|
146
|
+
def _print(self, tokens: list, math_expression: tuple):
|
|
147
|
+
problem = " ".join([t.get("text", "").strip() for t in tokens])
|
|
148
|
+
answer = " ".join(math_expression)
|
|
149
|
+
print(f"{problem}\n\nAnswer: {answer}")
|
|
150
|
+
|
|
151
|
+
def generate(self, language: str | None = None):
|
|
152
|
+
self.problems = []
|
|
153
|
+
lang = language if language else self.lang
|
|
154
|
+
client = Anthropic(api_key=self._key)
|
|
155
|
+
for exp in self.exps:
|
|
156
|
+
user_prompt = self._get_prompt(exp, lang)
|
|
157
|
+
response = client.messages.create(
|
|
158
|
+
model=self.MODEL,
|
|
159
|
+
max_tokens=1024,
|
|
160
|
+
system=self.SYSTEM_PROMPT,
|
|
161
|
+
messages=[{"role": "user", "content": user_prompt}],
|
|
162
|
+
output_config={
|
|
163
|
+
"format": {
|
|
164
|
+
"type": "json_schema",
|
|
165
|
+
"schema": self.SCHEMA,
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
)
|
|
169
|
+
text_block = next(b for b in response.content if b.type == "text")
|
|
170
|
+
parsed = json.loads(text_block.text)
|
|
171
|
+
self._print(parsed, exp)
|
|
172
|
+
self.problems.append(parsed)
|
|
File without changes
|