Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub
Browse files- README.md +28 -12
- app.py +207 -0
- requirements.txt +16 -0
README.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
| 1 |
-
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
-
app_file: app.py
|
| 9 |
-
pinned: false
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: UltraProTagger
|
| 3 |
+
emoji: 🚀
|
| 4 |
+
colorFrom: purple
|
| 5 |
+
colorTo: blue
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 4.44.0
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: other
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# 🚀 UltraProTagger
|
| 14 |
+
|
| 15 |
+
AI-powered image tagging tool for Stable Diffusion and AI art datasets.
|
| 16 |
+
|
| 17 |
+
## Features
|
| 18 |
+
- Multiple AI taggers (JTP-3, CL, PixAI, Anime, Gemini)
|
| 19 |
+
- Batch processing
|
| 20 |
+
- Tag refinement with regex rules
|
| 21 |
+
- Category organization
|
| 22 |
+
|
| 23 |
+
## Usage Limits
|
| 24 |
+
- Free: 20 images/day
|
| 25 |
+
- Premium: 1000 images/day
|
| 26 |
+
|
| 27 |
+
## Get Premium Access
|
| 28 |
+
Visit: [PAYMENT_LINK]
|
app.py
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
UltraProTagger - HuggingFace Space Version
|
| 3 |
+
Auth + Rate Limiting entegreli
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import os
|
| 7 |
+
import time
|
| 8 |
+
import hashlib
|
| 9 |
+
import gradio as gr
|
| 10 |
+
from functools import wraps
|
| 11 |
+
from collections import defaultdict
|
| 12 |
+
from datetime import datetime, timedelta
|
| 13 |
+
|
| 14 |
+
# ==================== YAPILANDIRMA ====================
|
| 15 |
+
|
| 16 |
+
# Kullanım Limitleri
|
| 17 |
+
DAILY_LIMIT_FREE = 20 # Ücretsiz kullanıcılar için günlük limit
|
| 18 |
+
DAILY_LIMIT_PREMIUM = 1000 # Premium kullanıcılar için günlük limit
|
| 19 |
+
RATE_LIMIT_SECONDS = 5 # İstekler arası minimum süre
|
| 20 |
+
|
| 21 |
+
# Premium kullanıcı listesi (HuggingFace username'leri)
|
| 22 |
+
# Bu liste harici bir veritabanı veya dosyadan da okunabilir
|
| 23 |
+
PREMIUM_USERS = set([
|
| 24 |
+
# "hf_username1",
|
| 25 |
+
# "hf_username2",
|
| 26 |
+
])
|
| 27 |
+
|
| 28 |
+
# Ödeme linki
|
| 29 |
+
PAYMENT_LINK = "https://YOUR_PAYMENT_LINK_HERE"
|
| 30 |
+
|
| 31 |
+
# ==================== RATE LIMITER ====================
|
| 32 |
+
|
| 33 |
+
class RateLimiter:
|
| 34 |
+
def __init__(self):
|
| 35 |
+
self.usage = defaultdict(lambda: {"count": 0, "last_reset": datetime.now(), "last_request": None})
|
| 36 |
+
|
| 37 |
+
def _get_user_key(self, request: gr.Request = None):
|
| 38 |
+
"""Kullanıcı kimliğini belirle"""
|
| 39 |
+
if request and hasattr(request, 'username') and request.username:
|
| 40 |
+
return f"user:{request.username}"
|
| 41 |
+
# IP bazlı fallback
|
| 42 |
+
if request and hasattr(request, 'client') and request.client:
|
| 43 |
+
return f"ip:{request.client.host}"
|
| 44 |
+
return "anonymous"
|
| 45 |
+
|
| 46 |
+
def _reset_if_needed(self, user_key: str):
|
| 47 |
+
"""Günlük sayacı sıfırla"""
|
| 48 |
+
user_data = self.usage[user_key]
|
| 49 |
+
now = datetime.now()
|
| 50 |
+
if now - user_data["last_reset"] > timedelta(days=1):
|
| 51 |
+
user_data["count"] = 0
|
| 52 |
+
user_data["last_reset"] = now
|
| 53 |
+
|
| 54 |
+
def check_limit(self, request: gr.Request = None) -> tuple[bool, str, int]:
|
| 55 |
+
"""
|
| 56 |
+
Limit kontrolü yap
|
| 57 |
+
Returns: (allowed, message, remaining)
|
| 58 |
+
"""
|
| 59 |
+
user_key = self._get_user_key(request)
|
| 60 |
+
self._reset_if_needed(user_key)
|
| 61 |
+
|
| 62 |
+
user_data = self.usage[user_key]
|
| 63 |
+
username = request.username if request and hasattr(request, 'username') else None
|
| 64 |
+
|
| 65 |
+
# Premium kontrolü
|
| 66 |
+
is_premium = username in PREMIUM_USERS if username else False
|
| 67 |
+
daily_limit = DAILY_LIMIT_PREMIUM if is_premium else DAILY_LIMIT_FREE
|
| 68 |
+
|
| 69 |
+
# Rate limit kontrolü
|
| 70 |
+
if user_data["last_request"]:
|
| 71 |
+
elapsed = (datetime.now() - user_data["last_request"]).total_seconds()
|
| 72 |
+
if elapsed < RATE_LIMIT_SECONDS:
|
| 73 |
+
wait_time = RATE_LIMIT_SECONDS - elapsed
|
| 74 |
+
return False, f"⏳ Lütfen {wait_time:.1f} saniye bekleyin.", daily_limit - user_data["count"]
|
| 75 |
+
|
| 76 |
+
# Günlük limit kontrolü
|
| 77 |
+
if user_data["count"] >= daily_limit:
|
| 78 |
+
if is_premium:
|
| 79 |
+
return False, "❌ Günlük limitinize ulaştınız. Yarın tekrar deneyin.", 0
|
| 80 |
+
return False, f"❌ Günlük ücretsiz limitinize ({DAILY_LIMIT_FREE}) ulaştınız.\n\n🌟 **Premium erişim için:** [{PAYMENT_LINK}]({PAYMENT_LINK})", 0
|
| 81 |
+
|
| 82 |
+
# Sayacı güncelle
|
| 83 |
+
user_data["count"] += 1
|
| 84 |
+
user_data["last_request"] = datetime.now()
|
| 85 |
+
remaining = daily_limit - user_data["count"]
|
| 86 |
+
|
| 87 |
+
return True, f"✅ Kalan kullanım: {remaining}/{daily_limit}", remaining
|
| 88 |
+
|
| 89 |
+
rate_limiter = RateLimiter()
|
| 90 |
+
|
| 91 |
+
# ==================== AUTH WRAPPER ====================
|
| 92 |
+
|
| 93 |
+
def require_auth(func):
|
| 94 |
+
"""Fonksiyonları auth ve rate limit ile sarmala"""
|
| 95 |
+
@wraps(func)
|
| 96 |
+
def wrapper(*args, request: gr.Request = None, **kwargs):
|
| 97 |
+
# Rate limit kontrolü
|
| 98 |
+
allowed, message, remaining = rate_limiter.check_limit(request)
|
| 99 |
+
if not allowed:
|
| 100 |
+
raise gr.Error(message)
|
| 101 |
+
|
| 102 |
+
# Orijinal fonksiyonu çağır
|
| 103 |
+
result = func(*args, **kwargs)
|
| 104 |
+
|
| 105 |
+
return result
|
| 106 |
+
return wrapper
|
| 107 |
+
|
| 108 |
+
# ==================== ANA UYGULAMA ====================
|
| 109 |
+
|
| 110 |
+
def create_demo():
|
| 111 |
+
"""Ana Gradio arayüzünü oluştur"""
|
| 112 |
+
|
| 113 |
+
# Burada orijinal UltraProTagger modüllerini import edin
|
| 114 |
+
# from modules.tagger import toplu_islem, toplu_islem_batch
|
| 115 |
+
# from modules.ui.tab_single import create_single_tab
|
| 116 |
+
# vs...
|
| 117 |
+
|
| 118 |
+
with gr.Blocks(title="🚀 UltraProTagger") as demo:
|
| 119 |
+
|
| 120 |
+
gr.Markdown("""
|
| 121 |
+
# 🚀 UltraProTagger
|
| 122 |
+
|
| 123 |
+
**AI Destekli Görsel Etiketleme Aracı**
|
| 124 |
+
|
| 125 |
+
> ⚠️ **Kullanım Limitleri:**
|
| 126 |
+
> - Ücretsiz: Günde {} resim
|
| 127 |
+
> - Premium: Günde {} resim
|
| 128 |
+
>
|
| 129 |
+
> [🌟 Premium Erişim Al]({})
|
| 130 |
+
""".format(DAILY_LIMIT_FREE, DAILY_LIMIT_PREMIUM, PAYMENT_LINK))
|
| 131 |
+
|
| 132 |
+
with gr.Tab("🏷️ Etiketleme"):
|
| 133 |
+
with gr.Row():
|
| 134 |
+
input_image = gr.Image(label="Görsel Yükle", type="pil")
|
| 135 |
+
output_tags = gr.Textbox(label="Etiketler", lines=10)
|
| 136 |
+
|
| 137 |
+
process_btn = gr.Button("🔍 Etiketle", variant="primary")
|
| 138 |
+
usage_info = gr.Markdown("Kullanım durumu burada görünecek")
|
| 139 |
+
|
| 140 |
+
# Örnek etiketleme fonksiyonu (gerçek implementasyonda değiştirilecek)
|
| 141 |
+
@require_auth
|
| 142 |
+
def process_image(image):
|
| 143 |
+
if image is None:
|
| 144 |
+
return "Lütfen bir görsel yükleyin.", ""
|
| 145 |
+
|
| 146 |
+
# Burada gerçek etiketleme mantığı olacak
|
| 147 |
+
# tags = toplu_islem(image, ...)
|
| 148 |
+
|
| 149 |
+
# Placeholder
|
| 150 |
+
tags = "1girl, solo, looking_at_viewer, smile, long_hair, brown_hair"
|
| 151 |
+
return tags
|
| 152 |
+
|
| 153 |
+
def process_with_info(image, request: gr.Request):
|
| 154 |
+
try:
|
| 155 |
+
# Rate limit kontrolü
|
| 156 |
+
allowed, message, remaining = rate_limiter.check_limit(request)
|
| 157 |
+
if not allowed:
|
| 158 |
+
return "", message
|
| 159 |
+
|
| 160 |
+
# İşlemi yap
|
| 161 |
+
tags = process_image.__wrapped__(image)
|
| 162 |
+
return tags, f"✅ Kalan kullanım: {remaining}"
|
| 163 |
+
except Exception as e:
|
| 164 |
+
return "", f"❌ Hata: {str(e)}"
|
| 165 |
+
|
| 166 |
+
process_btn.click(
|
| 167 |
+
fn=process_with_info,
|
| 168 |
+
inputs=[input_image],
|
| 169 |
+
outputs=[output_tags, usage_info]
|
| 170 |
+
)
|
| 171 |
+
|
| 172 |
+
with gr.Tab("ℹ️ Bilgi"):
|
| 173 |
+
gr.Markdown(f"""
|
| 174 |
+
## 📋 Kullanım Koşulları
|
| 175 |
+
|
| 176 |
+
### Ücretsiz Kullanım
|
| 177 |
+
- Günlük **{DAILY_LIMIT_FREE}** resim işleme hakkı
|
| 178 |
+
- Tüm temel özellikler
|
| 179 |
+
|
| 180 |
+
### Premium Kullanım
|
| 181 |
+
- Günlük **{DAILY_LIMIT_PREMIUM}** resim işleme hakkı
|
| 182 |
+
- Öncelikli destek
|
| 183 |
+
- Yeni özellikler için erken erişim
|
| 184 |
+
|
| 185 |
+
---
|
| 186 |
+
|
| 187 |
+
## 💳 Premium Erişim
|
| 188 |
+
|
| 189 |
+
1. [{PAYMENT_LINK}]({PAYMENT_LINK}) adresinden ödeme yapın
|
| 190 |
+
2. HuggingFace kullanıcı adınızı belirtin
|
| 191 |
+
3. 24 saat içinde erişiminiz aktifleştirilecek
|
| 192 |
+
|
| 193 |
+
---
|
| 194 |
+
|
| 195 |
+
## 📞 İletişim
|
| 196 |
+
|
| 197 |
+
Sorularınız için: [İLETİŞİM_BİLGİSİ]
|
| 198 |
+
""")
|
| 199 |
+
|
| 200 |
+
return demo
|
| 201 |
+
|
| 202 |
+
# ==================== UYGULAMA BAŞLAT ====================
|
| 203 |
+
|
| 204 |
+
if __name__ == "__main__":
|
| 205 |
+
demo = create_demo()
|
| 206 |
+
demo.queue()
|
| 207 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# HuggingFace Space için gereksinimler
|
| 2 |
+
gradio>=4.44.0
|
| 3 |
+
torch>=2.0.0
|
| 4 |
+
torchvision
|
| 5 |
+
numpy
|
| 6 |
+
Pillow
|
| 7 |
+
requests
|
| 8 |
+
pandas
|
| 9 |
+
timm>=0.9.0
|
| 10 |
+
onnxruntime
|
| 11 |
+
huggingface_hub
|
| 12 |
+
safetensors
|
| 13 |
+
einops
|
| 14 |
+
google-generativeai
|
| 15 |
+
lark
|
| 16 |
+
joblib
|