@laitszkin/apollo-toolkit 2.9.0 → 2.10.0
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.
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +11 -0
- package/README.md +2 -0
- package/document-vision-reader/LICENSE +21 -0
- package/document-vision-reader/README.md +66 -0
- package/document-vision-reader/SKILL.md +151 -0
- package/document-vision-reader/agents/openai.yaml +4 -0
- package/document-vision-reader/references/legibility-checklist.md +13 -0
- package/document-vision-reader/references/rendering-guide.md +37 -0
- package/katex/SKILL.md +92 -0
- package/katex/agents/openai.yaml +4 -0
- package/katex/references/insertion-patterns.md +54 -0
- package/katex/references/official-docs.md +35 -0
- package/katex/scripts/render_katex.py +247 -0
- package/katex/scripts/render_katex.sh +11 -0
- package/learning-error-book/SKILL.md +46 -31
- package/learning-error-book/agents/openai.yaml +2 -2
- package/learning-error-book/assets/long_question_reference_template.json +57 -0
- package/learning-error-book/assets/mc_question_reference_template.json +49 -0
- package/learning-error-book/scripts/render_error_book_json_to_pdf.py +590 -0
- package/package.json +1 -1
- package/learning-error-book/assets/error_book_template.md +0 -66
- package/learning-error-book/scripts/render_markdown_to_pdf.py +0 -367
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Render TeX formulas with the official KaTeX CLI and wrap the output for reuse."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
import os
|
|
9
|
+
import pathlib
|
|
10
|
+
import subprocess
|
|
11
|
+
import sys
|
|
12
|
+
import tempfile
|
|
13
|
+
from typing import Iterable
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
DEFAULT_CSS_HREF = "https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.css"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class KatexRenderError(Exception):
|
|
20
|
+
"""User-facing error for rendering failures."""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def parse_args(argv: list[str]) -> argparse.Namespace:
|
|
24
|
+
parser = argparse.ArgumentParser(
|
|
25
|
+
prog="render_katex.py",
|
|
26
|
+
description="Render TeX with KaTeX and emit insertion-ready output.",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
input_group = parser.add_mutually_exclusive_group(required=True)
|
|
30
|
+
input_group.add_argument("--tex", help="Raw TeX expression without delimiters.")
|
|
31
|
+
input_group.add_argument("--input-file", help="Path to a UTF-8 text file containing raw TeX.")
|
|
32
|
+
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"--output-format",
|
|
35
|
+
choices=("html-fragment", "html-page", "markdown-inline", "markdown-block", "json"),
|
|
36
|
+
default="html-fragment",
|
|
37
|
+
help="How to wrap the rendered KaTeX output.",
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--katex-format",
|
|
41
|
+
choices=("html", "mathml", "htmlAndMathml"),
|
|
42
|
+
default="htmlAndMathml",
|
|
43
|
+
help="KaTeX internal output format.",
|
|
44
|
+
)
|
|
45
|
+
parser.add_argument("--display-mode", action="store_true", help="Render in display mode.")
|
|
46
|
+
parser.add_argument("--output-file", help="Write the wrapped output to a file.")
|
|
47
|
+
parser.add_argument("--css-href", default=DEFAULT_CSS_HREF, help="Stylesheet href for html-page/json output.")
|
|
48
|
+
parser.add_argument("--title", default="KaTeX Render", help="Document title for html-page output.")
|
|
49
|
+
parser.add_argument("--lang", default="en", help="HTML lang attribute for html-page output.")
|
|
50
|
+
|
|
51
|
+
parser.add_argument("--macro", action="append", default=[], help="Macro definition in NAME:VALUE form.")
|
|
52
|
+
parser.add_argument("--macro-file", help="Path to a JSON file mapping macro names to expansion strings.")
|
|
53
|
+
parser.add_argument("--error-color", help="Hex color or CSS color name for parse errors.")
|
|
54
|
+
parser.add_argument("--strict", help="KaTeX strict mode setting.")
|
|
55
|
+
parser.add_argument("--trust", help="KaTeX trust mode setting.")
|
|
56
|
+
parser.add_argument("--max-size", type=float, help="Maximum user-specified size in em.")
|
|
57
|
+
parser.add_argument("--max-expand", type=int, help="Maximum macro expansion count.")
|
|
58
|
+
parser.add_argument("--min-rule-thickness", type=float, help="Minimum rule thickness in em.")
|
|
59
|
+
parser.add_argument("--leqno", action="store_true", help="Render display equations with left equation numbers.")
|
|
60
|
+
parser.add_argument("--fleqn", action="store_true", help="Render display equations flush left.")
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
"--color-is-text-color",
|
|
63
|
+
action="store_true",
|
|
64
|
+
help="Interpret \\\\color like legacy text color behavior.",
|
|
65
|
+
)
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"--no-throw-on-error",
|
|
68
|
+
action="store_true",
|
|
69
|
+
help="Render invalid input with colored source text instead of failing.",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return parser.parse_args(argv)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def normalize_path(raw_path: str) -> pathlib.Path:
|
|
76
|
+
path = pathlib.Path(raw_path).expanduser()
|
|
77
|
+
if not path.is_absolute():
|
|
78
|
+
path = pathlib.Path.cwd() / path
|
|
79
|
+
return path.resolve()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def load_tex(args: argparse.Namespace) -> str:
|
|
83
|
+
if args.input_file:
|
|
84
|
+
path = normalize_path(args.input_file)
|
|
85
|
+
if not path.is_file():
|
|
86
|
+
raise KatexRenderError(f"Input file not found: {path}")
|
|
87
|
+
return path.read_text(encoding="utf-8").strip()
|
|
88
|
+
return (args.tex or "").strip()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def load_macro_pairs(values: Iterable[str]) -> list[tuple[str, str]]:
|
|
92
|
+
pairs: list[tuple[str, str]] = []
|
|
93
|
+
for raw_value in values:
|
|
94
|
+
if ":" not in raw_value:
|
|
95
|
+
raise KatexRenderError(f"Invalid --macro value '{raw_value}'. Use NAME:VALUE.")
|
|
96
|
+
name, expansion = raw_value.split(":", 1)
|
|
97
|
+
name = name.strip()
|
|
98
|
+
expansion = expansion.strip()
|
|
99
|
+
if not name or not expansion:
|
|
100
|
+
raise KatexRenderError(f"Invalid --macro value '{raw_value}'. Use NAME:VALUE.")
|
|
101
|
+
pairs.append((name, expansion))
|
|
102
|
+
return pairs
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def run_katex_cli(tex: str, args: argparse.Namespace) -> str:
|
|
106
|
+
command = [
|
|
107
|
+
"npx",
|
|
108
|
+
"--yes",
|
|
109
|
+
"--package",
|
|
110
|
+
"katex",
|
|
111
|
+
"katex",
|
|
112
|
+
"--format",
|
|
113
|
+
args.katex_format,
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
if args.display_mode:
|
|
117
|
+
command.append("--display-mode")
|
|
118
|
+
if args.leqno:
|
|
119
|
+
command.append("--leqno")
|
|
120
|
+
if args.fleqn:
|
|
121
|
+
command.append("--fleqn")
|
|
122
|
+
if args.color_is_text_color:
|
|
123
|
+
command.append("--color-is-text-color")
|
|
124
|
+
if args.no_throw_on_error:
|
|
125
|
+
command.append("--no-throw-on-error")
|
|
126
|
+
|
|
127
|
+
if args.error_color:
|
|
128
|
+
command.extend(["--error-color", args.error_color])
|
|
129
|
+
if args.strict:
|
|
130
|
+
command.extend(["--strict", args.strict])
|
|
131
|
+
if args.trust:
|
|
132
|
+
command.extend(["--trust", args.trust])
|
|
133
|
+
if args.max_size is not None:
|
|
134
|
+
command.extend(["--max-size", str(args.max_size)])
|
|
135
|
+
if args.max_expand is not None:
|
|
136
|
+
command.extend(["--max-expand", str(args.max_expand)])
|
|
137
|
+
if args.min_rule_thickness is not None:
|
|
138
|
+
command.extend(["--min-rule-thickness", str(args.min_rule_thickness)])
|
|
139
|
+
|
|
140
|
+
for name, expansion in load_macro_pairs(args.macro):
|
|
141
|
+
command.extend(["--macro", f"{name}:{expansion}"])
|
|
142
|
+
|
|
143
|
+
if args.macro_file:
|
|
144
|
+
macro_file = normalize_path(args.macro_file)
|
|
145
|
+
if not macro_file.is_file():
|
|
146
|
+
raise KatexRenderError(f"Macro file not found: {macro_file}")
|
|
147
|
+
command.extend(["--macro-file", str(macro_file)])
|
|
148
|
+
|
|
149
|
+
with tempfile.NamedTemporaryFile("w", suffix=".tex", encoding="utf-8", delete=False) as handle:
|
|
150
|
+
handle.write(tex)
|
|
151
|
+
handle.write("\n")
|
|
152
|
+
temp_path = pathlib.Path(handle.name)
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
command.extend(["--input", str(temp_path)])
|
|
156
|
+
result = subprocess.run(
|
|
157
|
+
command,
|
|
158
|
+
check=False,
|
|
159
|
+
capture_output=True,
|
|
160
|
+
text=True,
|
|
161
|
+
encoding="utf-8",
|
|
162
|
+
)
|
|
163
|
+
finally:
|
|
164
|
+
temp_path.unlink(missing_ok=True)
|
|
165
|
+
|
|
166
|
+
if result.returncode != 0:
|
|
167
|
+
stderr = result.stderr.strip() or "KaTeX CLI failed."
|
|
168
|
+
raise KatexRenderError(stderr)
|
|
169
|
+
|
|
170
|
+
return result.stdout.strip()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def build_html_page(rendered_html: str, args: argparse.Namespace) -> str:
|
|
174
|
+
css_link = ""
|
|
175
|
+
if args.css_href.strip():
|
|
176
|
+
css_link = f' <link rel="stylesheet" href="{args.css_href.strip()}">\n'
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
"<!DOCTYPE html>\n"
|
|
180
|
+
f'<html lang="{args.lang}">\n'
|
|
181
|
+
"<head>\n"
|
|
182
|
+
' <meta charset="utf-8">\n'
|
|
183
|
+
f" <title>{args.title}</title>\n"
|
|
184
|
+
f"{css_link}"
|
|
185
|
+
"</head>\n"
|
|
186
|
+
"<body>\n"
|
|
187
|
+
f"{rendered_html}\n"
|
|
188
|
+
"</body>\n"
|
|
189
|
+
"</html>\n"
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def wrap_output(rendered_html: str, tex: str, args: argparse.Namespace) -> str:
|
|
194
|
+
if args.output_format == "html-fragment":
|
|
195
|
+
return f"{rendered_html}\n"
|
|
196
|
+
if args.output_format == "html-page":
|
|
197
|
+
return build_html_page(rendered_html, args)
|
|
198
|
+
if args.output_format == "markdown-inline":
|
|
199
|
+
return f"{rendered_html}\n"
|
|
200
|
+
if args.output_format == "markdown-block":
|
|
201
|
+
return f"\n{rendered_html}\n"
|
|
202
|
+
if args.output_format == "json":
|
|
203
|
+
payload = {
|
|
204
|
+
"tex": tex,
|
|
205
|
+
"displayMode": args.display_mode,
|
|
206
|
+
"katexFormat": args.katex_format,
|
|
207
|
+
"cssHref": args.css_href,
|
|
208
|
+
"content": rendered_html,
|
|
209
|
+
}
|
|
210
|
+
return json.dumps(payload, ensure_ascii=False, indent=2) + "\n"
|
|
211
|
+
raise KatexRenderError(f"Unsupported output format: {args.output_format}")
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def write_output(content: str, output_file: str | None) -> None:
|
|
215
|
+
if not output_file:
|
|
216
|
+
sys.stdout.write(content)
|
|
217
|
+
return
|
|
218
|
+
|
|
219
|
+
path = normalize_path(output_file)
|
|
220
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
221
|
+
path.write_text(content, encoding="utf-8")
|
|
222
|
+
sys.stdout.write(str(path) + "\n")
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def main(argv: list[str]) -> int:
|
|
226
|
+
try:
|
|
227
|
+
args = parse_args(argv)
|
|
228
|
+
tex = load_tex(args)
|
|
229
|
+
if not tex:
|
|
230
|
+
raise KatexRenderError("Input TeX is empty.")
|
|
231
|
+
rendered_html = run_katex_cli(tex, args)
|
|
232
|
+
wrapped = wrap_output(rendered_html, tex, args)
|
|
233
|
+
write_output(wrapped, args.output_file)
|
|
234
|
+
return 0
|
|
235
|
+
except KatexRenderError as exc:
|
|
236
|
+
print(f"[ERROR] {exc}", file=sys.stderr)
|
|
237
|
+
return 1
|
|
238
|
+
except FileNotFoundError as exc:
|
|
239
|
+
missing = exc.filename or "required executable"
|
|
240
|
+
if os.path.basename(missing) in {"npx", "node"}:
|
|
241
|
+
print("[ERROR] node and npx are required to render KaTeX.", file=sys.stderr)
|
|
242
|
+
return 1
|
|
243
|
+
raise
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
if __name__ == "__main__":
|
|
247
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
5
|
+
|
|
6
|
+
if ! command -v python3 >/dev/null 2>&1; then
|
|
7
|
+
echo "[ERROR] python3 is required." >&2
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
exec python3 "$script_dir/render_katex.py" "$@"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: learning-error-book
|
|
3
|
-
description: A learning-focused error-book workflow. When the user asks to summarize mistakes, the agent summarizes mistakes made while solving questions
|
|
3
|
+
description: A learning-focused error-book workflow. When the user asks to summarize mistakes, the agent summarizes mistakes made while solving questions, writes structured reference data, and renders polished PDFs directly without Markdown as an intermediate.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Learning Error Book Skill
|
|
@@ -15,23 +15,27 @@ description: A learning-focused error-book workflow. When the user asks to summa
|
|
|
15
15
|
## Standards
|
|
16
16
|
|
|
17
17
|
- Evidence: Summarize mistakes only from traceable question sources, user attempts, and correct-answer evidence.
|
|
18
|
-
- Execution: Build an evidence table first,
|
|
18
|
+
- Execution: Build an evidence table first, write structured reference data, then render polished PDFs directly with Chinese-safe fonts.
|
|
19
19
|
- Quality: Explain mistake types, concept misunderstandings, and per-question solutions in a way that is specific, complete, and non-speculative.
|
|
20
|
-
- Output: Deliver
|
|
20
|
+
- Output: Deliver separate MC and long-question error books, each backed by its own reference file and rendered PDF.
|
|
21
21
|
|
|
22
|
-
Goal: when the user asks to "summarize mistakes / summarize errors / compile an error book",
|
|
22
|
+
Goal: when the user asks to "summarize mistakes / summarize errors / compile an error book", summarize mistakes with evidence and generate or update structured error-book data plus polished PDFs directly from that data.
|
|
23
23
|
|
|
24
24
|
## Behavior Contract (GIVEN/THEN)
|
|
25
25
|
|
|
26
|
-
GIVEN the user asks to
|
|
27
|
-
THEN the agent summarizes the user's mistakes made while solving questions
|
|
28
|
-
AND generates or updates
|
|
26
|
+
GIVEN the user asks to summarize mistakes/errors
|
|
27
|
+
THEN the agent summarizes the user's mistakes made while solving questions
|
|
28
|
+
AND generates or updates two error-book tracks when relevant:
|
|
29
|
+
- one for multiple-choice questions
|
|
30
|
+
- one for long-answer questions
|
|
31
|
+
AND each track includes:
|
|
29
32
|
- Coverage scope (which question files / sources are included)
|
|
30
33
|
- Common mistake types overview
|
|
31
34
|
- Conceptual mistake highlights (definition, user's common misjudgment, cautions)
|
|
32
35
|
- Mistake-by-mistake analysis and solutions
|
|
33
|
-
- For MC questions: explain why
|
|
34
|
-
|
|
36
|
+
- For MC questions: explain why each option is wrong/right, and why the correct option is correct
|
|
37
|
+
- For long-answer questions: compare the expected solution steps against the user's steps, show exactly where the divergence starts, and identify the key concepts involved
|
|
38
|
+
AND the delivered error books must be polished PDFs rendered directly from structured data, without Markdown as an intermediate.
|
|
35
39
|
|
|
36
40
|
## Trigger Conditions
|
|
37
41
|
|
|
@@ -52,61 +56,72 @@ If the PDF is scanned/image-based and text extraction fails:
|
|
|
52
56
|
|
|
53
57
|
## Output Spec (Required Sections)
|
|
54
58
|
|
|
55
|
-
The error
|
|
56
|
-
1)
|
|
57
|
-
2)
|
|
58
|
-
3)
|
|
59
|
+
The error books must contain:
|
|
60
|
+
1) Coverage Scope: which question files/sources are included (with paths; include page/question ids when available)
|
|
61
|
+
2) Common Mistake Types Overview: 3-8 categories (concept misunderstanding, misreading conditions, derivation/calculation error, option traps, etc.), with representative questions
|
|
62
|
+
3) Conceptual Mistake Highlights (per concept):
|
|
59
63
|
- Definition (precise and actionable)
|
|
60
64
|
- User's common misjudgment (mapped to concrete mistakes)
|
|
61
65
|
- Cautions / checklists to avoid repeating the mistake
|
|
62
|
-
4)
|
|
66
|
+
4) Per-Question Mistake & Solution:
|
|
63
67
|
- Traceable locator: file + page/question id
|
|
64
68
|
- User answer vs correct answer
|
|
65
69
|
- Why it's wrong (link back to mistake type + concept)
|
|
66
70
|
- Correct solution (step-by-step)
|
|
67
|
-
- For
|
|
71
|
+
- For MC: explain why each option is wrong/right, and why the correct option is correct
|
|
72
|
+
- For Long Question: compare each expected step with the user's corresponding step, explain the gap at each step, state the first incorrect step clearly, and list the key concepts that question depends on
|
|
68
73
|
|
|
69
74
|
Formats:
|
|
70
|
-
-
|
|
71
|
-
-
|
|
75
|
+
- MC reference: `error_book/references/mc-question-reference.json`
|
|
76
|
+
- Long-question reference: `error_book/references/long-question-reference.json`
|
|
77
|
+
- MC deliverable: `error_book/mc-question-error-book.pdf`
|
|
78
|
+
- Long-question deliverable: `error_book/long-question-error-book.pdf`
|
|
72
79
|
|
|
73
80
|
## Recommended File Layout (Keep It Consistent)
|
|
74
81
|
|
|
75
82
|
```text
|
|
76
83
|
error_book/
|
|
77
|
-
error-book.
|
|
78
|
-
error-book.pdf
|
|
84
|
+
mc-question-error-book.pdf
|
|
85
|
+
long-question-error-book.pdf
|
|
86
|
+
references/
|
|
87
|
+
mc-question-reference.json
|
|
88
|
+
long-question-reference.json
|
|
79
89
|
sources/ # optional: shortcuts/copies/list of source PDFs
|
|
80
90
|
```
|
|
81
91
|
|
|
82
92
|
## Workflow (Required)
|
|
83
93
|
|
|
84
|
-
1)
|
|
94
|
+
1) Determine coverage
|
|
85
95
|
- If the user provided files/question ids: add them to Coverage Scope
|
|
86
96
|
- If not: search the workspace for relevant PDFs and confirm with the user
|
|
87
97
|
|
|
88
|
-
2)
|
|
98
|
+
2) Extract question text + answers/explanations (extract when possible)
|
|
89
99
|
- Use the `pdf` skill (pypdf/pdfplumber/OCR as available)
|
|
90
100
|
- If extraction fails, request user-provided text/screenshots
|
|
91
101
|
|
|
92
|
-
3)
|
|
102
|
+
3) Build an evidence table before writing
|
|
93
103
|
- For each question: locator, user answer, correct answer, mistake type, concept(s), explanation
|
|
94
|
-
-
|
|
104
|
+
- For long-answer questions, also collect expected steps, user steps, step-by-step gaps, first wrong step, and key concepts
|
|
105
|
+
- Then map it into the required sections for the relevant track
|
|
95
106
|
|
|
96
|
-
4)
|
|
97
|
-
-
|
|
98
|
-
-
|
|
107
|
+
4) Generate/update structured reference files
|
|
108
|
+
- For MC questions: start from `assets/mc_question_reference_template.json`
|
|
109
|
+
- For long-answer questions: start from `assets/long_question_reference_template.json`
|
|
110
|
+
- If a reference file already exists: preserve existing entries, append new evidence, and refresh overview/concept sections
|
|
99
111
|
|
|
100
|
-
5)
|
|
112
|
+
5) Render structured data -> PDF (CJK font support)
|
|
101
113
|
- Run:
|
|
102
|
-
- `python3 learning-error-book/scripts/
|
|
114
|
+
- `python3 learning-error-book/scripts/render_error_book_json_to_pdf.py error_book/references/mc-question-reference.json error_book/mc-question-error-book.pdf`
|
|
115
|
+
- `python3 learning-error-book/scripts/render_error_book_json_to_pdf.py error_book/references/long-question-reference.json error_book/long-question-error-book.pdf`
|
|
103
116
|
- If paper size/font needs change: adjust script flags (`--help`)
|
|
104
117
|
|
|
105
118
|
## Built-in Template
|
|
106
119
|
|
|
107
|
-
- `assets/
|
|
120
|
+
- `assets/mc_question_reference_template.json`: MC error-book structured template
|
|
121
|
+
- `assets/long_question_reference_template.json`: long-answer error-book structured template
|
|
108
122
|
|
|
109
123
|
## Rendering Notes (Avoid Pitfalls)
|
|
110
124
|
|
|
111
|
-
-
|
|
112
|
-
- For
|
|
125
|
+
- Avoid lossy Markdown conversion. Keep symbols, formulas, and option text in the structured reference payload.
|
|
126
|
+
- For long-answer questions, preserve the original step granularity instead of merging multiple reasoning steps into one.
|
|
127
|
+
- Keep key-concept labels stable across questions so the concept summary can aggregate them cleanly.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Learning Error Book"
|
|
3
|
-
short_description: "Summarize mistakes into
|
|
4
|
-
default_prompt: "Use $learning-error-book to gather evidence about the user's mistakes, use $pdf whenever PDF extraction or OCR is needed, generate or update error_book/
|
|
3
|
+
short_description: "Summarize mistakes into structured MC and long-question error books"
|
|
4
|
+
default_prompt: "Use $learning-error-book to gather evidence about the user's mistakes, use $pdf whenever PDF extraction or OCR is needed, generate or update error_book/references/mc-question-reference.json and error_book/references/long-question-reference.json as applicable, then render polished PDFs directly to error_book/mc-question-error-book.pdf and error_book/long-question-error-book.pdf without using Markdown as an intermediate."
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"book_type": "long-question",
|
|
3
|
+
"title": "Long Question Error Book",
|
|
4
|
+
"last_updated": "YYYY-MM-DD",
|
|
5
|
+
"coverage_scope": [
|
|
6
|
+
{
|
|
7
|
+
"source_path": "",
|
|
8
|
+
"included_questions": [],
|
|
9
|
+
"notes": ""
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"mistake_overview": [
|
|
13
|
+
{
|
|
14
|
+
"type": "Incomplete derivation",
|
|
15
|
+
"summary": "",
|
|
16
|
+
"representative_questions": []
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"concept_highlights": [
|
|
20
|
+
{
|
|
21
|
+
"name": "",
|
|
22
|
+
"definition": "",
|
|
23
|
+
"common_misjudgment": "",
|
|
24
|
+
"checklist": []
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"questions": [
|
|
28
|
+
{
|
|
29
|
+
"question_id": "",
|
|
30
|
+
"source_path": "",
|
|
31
|
+
"page_or_locator": "",
|
|
32
|
+
"stem": "",
|
|
33
|
+
"user_answer": "",
|
|
34
|
+
"correct_answer": "",
|
|
35
|
+
"mistake_type": "",
|
|
36
|
+
"concepts": [],
|
|
37
|
+
"why_wrong": "",
|
|
38
|
+
"first_incorrect_step": "",
|
|
39
|
+
"key_concepts": [
|
|
40
|
+
{
|
|
41
|
+
"name": "",
|
|
42
|
+
"why_it_matters": ""
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"correct_solution_steps": [],
|
|
46
|
+
"step_comparison": [
|
|
47
|
+
{
|
|
48
|
+
"step_no": 1,
|
|
49
|
+
"expected_step": "",
|
|
50
|
+
"user_step": "",
|
|
51
|
+
"gap": "",
|
|
52
|
+
"fix": ""
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"book_type": "mc-question",
|
|
3
|
+
"title": "MC Question Error Book",
|
|
4
|
+
"last_updated": "YYYY-MM-DD",
|
|
5
|
+
"coverage_scope": [
|
|
6
|
+
{
|
|
7
|
+
"source_path": "",
|
|
8
|
+
"included_questions": [],
|
|
9
|
+
"notes": ""
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"mistake_overview": [
|
|
13
|
+
{
|
|
14
|
+
"type": "Concept misunderstanding",
|
|
15
|
+
"summary": "",
|
|
16
|
+
"representative_questions": []
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"concept_highlights": [
|
|
20
|
+
{
|
|
21
|
+
"name": "",
|
|
22
|
+
"definition": "",
|
|
23
|
+
"common_misjudgment": "",
|
|
24
|
+
"checklist": []
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"questions": [
|
|
28
|
+
{
|
|
29
|
+
"question_id": "",
|
|
30
|
+
"source_path": "",
|
|
31
|
+
"page_or_locator": "",
|
|
32
|
+
"stem": "",
|
|
33
|
+
"user_answer": "",
|
|
34
|
+
"correct_answer": "",
|
|
35
|
+
"mistake_type": "",
|
|
36
|
+
"concepts": [],
|
|
37
|
+
"why_wrong": "",
|
|
38
|
+
"correct_solution_steps": [],
|
|
39
|
+
"options": [
|
|
40
|
+
{
|
|
41
|
+
"label": "A",
|
|
42
|
+
"text": "",
|
|
43
|
+
"verdict": "wrong",
|
|
44
|
+
"reason": ""
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|