fw7th commited on
Commit
6d3cb04
·
1 Parent(s): 0d4e07d

Add application file

Browse files
Files changed (3) hide show
  1. LICENSE +21 -0
  2. app.py +167 -0
  3. requirements.txt +5 -0
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 [7th]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
app.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import timm
3
+ import torch
4
+ from transformers import RobertaForSequenceClassification, RobertaTokenizer
5
+
6
+ "Vision"
7
+ vit_model = timm.create_model("hf_hub:Marqo/nsfw-image-detection-384", pretrained=True)
8
+ vit_model = vit_model.eval()
9
+
10
+ data_config = timm.data.resolve_model_data_config(vit_model)
11
+ transforms = timm.data.create_transform(**data_config, is_training=False)
12
+
13
+ "NLP"
14
+ tokenizer = RobertaTokenizer.from_pretrained("s-nlp/roberta_toxicity_classifier")
15
+ model = RobertaForSequenceClassification.from_pretrained(
16
+ "s-nlp/roberta_toxicity_classifier"
17
+ )
18
+
19
+
20
+ def moderate_image(img):
21
+ # Load your model
22
+ with torch.no_grad():
23
+ output = vit_model(transforms(img).unsqueeze(0)).softmax(dim=-1).cpu()
24
+
25
+ class_names = vit_model.pretrained_cfg["label_names"]
26
+ probabilities = output[0].tolist()
27
+ if probabilities[0] >= 0.3:
28
+ return class_names[0]
29
+ else:
30
+ return class_names[1]
31
+
32
+
33
+ def classify_toxic(text):
34
+ batch = tokenizer.encode(text, return_tensors="pt")
35
+ output = model(batch).cpu()
36
+ output = output.tolist()
37
+ max_idx = max(output)
38
+ return "Toxic" if output.index(max_idx) == 1 else "Neutral"
39
+
40
+
41
+ # -----------------------
42
+ # Apple-Minimal Styling
43
+ # -----------------------
44
+ custom_css = """
45
+ /* Center container and control width */
46
+ .gradio-container {
47
+ max-width: 900px !important;
48
+ margin: 0 auto !important;
49
+ padding: 20px 10px !important;
50
+ }
51
+
52
+ /* Header styling */
53
+ .clean-title {
54
+ font-size: 1.9rem;
55
+ font-weight: 600;
56
+ text-align: center;
57
+ margin-bottom: 1.2rem;
58
+ letter-spacing: -0.4px;
59
+ }
60
+
61
+ /* Apple-like card sections */
62
+ .apple-card {
63
+ padding: 18px;
64
+ border-radius: 12px;
65
+ border: 1px solid rgba(var(--block-border-color-rgb), 0.14);
66
+ background: var(--block-background-fill);
67
+ box-shadow: 0 1px 3px rgba(0,0,0,0.04);
68
+ margin-bottom: 18px;
69
+ }
70
+
71
+ /* Button styling: clean, flat, subtle */
72
+ .gr-button {
73
+ border-radius: 8px !important;
74
+ background: var(--button-secondary-background-fill) !important;
75
+ border: 1px solid rgba(var(--block-border-color-rgb), 0.22) !important;
76
+ transition: 0.2s ease !important;
77
+ }
78
+
79
+ .gr-button:hover {
80
+ background: var(--button-secondary-background-fill-hover) !important;
81
+ border-color: rgba(var(--block-border-color-rgb), 0.34) !important;
82
+ }
83
+
84
+ .gr-button:active {
85
+ background: var(--button-secondary-background-fill-pressed) !important;
86
+ }
87
+
88
+ /* Reduce blank space between elements */
89
+ .gr-block {
90
+ margin: 6px 0 !important;
91
+ }
92
+
93
+ /* Label style */
94
+ label {
95
+ font-weight: 500 !important;
96
+ }
97
+
98
+ /* Make body fill full height so footer can stick */
99
+ body, .gradio-container {
100
+ min-height: 100vh !important;
101
+ display: flex;
102
+ flex-direction: column;
103
+ }
104
+
105
+ /* Main content should expand, footer sits at bottom */
106
+ .main-content {
107
+ flex: 1 0 auto;
108
+ }
109
+
110
+ .footer {
111
+ flex-shrink: 0;
112
+ text-align: center;
113
+ font-size: 0.85rem;
114
+ opacity: 0.6;
115
+ padding: 14px 0;
116
+ border-top: 1px solid rgba(var(--block-border-color-rgb), 0.12);
117
+ margin-top: 25px;
118
+ }
119
+ """
120
+
121
+
122
+ # -----------------------
123
+ # UI Layout
124
+ # -----------------------
125
+ with gr.Blocks(
126
+ theme=gr.themes.Soft(primary_hue="violet", secondary_hue="slate"), css=custom_css
127
+ ) as demo:
128
+ with gr.Column(elem_classes="main-content"):
129
+ gr.Markdown("<div class='clean-title'>Content Safety Demo</div>")
130
+
131
+ with gr.Tabs():
132
+ # ---- NSFW Image Classification ---- #
133
+ with gr.Tab("NSFW Image Detection"):
134
+ with gr.Row():
135
+ with gr.Column(scale=3):
136
+ with gr.Group(elem_classes="apple-card"):
137
+ img_in = gr.Image(type="pil", label="Upload Image")
138
+ classify_img_btn = gr.Button("Classify")
139
+ img_clear_btn = gr.ClearButton(components=img_in)
140
+
141
+ with gr.Column(scale=2):
142
+ with gr.Group(elem_classes="apple-card"):
143
+ img_out = gr.Label(label="Prediction")
144
+
145
+ classify_img_btn.click(
146
+ fn=moderate_image, inputs=img_in, outputs=img_out
147
+ )
148
+
149
+ # ---- Toxic Text Classification ---- #
150
+ with gr.Tab("Toxic Text Detection"):
151
+ with gr.Row():
152
+ with gr.Column(scale=3):
153
+ with gr.Group(elem_classes="apple-card"):
154
+ txt_in = gr.Textbox(lines=6, label="Enter Text")
155
+ classify_txt_btn = gr.Button("Analyze")
156
+ text_clear_btn = gr.ClearButton(components=txt_in)
157
+
158
+ with gr.Column(scale=2):
159
+ with gr.Group(elem_classes="apple-card"):
160
+ txt_out = gr.Label(label="Prediction")
161
+
162
+ classify_txt_btn.click(classify_toxic, inputs=txt_in, outputs=txt_out)
163
+
164
+ gr.Markdown("<div class='footer'>Demo by 7th • Powered by Transformers</div>")
165
+
166
+ if __name__ == "__main__":
167
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio
2
+ transformers
3
+ torch
4
+ timm
5
+ pillow