sgattup commited on
Commit
7772044
·
verified ·
1 Parent(s): e37e0b0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -38
app.py CHANGED
@@ -1,31 +1,40 @@
1
  """
2
- Estella Explainer — HuggingFace Spaces / Lightning AI Demo
3
- A math reading coach for grades 3–8, based on Usable Math (usablemath.org)
4
-
5
- Developed by Sai Gattupalli, PhD
6
- College of Education, University of Massachusetts Amherst
7
- Principal Scientist, Society and AI Research Group
8
-
9
- Model: sgattup/EstellaExplainerLLM (Gemma 4 E4B fine-tuned)
10
  """
11
 
 
 
12
  import gradio as gr
13
  import torch
 
14
  from transformers import AutoModelForCausalLM, AutoTokenizer
15
 
16
- MODEL_ID = "sgattup/EstellaExplainerLLM"
17
 
18
- SYSTEM_PROMPT = """You are Estella Explainer, a math reading and language coach for young learners in grades 3 through 8. Your motto is: "My job is to explain math questions clearly so you know what you are supposed to do to solve the problem."
 
 
 
 
19
 
20
- Your rules:
 
 
 
 
 
 
21
  - Give only ONE hint per problem.
22
  - Do NOT solve the problem or show the answer.
23
- - Do NOT show calculation steps or compute anything.
24
- - Help the student understand what the problem is ASKING.
25
- - Use very simple words and short sentences (Flesch Reading Ease 90-100).
 
26
  - Identify what is known and what is being asked.
27
  - Use phrases like "We know...", "We are looking for...", or "Think about...".
28
- - Be friendly and encouraging."""
 
 
29
 
30
  EXAMPLES = [
31
  "A rectangle has a length of 12 cm and a width of 5 cm. What is the area?",
@@ -38,33 +47,85 @@ EXAMPLES = [
38
  "The perimeter of a square is 36 inches. What is the length of one side?",
39
  ]
40
 
41
- print(f"Loading {MODEL_ID}...")
42
- tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
43
- model = AutoModelForCausalLM.from_pretrained(
44
- MODEL_ID,
45
- torch_dtype=torch.float16,
46
- device_map="auto"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  )
 
48
  model.eval()
 
49
  print("Estella is ready.")
50
 
51
 
52
  def ask_estella(message: str, history: list) -> str:
53
- """Chat function — history is kept for UI display only; Estella gives one hint per problem."""
54
- if not message.strip():
55
- return "Please type a math word problem and I'll help explain what it's asking!"
 
56
 
57
  messages = [
58
- {"role": "user", "content": SYSTEM_PROMPT + f"\n\n### Math Problem:\n{message.strip()}\n\n### Estella's Hint:"}
 
 
 
 
 
 
 
 
 
 
 
59
  ]
60
- text = tokenizer.apply_chat_template(
 
61
  messages,
62
  add_generation_prompt=True,
63
- tokenize=False
 
 
 
 
 
64
  )
65
- inputs = tokenizer(text=[text], return_tensors="pt")
66
- inputs = {k: v.to(model.device) for k, v in inputs.items()}
67
- input_len = inputs["input_ids"].shape[1]
 
 
 
 
 
68
 
69
  with torch.no_grad():
70
  outputs = model.generate(
@@ -73,24 +134,37 @@ def ask_estella(message: str, history: list) -> str:
73
  temperature=0.7,
74
  do_sample=True,
75
  repetition_penalty=1.1,
 
76
  )
77
 
78
- hint = tokenizer.decode(outputs[0][input_len:], skip_special_tokens=True).strip()
 
 
 
 
 
 
79
  return hint
80
 
81
 
82
- # Gradio ChatInterface
83
  demo = gr.ChatInterface(
84
  fn=ask_estella,
85
  title="📚 Estella Explainer — Math Reading Coach",
86
- description="""**"My job is to explain math questions clearly so you know what you are supposed to do to solve the problem."**
87
-
88
- Type any math word problem (grades 3–8) and Estella will help you understand what it's asking — without solving it.
89
-
90
- *Developed by [Sai Gattupalli, PhD](https://huggingface.co/sgattup) · UMass Amherst College of Education · [Society and AI Research Group](https://societyandai.org) · Based on [Usable Math](https://usablemath.org)*""",
 
 
 
 
 
91
  examples=EXAMPLES,
92
  cache_examples=False,
93
  type="messages",
94
  )
95
 
96
- demo.launch()
 
 
 
1
  """
2
+ Estella Explainer — Hugging Face Space
3
+ A math reading coach for grades 3–8.
 
 
 
 
 
 
4
  """
5
 
6
+ import os
7
+
8
  import gradio as gr
9
  import torch
10
+ from peft import PeftModel
11
  from transformers import AutoModelForCausalLM, AutoTokenizer
12
 
 
13
 
14
+ ADAPTER_ID = "sgattup/EstellaExplainerLLM"
15
+ BASE_MODEL_ID = "unsloth/gemma-4-E4B-it"
16
+
17
+ HF_TOKEN = os.getenv("HF_TOKEN")
18
+ HUB_ARGS = {"token": HF_TOKEN} if HF_TOKEN else {}
19
 
20
+
21
+ SYSTEM_PROMPT = """You are Estella Explainer, a math reading and language coach for young learners in grades 3 through 8.
22
+
23
+ Your motto is:
24
+ "My job is to explain math questions clearly so you know what you are supposed to do to solve the problem."
25
+
26
+ Rules:
27
  - Give only ONE hint per problem.
28
  - Do NOT solve the problem or show the answer.
29
+ - Do NOT show calculation steps.
30
+ - Do NOT compute anything.
31
+ - Help the student understand what the problem is asking.
32
+ - Use very simple words and short sentences.
33
  - Identify what is known and what is being asked.
34
  - Use phrases like "We know...", "We are looking for...", or "Think about...".
35
+ - Be friendly and encouraging.
36
+ """
37
+
38
 
39
  EXAMPLES = [
40
  "A rectangle has a length of 12 cm and a width of 5 cm. What is the area?",
 
47
  "The perimeter of a square is 36 inches. What is the length of one side?",
48
  ]
49
 
50
+
51
+ print(f"Loading base model: {BASE_MODEL_ID}")
52
+
53
+ if torch.cuda.is_available():
54
+ model_dtype = torch.float16
55
+ device_map = "auto"
56
+ print("GPU detected. Loading model in float16.")
57
+ else:
58
+ model_dtype = torch.float32
59
+ device_map = None
60
+ print("No GPU detected. CPU loading may be slow or require more memory.")
61
+
62
+
63
+ base_model = AutoModelForCausalLM.from_pretrained(
64
+ BASE_MODEL_ID,
65
+ torch_dtype=model_dtype,
66
+ device_map=device_map,
67
+ low_cpu_mem_usage=True,
68
+ **HUB_ARGS,
69
+ )
70
+
71
+
72
+ print(f"Loading Estella adapter: {ADAPTER_ID}")
73
+
74
+ model = PeftModel.from_pretrained(
75
+ base_model,
76
+ ADAPTER_ID,
77
+ **HUB_ARGS,
78
+ )
79
+
80
+ tokenizer = AutoTokenizer.from_pretrained(
81
+ ADAPTER_ID,
82
+ **HUB_ARGS,
83
  )
84
+
85
  model.eval()
86
+
87
  print("Estella is ready.")
88
 
89
 
90
  def ask_estella(message: str, history: list) -> str:
91
+ """Return one reading hint without solving the math problem."""
92
+
93
+ if not message or not message.strip():
94
+ return "Please type a math word problem and I’ll help explain what it is asking!"
95
 
96
  messages = [
97
+ {
98
+ "role": "system",
99
+ "content": SYSTEM_PROMPT,
100
+ },
101
+ {
102
+ "role": "user",
103
+ "content": (
104
+ "### Math Problem:\n"
105
+ f"{message.strip()}\n\n"
106
+ "### Estella's Hint:"
107
+ ),
108
+ },
109
  ]
110
+
111
+ prompt = tokenizer.apply_chat_template(
112
  messages,
113
  add_generation_prompt=True,
114
+ tokenize=False,
115
+ )
116
+
117
+ inputs = tokenizer(
118
+ prompt,
119
+ return_tensors="pt",
120
  )
121
+
122
+ input_device = next(model.parameters()).device
123
+ inputs = {
124
+ key: value.to(input_device)
125
+ for key, value in inputs.items()
126
+ }
127
+
128
+ input_length = inputs["input_ids"].shape[1]
129
 
130
  with torch.no_grad():
131
  outputs = model.generate(
 
134
  temperature=0.7,
135
  do_sample=True,
136
  repetition_penalty=1.1,
137
+ pad_token_id=tokenizer.eos_token_id,
138
  )
139
 
140
+ generated_tokens = outputs[0][input_length:]
141
+
142
+ hint = tokenizer.decode(
143
+ generated_tokens,
144
+ skip_special_tokens=True,
145
+ ).strip()
146
+
147
  return hint
148
 
149
 
 
150
  demo = gr.ChatInterface(
151
  fn=ask_estella,
152
  title="📚 Estella Explainer — Math Reading Coach",
153
+ description=(
154
+ '**"My job is to explain math questions clearly so you know '
155
+ 'what you are supposed to do to solve the problem."**\n\n'
156
+ "Type any math word problem and Estella will help you understand "
157
+ "what it is asking—without solving it.\n\n"
158
+ "Developed by [Sai Gattupalli, PhD](https://huggingface.co/sgattup) · "
159
+ "[UMass Amherst College of Education](https://www.umass.edu/education/) · "
160
+ "[Society and AI Research Group](https://societyandai.org) · "
161
+ "[Usable Math](https://usablemath.org)"
162
+ ),
163
  examples=EXAMPLES,
164
  cache_examples=False,
165
  type="messages",
166
  )
167
 
168
+
169
+ if __name__ == "__main__":
170
+ demo.launch()