Jin Zhu commited on
Commit
8b24479
·
1 Parent(s): a298edd

update code

Browse files
Files changed (2) hide show
  1. README.md +3 -1
  2. src/app.py +206 -114
README.md CHANGED
@@ -10,4 +10,6 @@ tags:
10
  pinned: true
11
  short_description: Powerful LLM Detection
12
  license: apache-2.0
13
- ---
 
 
 
10
  pinned: true
11
  short_description: Powerful LLM Detection
12
  license: apache-2.0
13
+ ---
14
+
15
+ To run the web app on your local device, please run the command: `streamlit run src/app.py`.
src/app.py CHANGED
@@ -39,36 +39,118 @@ import time
39
  st.markdown(
40
  """
41
  <style>
42
- /* Primary button (Detect) */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  div.stButton > button[kind="primary"] {
44
- background-color: #2a4f7c; /* 学术蓝 */
45
- border-color: #2a4f7c;
46
- color: white;
47
  font-weight: 600;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
 
50
  div.stButton > button[kind="primary"]:hover {
51
- background-color: #1f3a5f; /* hover 深一点 */
52
- border-color: #1f3a5f;
53
- color: white;
54
  }
55
 
56
  div.stButton > button[kind="primary"]:active {
57
- background-color: #1b2f4a;
58
- border-color: #1b2f4a;
59
  }
60
  </style>
61
  """,
62
  unsafe_allow_html=True
63
  )
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  # -----------------
66
  # Page Configuration
67
  # -----------------
68
  st.set_page_config(
69
  page_title="DetectGPTPro",
70
- page_icon="🔍",
71
- layout="wide"
72
  )
73
 
74
  # -----------------
@@ -194,17 +276,15 @@ if 'feedback_given' not in st.session_state:
194
  # -----------------
195
  # Streamlit Layout
196
  # -----------------
197
- _, col0, _ = st.columns((1, 5, 1))
198
- with col0:
199
- st.markdown(
200
- "<h1 style='text-align: center; color: #0072C3;'>DetectGPTPro: Super Adaptive LLM's Texts Detection</h1>",
201
- unsafe_allow_html=True,
202
- )
203
-
204
  st.markdown(
205
- """Pasted the text to be detected below and click the 'Detect' button to get the p-value. Use a better option may improve detection."""
 
206
  )
207
 
 
 
 
 
208
  # Display model loading status
209
  if not model_loaded:
210
  st.error(f"❌ Failed to load model: {error_message}")
@@ -214,25 +294,37 @@ if not model_loaded:
214
  # Main Interface
215
  # -----------------
216
  # --- Two columns: Input text & button | Result displays ---
217
- col1, col2 = st.columns((1, 1))
218
-
219
- with col1:
220
- text_input = st.text_area(
221
- label="",
222
- placeholder="Paste your text to be detected here",
223
- help="Typically, providing text with a longer content would get a more reliable result.",
224
- height=200,
225
- )
226
-
227
- detect_clicked = st.button("Detect", type="primary", use_container_width=True)
228
 
229
- selected_domain = st.selectbox(
230
- label="⚙️ Domain (Optional)",
231
- options=DOMAINS,
232
- index=0, # Default to General
233
- help="💡 **Tip:** Select the domain that best matches your text for improving detection accuracy. Default is 'General' that means consider all domains."
234
- )
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  with col2:
237
  statistics_ph = st.empty()
238
  statistics_ph.text_input(
@@ -241,7 +333,8 @@ with col2:
241
  disabled=True,
242
  help="Statistic will appear here after clicking the Detect button.",
243
  )
244
-
 
245
  pvalue_ph = st.empty()
246
  pvalue_ph.text_input(
247
  label="p-value",
@@ -295,83 +388,82 @@ if detect_clicked:
295
  }
296
 
297
  # Update score displays
298
- with col2:
299
- statistics_ph.text_input(
300
- label="Statistics",
301
- value=f"{crit:.6f}",
302
- disabled=True,
303
- help="Detection statistics will appear here after clicking Detect.",
304
- )
305
-
306
- pvalue_ph.text_input(
307
- label="p-value",
308
- value=f"{p_value:.6f}",
309
- disabled=True,
310
- help="p-value will appear here after clicking Detect.",
311
- )
312
-
313
- st.info(
314
- """
315
- **📊 p-value:**
316
- - **Lower p-value** (closer to 0) indicates text is **more likely AI-generated**
317
- - **Higher p-value** (closer to 1) indicates text is **more likely human-written**
318
- - Generally, p-value < 0.05 suggests the text may be LLM-generated
319
- """,
320
- icon="💡"
321
- )
322
-
323
- # ========== 🆕 Feedback buttons (moved here for better UX) ==========
324
- st.markdown("**📝 Result Feedback**: Does this detection result meet your expectations?")
325
-
326
- current_text = text_input
327
- current_domain = selected_domain
328
- current_statistics = crit
329
- current_pvalue = p_value
330
- feedback_col1, feedback_col2 = st.columns(2)
331
-
332
- with feedback_col1:
333
- if st.button("✅ Expected", use_container_width=True, type="secondary", key=f"expected_btn_{hash(text_input[:50])}"):
334
- try:
335
- success, message = feedback_manager.save_feedback(
336
- current_text,
337
- current_domain,
338
- current_statistics,
339
- current_pvalue,
340
- 'expected'
341
- )
342
- if success:
343
- st.success(" Thank you for your feedback!")
344
- st.caption(f"💾 {message}")
345
- else:
346
- st.error(f"Failed to save feedback: {message}")
347
- except Exception as e:
348
- st.error(f"Failed to save feedback: {str(e)}")
349
- import traceback
350
- st.code(traceback.format_exc())
351
-
352
- with feedback_col2:
353
- if st.button("❌ Unexpected", use_container_width=True, type="secondary", key=f"unexpected_btn_{hash(text_input[:50])}"):
354
- try:
355
- success, message = feedback_manager.save_feedback(
356
- current_text,
357
- current_domain,
358
- current_statistics,
359
- current_pvalue,
360
- 'unexpected'
361
- )
362
- if success:
363
- st.warning(" Feedback recorded! This will help us improve.")
364
- st.caption(f"💾 {message}")
365
- else:
366
- st.error(f"Failed to save feedback: {message}")
367
- except Exception as e:
368
- st.error(f"Failed to save feedback: {str(e)}")
369
- import traceback
370
- st.code(traceback.format_exc())
371
-
372
- if st.session_state.feedback_given:
373
- st.success("✅ Feedback submitted successfully!")
374
- # ============================================
375
 
376
  # Show detailed results
377
  with result_placeholder:
 
39
  st.markdown(
40
  """
41
  <style>
42
+ /* 控制 Streamlit columns 间距 */
43
+ div[data-testid="column"] {
44
+ padding-left: 3.0rem;
45
+ padding-right: 3.0rem;
46
+ }
47
+ </style>
48
+ """,
49
+ unsafe_allow_html=True
50
+ )
51
+
52
+ st.markdown(
53
+ """
54
+ <style>
55
+ /* Text area & text input */
56
+ textarea, input[type="text"] {
57
+ background-color: #f8fafc !important;
58
+ border: 1px solid #e5e7eb !important;
59
+ color: #111827 !important;
60
+ }
61
+
62
+ textarea::placeholder {
63
+ color: #9ca3af !important;
64
+ }
65
+
66
+ /* Selectbox */
67
+ div[data-testid="stSelectbox"] > div {
68
+ background-color: #f8fafc !important;
69
+ border: 1px solid #e5e7eb !important;
70
+ }
71
+ </style>
72
+ """,
73
+ unsafe_allow_html=True
74
+ )
75
+
76
+ st.markdown(
77
+ """
78
+ <style>
79
+ /* Detect button */
80
  div.stButton > button[kind="primary"] {
81
+ background-color: #fdae6b;
82
+ border: white;
83
+ color: black;
84
  font-weight: 600;
85
+ height: 4.3rem;
86
+
87
+ font-size: 1.1rem;
88
+
89
+ display: flex;
90
+ align-items: center;
91
+ justify-content: center;
92
+ gap: 0.55rem;
93
+ }
94
+
95
+ /* Icon inside Detect button */
96
+ div.stButton > button[kind="primary"] span {
97
+ font-size: 1.25rem;
98
+ line-height: 1;
99
  }
100
 
101
  div.stButton > button[kind="primary"]:hover {
102
+ background-color: #fd8d3c;
103
+ border-color: white;
 
104
  }
105
 
106
  div.stButton > button[kind="primary"]:active {
107
+ background-color: #fd8d3c;
108
+ border-color: white;
109
  }
110
  </style>
111
  """,
112
  unsafe_allow_html=True
113
  )
114
 
115
+ st.markdown(
116
+ """
117
+ <style>
118
+ /* Significance slider – light purple (academic) */
119
+
120
+ /* Slider track (inactive) */
121
+ div[data-testid="stSlider"] > div > div > div > div {
122
+ background-color: #ebe7f2;
123
+ }
124
+
125
+ /* Slider active range */
126
+ div[data-testid="stSlider"] div[role="slider"] {
127
+ background-color: #bebada !important;
128
+ border-color: #bebada !important;
129
+ }
130
+
131
+ /* Slider thumb */
132
+ div[data-testid="stSlider"] div[role="slider"]::before {
133
+ background-color: #bc80bd;
134
+ box-shadow: 0 0 0 1px rgba(188,128,189,0.4);
135
+ }
136
+
137
+ /* α value text */
138
+ div[data-testid="stSlider"] span {
139
+ color: #bc80bd;
140
+ font-weight: 500;
141
+ }
142
+ </style>
143
+ """,
144
+ unsafe_allow_html=True
145
+ )
146
+
147
+
148
  # -----------------
149
  # Page Configuration
150
  # -----------------
151
  st.set_page_config(
152
  page_title="DetectGPTPro",
153
+ page_icon="🕵️",
 
154
  )
155
 
156
  # -----------------
 
276
  # -----------------
277
  # Streamlit Layout
278
  # -----------------
 
 
 
 
 
 
 
279
  st.markdown(
280
+ "<h1 style='text-align: center;'> 🕵️ Adaptive LLM-texts Detector</h1>",
281
+ unsafe_allow_html=True,
282
  )
283
 
284
+ # st.markdown(
285
+ # """Pasted the text to be detected below and click the 'Detect' button to get the p-value. Use a better option may improve detection."""
286
+ # )
287
+
288
  # Display model loading status
289
  if not model_loaded:
290
  st.error(f"❌ Failed to load model: {error_message}")
 
294
  # Main Interface
295
  # -----------------
296
  # --- Two columns: Input text & button | Result displays ---
297
+ text_input = st.text_area(
298
+ label="",
299
+ placeholder="Paste your text to be detected here",
300
+ help="Typically, providing text with a longer content would get a more reliable result.",
301
+ height=200,
302
+ )
 
 
 
 
 
303
 
304
+ subcol11, subcol12, subcol13 = st.columns((1, 1, 1))
 
 
 
 
 
305
 
306
+ selected_domain = subcol11.selectbox(
307
+ label="⚙️ Domain",
308
+ options=DOMAINS,
309
+ index=0, # Default to General
310
+ # label_visibility="collapsed",
311
+ # label_visibility="hidden",
312
+ help="💡 **Tip:** Select the domain that best matches your text for improving detection accuracy. Default is 'General' that means consider all domains."
313
+ )
314
+
315
+ detect_clicked = subcol12.button("🔍 Detect", type="primary", use_container_width=True)
316
+
317
+ selected_level = subcol13.slider(
318
+ label="Significance (α)",
319
+ min_value=0.01,
320
+ max_value=0.2,
321
+ value=0.05,
322
+ step=0.005,
323
+ # label_visibility="collapsed",
324
+ help="💡 **Tip:** Select the significance level for the detection test."
325
+ )
326
+
327
+ col2, col3 = st.columns((1, 1))
328
  with col2:
329
  statistics_ph = st.empty()
330
  statistics_ph.text_input(
 
333
  disabled=True,
334
  help="Statistic will appear here after clicking the Detect button.",
335
  )
336
+
337
+ with col3:
338
  pvalue_ph = st.empty()
339
  pvalue_ph.text_input(
340
  label="p-value",
 
388
  }
389
 
390
  # Update score displays
391
+ statistics_ph.text_input(
392
+ label="Statistics",
393
+ value=f"{crit:.6f}",
394
+ disabled=True,
395
+ help="Detection statistics will appear here after clicking Detect.",
396
+ )
397
+
398
+ pvalue_ph.text_input(
399
+ label="p-value",
400
+ value=f"{p_value:.6f}",
401
+ disabled=True,
402
+ help="p-value will appear here after clicking Detect.",
403
+ )
404
+
405
+ st.info(
406
+ """
407
+ **📊 p-value:**
408
+ - **Lower p-value** (closer to 0) indicates text is **more likely AI-generated**
409
+ - **Higher p-value** (closer to 1) indicates text is **more likely human-written**
410
+ - Generally, p-value < 0.05 suggests the text may be LLM-generated
411
+ """,
412
+ icon="💡"
413
+ )
414
+
415
+ # ========== 🆕 Feedback buttons (moved here for better UX) ==========
416
+ st.markdown("**📝 Result Feedback**: Does this detection result meet your expectations?")
417
+
418
+ current_text = text_input
419
+ current_domain = selected_domain
420
+ current_statistics = crit
421
+ current_pvalue = p_value
422
+ feedback_col1, feedback_col2 = st.columns(2)
423
+
424
+ with feedback_col1:
425
+ if st.button("✅ Expected", use_container_width=True, type="secondary", key=f"expected_btn_{hash(text_input[:50])}"):
426
+ try:
427
+ success, message = feedback_manager.save_feedback(
428
+ current_text,
429
+ current_domain,
430
+ current_statistics,
431
+ current_pvalue,
432
+ 'expected'
433
+ )
434
+ if success:
435
+ st.success("✅ Thank you for your feedback!")
436
+ st.caption(f"💾 {message}")
437
+ else:
438
+ st.error(f"Failed to save feedback: {message}")
439
+ except Exception as e:
440
+ st.error(f"Failed to save feedback: {str(e)}")
441
+ import traceback
442
+ st.code(traceback.format_exc())
443
+
444
+ with feedback_col2:
445
+ if st.button("❌ Unexpected", use_container_width=True, type="secondary", key=f"unexpected_btn_{hash(text_input[:50])}"):
446
+ try:
447
+ success, message = feedback_manager.save_feedback(
448
+ current_text,
449
+ current_domain,
450
+ current_statistics,
451
+ current_pvalue,
452
+ 'unexpected'
453
+ )
454
+ if success:
455
+ st.warning("❌ Feedback recorded! This will help us improve.")
456
+ st.caption(f"💾 {message}")
457
+ else:
458
+ st.error(f"Failed to save feedback: {message}")
459
+ except Exception as e:
460
+ st.error(f"Failed to save feedback: {str(e)}")
461
+ import traceback
462
+ st.code(traceback.format_exc())
463
+
464
+ if st.session_state.feedback_given:
465
+ st.success("✅ Feedback submitted successfully!")
466
+ # ============================================
 
467
 
468
  # Show detailed results
469
  with result_placeholder: