mihalykiss commited on
Commit
34b438b
·
verified ·
1 Parent(s): b57f115

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -107
app.py CHANGED
@@ -4,31 +4,36 @@ import torch
4
  import re
5
  from tokenizers import normalizers
6
  from tokenizers.normalizers import Sequence, Replace, Strip, NFKC
7
- from tokenizers import Regex
 
8
 
 
9
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
10
 
 
11
  model1_path = "modernbert.bin"
12
  model2_path = "https://huggingface.co/mihalykiss/modernbert_2/resolve/main/Model_groups_3class_seed12"
13
  model3_path = "https://huggingface.co/mihalykiss/modernbert_2/resolve/main/Model_groups_3class_seed22"
14
- device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
15
 
16
  tokenizer = AutoTokenizer.from_pretrained("answerdotai/ModernBERT-base")
17
 
 
18
  model_1 = AutoModelForSequenceClassification.from_pretrained("answerdotai/ModernBERT-base", num_labels=41)
19
  model_1.load_state_dict(torch.load(model1_path, map_location=device))
20
  model_1.to(device).eval()
21
 
 
22
  model_2 = AutoModelForSequenceClassification.from_pretrained("answerdotai/ModernBERT-base", num_labels=41)
23
  model_2.load_state_dict(torch.hub.load_state_dict_from_url(model2_path, map_location=device))
24
  model_2.to(device).eval()
25
 
 
26
  model_3 = AutoModelForSequenceClassification.from_pretrained("answerdotai/ModernBERT-base", num_labels=41)
27
  model_3.load_state_dict(torch.hub.load_state_dict_from_url(model3_path, map_location=device))
28
  model_3.to(device).eval()
29
 
30
 
31
-
32
  label_mapping = {
33
  0: '13B', 1: '30B', 2: '65B', 3: '7B', 4: 'GLM130B', 5: 'bloom_7b',
34
  6: 'bloomz', 7: 'cohere', 8: 'davinci', 9: 'dolly', 10: 'dolly-v2-12b',
@@ -43,14 +48,13 @@ label_mapping = {
43
  }
44
 
45
  def clean_text(text: str) -> str:
46
- text = re.sub(r'\s{2,}', ' ', text)
47
  text = re.sub(r'\s+([,.;:?!])', r'\1', text)
48
  return text
49
 
50
-
51
- newline_to_space = Replace(Regex(r'\s*\n\s*'), " ")
52
  join_hyphen_break = Replace(Regex(r'(\w+)[--]\s*\n\s*(\w+)'), r"\1\2")
53
-
54
  tokenizer.backend_tokenizer.normalizer = Sequence([
55
  tokenizer.backend_tokenizer.normalizer,
56
  join_hyphen_break,
@@ -58,51 +62,92 @@ tokenizer.backend_tokenizer.normalizer = Sequence([
58
  Strip()
59
  ])
60
 
 
61
  def classify_text(text):
 
 
 
 
62
  cleaned_text = clean_text(text)
63
- if not text.strip():
64
- result_message = (
65
- f"---- \n"
66
- )
67
- return result_message
68
 
 
69
  inputs = tokenizer(cleaned_text, return_tensors="pt", truncation=True, padding=True).to(device)
70
 
 
71
  with torch.no_grad():
72
  logits_1 = model_1(**inputs).logits
73
  logits_2 = model_2(**inputs).logits
74
  logits_3 = model_3(**inputs).logits
75
-
 
76
  softmax_1 = torch.softmax(logits_1, dim=1)
77
  softmax_2 = torch.softmax(logits_2, dim=1)
78
  softmax_3 = torch.softmax(logits_3, dim=1)
79
-
 
80
  averaged_probabilities = (softmax_1 + softmax_2 + softmax_3) / 3
81
  probabilities = averaged_probabilities[0]
82
 
83
- ai_probs = probabilities.clone()
84
- ai_probs[24] = 0
85
- ai_total_prob = ai_probs.sum().item() * 100
86
- human_prob = 100 - ai_total_prob
 
87
 
88
- ai_argmax_index = torch.argmax(ai_probs).item()
 
 
 
 
 
 
89
  ai_argmax_model = label_mapping[ai_argmax_index]
90
 
91
- if human_prob > ai_total_prob:
92
  result_message = (
93
- f"**The text is** <span class='highlight-human'>**{human_prob:.2f}%** likely <b>Human written</b>.</span>"
94
  )
95
  else:
96
  result_message = (
97
- f"**The text is** <span class='highlight-ai'>**{ai_total_prob:.2f}%** likely <b>AI generated</b>.</span>\n\n"
98
  f"**Identified LLM: {ai_argmax_model}**"
99
  )
100
 
101
- return result_message
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
 
 
103
 
 
 
104
 
105
 
 
106
 
107
  title = "AI Text Detector"
108
 
@@ -112,7 +157,7 @@ This tool uses the <b>ModernBERT</b> model to identify whether a given text was
112
  ✅ <b>Human Verification:</b> Human-written content is clearly marked.<br>
113
  🔍 <b>Model Detection:</b> Can identify content from over 40 AI models.<br>
114
  📈 <b>Accuracy:</b> Works best with longer texts.<br>
115
- 📄 <b>Read more:</b> Our method is detailed in our paper:
116
  <a href="https://aclanthology.org/2025.genaidetect-1.15/" target="_blank" style="color: #007bff; text-decoration: none;"><b>LINK</b></a>.
117
  </div>
118
  <br>
@@ -120,7 +165,7 @@ Paste your text below to analyze its origin.
120
  """
121
  bottom_text = "**Developed by SzegedAI**"
122
 
123
-
124
  AI_texts = [
125
  "Camels are remarkable desert animals known for their unique adaptations to harsh, arid environments. Native to the Middle East, North Africa, and parts of Asia, camels have been essential to human life for centuries, serving as a mode of transportation, a source of food, and even a symbol of endurance and survival. There are two primary species of camels: the dromedary camel, which has a single hump and is commonly found in the Middle East and North Africa, and the Bactrian camel, which has two humps and is native to Central Asia. Their humps store fat, not water, as commonly believed, allowing them to survive long periods without food by metabolizing the stored fat for energy. Camels are highly adapted to desert life. They can go for weeks without water, and when they do drink, they can consume up to 40 gallons in one sitting. Their thick eyelashes, sealable nostrils, and wide, padded feet protect them from sand and help them walk easily on loose desert terrain.",
126
  "Wines are a fascinating reflection of culture, history, and craftsmanship. They embody a rich diversity shaped by the land, climate, and traditions where they are produced. From the bold reds of Bordeaux to the crisp whites of New Zealand, each bottle tells a unique story. What makes wine so special is its ability to connect people. Whether shared at a family dinner, a celebratory event, or a quiet evening with friends, wine enhances experiences and brings people together. The variety of flavors and aromas, influenced by grape type, fermentation techniques, and aging processes, make wine tasting a complex yet rewarding journey for the senses.",
@@ -131,89 +176,21 @@ Human_texts = [
131
  "The present book is intended as a text in basic mathematics. As such, it can have multiple use: for a one-year course in the high schools during the third or fourth year (if possible the third, so that calculus can be taken during the fourth year); for a complementary reference in earlier high school grades (elementary algebra and geometry are covered); for a one-semester course at the college level, to review or to get a firm foundation in the basic mathematics necessary to go ahead in calculus, linear algebra, or other topics. Years ago, the colleges used to give courses in “ college algebra” and other subjects which should have been covered in high school. More recently, such courses have been thought unnecessary, but some experiences I have had show that they are just as necessary as ever. What is happening is that thecolleges are getting a wide variety of students from high schools, ranging from exceedingly well-prepared ones who have had a good first course in calculus, down to very poorly prepared ones.",
132
  "Fats are rich in energy, build body cells, support brain development of infants, help body processes, and facilitate the absorption and use of fat-soluble vitamins A, D, E, and K. The major component of lipids is glycerol and fatty acids. According to chemical properties, fatty acids can be divided into saturated and unsaturated fatty acids. Generally lipids containing saturated fatty acids are solid at room temperature and include animal fats (butter, lard, tallow, ghee) and tropical oils (palm,coconut, palm kernel). Saturated fats increase the risk of heart disease.",
133
  "To make BERT handle a variety of down-stream tasks, our input representation is able to unambiguously represent both a single sentence and a pair of sentences (e.g., h Question, Answeri) in one token sequence. Throughout this work, a “sentence” can be an arbitrary span of contiguous text, rather than an actual linguistic sentence. A “sequence” refers to the input token sequence to BERT, which may be a single sentence or two sentences packed together. We use WordPiece embeddings (Wu et al., 2016) with a 30,000 token vocabulary. The first token of every sequence is always a special classification token ([CLS]). The final hidden state corresponding to this token is used as the aggregate sequence representation for classification tasks. Sentence pairs are packed together into a single sequence."]
 
 
134
  iface = gr.Blocks(css="""
135
  @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&display=swap');
136
- #text_input_box {
137
- border-radius: 10px;
138
- border: 2px solid #4CAF50;
139
- font-size: 18px;
140
- padding: 15px;
141
- margin-bottom: 20px;
142
- width: 60%;
143
- box-sizing: border-box;
144
- margin: auto;
145
- }
146
- .form.svelte-633qhp {
147
- background: none;
148
- border: none;
149
- box-shadow: none;
150
- }
151
- #result_output_box {
152
- border-radius: 10px;
153
- border: 2px solid #4CAF50;
154
- font-size: 18px;
155
- padding: 15px;
156
- margin-top: 20px;
157
- width: 40%;
158
- box-sizing: border-box;
159
- text-align: center;
160
- margin: auto;
161
- }
162
- @media (max-width: 768px) {
163
- #result_output_box {
164
- width: 100%;
165
- }
166
- #text_input_box{
167
- width: 100%;
168
- }
169
- }
170
- body {
171
- font-family: 'Roboto Mono', sans-serif !important;
172
- padding: 20px;
173
- display: block;
174
- justify-content: center;
175
- align-items: center;
176
- height: 100vh;
177
- overflow-y: auto;
178
- }
179
- .gradio-container {
180
- border: 1px solid #4CAF50;
181
- border-radius: 15px;
182
- padding: 30px;
183
- box-shadow: 0px 0px 10px rgba(0,255,0,0.6);
184
- max-width: 600px;
185
- margin: auto;
186
- overflow-y: auto;
187
- }
188
- h1 {
189
- text-align: center;
190
- font-size: 32px;
191
- font-weight: bold;
192
- margin-bottom: 30px;
193
- }
194
- .highlight-human {
195
- color: #4CAF50;
196
- font-weight: bold;
197
- background: rgba(76, 175, 80, 0.2);
198
- padding: 5px;
199
- border-radius: 8px;
200
- }
201
- .highlight-ai {
202
- color: #FF5733;
203
- font-weight: bold;
204
- background: rgba(255, 87, 51, 0.2);
205
- padding: 5px;
206
- border-radius: 8px;
207
- }
208
- #bottom_text {
209
- text-align: center;
210
- margin-top: 50px;
211
- font-weight: bold;
212
- font-size: 20px;
213
- }
214
- .block.svelte-11xb1hd{
215
- background: none !important;
216
- }
217
  """)
218
 
219
  with iface:
@@ -221,7 +198,10 @@ with iface:
221
  gr.Markdown(description)
222
  text_input = gr.Textbox(label="", placeholder="Type or paste your content here...", elem_id="text_input_box", lines=5)
223
  result_output = gr.Markdown("", elem_id="result_output_box")
224
- text_input.change(classify_text, inputs=text_input, outputs=result_output)
 
 
 
225
  with gr.Tab("AI text examples"):
226
  gr.Examples(AI_texts, inputs=text_input)
227
  with gr.Tab("Human text examples"):
 
4
  import re
5
  from tokenizers import normalizers
6
  from tokenizers.normalizers import Sequence, Replace, Strip, NFKC
7
+ from tokenizers import Regex
8
+ import matplotlib.pyplot as plt
9
 
10
+ # Set device to GPU if available, otherwise CPU
11
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
12
 
13
+ # --- Model and Tokenizer Setup ---
14
  model1_path = "modernbert.bin"
15
  model2_path = "https://huggingface.co/mihalykiss/modernbert_2/resolve/main/Model_groups_3class_seed12"
16
  model3_path = "https://huggingface.co/mihalykiss/modernbert_2/resolve/main/Model_groups_3class_seed22"
 
17
 
18
  tokenizer = AutoTokenizer.from_pretrained("answerdotai/ModernBERT-base")
19
 
20
+ # Load Model 1 from local path
21
  model_1 = AutoModelForSequenceClassification.from_pretrained("answerdotai/ModernBERT-base", num_labels=41)
22
  model_1.load_state_dict(torch.load(model1_path, map_location=device))
23
  model_1.to(device).eval()
24
 
25
+ # Load Model 2 from URL
26
  model_2 = AutoModelForSequenceClassification.from_pretrained("answerdotai/ModernBERT-base", num_labels=41)
27
  model_2.load_state_dict(torch.hub.load_state_dict_from_url(model2_path, map_location=device))
28
  model_2.to(device).eval()
29
 
30
+ # Load Model 3 from URL
31
  model_3 = AutoModelForSequenceClassification.from_pretrained("answerdotai/ModernBERT-base", num_labels=41)
32
  model_3.load_state_dict(torch.hub.load_state_dict_from_url(model3_path, map_location=device))
33
  model_3.to(device).eval()
34
 
35
 
36
+ # --- Label Mapping and Text Cleaning ---
37
  label_mapping = {
38
  0: '13B', 1: '30B', 2: '65B', 3: '7B', 4: 'GLM130B', 5: 'bloom_7b',
39
  6: 'bloomz', 7: 'cohere', 8: 'davinci', 9: 'dolly', 10: 'dolly-v2-12b',
 
48
  }
49
 
50
  def clean_text(text: str) -> str:
51
+ text = re.sub(r'\s{2,}', ' ', text)
52
  text = re.sub(r'\s+([,.;:?!])', r'\1', text)
53
  return text
54
 
55
+ # --- Tokenizer Normalizer Configuration ---
56
+ newline_to_space = Replace(Regex(r'\s*\n\s*'), " ")
57
  join_hyphen_break = Replace(Regex(r'(\w+)[--]\s*\n\s*(\w+)'), r"\1\2")
 
58
  tokenizer.backend_tokenizer.normalizer = Sequence([
59
  tokenizer.backend_tokenizer.normalizer,
60
  join_hyphen_break,
 
62
  Strip()
63
  ])
64
 
65
+
66
  def classify_text(text):
67
+ """
68
+ Classifies the text and generates a plot of the top 5 AI model predictions.
69
+ Returns both the result message and the plot figure.
70
+ """
71
  cleaned_text = clean_text(text)
72
+ # If input is empty, clear the outputs
73
+ if not cleaned_text.strip():
74
+ return "", None
 
 
75
 
76
+ # Tokenize input and move to the appropriate device
77
  inputs = tokenizer(cleaned_text, return_tensors="pt", truncation=True, padding=True).to(device)
78
 
79
+ # Perform inference with the three models
80
  with torch.no_grad():
81
  logits_1 = model_1(**inputs).logits
82
  logits_2 = model_2(**inputs).logits
83
  logits_3 = model_3(**inputs).logits
84
+
85
+ # Apply softmax to get probabilities
86
  softmax_1 = torch.softmax(logits_1, dim=1)
87
  softmax_2 = torch.softmax(logits_2, dim=1)
88
  softmax_3 = torch.softmax(logits_3, dim=1)
89
+
90
+ # Average the probabilities from the three models
91
  averaged_probabilities = (softmax_1 + softmax_2 + softmax_3) / 3
92
  probabilities = averaged_probabilities[0]
93
 
94
+ # --- Generate Text Result ---
95
+ human_prob = probabilities[24].item()
96
+ ai_probs_clone = probabilities.clone()
97
+ ai_probs_clone[24] = 0 # Exclude human probability for AI total
98
+ ai_total_prob = ai_probs_clone.sum().item()
99
 
100
+ # Normalize probabilities to get a percentage-based decision
101
+ total_decision_prob = human_prob + ai_total_prob
102
+ human_percentage = (human_prob / total_decision_prob) * 100
103
+ ai_percentage = (ai_total_prob / total_decision_prob) * 100
104
+
105
+ # Determine the most likely AI model
106
+ ai_argmax_index = torch.argmax(ai_probs_clone).item()
107
  ai_argmax_model = label_mapping[ai_argmax_index]
108
 
109
+ if human_percentage > ai_percentage:
110
  result_message = (
111
+ f"**The text is** <span class='highlight-human'>**{human_percentage:.2f}%** likely <b>Human written</b>.</span>"
112
  )
113
  else:
114
  result_message = (
115
+ f"**The text is** <span class='highlight-ai'>**{ai_percentage:.2f}%** likely <b>AI generated</b>.</span>\n\n"
116
  f"**Identified LLM: {ai_argmax_model}**"
117
  )
118
 
119
+ # --- Generate Plot ---
120
+ # Find the top 5 AI models by probability
121
+ ai_probs_for_plot = probabilities.clone()
122
+ ai_probs_for_plot[24] = -1 # Ensure 'human' isn't in the top 5 AI list
123
+ top_5_probs, top_5_indices = torch.topk(ai_probs_for_plot, 5)
124
+
125
+ # Prepare data for plotting
126
+ top_5_probs = top_5_probs.cpu().numpy()
127
+ top_5_labels = [label_mapping[i.item()] for i in top_5_indices]
128
+
129
+ # Create a horizontal bar plot
130
+ fig, ax = plt.subplots(figsize=(10, 5))
131
+ bars = ax.barh(top_5_labels, top_5_probs, color='#4CAF50', alpha=0.8)
132
+ ax.set_xlabel('Probability', fontsize=12)
133
+ ax.set_title('Top 5 Predicted AI Models', fontsize=14, fontweight='bold')
134
+ ax.invert_yaxis() # Highest probability on top
135
+ ax.grid(axis='x', linestyle='--', alpha=0.6)
136
+
137
+ # Add percentage labels on the bars
138
+ for bar in bars:
139
+ width = bar.get_width()
140
+ label_x_pos = width + 0.01
141
+ ax.text(label_x_pos, bar.get_y() + bar.get_height() / 2, f'{width:.2%}', va='center')
142
 
143
+ ax.set_xlim(0, max(top_5_probs) * 1.18) # Adjust x-axis limit for labels
144
+ plt.tight_layout()
145
 
146
+ # Return both the text message and the plot figure
147
+ return result_message, fig
148
 
149
 
150
+ # --- Gradio Interface Definition ---
151
 
152
  title = "AI Text Detector"
153
 
 
157
  ✅ <b>Human Verification:</b> Human-written content is clearly marked.<br>
158
  🔍 <b>Model Detection:</b> Can identify content from over 40 AI models.<br>
159
  📈 <b>Accuracy:</b> Works best with longer texts.<br>
160
+ 📄 <b>Read more:</b> Our method is detailed in our paper:
161
  <a href="https://aclanthology.org/2025.genaidetect-1.15/" target="_blank" style="color: #007bff; text-decoration: none;"><b>LINK</b></a>.
162
  </div>
163
  <br>
 
165
  """
166
  bottom_text = "**Developed by SzegedAI**"
167
 
168
+ # Example texts
169
  AI_texts = [
170
  "Camels are remarkable desert animals known for their unique adaptations to harsh, arid environments. Native to the Middle East, North Africa, and parts of Asia, camels have been essential to human life for centuries, serving as a mode of transportation, a source of food, and even a symbol of endurance and survival. There are two primary species of camels: the dromedary camel, which has a single hump and is commonly found in the Middle East and North Africa, and the Bactrian camel, which has two humps and is native to Central Asia. Their humps store fat, not water, as commonly believed, allowing them to survive long periods without food by metabolizing the stored fat for energy. Camels are highly adapted to desert life. They can go for weeks without water, and when they do drink, they can consume up to 40 gallons in one sitting. Their thick eyelashes, sealable nostrils, and wide, padded feet protect them from sand and help them walk easily on loose desert terrain.",
171
  "Wines are a fascinating reflection of culture, history, and craftsmanship. They embody a rich diversity shaped by the land, climate, and traditions where they are produced. From the bold reds of Bordeaux to the crisp whites of New Zealand, each bottle tells a unique story. What makes wine so special is its ability to connect people. Whether shared at a family dinner, a celebratory event, or a quiet evening with friends, wine enhances experiences and brings people together. The variety of flavors and aromas, influenced by grape type, fermentation techniques, and aging processes, make wine tasting a complex yet rewarding journey for the senses.",
 
176
  "The present book is intended as a text in basic mathematics. As such, it can have multiple use: for a one-year course in the high schools during the third or fourth year (if possible the third, so that calculus can be taken during the fourth year); for a complementary reference in earlier high school grades (elementary algebra and geometry are covered); for a one-semester course at the college level, to review or to get a firm foundation in the basic mathematics necessary to go ahead in calculus, linear algebra, or other topics. Years ago, the colleges used to give courses in “ college algebra” and other subjects which should have been covered in high school. More recently, such courses have been thought unnecessary, but some experiences I have had show that they are just as necessary as ever. What is happening is that thecolleges are getting a wide variety of students from high schools, ranging from exceedingly well-prepared ones who have had a good first course in calculus, down to very poorly prepared ones.",
177
  "Fats are rich in energy, build body cells, support brain development of infants, help body processes, and facilitate the absorption and use of fat-soluble vitamins A, D, E, and K. The major component of lipids is glycerol and fatty acids. According to chemical properties, fatty acids can be divided into saturated and unsaturated fatty acids. Generally lipids containing saturated fatty acids are solid at room temperature and include animal fats (butter, lard, tallow, ghee) and tropical oils (palm,coconut, palm kernel). Saturated fats increase the risk of heart disease.",
178
  "To make BERT handle a variety of down-stream tasks, our input representation is able to unambiguously represent both a single sentence and a pair of sentences (e.g., h Question, Answeri) in one token sequence. Throughout this work, a “sentence” can be an arbitrary span of contiguous text, rather than an actual linguistic sentence. A “sequence” refers to the input token sequence to BERT, which may be a single sentence or two sentences packed together. We use WordPiece embeddings (Wu et al., 2016) with a 30,000 token vocabulary. The first token of every sequence is always a special classification token ([CLS]). The final hidden state corresponding to this token is used as the aggregate sequence representation for classification tasks. Sentence pairs are packed together into a single sequence."]
179
+
180
+ # Define the Gradio interface with CSS styling
181
  iface = gr.Blocks(css="""
182
  @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&display=swap');
183
+ #text_input_box { border-radius: 10px; border: 2px solid #4CAF50; font-size: 18px; padding: 15px; margin-bottom: 20px; width: 60%; box-sizing: border-box; margin: auto; }
184
+ .form.svelte-633qhp { background: none; border: none; box-shadow: none; }
185
+ #result_output_box { border-radius: 10px; border: 2px solid #4CAF50; font-size: 18px; padding: 15px; margin-top: 20px; width: 40%; box-sizing: border-box; text-align: center; margin: auto; }
186
+ @media (max-width: 768px) { #result_output_box { width: 100%; } #text_input_box{ width: 100%; } }
187
+ body { font-family: 'Roboto Mono', sans-serif !important; padding: 20px; display: block; justify-content: center; align-items: center; height: 100vh; overflow-y: auto; }
188
+ .gradio-container { border: 1px solid #4CAF50; border-radius: 15px; padding: 30px; box-shadow: 0px 0px 10px rgba(0,255,0,0.6); max-width: 800px; margin: auto; overflow-y: auto; }
189
+ h1 { text-align: center; font-size: 32px; font-weight: bold; margin-bottom: 30px; }
190
+ .highlight-human { color: #4CAF50; font-weight: bold; background: rgba(76, 175, 80, 0.2); padding: 5px; border-radius: 8px; }
191
+ .highlight-ai { color: #FF5733; font-weight: bold; background: rgba(255, 87, 51, 0.2); padding: 5px; border-radius: 8px; }
192
+ #bottom_text { text-align: center; margin-top: 50px; font-weight: bold; font-size: 20px; }
193
+ .block.svelte-11xb1hd{ background: none !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  """)
195
 
196
  with iface:
 
198
  gr.Markdown(description)
199
  text_input = gr.Textbox(label="", placeholder="Type or paste your content here...", elem_id="text_input_box", lines=5)
200
  result_output = gr.Markdown("", elem_id="result_output_box")
201
+ plot_output = gr.Plot(label="Model Probability Distribution")
202
+
203
+ text_input.change(classify_text, inputs=text_input, outputs=[result_output, plot_output])
204
+
205
  with gr.Tab("AI text examples"):
206
  gr.Examples(AI_texts, inputs=text_input)
207
  with gr.Tab("Human text examples"):