fcakyon commited on
Commit
270ca78
·
verified ·
1 Parent(s): 3dd1121

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +8 -166
app.py CHANGED
@@ -1,19 +1,17 @@
1
  import os
2
  import gradio as gr
3
- import json
4
- from typing import Any, Dict, Tuple
5
  from dotenv import load_dotenv
6
- from urllib.request import urlopen, Request, urlretrieve
7
- from io import BytesIO
8
- from PIL import Image
9
- from functools import lru_cache
 
 
10
 
11
  load_dotenv()
12
 
13
  VIDDEXA_TOKEN = os.getenv("HF_TOKEN")
14
 
15
- _MODEL_CACHE: Dict[str, Any] = {}
16
-
17
  CUSTOM_CSS = """
18
  .verdict-safe { background-color: #D5F5E3; border: 2px solid #2ECC71; color: #1D8348; }
19
  .verdict-sensitive { background-color: #FCF3CF; border: 2px solid #F1C40F; color: #B7950B; }
@@ -23,162 +21,6 @@ CUSTOM_CSS = """
23
  footer {visibility: hidden}
24
  """
25
 
26
-
27
- @lru_cache(maxsize=32)
28
- def _download_image_bytes(image_url: str) -> bytes:
29
- req = Request(image_url, headers={"User-Agent": "viddexa-gradio-demo/1.0"})
30
- with urlopen(req, timeout=20) as resp:
31
- return resp.read()
32
-
33
-
34
- def _load_model(model_id: str) -> Any:
35
- """Loads a model and caches it."""
36
- if model_id in _MODEL_CACHE:
37
- return _MODEL_CACHE[model_id]
38
- try:
39
- from moderators.auto_model import AutoModerator
40
- model = AutoModerator.from_pretrained(model_id, token=VIDDEXA_TOKEN, use_fast=True)
41
- _MODEL_CACHE[model_id] = model
42
- return model
43
- except Exception as e:
44
- error_msg = f"Failed to load model: {model_id}. Error: {e}"
45
- if "401" in str(e):
46
- error_msg += "\n\nThis model may be private. Please ensure you have provided a valid Hugging Face token if required."
47
- raise gr.Error(error_msg)
48
-
49
-
50
- def _get_image_input(image_path: str | None, image_url: str | None) -> Image.Image:
51
- """Gets image data from either an uploaded file path or a URL."""
52
- if image_url:
53
- try:
54
- data = _download_image_bytes(image_url)
55
- img = Image.open(BytesIO(data))
56
- return img.convert("RGB")
57
- except Exception as fetch_err:
58
- raise gr.Error(f"Could not download or open the image from the URL: {fetch_err}")
59
- elif image_path:
60
- img = Image.open(image_path)
61
- return img.convert("RGB")
62
- else:
63
- raise gr.Error("Please upload an image or provide an image URL.")
64
-
65
-
66
- def _format_results(results: list) -> Tuple[str, Dict[str, float], str, Dict]:
67
- """Formats the model output for the Gradio interface."""
68
- if not results or "classifications" not in results[0]:
69
- return "<div class='verdict-card'>No classifications found.</div>", {}, "No classifications found.", {}
70
-
71
- classifications = results[0]["classifications"]
72
-
73
- label_output: Dict[str, float]
74
- if isinstance(classifications, dict):
75
- label_output = {str(k): float(v) for k, v in classifications.items()}
76
- else:
77
- try:
78
- label_output = {str(item['label']): float(item['score']) for item in classifications}
79
- except Exception:
80
- label_output = {}
81
-
82
- scores = {label.lower(): score for label, score in label_output.items()}
83
- nsfw_score = scores.get("nsfw", 0.0)
84
-
85
- if nsfw_score > 0.7:
86
- verdict_text = "HIGH RISK: NSFW"
87
- verdict_class = "verdict-nsfw"
88
- elif nsfw_score > 0.2:
89
- verdict_text = "MEDIUM RISK: SENSITIVE"
90
- verdict_class = "verdict-sensitive"
91
- else:
92
- verdict_text = "LOW RISK: SAFE"
93
- verdict_class = "verdict-safe"
94
-
95
- verdict_html = f"<div class='verdict-card {verdict_class}'>{verdict_text}</div>"
96
-
97
- markdown_output = "### All Scores\n---\n"
98
- for label, score in sorted(label_output.items(), key=lambda kv: kv[1], reverse=True):
99
- markdown_output += f"- **{label.capitalize()}**: {score:.4f}\n"
100
-
101
- return verdict_html, label_output, markdown_output, results[0]
102
-
103
-
104
- def analyze_image(image_path: str | None, image_url: str | None, model_choice: str,
105
- progress=gr.Progress(track_tqdm=True)):
106
- """The main inference function for the Gradio interface."""
107
- progress(0, desc="Initializing Analysis...")
108
- progress(0.2, desc="Processing Image...")
109
- input_image = _get_image_input(image_path, image_url)
110
- progress(0.5, desc=f"Loading Model: {os.path.basename(model_choice)}...")
111
- model = _load_model(model_choice)
112
- progress(0.8, desc="Running Inference...")
113
- results = model(input_image)
114
-
115
- json_results = [
116
- {"classifications": getattr(r, "classifications", r)}
117
- for r in results
118
- ]
119
- json_results = json.loads(json.dumps(json_results, ensure_ascii=False))
120
-
121
- progress(1, desc="Complete!")
122
- return _format_results(json_results)
123
-
124
-
125
- def analyze_image_with_status(image_path: str | None, image_url: str | None, model_choice: str,
126
- progress=gr.Progress(track_tqdm=True)):
127
- """Run analysis and also return a user-friendly status string."""
128
- verdict_html, label_scores, md_scores, json_obj = analyze_image(image_path, image_url, model_choice, progress)
129
- if image_url:
130
- status = f"Last analysed URL: {image_url}"
131
- elif image_path:
132
- status = "Last analysed uploaded image."
133
- else:
134
- status = "Last analysed: —"
135
- return verdict_html, label_scores, md_scores, json_obj, status
136
-
137
-
138
- EXAMPLE_ITEMS = [
139
- (
140
- "https://assets.clevelandclinic.org/transform/LargeFeatureImage/cd71f4bd-81d4-45d8-a450-74df78e4477a/Apples-184940975-770x533-1_jpg",
141
- "viddexa/nsfw-mini",
142
- "Apples (mini)",
143
- ),
144
- (
145
- "https://img.freepik.com/free-photo/breast-screening-is-very-important-every-woman_329181-14953.jpg",
146
- "viddexa/nsfw-nano",
147
- "Breast screening (nano)",
148
- ),
149
- (
150
- "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSbRwt56NYsiHwrT8oS-igzgeEzp7p3Jbe2dw&s",
151
- "viddexa/nsfw-mini",
152
- "Thumbnail (mini)",
153
- ),
154
- (
155
- "https://img.freepik.com/premium-photo/portrait-beautiful-young-woman_1048944-5548042.jpg",
156
- "viddexa/nsfw-nano",
157
- "Portrait (nano)",
158
- ),
159
- ]
160
-
161
-
162
- def run_example_by_index(evt: gr.SelectData):
163
- """Handle gallery selection: run analysis for the selected example and update inputs."""
164
- try:
165
- idx = int(getattr(evt, "index", 0))
166
- except Exception:
167
- idx = 0
168
- idx = max(0, min(idx, len(EXAMPLE_ITEMS) - 1))
169
- url, model, caption = EXAMPLE_ITEMS[idx]
170
- verdict_html, label_scores, md_scores, json_obj = analyze_image(None, url, model)
171
- status = f"Last analysed example: {caption}"
172
- return (
173
- verdict_html,
174
- label_scores,
175
- md_scores,
176
- json_obj,
177
- gr.update(value=model),
178
- gr.update(value=url),
179
- status,
180
- )
181
-
182
  with gr.Blocks(
183
  theme=gr.themes.Default(primary_hue=gr.themes.colors.teal),
184
  title="Visual Content Moderation",
@@ -261,7 +103,7 @@ with gr.Blocks(
261
  status_md = gr.Markdown("Last analysed: —", elem_id="last-example-status")
262
 
263
  examples_gallery.select(
264
- fn=run_example_by_index,
265
  outputs=[
266
  verdict_output,
267
  label_output,
@@ -274,7 +116,7 @@ with gr.Blocks(
274
  )
275
 
276
  run_btn.click(
277
- fn=analyze_image_with_status,
278
  inputs=[image_input, image_url_input, model_choice],
279
  outputs=[verdict_output, label_output, markdown_output, json_output, status_md],
280
  )
 
1
  import os
2
  import gradio as gr
 
 
3
  from dotenv import load_dotenv
4
+ from urllib.request import urlretrieve
5
+ from utils import (
6
+ EXAMPLE_ITEMS,
7
+ analyze_image_with_status,
8
+ run_example_by_index,
9
+ )
10
 
11
  load_dotenv()
12
 
13
  VIDDEXA_TOKEN = os.getenv("HF_TOKEN")
14
 
 
 
15
  CUSTOM_CSS = """
16
  .verdict-safe { background-color: #D5F5E3; border: 2px solid #2ECC71; color: #1D8348; }
17
  .verdict-sensitive { background-color: #FCF3CF; border: 2px solid #F1C40F; color: #B7950B; }
 
21
  footer {visibility: hidden}
22
  """
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  with gr.Blocks(
25
  theme=gr.themes.Default(primary_hue=gr.themes.colors.teal),
26
  title="Visual Content Moderation",
 
103
  status_md = gr.Markdown("Last analysed: —", elem_id="last-example-status")
104
 
105
  examples_gallery.select(
106
+ fn=lambda evt: run_example_by_index(evt, VIDDEXA_TOKEN),
107
  outputs=[
108
  verdict_output,
109
  label_output,
 
116
  )
117
 
118
  run_btn.click(
119
+ fn=lambda img, url, model, progress: analyze_image_with_status(img, url, model, VIDDEXA_TOKEN, progress),
120
  inputs=[image_input, image_url_input, model_choice],
121
  outputs=[verdict_output, label_output, markdown_output, json_output, status_md],
122
  )