BuddyMath / micro_prompts.py
dotandru's picture
Fix: Clean production deployment with sse-starlette
9d29c62
# micro_prompts.py — Textbook JSON / Hebrew Centric
# Topic-specific micro-prompts for BuddyMath
# ALL TEMPLATES: enforce [{type: "text"|"math", content: "..."}] JSON only.
# ZERO mentions of ctx, sp, sympy, MathEngine, or Python.
"""
Micro-Prompt Library
Each entry adds topic-specific focus on TOP of the specialist prompt in prompts.py.
The specialist prompt already defines the full Textbook JSON schema — these just
focus the LLM on which formula/technique to use.
"""
import json # needed by get_general_prompt
# ==================== MICRO-PROMPT TEMPLATES ====================
# Each template is a SHORT topic-focused instruction.
# It is prepended to the full specialist prompt (which already has the JSON schema).
# DO NOT add any output format instructions here — the specialist prompt handles that.
MICRO_PROMPTS = {
# ========== GEOMETRY ==========
"CIRCLE_EQUATION": {
"template": """🎯 נושא: משוואת מעגל / מקום גיאומטרי
השתמש בנוסחה: (x-a)² + (y-b)² = r²
זהה: מרכז (a,b) ורדיוס r מהנתונים. הצב. פשט. הגדר.</p>""",
"tokens": 60,
"requires": []
},
"CIRCLE_TANGENT": {
"template": """🎯 נושא: משיק למעגל בנקודה
שלב 1: בדוק שהנקודה על המעגל.
שלב 2: מצא שיפוע הרדיוס (מהמרכז לנקודה).
שלב 3: שיפוע המשיק = -1 / שיפוע הרדיוס (מאונך). כתוב משוואת ישר.""",
"tokens": 70,
"requires": []
},
"TRIANGLE_AREA": {
"template": """🎯 נושא: שטח משולש
נוסחה: S = ½ × בסיס × גובה. הצב וחשב.""",
"tokens": 40,
"requires": []
},
"LINE_EQUATION": {
"template": """🎯 נושא: משוואת ישר
מצא שיפוע m ונקודת חיתוך b. כתוב: y = mx + b.""",
"tokens": 40,
"requires": []
},
"LINE_PERPENDICULAR": {
"template": """🎯 נושא: ישר מאונך
כלל: m₁ × m₂ = -1. מצא שיפוע המאונך, הצב נקודה, כתוב משוואה.""",
"tokens": 50,
"requires": []
},
"DISTANCE_FORMULA": {
"template": """🎯 נושא: מרחק בין שתי נקודות
נוסחה: d = √[(x₂-x₁)² + (y₂-y₁)²]. הצב מספרים. פשט.""",
"tokens": 50,
"requires": []
},
# ========== CALCULUS ==========
"DERIVATIVE_POWER": {
"template": """🎯 נושא: נגזרת — כלל החזקה
כלל: (xⁿ)' = n·xⁿ⁻¹. גזור כל איבר בנפרד. פשט.""",
"tokens": 50,
"requires": []
},
"DERIVATIVE_QUOTIENT": {
"template": """🎯 נושא: נגזרת — כלל המנה
כלל: (u/v)' = (u'v - uv') / v². זהה u ו-v. גזור כל אחד. הצב.""",
"tokens": 60,
"requires": []
},
"DERIVATIVE_PRODUCT": {
"template": """🎯 נושא: נגזרת — כלל המכפלה
כלל: (u·v)' = u'v + uv'. זהה u ו-v. גזור כל אחד. הצב.""",
"tokens": 60,
"requires": []
},
"DERIVATIVE_CHAIN": {
"template": """🎯 נושא: נגזרת — כלל השרשרת
כלל: [f(g(x))]' = f'(g(x)) · g'(x). זהה פונקציה חיצונית ופנימית. גזור.""",
"tokens": 70,
"requires": []
},
"INVESTIGATION_EXTREMA": {
"template": """🎯 נושא: חישוב נקודות קיצון
שלב 1: f'(x) = 0 — מצא נקודות אפשריות.
שלב 2: בדוק ב-f''(x) — f''>0 → מינימום, f''<0 → מקסימום.
שלב 3: הצב בחזרה ב-f(x) למציאת ערך y.""",
"tokens": 90,
"requires": []
},
"INVESTIGATION_MONOTONICITY": {
"template": """🎯 נושא: עליה וירידה של פונקציה
מצא f'(x). פתור f'(x) = 0. בדוק סימן f'(x) בכל קטע.
f'>0 → עולה, f'<0 → יורדת.""",
"tokens": 80,
"requires": []
},
# ========== ALGEBRA ==========
"LINEAR_EQUATION": {
"template": """🎯 נושא: משוואה לינארית
פתור שלב-אחר-שלב: בודד x בצד אחד.""",
"tokens": 30,
"requires": []
},
"QUADRATIC_EQUATION": {
"template": """🎯 נושא: משוואה ריבועית
השתמש בנוסחת פתרון: x = [-b ± √(b²-4ac)] / 2a
חשב דיסקרימיננטה. מצא שתי תשובות (או שורש כפול).""",
"tokens": 60,
"requires": []
},
"SYSTEM_EQUATIONS": {
"template": """🎯 נושא: מערכת משוואות
פתור בשיטת הצבה או החסרה. הצב x חזרה למשוואה לווידוא.""",
"tokens": 60,
"requires": []
},
}
# ==================== PROMPT BUILDER ====================
def get_micro_prompt(topic_id: str, data: dict, grade: str = "10") -> str:
"""
Returns topic-focused prefix only.
Safety filter: Middle school (7-9) cannot use CALCULUS topics.
"""
if topic_id not in MICRO_PROMPTS:
raise KeyError(f"Topic '{topic_id}' not found in MICRO_PROMPTS")
# Safety Filter for V4.2.11
is_middle_school = False
try:
grade_val = int(re.search(r'\d+', str(grade)).group())
is_middle_school = 7 <= grade_val <= 9
except:
pass
if is_middle_school and ("DERIVATIVE" in topic_id or "INVESTIGATION" in topic_id):
print(f"🛡️ [Safety Filter] Micro-Prompt Filter: Topic {topic_id} blocked for Grade {grade}. Falling back to GENERAL.")
return get_general_prompt(data)
config = MICRO_PROMPTS[topic_id]
template = config["template"]
# No required fields anymore — all templates are self-contained
focus_block = template.strip()
# Prepend focus to the general prompt (which has the anchor + schema)
return f"{focus_block}\n\n{get_general_prompt(data)}"
def get_prompt_token_count(topic_id: str) -> int:
"""Get estimated token count for topic's micro-prompt"""
return MICRO_PROMPTS.get(topic_id, {}).get("tokens", 60)
def get_general_prompt(data_anchor: dict) -> str:
"""
Clean context provider.
Provides the data anchor without conflicting schemas.
"""
anchor_json = json.dumps(data_anchor, ensure_ascii=False, indent=2)
return f"""📊 [DATA ANCHOR] Problem context (Absolute Truth):
{anchor_json}
Instruction: Use the specific data above to solve the problem.
Do not provide any explanations outside the required JSON structure."""
# ==================== USAGE EXAMPLE ====================
if __name__ == "__main__":
test_data = {"equations": ["x^2 - 4 = 0"], "function_equations": ["f(x) = ln(x)/(x^2-4)"]}
for topic in ["CIRCLE_EQUATION", "DERIVATIVE_QUOTIENT", "LINEAR_EQUATION"]:
prompt = get_micro_prompt(topic, test_data)
print(f"=== {topic} ===\n{prompt[:200]}\n")