test
Browse files- .gitignore +176 -0
- app.py +109 -0
- prompts/initial_prompt.py +6 -0
- prompts/main_prompt.py +64 -0
- requirements.txt +3 -0
.gitignore
ADDED
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.env
|
2 |
+
|
3 |
+
# Byte-compiled / optimized / DLL files
|
4 |
+
__pycache__/
|
5 |
+
*.py[cod]
|
6 |
+
*$py.class
|
7 |
+
|
8 |
+
# C extensions
|
9 |
+
*.so
|
10 |
+
|
11 |
+
# Distribution / packaging
|
12 |
+
.Python
|
13 |
+
build/
|
14 |
+
develop-eggs/
|
15 |
+
dist/
|
16 |
+
downloads/
|
17 |
+
eggs/
|
18 |
+
.eggs/
|
19 |
+
lib/
|
20 |
+
lib64/
|
21 |
+
parts/
|
22 |
+
sdist/
|
23 |
+
var/
|
24 |
+
wheels/
|
25 |
+
share/python-wheels/
|
26 |
+
*.egg-info/
|
27 |
+
.installed.cfg
|
28 |
+
*.egg
|
29 |
+
MANIFEST
|
30 |
+
|
31 |
+
# PyInstaller
|
32 |
+
# Usually these files are written by a python script from a template
|
33 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
34 |
+
*.manifest
|
35 |
+
*.spec
|
36 |
+
|
37 |
+
# Installer logs
|
38 |
+
pip-log.txt
|
39 |
+
pip-delete-this-directory.txt
|
40 |
+
|
41 |
+
# Unit test / coverage reports
|
42 |
+
htmlcov/
|
43 |
+
.tox/
|
44 |
+
.nox/
|
45 |
+
.coverage
|
46 |
+
.coverage.*
|
47 |
+
.cache
|
48 |
+
nosetests.xml
|
49 |
+
coverage.xml
|
50 |
+
*.cover
|
51 |
+
*.py,cover
|
52 |
+
.hypothesis/
|
53 |
+
.pytest_cache/
|
54 |
+
cover/
|
55 |
+
|
56 |
+
# Translations
|
57 |
+
*.mo
|
58 |
+
*.pot
|
59 |
+
|
60 |
+
# Django stuff:
|
61 |
+
*.log
|
62 |
+
local_settings.py
|
63 |
+
db.sqlite3
|
64 |
+
db.sqlite3-journal
|
65 |
+
|
66 |
+
# Flask stuff:
|
67 |
+
instance/
|
68 |
+
.webassets-cache
|
69 |
+
|
70 |
+
# Scrapy stuff:
|
71 |
+
.scrapy
|
72 |
+
|
73 |
+
# Sphinx documentation
|
74 |
+
docs/_build/
|
75 |
+
|
76 |
+
# PyBuilder
|
77 |
+
.pybuilder/
|
78 |
+
target/
|
79 |
+
|
80 |
+
# Jupyter Notebook
|
81 |
+
.ipynb_checkpoints
|
82 |
+
|
83 |
+
# IPython
|
84 |
+
profile_default/
|
85 |
+
ipython_config.py
|
86 |
+
|
87 |
+
# pyenv
|
88 |
+
# For a library or package, you might want to ignore these files since the code is
|
89 |
+
# intended to run in multiple environments; otherwise, check them in:
|
90 |
+
# .python-version
|
91 |
+
|
92 |
+
# pipenv
|
93 |
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
94 |
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
95 |
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
96 |
+
# install all needed dependencies.
|
97 |
+
#Pipfile.lock
|
98 |
+
|
99 |
+
# UV
|
100 |
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
101 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
102 |
+
# commonly ignored for libraries.
|
103 |
+
#uv.lock
|
104 |
+
|
105 |
+
# poetry
|
106 |
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
107 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
108 |
+
# commonly ignored for libraries.
|
109 |
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
110 |
+
#poetry.lock
|
111 |
+
|
112 |
+
# pdm
|
113 |
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
114 |
+
#pdm.lock
|
115 |
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
116 |
+
# in version control.
|
117 |
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
118 |
+
.pdm.toml
|
119 |
+
.pdm-python
|
120 |
+
.pdm-build/
|
121 |
+
|
122 |
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
123 |
+
__pypackages__/
|
124 |
+
|
125 |
+
# Celery stuff
|
126 |
+
celerybeat-schedule
|
127 |
+
celerybeat.pid
|
128 |
+
|
129 |
+
# SageMath parsed files
|
130 |
+
*.sage.py
|
131 |
+
|
132 |
+
# Environments
|
133 |
+
.env
|
134 |
+
.venv
|
135 |
+
env/
|
136 |
+
venv/
|
137 |
+
ENV/
|
138 |
+
env.bak/
|
139 |
+
venv.bak/
|
140 |
+
|
141 |
+
# Spyder project settings
|
142 |
+
.spyderproject
|
143 |
+
.spyproject
|
144 |
+
|
145 |
+
# Rope project settings
|
146 |
+
.ropeproject
|
147 |
+
|
148 |
+
# mkdocs documentation
|
149 |
+
/site
|
150 |
+
|
151 |
+
# mypy
|
152 |
+
.mypy_cache/
|
153 |
+
.dmypy.json
|
154 |
+
dmypy.json
|
155 |
+
|
156 |
+
# Pyre type checker
|
157 |
+
.pyre/
|
158 |
+
|
159 |
+
# pytype static type analyzer
|
160 |
+
.pytype/
|
161 |
+
|
162 |
+
# Cython debug symbols
|
163 |
+
cython_debug/
|
164 |
+
|
165 |
+
# PyCharm
|
166 |
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
167 |
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
168 |
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
169 |
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
170 |
+
#.idea/
|
171 |
+
|
172 |
+
# Ruff stuff:
|
173 |
+
.ruff_cache/
|
174 |
+
|
175 |
+
# PyPI configuration file
|
176 |
+
.pypirc
|
app.py
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import gradio as gr
|
3 |
+
from dotenv import load_dotenv
|
4 |
+
from openai import OpenAI
|
5 |
+
from prompts.initial_prompt import INITIAL_PROMPT
|
6 |
+
from prompts.main_prompt import MAIN_PROMPT
|
7 |
+
|
8 |
+
# .env 파일에서 OPENAI_API_KEY 로드
|
9 |
+
if os.path.exists(".env"):
|
10 |
+
load_dotenv(".env")
|
11 |
+
|
12 |
+
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
13 |
+
|
14 |
+
client = OpenAI(api_key=OPENAI_API_KEY)
|
15 |
+
|
16 |
+
|
17 |
+
|
18 |
+
def gpt_call(history, user_message,
|
19 |
+
model="gpt-4o-mini",
|
20 |
+
max_tokens=512,
|
21 |
+
temperature=0.7,
|
22 |
+
top_p=0.95):
|
23 |
+
"""
|
24 |
+
OpenAI ChatCompletion API를 통해 답변을 생성하는 함수.
|
25 |
+
- history: [(user_text, assistant_text), ...]
|
26 |
+
- user_message: 사용자가 방금 입력한 메시지
|
27 |
+
"""
|
28 |
+
# 1) 시스템 메시지(=MAIN_PROMPT)를 가장 앞에 추가
|
29 |
+
messages = [{"role": "system", "content": MAIN_PROMPT}]
|
30 |
+
|
31 |
+
# 2) 기존 대화 기록(history)을 OpenAI 형식으로 변환
|
32 |
+
# user_text -> 'user' / assistant_text -> 'assistant'
|
33 |
+
for user_text, assistant_text in history:
|
34 |
+
if user_text:
|
35 |
+
messages.append({"role": "user", "content": user_text})
|
36 |
+
if assistant_text:
|
37 |
+
messages.append({"role": "assistant", "content": assistant_text})
|
38 |
+
|
39 |
+
# 3) 마지막에 이번 사용자의 입력을 추가
|
40 |
+
messages.append({"role": "user", "content": user_message})
|
41 |
+
|
42 |
+
# 4) OpenAI API 호출
|
43 |
+
completion = client.chat.completions.create(
|
44 |
+
model=model,
|
45 |
+
messages=messages,
|
46 |
+
max_tokens=max_tokens,
|
47 |
+
temperature=temperature,
|
48 |
+
top_p=top_p
|
49 |
+
)
|
50 |
+
return completion.choices[0].message.content
|
51 |
+
|
52 |
+
def respond(user_message, history):
|
53 |
+
"""
|
54 |
+
Gradio 상에서 submit할 때 호출되는 함수
|
55 |
+
- user_message: 사용자가 방금 친 메시지
|
56 |
+
- history: 기존 (user, assistant) 튜플 리스트
|
57 |
+
"""
|
58 |
+
# 사용자가 빈 문자열을 보냈다면 아무 일도 하지 않음
|
59 |
+
if not user_message:
|
60 |
+
return "", history
|
61 |
+
|
62 |
+
# GPT 모델로부터 응답을 받음
|
63 |
+
assistant_reply = gpt_call(history, user_message)
|
64 |
+
|
65 |
+
# history에 (user, assistant) 쌍 추가
|
66 |
+
history.append((user_message, assistant_reply))
|
67 |
+
|
68 |
+
# Gradio에서는 (새로 비워질 입력창, 갱신된 history)를 반환
|
69 |
+
return "", history
|
70 |
+
|
71 |
+
##############################
|
72 |
+
# Gradio Blocks UI
|
73 |
+
##############################
|
74 |
+
with gr.Blocks() as demo:
|
75 |
+
gr.Markdown("## Simple Chat Interface")
|
76 |
+
|
77 |
+
# Chatbot 초기 상태를 설정
|
78 |
+
# 첫 번째 메시지는 (user="", assistant=INITIAL_PROMPT) 형태로 넣어
|
79 |
+
# 화면상에서 'assistant'가 INITIAL_PROMPT를 말한 것처럼 보이게 함
|
80 |
+
chatbot = gr.Chatbot(
|
81 |
+
value=[("", INITIAL_PROMPT)], # (user, assistant)
|
82 |
+
height=500
|
83 |
+
)
|
84 |
+
|
85 |
+
# (user, assistant) 쌍을 저장할 히스토리 상태
|
86 |
+
# 여기서도 동일한 초기 상태를 넣어줌
|
87 |
+
state_history = gr.State([("", INITIAL_PROMPT)])
|
88 |
+
|
89 |
+
# 사용자 입력
|
90 |
+
user_input = gr.Textbox(
|
91 |
+
placeholder="Type your message here...",
|
92 |
+
label="Your Input"
|
93 |
+
)
|
94 |
+
|
95 |
+
# 입력이 submit되면 respond() 호출 → 출력은 (새 입력창, 갱신된 chatbot)
|
96 |
+
user_input.submit(
|
97 |
+
respond,
|
98 |
+
inputs=[user_input, state_history],
|
99 |
+
outputs=[user_input, chatbot]
|
100 |
+
).then(
|
101 |
+
# respond 끝난 뒤, 최신 history를 state_history에 반영
|
102 |
+
fn=lambda _, h: h,
|
103 |
+
inputs=[user_input, chatbot],
|
104 |
+
outputs=[state_history]
|
105 |
+
)
|
106 |
+
|
107 |
+
# 메인 실행
|
108 |
+
if __name__ == "__main__":
|
109 |
+
demo.launch(server_name="0.0.0.0", server_port=7860, share=True)
|
prompts/initial_prompt.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
INITIAL_PROMPT = """
|
2 |
+
Welcome to this module on proportional reasoning and creativity in mathematics! \
|
3 |
+
Your goal is to determine which section is more crowded based on the classroom data provided. \
|
4 |
+
Try to use as many methods as possible and explain your reasoning after each solution. \
|
5 |
+
Let’s begin!
|
6 |
+
"""
|
prompts/main_prompt.py
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MAIN_PROMPT = """
|
2 |
+
Module 1: Solving Problems with Multiple Solutions Through AI
|
3 |
+
Prompts:
|
4 |
+
Initial Introduction by AI
|
5 |
+
"Welcome to this module on proportional reasoning and creativity in mathematics! Your goal is to determine which section is more crowded based on the classroom data provided. Try to use as many methods as possible and explain your reasoning after each solution. Let’s begin!"
|
6 |
+
Step-by-Step Prompts with Adaptive Hints
|
7 |
+
Solution 1: Comparing Ratios (Students to Capacity)
|
8 |
+
"What about comparing the ratio of students to total capacity for each section? How might that help you determine which section is more crowded?"
|
9 |
+
If no response: "For Section 1, the ratio is 18/34. What do you think the ratio is for Section 2?"
|
10 |
+
If incorrect: "It seems like there’s a small mistake in your calculation. Try dividing 14 by 30 for Section 2. What result do you get?"
|
11 |
+
If correct: "Great! Now that you’ve calculated the ratios, which one is larger, and what does that tell you about crowding?"
|
12 |
+
Solution 2: Comparing Ratios (Students to Available Seats)
|
13 |
+
"Have you considered looking at the ratio of students to available seats? For example, in Section 1, there are 18 students and 16 available seats. What would the ratio be for Section 2?"
|
14 |
+
If no response: "Think about how you can compare the number of students to the seats left in each section. How does this ratio give insight into the crowding?"
|
15 |
+
If incorrect: "Check your numbers again—how many seats are available in Section 2? Now divide the students by that number. What does the ratio show?"
|
16 |
+
If correct: "Excellent! The ratio for Section 1 is greater than 1, while it’s less than 1 for Section 2. What does that tell you about which section is more crowded?"
|
17 |
+
Solution 3: Decimal Conversion
|
18 |
+
"What happens if you convert the ratios into decimals? How might that make it easier to compare the sections?"
|
19 |
+
If no response: "To convert the ratios into decimals, divide the number of students by the total capacity. For Section 1, divide 18 by 34. What do you get?"
|
20 |
+
If incorrect: "Double-check your calculation. For Section 1, dividing 18 by 34 gives approximately 0.53. What do you think the decimal for Section 2 would be?"
|
21 |
+
If correct: "That’s right! Comparing 0.53 for Section 1 to 0.47 for Section 2 shows which section is more crowded. Great job!"
|
22 |
+
Solution 4: Percentages
|
23 |
+
"What about converting the ratios into percentages? How might percentages help clarify the problem?"
|
24 |
+
If no response: "Multiply the ratio by 100 to convert it into a percentage. For Section 1, (18/34) × 100 gives what result?"
|
25 |
+
If incorrect: "Let’s try that again. Dividing 18 by 34 and multiplying by 100 gives 52.94%. What percentage do you get for Section 2?"
|
26 |
+
If correct: "Nice work! Comparing 52.94% for Section 1 to 46.67% for Section 2 shows that Section 1 is more crowded. Well done!"
|
27 |
+
Solution 5: Visual Representation
|
28 |
+
"Sometimes drawing a diagram or picture helps make things clearer. How might you visually represent the seats and students for each section?"
|
29 |
+
If no response: "Try sketching out each section as a set of seats, shading the filled ones. What do you notice when you compare the two diagrams?"
|
30 |
+
If incorrect or unclear: "In your diagram, did you show that Section 1 has 18 filled seats out of 34, and Section 2 has 14 filled seats out of 30? How does the shading compare between the two?"
|
31 |
+
If correct: "Great visualization! Your diagram clearly shows that Section 1 is more crowded. Nice work!"
|
32 |
+
Feedback Prompts for Missing or Overlooked Methods
|
33 |
+
"You’ve explored a few great strategies so far. What about trying percentages or decimals next? How might those approaches provide new insights?"
|
34 |
+
"It looks like you’re on the right track! Have you considered drawing a picture or diagram? Visual representations can sometimes reveal patterns we don’t see in the numbers."
|
35 |
+
Encouragement for Correct Solutions
|
36 |
+
"Fantastic work! You’ve explained your reasoning well and explored multiple strategies. Let’s move on to another method to deepen your understanding."
|
37 |
+
"You’re doing great! Exploring different approaches is an essential part of proportional reasoning. Keep up the excellent work!"
|
38 |
+
Hints for Incorrect or Incomplete Solutions
|
39 |
+
"It seems like there’s a small mistake in your calculation. Let’s revisit the ratios—are you dividing the correct numbers?"
|
40 |
+
"That’s an interesting approach! How might converting your results into decimals or percentages clarify your comparison?"
|
41 |
+
"Your reasoning is on the right track, but what happens if you include another method, like drawing a diagram? Let’s explore that idea."
|
42 |
+
Comparing and Connecting Solutions
|
43 |
+
Prompt to Compare Student Solutions
|
44 |
+
"Student 1 said, 'Section 1 is more crowded because 18 students is more than 14 students.' Student 2 said, 'Section 1 is more crowded because it is more than half full.' Which reasoning aligns better with proportional reasoning, and why?"
|
45 |
+
Feedback for Absolute vs. Relative Thinking
|
46 |
+
"Focusing on absolute numbers is a good start, but proportional reasoning involves comparing relationships, like ratios or percentages. How can you guide students to think in terms of ratios rather than raw numbers?"
|
47 |
+
Reflection and Common Core Connections
|
48 |
+
Connecting Creativity-Directed Practices
|
49 |
+
"Which creativity-directed practices did you engage in while solving this problem? Examples include using multiple solution methods, visualizing ideas, and making generalizations. How do these practices support student engagement?"
|
50 |
+
Common Core Standards Alignment
|
51 |
+
*"Which Common Core Mathematical Practice Standards do you think apply to this task? Examples include:
|
52 |
+
Make sense of problems and persevere in solving them.
|
53 |
+
Reason abstractly and quantitatively."*
|
54 |
+
If they miss a key standard:
|
55 |
+
"Did this task require you to analyze the ratios and interpret their meaning? That aligns with Standard #2, Reason Abstractly and Quantitatively. Can you see how that applies here?"
|
56 |
+
"How might engaging students in this task encourage productive struggle (#1)? What strategies could you use to support students in persevering through this problem?"
|
57 |
+
AI Summary Prompts
|
58 |
+
Content Knowledge
|
59 |
+
"We explored proportional reasoning through multiple strategies: comparing ratios, converting to decimals, calculating percentages, and using visual representations. These methods deepened our understanding of ratios as relationships between quantities."
|
60 |
+
Creativity-Directed Practices
|
61 |
+
"We engaged in multiple solution tasks, visualized mathematical ideas, and made generalizations. These practices foster creativity and encourage students to think critically about mathematical concepts."
|
62 |
+
Pedagogical Content Knowledge
|
63 |
+
"You learned how to guide students from absolute thinking to relative thinking, focusing on proportional reasoning. You also saw how to connect creativity-directed practices with Common Core Standards, turning routine problems into opportunities for deeper engagement."
|
64 |
+
"""
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
huggingface_hub==0.25.2
|
2 |
+
openai
|
3 |
+
python-dotenv
|