monstah0811 commited on
Commit
e02b410
ยท
verified ยท
1 Parent(s): 9a35c5c

Smaug branding; public-address check for links; upload size cap; queue cap; 10 s GPU reservation

Browse files
Files changed (2) hide show
  1. README.md +4 -3
  2. app.py +35 -13
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: AI Image Detector
3
  emoji: ๐Ÿ”
4
  colorFrom: blue
5
  colorTo: indigo
@@ -11,10 +11,11 @@ pinned: false
11
  license: apache-2.0
12
  models:
13
  - abacusai/Smaug-AI-Image-Detector
14
- short_description: Is this image AI-generated? Upload one or paste a link.
15
  ---
16
 
17
- Upload an image or paste a link to check whether it was made by an AI image generator, using
 
18
  [abacusai/Smaug-AI-Image-Detector](https://huggingface.co/abacusai/Smaug-AI-Image-Detector).
19
 
20
  Example images: a public-domain Flickr photo (CC0, via Megalith-10m) and an image generated with Z-Image-Turbo (Apache 2.0).
 
1
  ---
2
+ title: Smaug AI Image Detector
3
  emoji: ๐Ÿ”
4
  colorFrom: blue
5
  colorTo: indigo
 
11
  license: apache-2.0
12
  models:
13
  - abacusai/Smaug-AI-Image-Detector
14
+ short_description: Is this image AI-generated? Free, open-source detector
15
  ---
16
 
17
+ Smaug AI Image Detector by Abacus.AI: upload an image or paste a link to check whether it was made by an AI image
18
+ generator. Free and open source, running
19
  [abacusai/Smaug-AI-Image-Detector](https://huggingface.co/abacusai/Smaug-AI-Image-Detector).
20
 
21
  Example images: a public-domain Flickr photo (CC0, via Megalith-10m) and an image generated with Z-Image-Turbo (Apache 2.0).
app.py CHANGED
@@ -1,7 +1,9 @@
1
- """Demo for abacusai/Smaug-AI-Image-Detector: upload an image or paste a link, get the probability it is AI-generated."""
2
  import io
3
- import os
 
4
  import sys
 
5
 
6
  import gradio as gr
7
  import requests
@@ -12,26 +14,46 @@ from PIL import Image
12
 
13
  MODEL = 'abacusai/Smaug-AI-Image-Detector'
14
  MAX_BYTES = 20 * 1024 * 1024
 
15
 
16
- path = snapshot_download(MODEL, token=os.environ.get('HF_TOKEN')) # token only needed while the model repo is private
17
  sys.path.insert(0, path)
18
  from smaug_image_detect import SmaugImageDetect # noqa: E402 - ships with the model repo
19
 
20
  det = SmaugImageDetect.from_pretrained(path, device="cuda") # ZeroGPU: place on cuda at startup, real GPU inside @spaces.GPU
21
 
22
 
23
- @spaces.GPU(duration=20)
24
  def score(img):
25
  return det(img)
26
 
27
 
28
- def fetch(url):
29
- if not url.startswith(('http://', 'https://')):
 
 
30
  raise gr.Error('The link must start with http:// or https://')
31
  try:
32
- r = requests.get(url, timeout=15, stream=True, headers={'User-Agent': 'AbacusAI-AIImageDetectorDemo/1.0 (https://huggingface.co/spaces/abacusai/Smaug-AI-Image-Detector-demo)'})
33
- r.raise_for_status()
34
- data = r.raw.read(MAX_BYTES + 1, decode_content=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  except requests.RequestException as e:
36
  raise gr.Error(f'Could not download the image: {e}')
37
  if len(data) > MAX_BYTES:
@@ -54,9 +76,9 @@ def predict(image, url):
54
  return {'AI-generated': p, 'Real': 1 - p}, f'### {verdict}\nProbability AI-generated: **{p:.1%}** (threshold 50%)'
55
 
56
 
57
- with gr.Blocks(title='AI Image Detector') as demo:
58
- gr.Markdown('# AI Image Detector\nIs this image AI-generated? Upload one or paste a link. '
59
- f'Model: [{MODEL}](https://huggingface.co/{MODEL}) by [Abacus.AI](https://abacus.ai).')
60
  with gr.Row():
61
  with gr.Column():
62
  image = gr.Image(type='pil', label='Image', sources=['upload', 'clipboard'])
@@ -70,4 +92,4 @@ with gr.Blocks(title='AI Image Detector') as demo:
70
  'with a small AI-edited region as real. Do not use it as the only basis for decisions about people or their work.')
71
  btn.click(predict, [image, url], [label, text])
72
 
73
- demo.launch()
 
1
+ """Smaug AI Image Detector demo: upload an image or paste a link, get the probability it is AI-generated."""
2
  import io
3
+ import ipaddress
4
+ import socket
5
  import sys
6
+ from urllib.parse import urljoin, urlparse
7
 
8
  import gradio as gr
9
  import requests
 
14
 
15
  MODEL = 'abacusai/Smaug-AI-Image-Detector'
16
  MAX_BYTES = 20 * 1024 * 1024
17
+ UA = 'AbacusAI-SmaugAIImageDetector/1.0 (https://huggingface.co/spaces/abacusai/Smaug-AI-Image-Detector)'
18
 
19
+ path = snapshot_download(MODEL)
20
  sys.path.insert(0, path)
21
  from smaug_image_detect import SmaugImageDetect # noqa: E402 - ships with the model repo
22
 
23
  det = SmaugImageDetect.from_pretrained(path, device="cuda") # ZeroGPU: place on cuda at startup, real GPU inside @spaces.GPU
24
 
25
 
26
+ @spaces.GPU(duration=10) # scoring takes ~1-2 s; a short reservation leaves more of each visitor's GPU quota
27
  def score(img):
28
  return det(img)
29
 
30
 
31
+ def check_public(url):
32
+ """Only fetch from public internet addresses: no localhost, private networks or cloud metadata endpoints."""
33
+ u = urlparse(url)
34
+ if u.scheme not in ('http', 'https') or not u.hostname:
35
  raise gr.Error('The link must start with http:// or https://')
36
  try:
37
+ addrs = {a[4][0] for a in socket.getaddrinfo(u.hostname, u.port or (443 if u.scheme == 'https' else 80))}
38
+ except socket.gaierror:
39
+ raise gr.Error('Could not find that website.')
40
+ if not all(ipaddress.ip_address(a.split('%')[0]).is_global for a in addrs):
41
+ raise gr.Error('That link does not point to a public website.')
42
+
43
+
44
+ def fetch(url):
45
+ try:
46
+ for _ in range(4): # the link plus up to 3 redirects, each checked before it is followed
47
+ check_public(url)
48
+ r = requests.get(url, timeout=15, stream=True, allow_redirects=False, headers={'User-Agent': UA})
49
+ if r.is_redirect:
50
+ url = urljoin(url, r.headers['Location'])
51
+ continue
52
+ r.raise_for_status()
53
+ data = r.raw.read(MAX_BYTES + 1, decode_content=True)
54
+ break
55
+ else:
56
+ raise gr.Error('That link redirects too many times.')
57
  except requests.RequestException as e:
58
  raise gr.Error(f'Could not download the image: {e}')
59
  if len(data) > MAX_BYTES:
 
76
  return {'AI-generated': p, 'Real': 1 - p}, f'### {verdict}\nProbability AI-generated: **{p:.1%}** (threshold 50%)'
77
 
78
 
79
+ with gr.Blocks(title='Smaug AI Image Detector: is this image AI-generated?') as demo:
80
+ gr.Markdown('# Smaug AI Image Detector\nIs this image AI-generated? Upload one or paste a link. Free and open source: '
81
+ f'[{MODEL}](https://huggingface.co/{MODEL}) by [Abacus.AI](https://abacus.ai).')
82
  with gr.Row():
83
  with gr.Column():
84
  image = gr.Image(type='pil', label='Image', sources=['upload', 'clipboard'])
 
92
  'with a small AI-edited region as real. Do not use it as the only basis for decisions about people or their work.')
93
  btn.click(predict, [image, url], [label, text])
94
 
95
+ demo.queue(max_size=40).launch(max_file_size='20mb')