dayuian commited on
Commit
c76dc5b
·
verified ·
1 Parent(s): dd25581

Update quiz.py

Browse files
Files changed (1) hide show
  1. quiz.py +77 -149
quiz.py CHANGED
@@ -1,152 +1,80 @@
1
- import gradio as gr
2
  import random
3
- from vocab import get_sources, get_words_from_source
4
- from sentences import generate_sentences
5
- from ai_sentence import MODEL_LIST
6
- from quiz import generate_fill_in_blank_exam, check_exam, render_exam_interface
7
-
8
- def process_sentence(mode, word, source, num, use_ai, model_name):
9
- try:
10
- if mode == '查詢單字':
11
- if not word:
12
- return "<p style='color:red;'>❌ 請輸入單字</p>", "未輸入單字"
13
- words = [word.strip()]
14
- elif mode == '隨機抽單字':
15
- num = int(num)
16
- if num <= 0:
17
- return "<p style='color:red;'>❌ 抽取數量須大於0</p>", "數量錯誤"
18
- words_data = get_words_from_source(source)
19
- words = [w['word'] for w in words_data]
20
- words = random.sample(words, num)
21
- else:
22
- return "<p style='color:red;'>❌ 模式錯誤</p>", "模式選擇異常"
23
-
24
- result_display, status_log = generate_sentences(words, source, use_ai, model_name)
25
-
26
- return result_display, status_log
27
-
28
- except Exception as e:
29
- return f"<p style='color:red;'>❌ 發生錯誤:{str(e)}</p>", f"錯誤:{str(e)}"
30
-
31
- def project_description():
32
- return """
33
- # 📖 VocabLine 單字例句工具
34
- 支援單字例句查詢,AI 自動生成句子。適合作為 LINE 單字推播、英文學習輔助工具。
35
- ## 🔍 核心功能
36
- - 查詢單字 → 獲取例句
37
- - 抽取單字 → 批量獲取例句
38
- - 可選 AI 生成句子(模型:GPT2 / Pythia)
39
- ## 🧑‍💻 技術架構
40
- - Gradio Blocks + Transformers (Hugging Face)
41
- - SQLite 句庫管理
42
- - 支援多單字庫擴展
43
- ## 📚 資料來源
44
- - 常用 3000 單字表
45
- - 英文例句資料庫 (Tatoeba)
46
- ## 👨‍💻 開發資訊
47
- - 開發者:余彦志 (大宇 ian)
48
- - 信箱:[email protected]
49
- - GitHub:[https://github.com/dayuian](https://github.com/dayuian)
50
- """
51
-
52
- with gr.Blocks(css="""
53
- #card-group { padding: 15px; border-radius: 12px; background-color: rgba(255, 255, 255, 0.05); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); margin-bottom: 15px; }
54
- .gradio-container { max-width: 800px; margin: auto; }
55
- """) as demo:
56
- gr.Markdown(project_description())
57
-
58
- with gr.Tab("單字查詢/生成例句"):
59
- with gr.Group():
60
- with gr.Row():
61
- mode_radio = gr.Radio(
62
- ["查詢單字", "隨機抽單字"],
63
- label="選擇模式",
64
- value="查詢單字",
65
- interactive=True
66
- )
67
-
68
- with gr.Group(elem_id="card-group"):
69
- word_input = gr.Textbox(label="輸入單字", visible=True)
70
- num_input = gr.Slider(minimum=1, maximum=10, value=5, step=1, label="抽取單字數量")
71
- source_dropdown = gr.Dropdown(
72
- choices=get_sources(),
73
- value="common3000",
74
- label="選擇單字庫"
75
- )
76
-
77
- with gr.Group(elem_id="card-group"):
78
- use_ai_checkbox = gr.Checkbox(label="使用 AI 生成句子(較慢,約 30 秒)", elem_id="use-ai-checkbox")
79
-
80
- with gr.Row():
81
- model_dropdown = gr.Dropdown(
82
- choices=MODEL_LIST,
83
- value="gpt2",
84
- label="選擇 AI 模型",
85
- visible=False
86
- )
87
- gr.Markdown("🔷 **建議使用 GPT2(表現較佳),Pythia-410m 很爛慎選!**", visible=False)
88
-
89
- ai_warning = gr.Textbox(
90
- value="⚠️ 使用 AI 生成句子為功能測試,每一個單字的生成過程可能需要 30 秒以上,請耐心等待。",
91
- visible=False,
92
- interactive=False,
93
- label=""
94
- )
95
-
96
- result_output = gr.HTML(label="結果")
97
- status_output = gr.Textbox(label="處理狀態", interactive=False)
98
-
99
- with gr.Row():
100
- generate_button = gr.Button("✨ 生成句子", elem_id="generate-button")
101
-
102
- with gr.Tab("英文小考"):
103
- quiz_source_dropdown = gr.Dropdown(
104
- choices=get_sources(),
105
- value="common3000",
106
- label="選擇單字庫"
107
- )
108
- quiz_num_slider = gr.Slider(minimum=1, maximum=10, value=2, step=1, label="題目數量")
109
-
110
- quiz_generate_button = gr.Button("📄 生成試卷")
111
- quiz_submit_button = gr.Button("✅ 提交試卷")
112
-
113
- quiz_questions_container = gr.Column()
114
- quiz_score_display = gr.HTML()
115
-
116
- quiz_questions_state = gr.State([])
117
-
118
- def display_exam(source, num):
119
- questions = generate_fill_in_blank_exam(source, num)
120
- quiz_questions_state.value = questions
121
-
122
- radios = []
123
- for i, q in enumerate(questions):
124
- radios.append(
125
- gr.Radio(
126
- choices=q['options'],
127
- label=f"第 {i + 1} 題:{q['sentence']}",
128
- interactive=True
129
- )
130
- )
131
-
132
- return radios
133
-
134
- def submit_exam(*user_answers):
135
- questions = quiz_questions_state.value
136
- score_html = check_exam(user_answers, questions)
137
- return score_html
138
-
139
- quiz_generate_button.click(
140
- display_exam,
141
- inputs=[quiz_source_dropdown, quiz_num_slider],
142
- outputs=quiz_questions_container
143
- )
144
 
145
- quiz_submit_button.click(
146
- submit_exam,
147
- inputs=quiz_questions_container,
148
- outputs=quiz_score_display
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  )
150
-
151
-
152
- demo.launch()
 
 
1
  import random
2
+ from vocab import get_words_from_source
3
+ from sentences import get_sentence
4
+ import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
+ # 生成單字選擇題資料
7
+ def generate_fill_in_blank_exam(source, num):
8
+ words_data = get_words_from_source(source)
9
+ words = random.sample(words_data, num)
10
+
11
+ questions = []
12
+ for word_data in words:
13
+ word = word_data['word']
14
+
15
+ # 取得例句
16
+ sentence_data = get_sentence(word)
17
+ if not sentence_data:
18
+ continue
19
+
20
+ sentence = sentence_data[2]
21
+ blank_sentence = sentence.replace(word, '______')
22
+
23
+ # 生成干擾選項 (亂數抽 3 個其他單字)
24
+ other_words = [w['word'] for w in words_data if w['word'] != word]
25
+ distractors = random.sample(other_words, 3)
26
+ options = [word] + distractors
27
+ random.shuffle(options)
28
+
29
+ questions.append({
30
+ "sentence": blank_sentence,
31
+ "options": options,
32
+ "answer": word,
33
+ })
34
+
35
+ return questions
36
+
37
+
38
+ # 自動對答案並計分
39
+ def check_exam(user_answers, questions):
40
+ correct_count = 0
41
+ results = []
42
+
43
+ for i, user_answer in enumerate(user_answers):
44
+ correct_answer = questions[i]['answer']
45
+ is_correct = (user_answer == correct_answer)
46
+
47
+ results.append({
48
+ "question": questions[i]['sentence'],
49
+ "user_answer": user_answer,
50
+ "correct_answer": correct_answer,
51
+ "is_correct": is_correct,
52
+ })
53
+
54
+ if is_correct:
55
+ correct_count += 1
56
+
57
+ score = f"{correct_count}/{len(questions)} 分"
58
+
59
+ result_html = f"<p><strong>得分:</strong> {score}</p>"
60
+ for res in results:
61
+ color = "green" if res["is_correct"] else "red"
62
+ result_html += f"<p style='color:{color};'><strong>題目:</strong> {res['question']}<br>"
63
+ result_html += f"<strong>你的答案:</strong> {res['user_answer']}<br>"
64
+ result_html += f"<strong>正確答案:</strong> {res['correct_answer']}</p>"
65
+
66
+ return result_html
67
+
68
+
69
+ # 動態生成 Gradio Radio 元件
70
+ def render_exam_interface(questions):
71
+ radios = []
72
+ for i, q in enumerate(questions):
73
+ radios.append(
74
+ gr.Radio(
75
+ choices=q['options'],
76
+ label=f"第 {i + 1} 題:{q['sentence']}",
77
+ interactive=True
78
+ )
79
  )
80
+ return radios