Toya0421 commited on
Commit
0dadbc6
·
verified ·
1 Parent(s): d7e4bc5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +161 -88
app.py CHANGED
@@ -1,109 +1,182 @@
1
- import os
2
- import random
3
  import gradio as gr
 
 
4
 
5
- # OpenRouter APIキーを指定
6
  API_KEY = "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"
7
-
8
- # Lexileレベルごとの文章セット(各3問)
9
- texts_by_level = {
10
- 400: [
11
- {"text": "Tom has a little dog. The dog likes to run in the park.", "question": "What does Tom's dog like to do?", "options": ["Run in the park", "Sleep all day", "Eat candy", "Climb trees"], "answer": "Run in the park"},
12
- {"text": "The sun is bright today. Many children are playing outside.", "question": "Where are the children playing?", "options": ["Outside", "In school", "At night", "In the house"], "answer": "Outside"},
13
- {"text": "Anna has a red ball. She throws it to her friend in the garden.", "question": "Where does Anna throw the ball?", "options": ["In the garden", "In the kitchen", "In the school", "In the store"], "answer": "In the garden"},
 
14
  ],
15
  600: [
16
- {"text": "Sara goes to the library every Saturday. She likes to read mystery books.", "question": "What kind of books does Sara like?", "options": ["Mystery books", "Science books", "History books", "Cooking books"], "answer": "Mystery books"},
17
- {"text": "A frog can jump far. It uses its strong legs to move fast.", "question": "What helps the frog jump far?", "options": ["Its strong legs", "Its arms", "Its eyes", "Its color"], "answer": "Its strong legs"},
18
- {"text": "Ben plants some seeds in the garden. After a few days, small plants grow.", "question": "What happens after a few days?", "options": ["Small plants grow", "The seeds disappear", "It starts to snow", "The garden becomes empty"], "answer": "Small plants grow"},
19
  ],
20
- 800: [
21
- {"text": "David wanted to learn how machines work. He took apart an old radio to see the parts inside.", "question": "Why did David take apart the radio?", "options": ["To see the parts inside", "To break it", "To sell it", "To clean it"], "answer": "To see the parts inside"},
22
- {"text": "In winter, many animals rest or sleep for a long time. This is called hibernation.", "question": "What do animals do during hibernation?", "options": ["Sleep for a long time", "Eat more food", "Play outside", "Travel to other countries"], "answer": "Sleep for a long time"},
23
- {"text": "Lisa looked through the telescope and saw bright stars in the night sky.", "question": "What did Lisa use to see the stars?", "options": ["A telescope", "A microscope", "A flashlight", "A magnifier"], "answer": "A telescope"},
24
  ],
25
- 1000: [
26
- {"text": "Plants use sunlight to make food. This process is called photosynthesis.", "question": "What do plants use to make food?", "options": ["Sunlight", "Wind", "Soil", "Rain"], "answer": "Sunlight"},
27
- {"text": "Electric cars are better for the environment because they produce less pollution.", "question": "Why are electric cars better for the environment?", "options": ["They produce less pollution", "They are faster", "They use gasoline", "They make noise"], "answer": "They produce less pollution"},
28
- {"text": "The computer stores data in its memory. This allows users to save their work.", "question": "What does the computer store in its memory?", "options": ["Data", "Food", "Games", "Pictures only"], "answer": "Data"},
29
  ],
30
- 1200: [
31
- {"text": "The scientist observed how the new medicine affected the cells under a microscope.", "question": "What did the scientist use to see the cells?", "options": ["A microscope", "A telescope", "A camera", "A ruler"], "answer": "A microscope"},
32
- {"text": "During the experiment, the temperature was carefully controlled to ensure accurate results.", "question": "Why was the temperature controlled?", "options": ["To ensure accurate results", "To make it hotter", "To test faster", "To make it colder"], "answer": "To ensure accurate results"},
33
- {"text": "Researchers developed a new algorithm that can predict weather patterns more accurately.", "question": "What can the new algorithm do?", "options": ["Predict weather patterns", "Make maps", "Control the wind", "Measure temperature"], "answer": "Predict weather patterns"},
34
  ]
35
  }
36
 
37
- # 状態管理
38
- state = {
39
- "current_level": 600,
40
- "question_count": 0,
41
- "used_texts": set(),
42
- "correct_count": 0,
43
- "finished": False
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- def get_next_question():
47
- level_texts = texts_by_level[state["current_level"]]
48
- available = [t for t in level_texts if t["text"] not in state["used_texts"]]
49
- if not available:
50
- return None
51
- question = random.choice(available)
52
- state["used_texts"].add(question["text"])
53
- return question
54
-
55
- def check_answer(user_answer):
56
- correct = state["current_question"]["answer"]
57
- return user_answer == correct
58
-
59
- def quiz_flow(user_answer=None):
60
- if state["finished"]:
61
- return "テストはすでに終了しています。再開するにはページをリロードしてください。", None, None, None
62
-
63
- # 回答処理
64
- if user_answer is not None:
65
- if check_answer(user_answer):
66
- state["correct_count"] += 1
67
- state["current_level"] = min(state["current_level"] + 200, 1200)
68
- else:
69
- state["current_level"] = max(state["current_level"] - 200, 400)
70
- state["question_count"] += 1
71
-
72
- # 5問で終了
73
- if state["question_count"] >= 5:
74
- state["finished"] = True
75
- return f"✅ テスト終了!あなたの推定読解レベルは {state['current_level']}L です。", None, None, None
76
-
77
- # 次の問題取得
78
- question = get_next_question()
79
- if not question:
80
- state["finished"] = True
81
- return f"📘 これ以上の問題がありません。あなたの推定レベルは {state['current_level']}L です。", None, None, None
82
-
83
- state["current_question"] = question
84
- return question["text"], question["question"], question["options"], None
85
-
86
- # Gradio UI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  with gr.Blocks() as demo:
88
- gr.Markdown("## 📖 英文読解テスト(全5問)")
89
 
90
- passage = gr.Textbox(label="文章", interactive=False, lines=4)
91
- question_box = gr.Textbox(label="問題", interactive=False)
92
- options = gr.Radio(label="選択肢", choices=[])
93
- result = gr.Textbox(label="結果表示", interactive=False)
94
 
95
- next_btn = gr.Button("次へ")
 
96
 
97
- def next_step(user_choice):
98
- return quiz_flow(user_choice)
99
 
100
- next_btn.click(
101
- fn=next_step,
102
- inputs=[options],
103
- outputs=[passage, question_box, options, result],
 
 
 
 
 
104
  )
105
 
106
- # 初期化時に最初の問題表示
107
- demo.load(fn=quiz_flow, inputs=None, outputs=[passage, question_box, options, result])
 
 
 
 
108
 
109
  demo.launch()
 
 
 
1
  import gradio as gr
2
+ from openai import OpenAI
3
+ import random
4
 
5
+ # OpenRouter APIキー(ここに直接書く)
6
  API_KEY = "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"
7
+ BASE_URL = "https://openrouter.ai/api/v1"
8
+
9
+ # --- Lexile難易度別教材(各段階3つずつ) ---
10
+ texts = {
11
+ 300: [
12
+ "Tom has a red ball. He plays with it in the park. The sun is bright.",
13
+ "Anna likes cats. She feeds them milk every morning.",
14
+ "The boy sees a bird in the tree. It sings a happy song."
15
  ],
16
  600: [
17
+ "A young boy found a lost puppy near the river. He decided to take care of it.",
18
+ "Lisa visits her grandmother every weekend. They bake cookies together.",
19
+ "The farmer plants rice in the spring and harvests it in the autumn."
20
  ],
21
+ 850: [
22
+ "Sarah enjoyed reading stories about ancient civilizations and their discoveries.",
23
+ "Tom built a small robot that could move and pick up light objects.",
24
+ "Maria was fascinated by how airplanes could stay in the air for hours."
25
  ],
26
+ 1050: [
27
+ "The scientist developed a new hypothesis about the evolution of animal behavior.",
28
+ "A group of engineers designed a bridge that could resist strong winds.",
29
+ "Students discussed how technology changes communication in modern society."
30
  ],
31
+ 1250: [
32
+ "Philosophers have long debated the intricate relationship between free will and determinism.",
33
+ "Economists analyzed the impact of automation on global labor markets.",
34
+ "Researchers investigated how cultural identity influences moral decision-making."
35
  ]
36
  }
37
 
38
+ levels = [300, 600, 850, 1050, 1250]
39
+
40
+ # --- OpenAIクライアント設定 ---
41
+ client = OpenAI(
42
+ base_url=BASE_URL,
43
+ api_key=API_KEY
44
+ )
45
+
46
+ # --- AIに問題生成を依頼 ---
47
+ def generate_question(text):
48
+ prompt = f"""
49
+ Read the following passage and create ONE multiple-choice question with 4 options (A–D).
50
+ Only output the question and options — DO NOT include which one is correct.
51
+ Format strictly as:
52
+ Q: <question text>
53
+ A. <option>
54
+ B. <option>
55
+ C. <option>
56
+ D. <option>
57
+
58
+ Passage:
59
+ {text}
60
+ """
61
+
62
+ response = client.chat.completions.create(
63
+ model="google/gemma-3-27b-it:free",
64
+ messages=[{"role": "user", "content": prompt}],
65
+ max_tokens=300,
66
+ temperature=0.7,
67
+ )
68
+ return response.choices[0].message.content.strip()
69
+
70
+ # --- AIで正解を判定(別プロンプト) ---
71
+ def check_answer_with_ai(text, question, user_answer):
72
+ prompt = f"""
73
+ Read the passage and question below. Decide if the user's answer is correct.
74
+
75
+ Passage:
76
+ {text}
77
+
78
+ Question:
79
+ {question}
80
 
81
+ User Answer: {user_answer}
82
+
83
+ Respond with only one word: "Correct" or "Incorrect".
84
+ """
85
+
86
+ response = client.chat.completions.create(
87
+ model="google/gemma-3-27b-it:free",
88
+ messages=[{"role": "user", "content": prompt}],
89
+ max_tokens=10,
90
+ temperature=0,
91
+ )
92
+ return response.choices[0].message.content.strip().lower() == "correct"
93
+
94
+ # --- 適応型テストの進行 ---
95
+ def adaptive_test(prev_level, prev_correct):
96
+ idx = levels.index(prev_level)
97
+ if prev_correct and idx < len(levels) - 1:
98
+ new_level = levels[idx + 1]
99
+ elif not prev_correct and idx > 0:
100
+ new_level = levels[idx - 1]
101
+ else:
102
+ new_level = prev_level
103
+ return new_level
104
+
105
+ # --- 状態管理 ---
106
+ used_texts = set()
107
+ question_count = 0
108
+ MAX_QUESTIONS = 5
109
+
110
+ # --- テスト開始 ---
111
+ def start_test():
112
+ global used_texts, question_count
113
+ used_texts = set()
114
+ question_count = 0
115
+
116
+ level = 850 # 中間レベルから開始
117
+ text = random.choice(texts[level])
118
+ used_texts.add(text)
119
+ question = generate_question(text)
120
+ return text, question, level, None, "", ""
121
+
122
+ # --- 回答処理して次へ ---
123
+ def next_step(prev_level, user_answer, question_text, passage_text):
124
+ global question_count, used_texts
125
+ question_count += 1
126
+
127
+ # 正解判定(AIに依頼)
128
+ correct = check_answer_with_ai(passage_text, question_text, user_answer)
129
+
130
+ # レベルを更新
131
+ new_level = adaptive_test(prev_level, correct)
132
+
133
+ feedback = "✅ Correct!" if correct else "❌ Incorrect."
134
+
135
+ # --- 終了条件 ---
136
+ if question_count >= MAX_QUESTIONS:
137
+ feedback += f"\n🎯 Test finished! Your estimated reading level is **{new_level}L**."
138
+ return feedback, passage_text, question_text, new_level, None, ""
139
+
140
+ # --- 次の文章を選択(同じものを避ける) ---
141
+ available = [t for t in texts[new_level] if t not in used_texts]
142
+ if not available: # 全て使い切ったらランダムに戻す
143
+ available = texts[new_level]
144
+ next_text = random.choice(available)
145
+ used_texts.add(next_text)
146
+
147
+ next_question = generate_question(next_text)
148
+ feedback += f"\n➡️ Next question is at a different level."
149
+
150
+ return feedback, next_text, next_question, new_level, None, ""
151
+
152
+ # --- Gradio UI ---
153
  with gr.Blocks() as demo:
154
+ gr.Markdown("# 📘 Adaptive Reading Level Test (Lexile-based)")
155
 
156
+ start_btn = gr.Button("▶️ Start Test")
 
 
 
157
 
158
+ text_display = gr.Textbox(label="Reading Passage", lines=6, interactive=False)
159
+ question_display = gr.Textbox(label="Generated Question", lines=8, interactive=False)
160
 
161
+ user_answer = gr.Radio(choices=["A", "B", "C", "D"], label="Your Answer")
162
+ submit_btn = gr.Button("Submit Answer")
163
 
164
+ feedback_display = gr.Markdown()
165
+ hidden_level = gr.Number(visible=False)
166
+ hidden_passage = gr.Textbox(visible=False)
167
+
168
+ # --- Start Test ---
169
+ start_btn.click(
170
+ fn=start_test,
171
+ inputs=[],
172
+ outputs=[text_display, question_display, hidden_level, user_answer, feedback_display, hidden_passage]
173
  )
174
 
175
+ # --- Submit & Move to Next ---
176
+ submit_btn.click(
177
+ fn=next_step,
178
+ inputs=[hidden_level, user_answer, question_display, text_display],
179
+ outputs=[feedback_display, text_display, question_display, hidden_level, user_answer, hidden_passage]
180
+ )
181
 
182
  demo.launch()