File size: 2,851 Bytes
7c6ffa6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
"""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)  # noqa: E731

    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())