| """Regenerate only the specific missions that failed validation with thin content. |
| |
| Cheaper than re-running a whole chapter: reuses the same skeleton (title/hook/ |
| source_pages/focus_notes already on disk) and only calls the model for the |
| flagged mission_ids, with an extra reminder about the minimum note count. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import json |
| import sys |
| from pathlib import Path |
|
|
| ROOT = Path(__file__).resolve().parents[2] |
| sys.path.insert(0, str(ROOT / "backend" / "scripts")) |
|
|
| import importlib.util |
|
|
| spec = importlib.util.spec_from_file_location("blueprints", ROOT / "backend/scripts/generate_source_backed_science_blueprints.py") |
| mod = importlib.util.module_from_spec(spec) |
| spec.loader.exec_module(mod) |
|
|
| TARGETS = { |
| "bio-p1-c5": ["M2", "M10"], |
| "chem-p1-c2": ["M5"], |
| "chem-p1-c4": ["M4", "M7"], |
| "chem-p2-c6": ["M8"], |
| } |
|
|
|
|
| def main() -> int: |
| groq_key = mod.env_value("GROQ_API_KEY") |
| model = "meta-llama/llama-4-scout-17b-16e-instruct" |
| generate = lambda prompt: mod.call_groq(prompt, groq_key, model) |
|
|
| chapters_by_id = {chapter[0]: chapter for chapter in mod.CHAPTERS} |
| for chapter_id, mission_ids in TARGETS.items(): |
| chapter_id_, subject, title, markdown_file, first_page, last_page = chapters_by_id[chapter_id] |
| path = mod.OUTPUT / f"{chapter_id}.json" |
| data = json.loads(path.read_text(encoding="utf-8")) |
| markdown_path = mod.MARKDOWN / markdown_file |
| for mission in data["missions"]: |
| if mission["mission_id"] not in mission_ids: |
| continue |
| excerpt = mod.mission_excerpt(markdown_path, mission.get("source_pages") or [], first_page, last_page) |
| skeleton_like = { |
| "mission_id": mission["mission_id"], |
| "title": mission["title"], |
| "source_pages": mission.get("source_pages") or [first_page], |
| "hook": mission.get("hook", ""), |
| "focus_notes": "IMPORTANT: notebook_notes must contain at least 4 concise, distinct notes. " + mission.get("title", ""), |
| } |
| prompt = mod.mission_prompt_for(chapter_id, subject, title, first_page, last_page, markdown_file, excerpt, skeleton_like) |
| new_mission = mod.generate_with_retries(generate, prompt, chapter_id, f"patch {mission['mission_id']}") |
| mission.clear() |
| mission.update(new_mission) |
| print(f"[{chapter_id}] patched {skeleton_like['mission_id']}", flush=True) |
| path.write_text(json.dumps(data, indent=2, ensure_ascii=False) + "\n", encoding="utf-8") |
| issues = mod.validate(data, chapter_id, subject, title, first_page, last_page) |
| print(json.dumps({"chapter_id": chapter_id, "passed": not issues, "issues": issues}), flush=True) |
| return 0 |
|
|
|
|
| if __name__ == "__main__": |
| sys.exit(main()) |
|
|