GeetaAIVisionary commited on
Commit
ea612ad
·
verified ·
1 Parent(s): 286b3bb

mimicking to imitate the same in github

Browse files
Files changed (1) hide show
  1. app.py +187 -19
app.py CHANGED
@@ -1,36 +1,204 @@
1
  # app.py
 
2
  import gradio as gr
3
  import pandas as pd
4
  from pathlib import Path
5
 
6
  WORDS_PATH = Path("words.csv")
7
 
8
- def lookup(prefix: str):
 
 
9
  if not WORDS_PATH.exists():
10
- return "words.csv not found in repo."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  try:
12
- df = pd.read_csv(WORDS_PATH)
13
- except Exception as e:
14
- return f"Failed to read words.csv: {e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- # Expecting a column named 'word'. Fallback to first column if not present.
17
- col = "word" if "word" in df.columns else df.columns[0]
18
- s = df[col].astype(str)
 
 
 
19
 
20
- prefix = (prefix or "").strip()
21
- if not prefix:
22
- return "Type a prefix to see matches."
 
 
 
23
 
24
- matches = s[s.str.lower().str.startswith(prefix.lower())].head(20)
25
- if matches.empty:
26
- return "No matches."
27
- return "\n".join(matches.tolist())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
  with gr.Blocks() as demo:
30
- gr.Markdown("# NeMo Guardrails Demo (starter UI)\nType a prefix to see matching words from **words.csv**.")
31
- inp = gr.Textbox(label="Prefix")
32
- out = gr.Textbox(label="Matches", lines=12)
33
- inp.change(fn=lookup, inputs=inp, outputs=out)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  if __name__ == "__main__":
36
  demo.launch()
 
1
  # app.py
2
+ # CLI-like Spelling Bee Tutor as a simple Gradio UI (no LLMs, all offline)
3
  import gradio as gr
4
  import pandas as pd
5
  from pathlib import Path
6
 
7
  WORDS_PATH = Path("words.csv")
8
 
9
+ def _load_words():
10
+ """Load CSV; ensure we have a 'word' column; create optional columns if missing.
11
+ Also compute a difficulty score (fallback = word length)."""
12
  if not WORDS_PATH.exists():
13
+ # return empty df with expected columns
14
+ return pd.DataFrame(columns=["word", "definition", "origin", "sentence", "difficulty_score"])
15
+
16
+ df = pd.read_csv(WORDS_PATH)
17
+
18
+ # normalize required/optional columns
19
+ if "word" not in df.columns:
20
+ # treat first column as 'word'
21
+ df = df.rename(columns={df.columns[0]: "word"})
22
+
23
+ for col in ["definition", "origin", "sentence"]:
24
+ if col not in df.columns:
25
+ df[col] = ""
26
+
27
+ # difficulty: use numeric 'difficulty' if present; else use length
28
+ if "difficulty" in df.columns:
29
+ ds = pd.to_numeric(df["difficulty"], errors="coerce").fillna(0)
30
+ df["difficulty_score"] = ds
31
+ else:
32
+ df["difficulty_score"] = df["word"].astype(str).str.len()
33
+
34
+ # sort hardest -> easiest
35
+ df = df.sort_values("difficulty_score", ascending=False).reset_index(drop=True)
36
+ return df
37
+
38
+ DF = _load_words()
39
+
40
+ def _summary(state):
41
+ if not state:
42
+ return "No round active."
43
+ n = state["n"]
44
+ score = state["score"]
45
+ return f"Round complete. Score this round: {score}/{n}."
46
+
47
+ def start_quiz(n_words, state):
48
+ df = DF
49
+ if df.empty:
50
+ # disable input if no words
51
+ return (state,
52
+ "words.csv not found or empty.",
53
+ gr.update(value="", interactive=False),
54
+ "Please add a words.csv with at least one 'word' column.",
55
+ "Score: 0/0",
56
+ gr.update(value="", interactive=False))
57
+
58
  try:
59
+ n = int(n_words or 5)
60
+ except Exception:
61
+ n = 5
62
+
63
+ # clip to available size
64
+ n = max(1, min(n, len(df)))
65
+
66
+ # take top-n hardest words
67
+ block = df.head(n).reset_index(drop=True)
68
+
69
+ s = {
70
+ "i": 0,
71
+ "n": n,
72
+ "score": 0,
73
+ "words": block["word"].astype(str).tolist(),
74
+ "defs": block["definition"].astype(str).tolist(),
75
+ "orig": block["origin"].astype(str).tolist(),
76
+ "sent": block["sentence"].astype(str).tolist(),
77
+ }
78
+
79
+ current = s["words"][0]
80
+ hist = f"Okay! We'll do {n} words this round, hardest → easiest.\nSpell this word: {current}"
81
+ status = "Type your spelling attempt, or click definition/origin/sentence."
82
+ return s, hist, gr.update(value=current, interactive=False), status, f"Score: 0/{n}", gr.update(value="", interactive=True)
83
+
84
+ def _check_state(state):
85
+ if not state or "words" not in state or state["i"] >= state["n"]:
86
+ return False
87
+ return True
88
 
89
+ def check_attempt(state, attempt, history, current_word, score_md):
90
+ if not _check_state(state):
91
+ return state, history, current_word, "No round active. Click Start.", score_md, gr.update(value="")
92
+ attempt = (attempt or "").strip()
93
+ if not attempt:
94
+ return state, history, current_word, "Type your attempt first.", score_md, gr.update(value="")
95
 
96
+ target = state["words"][state["i"]]
97
+ if attempt.lower() == target.lower():
98
+ state["score"] += 1
99
+ msg = "✅ Correct!"
100
+ else:
101
+ msg = "❌ Not quite. Try again or ask for definition/origin/sentence."
102
 
103
+ # append to history
104
+ history = f"{history}\nYou: {attempt}\nTutor: {msg}"
105
+ score_md = f"Score: {state['score']}/{state['n']}"
106
+
107
+ return state, history, current_word, msg, score_md, gr.update(value="")
108
+
109
+ def _safe_text(val, fallback="Not available."):
110
+ v = (val or "").strip()
111
+ return v if v else fallback
112
+
113
+ def show_def(state, history, current_word, score_md):
114
+ if not _check_state(state):
115
+ return state, history, current_word, "No round active. Click Start.", score_md
116
+ i = state["i"]
117
+ word = state["words"][i]
118
+ text = _safe_text(state["defs"][i])
119
+ history = f"{history}\nTutor (definition of {word}): {text}"
120
+ return state, history, current_word, f"Definition of {word}: {text}", score_md
121
+
122
+ def show_origin(state, history, current_word, score_md):
123
+ if not _check_state(state):
124
+ return state, history, current_word, "No round active. Click Start.", score_md
125
+ i = state["i"]
126
+ word = state["words"][i]
127
+ text = _safe_text(state["orig"][i])
128
+ history = f"{history}\nTutor (origin of {word}): {text}"
129
+ return state, history, current_word, f"Origin of {word}: {text}", score_md
130
+
131
+ def show_sentence(state, history, current_word, score_md):
132
+ if not _check_state(state):
133
+ return state, history, current_word, "No round active. Click Start.", score_md
134
+ i = state["i"]
135
+ word = state["words"][i]
136
+ text = _safe_text(state["sent"][i])
137
+ history = f"{history}\nTutor (sentence with {word}): {text}"
138
+ return state, history, current_word, f"Sentence: {text}", score_md
139
+
140
+ def next_word(state, history, current_word, score_md):
141
+ if not _check_state(state):
142
+ return state, history, current_word, "No round active. Click Start.", score_md
143
+ state["i"] += 1
144
+ if state["i"] >= state["n"]:
145
+ # finished
146
+ summary = _summary(state)
147
+ history = f"{history}\n{summary}"
148
+ return {}, history, gr.update(value="", interactive=False), summary, f"Score: {state['score']}/{state['n']}"
149
+ # go to next word
150
+ w = state["words"][state["i"]]
151
+ history = f"{history}\nNext word: {w}"
152
+ status = "Type your spelling attempt, or click definition/origin/sentence."
153
+ return state, history, gr.update(value=w, interactive=False), status, f"Score: {state['score']}/{state['n']}"
154
+
155
+ def stop_round(state, history, current_word, score_md):
156
+ if not state:
157
+ return {}, history, current_word, "Stopped.", score_md
158
+ summary = _summary(state)
159
+ history = f"{history}\n{summary}"
160
+ return {}, history, gr.update(value="", interactive=False), "Stopped.", f"Score: {state['score']}/{state['n']}"
161
 
162
  with gr.Blocks() as demo:
163
+ gr.Markdown("# NeMo Guardrails Demo (starter UI)\n**CLI-style spelling quiz** works offline from `words.csv`.")
164
+
165
+ with gr.Row():
166
+ n_words = gr.Number(value=5, precision=0, label="Words this round")
167
+ start = gr.Button("Start quiz")
168
+
169
+ current_word = gr.Textbox(label="Spell this word", interactive=False)
170
+ attempt = gr.Textbox(label="Your attempt")
171
+ with gr.Row():
172
+ check = gr.Button("Check")
173
+ bdef = gr.Button("definition")
174
+ borg = gr.Button("origin")
175
+ bsent = gr.Button("sentence")
176
+ bnext = gr.Button("next")
177
+ bstop = gr.Button("stop")
178
+
179
+ status = gr.Markdown("")
180
+ score_md = gr.Markdown("Score: 0/0")
181
+ history = gr.Textbox(label="History", lines=14)
182
+
183
+ state = gr.State({})
184
+
185
+ # wire events
186
+ start.click(start_quiz, [n_words, state],
187
+ [state, history, current_word, status, score_md, attempt])
188
+
189
+ check.click(check_attempt, [state, attempt, history, current_word, score_md],
190
+ [state, history, current_word, status, score_md, attempt])
191
+
192
+ bdef.click(show_def, [state, history, current_word, score_md],
193
+ [state, history, current_word, status, score_md], queue=False)
194
+ borg.click(show_origin, [state, history, current_word, score_md],
195
+ [state, history, current_word, status, score_md], queue=False)
196
+ bsent.click(show_sentence, [state, history, current_word, score_md],
197
+ [state, history, current_word, status, score_md], queue=False)
198
+ bnext.click(next_word, [state, history, current_word, score_md],
199
+ [state, history, current_word, status, score_md], queue=False)
200
+ bstop.click(stop_round, [state, history, current_word, score_md],
201
+ [state, history, current_word, status, score_md], queue=False)
202
 
203
  if __name__ == "__main__":
204
  demo.launch()