Spaces:
Paused
Paused
NightfuryEquinn commited on
Commit Β·
e168089
1
Parent(s): 516a4f2
Improve UI design
Browse files- .gitignore +1 -0
- app.py +84 -40
.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
stitch_ielts_ai_evaluator
|
app.py
CHANGED
|
@@ -902,11 +902,52 @@ def evaluate_reading(answers_text: str, reading_state: str):
|
|
| 902 |
# Gradio UI
|
| 903 |
# =========
|
| 904 |
CSS = """
|
|
|
|
| 905 |
.gr-button-primary { font-weight: 600; }
|
| 906 |
.band-box { font-size: 1.4rem; font-weight: 700; text-align: center; }
|
| 907 |
#wc1, #wc2 { max-width: 120px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 908 |
"""
|
| 909 |
|
|
|
|
| 910 |
FORCE_LIGHT_JS = """
|
| 911 |
function() {
|
| 912 |
document.documentElement.classList.remove('dark');
|
|
@@ -930,17 +971,18 @@ Powered by **Gemini 2.5 Flash** Β· Academic Module Β· Writing Tasks 1 & 2 Β· Rea
|
|
| 930 |
|
| 931 |
with gr.Row():
|
| 932 |
gen_btn_1 = gr.Button("π² Generate Chart & Question",
|
| 933 |
-
|
| 934 |
with gr.Column(scale=3):
|
| 935 |
-
gr.Markdown("
|
| 936 |
|
| 937 |
with gr.Row():
|
| 938 |
with gr.Column(scale=5):
|
| 939 |
-
chart_img = gr.Image(label="Chart / Diagram", type="pil")
|
| 940 |
with gr.Column(scale=5):
|
| 941 |
task1_q = gr.Textbox(
|
| 942 |
-
label="
|
| 943 |
-
placeholder="Click 'Generate' to load a questionβ¦"
|
|
|
|
| 944 |
)
|
| 945 |
|
| 946 |
gr.Markdown("---")
|
|
@@ -949,23 +991,25 @@ Powered by **Gemini 2.5 Flash** Β· Academic Module Β· Writing Tasks 1 & 2 Β· Rea
|
|
| 949 |
with gr.Column(scale=7):
|
| 950 |
essay1 = gr.Textbox(
|
| 951 |
label="Your Response", lines=16,
|
| 952 |
-
placeholder="
|
|
|
|
| 953 |
)
|
| 954 |
with gr.Column(scale=3):
|
| 955 |
wc_label1 = gr.Textbox(label="Word Count", elem_id="wc1",
|
| 956 |
-
|
| 957 |
-
eval_btn_1 = gr.Button("π Evaluate", variant="primary")
|
| 958 |
-
band_1 = gr.Textbox(label="Band Score", interactive=False,
|
| 959 |
elem_classes="band-box")
|
| 960 |
|
| 961 |
-
feedback1 = gr.Markdown(label="Feedback")
|
|
|
|
| 962 |
|
| 963 |
-
|
| 964 |
-
|
| 965 |
-
|
| 966 |
-
|
| 967 |
-
|
| 968 |
-
|
| 969 |
|
| 970 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββοΏ½οΏ½οΏ½βββββββββ
|
| 971 |
# TASK 2
|
|
@@ -974,14 +1018,14 @@ Powered by **Gemini 2.5 Flash** Β· Academic Module Β· Writing Tasks 1 & 2 Β· Rea
|
|
| 974 |
|
| 975 |
with gr.Row():
|
| 976 |
gen_btn_2 = gr.Button("π² Generate Essay Question",
|
| 977 |
-
|
| 978 |
with gr.Column(scale=3):
|
| 979 |
-
gr.Markdown("
|
| 980 |
-
"advantages/disadvantages, direct question*")
|
| 981 |
|
| 982 |
task2_q = gr.Textbox(
|
| 983 |
-
label="
|
| 984 |
-
placeholder="Click 'Generate' to load a questionβ¦"
|
|
|
|
| 985 |
)
|
| 986 |
|
| 987 |
gr.Markdown("---")
|
|
@@ -990,16 +1034,18 @@ Powered by **Gemini 2.5 Flash** Β· Academic Module Β· Writing Tasks 1 & 2 Β· Rea
|
|
| 990 |
with gr.Column(scale=7):
|
| 991 |
essay2 = gr.Textbox(
|
| 992 |
label="Your Response", lines=18,
|
| 993 |
-
placeholder="
|
|
|
|
| 994 |
)
|
| 995 |
with gr.Column(scale=3):
|
| 996 |
wc_label2 = gr.Textbox(label="Word Count", elem_id="wc2",
|
| 997 |
interactive=False, value="0 words")
|
| 998 |
-
eval_btn_2 = gr.Button("π Evaluate", variant="primary")
|
| 999 |
-
band_2 = gr.Textbox(label="Band Score", interactive=False,
|
| 1000 |
-
|
|
|
|
|
|
|
| 1001 |
|
| 1002 |
-
feedback2 = gr.Markdown(label="Feedback")
|
| 1003 |
|
| 1004 |
essay2.change(word_count, inputs=essay2, outputs=wc_label2)
|
| 1005 |
gen_btn_2.click(generate_task2, outputs=task2_q)
|
|
@@ -1016,13 +1062,10 @@ Powered by **Gemini 2.5 Flash** Β· Academic Module Β· Writing Tasks 1 & 2 Β· Rea
|
|
| 1016 |
# ββ Header controls ββββββββββββββββββββββββββββββββββββββββββββ
|
| 1017 |
with gr.Row():
|
| 1018 |
gen_reading_btn = gr.Button(
|
| 1019 |
-
"π² Generate New Reading Test", variant="primary", scale=2
|
| 1020 |
)
|
| 1021 |
with gr.Column(scale=3):
|
| 1022 |
-
gr.Markdown(
|
| 1023 |
-
"*3 academic passages Β· 40 questions Β· 60 minutes Β· "
|
| 1024 |
-
"Passages & questions generated together by Gemini*"
|
| 1025 |
-
)
|
| 1026 |
|
| 1027 |
# ββ Countdown timer (injected by generate_reading_test) ββββββββ
|
| 1028 |
timer_html_comp = gr.HTML("")
|
|
@@ -1037,19 +1080,20 @@ Powered by **Gemini 2.5 Flash** Β· Academic Module Β· Writing Tasks 1 & 2 Β· Rea
|
|
| 1037 |
)
|
| 1038 |
|
| 1039 |
with gr.Accordion("π Passage 1", open=False):
|
| 1040 |
-
reading_p1 = gr.Markdown("
|
| 1041 |
|
| 1042 |
with gr.Accordion("π Passage 2", open=False):
|
| 1043 |
-
reading_p2 = gr.Markdown("
|
| 1044 |
|
| 1045 |
with gr.Accordion("π Passage 3", open=False):
|
| 1046 |
-
reading_p3 = gr.Markdown("
|
| 1047 |
|
| 1048 |
gr.Markdown("---")
|
| 1049 |
|
| 1050 |
# ββ Questions display ββββββββββββββββββββββββββββββββββββββββββ
|
| 1051 |
reading_questions = gr.Markdown(
|
| 1052 |
-
"*Questions will appear here after you generate a test.*"
|
|
|
|
| 1053 |
)
|
| 1054 |
|
| 1055 |
gr.Markdown("---")
|
|
@@ -1062,8 +1106,7 @@ Powered by **Gemini 2.5 Flash** Β· Academic Module Β· Writing Tasks 1 & 2 Β· Rea
|
|
| 1062 |
"- True / False / Not Given: `2. TRUE` or `3. NOT GIVEN`\n"
|
| 1063 |
"- Matching headings: `4. iii`\n"
|
| 1064 |
"- Sentence / Short answer: `5. carbon dioxide`\n\n"
|
| 1065 |
-
"Answers are evaluated by Gemini against the generated answer key.
|
| 1066 |
-
"*(Evaluator will be replaced by your fine-tuned model once trained.)*"
|
| 1067 |
)
|
| 1068 |
|
| 1069 |
with gr.Row():
|
|
@@ -1081,18 +1124,19 @@ Powered by **Gemini 2.5 Flash** Β· Academic Module Β· Writing Tasks 1 & 2 Β· Rea
|
|
| 1081 |
"...\n"
|
| 1082 |
"40. YES"
|
| 1083 |
),
|
|
|
|
| 1084 |
)
|
| 1085 |
with gr.Column(scale=3):
|
| 1086 |
submit_reading_btn = gr.Button(
|
| 1087 |
-
"π Submit & Evaluate", variant="primary"
|
| 1088 |
)
|
| 1089 |
reading_band_box = gr.Textbox(
|
| 1090 |
-
label="Band Score",
|
| 1091 |
interactive=False,
|
| 1092 |
elem_classes="band-box",
|
| 1093 |
)
|
| 1094 |
|
| 1095 |
-
reading_feedback_md = gr.Markdown()
|
| 1096 |
|
| 1097 |
# ββ Events ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1098 |
gen_reading_btn.click(
|
|
|
|
| 902 |
# Gradio UI
|
| 903 |
# =========
|
| 904 |
CSS = """
|
| 905 |
+
/* Global UI Styles */
|
| 906 |
.gr-button-primary { font-weight: 600; }
|
| 907 |
.band-box { font-size: 1.4rem; font-weight: 700; text-align: center; }
|
| 908 |
#wc1, #wc2 { max-width: 120px; }
|
| 909 |
+
|
| 910 |
+
/* Custom Styling to mimic Tailwind/Material Design from HTML files */
|
| 911 |
+
.ielts-card {
|
| 912 |
+
border: 1px solid #c3c6d7;
|
| 913 |
+
border-radius: 12px;
|
| 914 |
+
padding: 24px;
|
| 915 |
+
background-color: #ffffff;
|
| 916 |
+
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
| 917 |
+
margin-bottom: 20px;
|
| 918 |
+
}
|
| 919 |
+
.ielts-header {
|
| 920 |
+
font-family: 'Public Sans', sans-serif;
|
| 921 |
+
color: #111c2d;
|
| 922 |
+
border-bottom: 1px solid #c3c6d7;
|
| 923 |
+
padding-bottom: 16px;
|
| 924 |
+
margin-bottom: 24px;
|
| 925 |
+
}
|
| 926 |
+
.ielts-prompt-box {
|
| 927 |
+
background-color: #f0f3ff;
|
| 928 |
+
border: 1px solid #c3c6d7;
|
| 929 |
+
border-left: 4px solid #004ac6;
|
| 930 |
+
padding: 16px;
|
| 931 |
+
border-radius: 8px;
|
| 932 |
+
font-family: 'Public Sans', sans-serif;
|
| 933 |
+
font-size: 18px;
|
| 934 |
+
line-height: 1.6;
|
| 935 |
+
}
|
| 936 |
+
.ielts-btn-primary {
|
| 937 |
+
background-color: #004ac6 !important;
|
| 938 |
+
color: white !important;
|
| 939 |
+
border-radius: 8px !important;
|
| 940 |
+
}
|
| 941 |
+
.writing-area {
|
| 942 |
+
font-family: 'Public Sans', sans-serif;
|
| 943 |
+
font-size: 18px;
|
| 944 |
+
line-height: 1.6;
|
| 945 |
+
border: 1px solid #c3c6d7;
|
| 946 |
+
border-radius: 12px;
|
| 947 |
+
}
|
| 948 |
"""
|
| 949 |
|
| 950 |
+
|
| 951 |
FORCE_LIGHT_JS = """
|
| 952 |
function() {
|
| 953 |
document.documentElement.classList.remove('dark');
|
|
|
|
| 971 |
|
| 972 |
with gr.Row():
|
| 973 |
gen_btn_1 = gr.Button("π² Generate Chart & Question",
|
| 974 |
+
variant="primary", scale=2, elem_classes="ielts-btn-primary")
|
| 975 |
with gr.Column(scale=3):
|
| 976 |
+
gr.Markdown("<div class='ielts-header'><h3>Academic Module: Writing Task 1</h3><p>Data Interpretation Report β’ 20 Minutes Recommended</p></div>")
|
| 977 |
|
| 978 |
with gr.Row():
|
| 979 |
with gr.Column(scale=5):
|
| 980 |
+
chart_img = gr.Image(label="Chart / Diagram", type="pil", elem_classes="ielts-card")
|
| 981 |
with gr.Column(scale=5):
|
| 982 |
task1_q = gr.Textbox(
|
| 983 |
+
label="AI Generated Prompt", lines=4, interactive=False,
|
| 984 |
+
placeholder="Click 'Generate' to load a questionβ¦",
|
| 985 |
+
elem_classes="ielts-prompt-box"
|
| 986 |
)
|
| 987 |
|
| 988 |
gr.Markdown("---")
|
|
|
|
| 991 |
with gr.Column(scale=7):
|
| 992 |
essay1 = gr.Textbox(
|
| 993 |
label="Your Response", lines=16,
|
| 994 |
+
placeholder="Begin drafting your report here (minimum 150 words)β¦",
|
| 995 |
+
elem_classes="writing-area"
|
| 996 |
)
|
| 997 |
with gr.Column(scale=3):
|
| 998 |
wc_label1 = gr.Textbox(label="Word Count", elem_id="wc1",
|
| 999 |
+
interactive=False, value="0 words")
|
| 1000 |
+
eval_btn_1 = gr.Button("π Evaluate Response", variant="primary", elem_classes="ielts-btn-primary")
|
| 1001 |
+
band_1 = gr.Textbox(label="Estimated Band Score", interactive=False,
|
| 1002 |
elem_classes="band-box")
|
| 1003 |
|
| 1004 |
+
feedback1 = gr.Markdown(label="AI Evaluation Feedback")
|
| 1005 |
+
|
| 1006 |
|
| 1007 |
+
essay1.change(word_count, inputs=essay1, outputs=wc_label1)
|
| 1008 |
+
gen_btn_1.click(generate_task1,
|
| 1009 |
+
outputs=[chart_img, task1_q, chart_spec_state])
|
| 1010 |
+
eval_btn_1.click(evaluate_task1,
|
| 1011 |
+
inputs=[essay1, chart_spec_state],
|
| 1012 |
+
outputs=[feedback1, band_1])
|
| 1013 |
|
| 1014 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββοΏ½οΏ½οΏ½βββββββββ
|
| 1015 |
# TASK 2
|
|
|
|
| 1018 |
|
| 1019 |
with gr.Row():
|
| 1020 |
gen_btn_2 = gr.Button("π² Generate Essay Question",
|
| 1021 |
+
variant="primary", scale=2, elem_classes="ielts-btn-primary")
|
| 1022 |
with gr.Column(scale=3):
|
| 1023 |
+
gr.Markdown("<div class='ielts-header'><h3>Academic Module: Writing Task 2</h3><p>Discursive Essay β’ 40 Minutes Recommended</p></div>")
|
|
|
|
| 1024 |
|
| 1025 |
task2_q = gr.Textbox(
|
| 1026 |
+
label="AI Generated Prompt", lines=5, interactive=False,
|
| 1027 |
+
placeholder="Click 'Generate' to load a questionβ¦",
|
| 1028 |
+
elem_classes="ielts-prompt-box"
|
| 1029 |
)
|
| 1030 |
|
| 1031 |
gr.Markdown("---")
|
|
|
|
| 1034 |
with gr.Column(scale=7):
|
| 1035 |
essay2 = gr.Textbox(
|
| 1036 |
label="Your Response", lines=18,
|
| 1037 |
+
placeholder="Begin drafting your essay here (minimum 250 words)β¦",
|
| 1038 |
+
elem_classes="writing-area"
|
| 1039 |
)
|
| 1040 |
with gr.Column(scale=3):
|
| 1041 |
wc_label2 = gr.Textbox(label="Word Count", elem_id="wc2",
|
| 1042 |
interactive=False, value="0 words")
|
| 1043 |
+
eval_btn_2 = gr.Button("π Evaluate Response", variant="primary", elem_classes="ielts-btn-primary")
|
| 1044 |
+
band_2 = gr.Textbox(label="Estimated Band Score", interactive=False,
|
| 1045 |
+
elem_classes="band-box")
|
| 1046 |
+
|
| 1047 |
+
feedback2 = gr.Markdown(label="AI Evaluation Feedback")
|
| 1048 |
|
|
|
|
| 1049 |
|
| 1050 |
essay2.change(word_count, inputs=essay2, outputs=wc_label2)
|
| 1051 |
gen_btn_2.click(generate_task2, outputs=task2_q)
|
|
|
|
| 1062 |
# ββ Header controls ββββββββββββββββββββββββββββββββββββββββββββ
|
| 1063 |
with gr.Row():
|
| 1064 |
gen_reading_btn = gr.Button(
|
| 1065 |
+
"π² Generate New Reading Test", variant="primary", scale=2, elem_classes="ielts-btn-primary"
|
| 1066 |
)
|
| 1067 |
with gr.Column(scale=3):
|
| 1068 |
+
gr.Markdown("<div class='ielts-header'><h3>Academic Module: Reading Paper</h3><p>3 Passages Β· 40 Questions Β· 60 Minutes Recommended</p></div>")
|
|
|
|
|
|
|
|
|
|
| 1069 |
|
| 1070 |
# ββ Countdown timer (injected by generate_reading_test) ββββββββ
|
| 1071 |
timer_html_comp = gr.HTML("")
|
|
|
|
| 1080 |
)
|
| 1081 |
|
| 1082 |
with gr.Accordion("π Passage 1", open=False):
|
| 1083 |
+
reading_p1 = gr.Markdown(elem_classes="ielts-card")
|
| 1084 |
|
| 1085 |
with gr.Accordion("π Passage 2", open=False):
|
| 1086 |
+
reading_p2 = gr.Markdown(elem_classes="ielts-card")
|
| 1087 |
|
| 1088 |
with gr.Accordion("π Passage 3", open=False):
|
| 1089 |
+
reading_p3 = gr.Markdown(elem_classes="ielts-card")
|
| 1090 |
|
| 1091 |
gr.Markdown("---")
|
| 1092 |
|
| 1093 |
# ββ Questions display ββββββββββββββββββββββββββββββββββββββββββ
|
| 1094 |
reading_questions = gr.Markdown(
|
| 1095 |
+
"*Questions will appear here after you generate a test.*",
|
| 1096 |
+
elem_classes="ielts-prompt-box"
|
| 1097 |
)
|
| 1098 |
|
| 1099 |
gr.Markdown("---")
|
|
|
|
| 1106 |
"- True / False / Not Given: `2. TRUE` or `3. NOT GIVEN`\n"
|
| 1107 |
"- Matching headings: `4. iii`\n"
|
| 1108 |
"- Sentence / Short answer: `5. carbon dioxide`\n\n"
|
| 1109 |
+
"Answers are evaluated by Gemini against the generated answer key."
|
|
|
|
| 1110 |
)
|
| 1111 |
|
| 1112 |
with gr.Row():
|
|
|
|
| 1124 |
"...\n"
|
| 1125 |
"40. YES"
|
| 1126 |
),
|
| 1127 |
+
elem_classes="writing-area"
|
| 1128 |
)
|
| 1129 |
with gr.Column(scale=3):
|
| 1130 |
submit_reading_btn = gr.Button(
|
| 1131 |
+
"π Submit & Evaluate", variant="primary", elem_classes="ielts-btn-primary"
|
| 1132 |
)
|
| 1133 |
reading_band_box = gr.Textbox(
|
| 1134 |
+
label="Estimated Band Score",
|
| 1135 |
interactive=False,
|
| 1136 |
elem_classes="band-box",
|
| 1137 |
)
|
| 1138 |
|
| 1139 |
+
reading_feedback_md = gr.Markdown(label="AI Evaluation Feedback")
|
| 1140 |
|
| 1141 |
# ββ Events ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1142 |
gen_reading_btn.click(
|