mihalykiss commited on
Commit
ffaf2b4
Β·
verified Β·
1 Parent(s): 57d366e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +193 -179
app.py CHANGED
@@ -1,196 +1,210 @@
1
  import gradio as gr
2
 
3
  title = "AI Text Detector"
 
4
  description = """
5
- <div class="app-logo-title">
6
- <img src="https://raw.githubusercontent.com/google/material-design-icons/master/src/action/insights/materialiconsoutlined/24px.svg" alt="SzegedAI Logo" style="height:36px;vertical-align:middle;margin-right:10px;">
7
- <span>AI Text Detector</span>
8
- </div>
9
- <div class="app-desc">
10
- This tool uses the <b>ModernBERT</b> model to identify whether a given text was written by a human or generated by artificial intelligence (AI). It works with a soft voting ensemble using <b>three</b> models, combining their outputs to improve the accuracy.<br>
11
- βœ… <b>Human Verification:</b> Human-written content is clearly marked.<br>
12
- πŸ” <b>Model Detection:</b> Can identify content from over 40 AI models.<br>
13
- πŸ“ˆ <b>Accuracy:</b> Works best with longer texts.<br>
14
- πŸ“„ <b>Read more:</b> Our method is detailed in our paper:
15
- <a href="https://aclanthology.org/2025.genaidetect-1.15/" target="_blank" style="color: #0be6c1; text-decoration: underline;"><b>LINK</b></a>.
 
16
  </div>
17
- <br>
18
- Paste your text below to analyze its origin.
19
  """
 
20
  bottom_text = "**Developed by SzegedAI**"
21
 
22
- AI_texts = [
23
- "Camels are remarkable desert animals...",
24
- ]
25
- Human_texts = [
26
- "To make BERT handle a variety of down-stream tasks...",
27
- ]
28
-
29
- iface = gr.Blocks(css="""
30
- @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Inter:wght@400;600;800&display=swap');
31
-
32
- body, .gradio-container {
33
- font-family: 'Inter', 'Roboto', Arial, sans-serif !important;
34
- background: linear-gradient(120deg, #0e223f 0%, #1e2957 100%) fixed;
35
- color: #1c2025;
36
- min-height: 100vh;
37
- }
38
-
39
- .gradio-container {
40
- display: flex; flex-direction: column; align-items: center;
41
- padding: 0;
42
- border: none;
43
- min-height: 100vh;
44
- }
45
-
46
- #main_card {
47
- background: rgba(255,255,255,0.17);
48
- box-shadow: 0 8px 32px 0 rgba(31,38,135,0.25);
49
- border-radius: 24px;
50
- padding: 42px 36px 30px 36px;
51
- margin: 60px auto 0 auto;
52
- backdrop-filter: blur(12px);
53
- border: 1.5px solid rgba(255,255,255,0.25);
54
- max-width: 620px;
55
- width: 100%;
56
- }
57
-
58
- .app-logo-title {
59
- display: flex; align-items: center; font-weight: 800; font-size: 2.2rem;
60
- color: #111b31; letter-spacing: -.02em; margin-bottom: 12px;
61
- }
62
-
63
- .app-desc {
64
- color: #283352; font-size: 1.1rem; margin-bottom: 22px; line-height: 1.75;
65
- }
66
-
67
- #text_input_box {
68
- border-radius: 16px;
69
- border: 2.2px solid #0be6c1;
70
- font-size: 18px;
71
- padding: 18px;
72
- margin-bottom: 24px;
73
- background: rgba(255,255,255,0.7);
74
- font-family: 'Inter', monospace;
75
- box-shadow: 0 1px 6px 0 rgba(11,230,193,0.08);
76
- transition: border-color .25s;
77
- width: 100%;
78
- }
79
-
80
- #text_input_box:focus {
81
- outline: none;
82
- border-color: #ff6f61;
83
- background: rgba(255,255,255,0.94);
84
- }
85
-
86
- .gr-button, button {
87
- border: none;
88
- background: linear-gradient(90deg, #0be6c1 20%, #2196f3 100%);
89
- color: #fff;
90
- font-size: 1.15rem;
91
- font-weight: 700;
92
- border-radius: 12px;
93
- padding: 14px 0;
94
- box-shadow: 0 2px 10px 0 rgba(11,230,193,0.13);
95
- margin: 8px 0 18px 0;
96
- width: 100%;
97
- cursor: pointer;
98
- transition: background .18s, box-shadow .18s;
99
- }
100
-
101
- .gr-button:active, button:active {
102
- background: linear-gradient(90deg, #26a69a 20%, #0be6c1 100%);
103
- box-shadow: 0 2px 10px 0 rgba(11,230,193,0.18);
104
- }
105
-
106
- #result_output_box {
107
- border-radius: 14px;
108
- border: 2px solid #fff;
109
- font-size: 20px;
110
- padding: 18px;
111
- margin-top: 24px;
112
- width: 100%;
113
- min-height: 56px;
114
- background: rgba(255,255,255,0.9);
115
- box-shadow: 0 1px 10px 0 rgba(34,86,122,0.05);
116
- text-align: center;
117
- transition: box-shadow .22s;
118
- font-weight: 600;
119
- }
120
-
121
- .highlight-human {
122
- color: #2196f3;
123
- font-weight: bold;
124
- background: rgba(33,150,243,0.08);
125
- border-radius: 8px;
126
- padding: 6px 14px;
127
- display: inline-block;
128
- }
129
-
130
- .highlight-ai {
131
- color: #ff6f61;
132
- font-weight: bold;
133
- background: rgba(255,111,97,0.08);
134
- border-radius: 8px;
135
- padding: 6px 14px;
136
- display: inline-block;
137
- }
138
-
139
- .tab {
140
- margin-top: 22px;
141
- }
142
-
143
- .gr-examples {
144
- border: none !important;
145
- background: rgba(255,255,255,0.22) !important;
146
- border-radius: 12px !important;
147
- box-shadow: 0 1px 8px 0 rgba(0,0,0,0.04) !important;
148
- }
149
-
150
- #bottom_text {
151
- text-align: center;
152
- margin-top: 44px;
153
- font-weight: 700;
154
- font-size: 1.11rem;
155
- color: #111b31;
156
- opacity: .9;
157
- }
158
-
159
- @media (max-width: 768px) {
160
- #main_card { padding: 18px 7vw; margin: 14px 0 0 0; }
161
- #result_output_box { font-size: 1rem; min-height: 44px; }
162
- .app-logo-title { font-size: 1.4rem; }
163
- }
164
- """)
165
-
166
- def classify_text(text):
167
- # Your model logic here (placeholder)
168
- import random
169
- is_ai = random.choice([True, False])
170
- if is_ai:
171
- return '<span class="highlight-ai" role="alert" aria-live="polite">Detected as: AI-generated</span>'
172
- else:
173
- return '<span class="highlight-human" role="alert" aria-live="polite">Detected as: Human-written</span>'
174
 
175
  with iface:
176
- with gr.Column(elem_id="main_card"):
 
177
  gr.Markdown(description)
 
 
178
  text_input = gr.Textbox(
179
- label="",
180
- placeholder="Type or paste your content here...",
181
  elem_id="text_input_box",
182
- lines=5,
183
- show_label=False
184
  )
 
 
 
 
 
185
  result_output = gr.Markdown("", elem_id="result_output_box")
186
- # Add clear feedback/animation on result
187
- text_input.change(classify_text, inputs=text_input, outputs=result_output)
188
-
189
- with gr.Tab("AI text examples", elem_classes=["tab"]):
190
- gr.Examples(AI_texts, inputs=text_input)
191
- with gr.Tab("Human text examples", elem_classes=["tab"]):
192
- gr.Examples(Human_texts, inputs=text_input)
193
-
194
- gr.Markdown(bottom_text, elem_id="bottom_text")
 
 
 
 
 
 
 
195
 
196
  iface.launch(share=True)
 
1
  import gradio as gr
2
 
3
  title = "AI Text Detector"
4
+
5
  description = """
6
+ <div class="hero">
7
+ <h1>πŸ”Ž AI Text Detector</h1>
8
+ <p>
9
+ Built on the <b>ModernBERT</b> ensemble (3 variants, soft-voting).<br>
10
+ <span class="point">βœ… Human verification</span> &nbsp;|&nbsp;
11
+ <span class="point">πŸ” Detects 40+ AI models</span> &nbsp;|&nbsp;
12
+ <span class="point">πŸ“ˆ Best on longer passages</span>
13
+ </p>
14
+ <p class="paper">
15
+ Read the full paper&nbsp;β†’&nbsp;
16
+ <a href="https://aclanthology.org/2025.genaidetect-1.15/" target="_blank">LINK</a>
17
+ </p>
18
  </div>
 
 
19
  """
20
+
21
  bottom_text = "**Developed by SzegedAI**"
22
 
23
+ # ---------- UI ----------
24
+ iface = gr.Blocks(
25
+ theme=gr.themes.Default(), # keep defaults; we'll override in CSS
26
+ css="""
27
+ /* ---------- Global tokens ---------- */
28
+ :root{
29
+ --primary:#203A6B; /* midnight-indigo */
30
+ --accent :#14B8A6; /* teal-mint */
31
+ --bg :#F8FAFC; /* light-gray */
32
+ --bg-card:rgba(255,255,255,0.55);
33
+ --radius :16px;
34
+ --shadow :0 6px 24px rgba(0,0,0,.08);
35
+ --transition:180ms cubic-bezier(.4,0,.2,1);
36
+ --font:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;
37
+ }
38
+
39
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
40
+
41
+ html,body{
42
+ font-family:var(--font);
43
+ background: var(--bg);
44
+ color:var(--primary);
45
+ height:100%;
46
+ margin:0;
47
+ }
48
+
49
+ /* ---------- Main container ---------- */
50
+ .gradio-container{
51
+ display:grid;
52
+ place-items:center;
53
+ padding:5vmin;
54
+ min-height:100dvh;
55
+ animation:fade-slide-in .6s ease-out both;
56
+ }
57
+
58
+ .container{
59
+ background:var(--bg-card);
60
+ backdrop-filter:blur(12px) saturate(120%);
61
+ border:1px solid rgba(255,255,255,.35);
62
+ border-radius:var(--radius);
63
+ box-shadow:var(--shadow);
64
+ padding:clamp(1.5rem,4vw,3rem);
65
+ width:min(680px,90vw);
66
+ display:grid;
67
+ gap:2rem;
68
+ }
69
+
70
+ /* ---------- Hero / heading ---------- */
71
+ .hero{
72
+ text-align:center;
73
+ line-height:1.6;
74
+ }
75
+ .hero h1{
76
+ margin:0 0 .5rem;
77
+ font-size:clamp(1.8rem,4vw,2.4rem);
78
+ font-weight:700;
79
+ }
80
+ .point{
81
+ font-weight:600;
82
+ }
83
+ .paper a{
84
+ color:var(--accent);
85
+ text-decoration:none;
86
+ font-weight:600;
87
+ }
88
+
89
+ /* ---------- Inputs & button ---------- */
90
+ #text_input_box{
91
+ border:2px solid rgba(32,58,107,.25);
92
+ border-radius:var(--radius);
93
+ padding:1rem 1.25rem;
94
+ font-size:1rem;
95
+ width:100%;
96
+ transition:border-color var(--transition), box-shadow var(--transition);
97
+ }
98
+ #text_input_box:focus{
99
+ outline:none;
100
+ border-color:var(--accent);
101
+ box-shadow:0 0 0 4px rgba(20,184,166,.18);
102
+ }
103
+
104
+ .analyze-btn{
105
+ display:inline-flex;
106
+ align-items:center;
107
+ justify-content:center;
108
+ gap:.5rem;
109
+ font-weight:600;
110
+ font-size:1rem;
111
+ padding:.9rem 1.6rem;
112
+ background:var(--primary);
113
+ color:#fff;
114
+ border:none;
115
+ border-radius:var(--radius);
116
+ cursor:pointer;
117
+ transition:transform var(--transition), box-shadow var(--transition);
118
+ }
119
+ .analyze-btn:hover{
120
+ transform:translateY(-2px);
121
+ box-shadow:0 8px 24px rgba(0,0,0,.12);
122
+ }
123
+ .analyze-btn:active{
124
+ transform:translateY(1px) scale(.98);
125
+ }
126
+
127
+ /* spinner placeholder */
128
+ .spinner{
129
+ width:1rem;height:1rem;
130
+ border:3px solid rgba(255,255,255,.4);
131
+ border-top-color:#fff;
132
+ border-radius:50%;
133
+ animation:spin 1s linear infinite;
134
+ }
135
+
136
+ @keyframes spin{to{transform:rotate(360deg);}}
137
+
138
+ /* ---------- Output box ---------- */
139
+ #result_output_box{
140
+ text-align:center;
141
+ font-size:1.15rem;
142
+ padding:1rem 1.5rem;
143
+ border-radius:var(--radius);
144
+ border:2px solid transparent;
145
+ min-height:3.5rem;
146
+ word-wrap:break-word;
147
+ }
148
+ .highlight-human{color:var(--accent);}
149
+ .highlight-ai{color:#EF4444;} /* red-500 */
150
+
151
+ /* ---------- Tabs ---------- */
152
+ .gradio-container .tabs{
153
+ margin-top:1rem!important;
154
+ }
155
+ .gradio-container .tab{
156
+ border:none!important;
157
+ }
158
+ .gradio-container .tabitem{
159
+ padding:.35rem .75rem!important;
160
+ border-radius:var(--radius) var(--radius) 0 0!important;
161
+ }
162
+
163
+ /* ---------- Utilities & media ---------- */
164
+ @media(max-width:768px){
165
+ .container{padding:1.25rem;}
166
+ }
167
+
168
+ @keyframes fade-slide-in{
169
+ from{opacity:0;transform:translateY(12px);}
170
+ to{opacity:1;transform:none;}
171
+ }
172
+ """
173
+ )
 
174
 
175
  with iface:
176
+ with gr.Column(elem_classes="container"):
177
+ # Hero section
178
  gr.Markdown(description)
179
+
180
+ # Input
181
  text_input = gr.Textbox(
182
+ label="Paste or type your text...",
183
+ placeholder="Start writing here…",
184
  elem_id="text_input_box",
185
+ lines=6
 
186
  )
187
+
188
+ # Analyze button (triggers classify_text)
189
+ analyze_btn = gr.Button("Analyze", elem_classes="analyze-btn")
190
+
191
+ # Output
192
  result_output = gr.Markdown("", elem_id="result_output_box")
193
+
194
+ # Example tabs
195
+ with gr.Tab("AI examples"):
196
+ gr.Examples(examples=AI_texts, inputs=text_input)
197
+ with gr.Tab("Human examples"):
198
+ gr.Examples(examples=Human_texts, inputs=text_input)
199
+
200
+ gr.Markdown(bottom_text, elem_id="bottom_text", elem_classes="footer")
201
+
202
+ # Wire the interaction
203
+ analyze_btn.click(
204
+ fn=classify_text,
205
+ inputs=text_input,
206
+ outputs=result_output,
207
+ show_progress="minimal" # toggles spinner internally
208
+ )
209
 
210
  iface.launch(share=True)