Upload 7 files
Browse files- explainers/Percent Explainer +49 -0
- explainers/__init__.py +1 -0
- explainers/explainer_result +21 -0
- explainers/explainer_router +17 -0
- explainers/formatters +23 -0
- explainers/integrate to convo logic +13 -0
- explainers/main flow +5 -0
explainers/Percent Explainer
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# explainer_percent
|
| 2 |
+
|
| 3 |
+
import re
|
| 4 |
+
from models import ExplainerResult
|
| 5 |
+
|
| 6 |
+
def explain_percent_question(text: str) -> ExplainerResult | None:
|
| 7 |
+
t = text.lower()
|
| 8 |
+
|
| 9 |
+
if "%" not in t and "percent" not in t:
|
| 10 |
+
return None
|
| 11 |
+
|
| 12 |
+
# basic detection
|
| 13 |
+
numbers = re.findall(r'\d+', t)
|
| 14 |
+
|
| 15 |
+
givens = []
|
| 16 |
+
relationships = []
|
| 17 |
+
|
| 18 |
+
if "of" in t:
|
| 19 |
+
relationships.append("This is a part-of-whole relationship")
|
| 20 |
+
|
| 21 |
+
if "%" in t:
|
| 22 |
+
givens.append("A percentage is given")
|
| 23 |
+
|
| 24 |
+
asks_for = None
|
| 25 |
+
if "what is" in t or "find" in t:
|
| 26 |
+
asks_for = "the unknown quantity (likely the whole or part)"
|
| 27 |
+
|
| 28 |
+
return ExplainerResult(
|
| 29 |
+
understood=True,
|
| 30 |
+
topic="percent",
|
| 31 |
+
|
| 32 |
+
asks_for=asks_for,
|
| 33 |
+
givens=givens,
|
| 34 |
+
constraints=[],
|
| 35 |
+
|
| 36 |
+
relationships=relationships,
|
| 37 |
+
needed_concepts=[
|
| 38 |
+
"percent equation (part = percent × whole)"
|
| 39 |
+
],
|
| 40 |
+
|
| 41 |
+
trap_notes=[
|
| 42 |
+
"Do not confuse the part and the whole",
|
| 43 |
+
"Check whether you are solving forward or backward"
|
| 44 |
+
],
|
| 45 |
+
|
| 46 |
+
strategy_hint="Translate the sentence into a percent equation before solving.",
|
| 47 |
+
|
| 48 |
+
plain_english="The question describes a percentage relationship and is asking you to identify the missing value in that relationship."
|
| 49 |
+
)
|
explainers/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
.
|
explainers/explainer_result
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# models.py
|
| 2 |
+
|
| 3 |
+
from dataclasses import dataclass
|
| 4 |
+
from typing import List, Optional
|
| 5 |
+
|
| 6 |
+
@dataclass
|
| 7 |
+
class ExplainerResult:
|
| 8 |
+
understood: bool
|
| 9 |
+
topic: Optional[str]
|
| 10 |
+
|
| 11 |
+
asks_for: Optional[str] # what is the target
|
| 12 |
+
givens: List[str] # extracted facts
|
| 13 |
+
constraints: List[str] # conditions / limits
|
| 14 |
+
|
| 15 |
+
relationships: List[str] # how things connect (key insight)
|
| 16 |
+
needed_concepts: List[str] # what math idea is required
|
| 17 |
+
|
| 18 |
+
trap_notes: List[str] # common mistakes
|
| 19 |
+
strategy_hint: Optional[str] # how you'd approach (no solving)
|
| 20 |
+
|
| 21 |
+
plain_english: Optional[str] # simplified restatement
|
explainers/explainer_router
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# explainer_router.py
|
| 2 |
+
|
| 3 |
+
from explainer_percent import explain_percent_question
|
| 4 |
+
from explainer_ratio import explain_ratio_question
|
| 5 |
+
from explainer_algebra import explain_algebra_question
|
| 6 |
+
|
| 7 |
+
def route_explainer(text: str):
|
| 8 |
+
for fn in [
|
| 9 |
+
explain_percent_question,
|
| 10 |
+
explain_ratio_question,
|
| 11 |
+
explain_algebra_question,
|
| 12 |
+
]:
|
| 13 |
+
result = fn(text)
|
| 14 |
+
if result:
|
| 15 |
+
return result
|
| 16 |
+
|
| 17 |
+
return None
|
explainers/formatters
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def format_explainer_response(result, sliders):
|
| 2 |
+
lines = []
|
| 3 |
+
|
| 4 |
+
if result.plain_english:
|
| 5 |
+
lines.append(result.plain_english)
|
| 6 |
+
|
| 7 |
+
if sliders.transparency > 0.5:
|
| 8 |
+
if result.asks_for:
|
| 9 |
+
lines.append(f"\n👉 The question is asking for: {result.asks_for}")
|
| 10 |
+
|
| 11 |
+
if result.relationships:
|
| 12 |
+
lines.append("\n🔗 Key relationship:")
|
| 13 |
+
lines.extend(f"- {r}" for r in result.relationships)
|
| 14 |
+
|
| 15 |
+
if result.needed_concepts:
|
| 16 |
+
lines.append("\n🧠 Concepts you'll need:")
|
| 17 |
+
lines.extend(f"- {c}" for c in result.needed_concepts)
|
| 18 |
+
|
| 19 |
+
if result.trap_notes:
|
| 20 |
+
lines.append("\n⚠️ Watch out:")
|
| 21 |
+
lines.extend(f"- {t}" for t in result.trap_notes)
|
| 22 |
+
|
| 23 |
+
return "\n".join(lines)
|
explainers/integrate to convo logic
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def is_explainer_request(text: str) -> bool:
|
| 2 |
+
t = text.lower()
|
| 3 |
+
|
| 4 |
+
triggers = [
|
| 5 |
+
"what is this asking",
|
| 6 |
+
"what does this mean",
|
| 7 |
+
"explain the question",
|
| 8 |
+
"what do i need to find",
|
| 9 |
+
"decode this",
|
| 10 |
+
"what is being asked"
|
| 11 |
+
]
|
| 12 |
+
|
| 13 |
+
return any(p in t for p in triggers)
|
explainers/main flow
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
if is_explainer_request(user_text):
|
| 2 |
+
explainer_result = route_explainer(user_text)
|
| 3 |
+
|
| 4 |
+
if explainer_result:
|
| 5 |
+
return format_explainer_response(explainer_result, sliders)
|