Hydragee commited on
Commit
d066e07
·
verified ·
1 Parent(s): 410d578

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +203 -179
  2. requirements.txt +23 -2
app.py CHANGED
@@ -1,207 +1,231 @@
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()
 
1
  """
2
+ UltraProTagger - HuggingFace Space Full Version
3
+ Dataset'ten tam uygulamayı yükler ve çalıştırır
4
  """
5
 
6
  import os
7
+ import sys
8
+ import subprocess
9
+
10
+ # ==================== DATASET'TEN KODU İNDİR ====================
11
+
12
+ def setup_from_dataset():
13
+ """Dataset'ten kaynak kodu indir ve kurulum yap"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ DATASET_REPO = "Hydragee/ultrapro-tagger"
16
+ LOCAL_PATH = "/home/user/app/ultrapro-tagger"
 
 
 
 
 
 
17
 
18
+ # Zaten indirilmişse atla
19
+ if os.path.exists(os.path.join(LOCAL_PATH, "main.py")):
20
+ print("✅ Kod zaten mevcut")
21
+ return LOCAL_PATH
 
 
 
22
 
23
+ print("📥 Dataset'ten kod indiriliyor...")
24
+
25
+ try:
26
+ from huggingface_hub import snapshot_download
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ # Dataset'i indir
29
+ local_dir = snapshot_download(
30
+ repo_id=DATASET_REPO,
31
+ repo_type="dataset",
32
+ local_dir=LOCAL_PATH,
33
+ token=os.environ.get("HF_TOKEN")
34
+ )
35
 
36
+ print(f"✅ Kod indirildi: {local_dir}")
37
+ return local_dir
 
 
38
 
39
+ except Exception as e:
40
+ print(f"❌ İndirme hatası: {e}")
41
+ return None
42
 
43
+ # Kurulum yap
44
+ APP_PATH = setup_from_dataset()
45
 
46
+ if APP_PATH:
47
+ # Sys path'e ekle
48
+ sys.path.insert(0, APP_PATH)
49
+ os.chdir(APP_PATH)
50
+
51
+ # ==================== ORIJINAL UYGULAMAYI YÜKLE ====================
52
+
53
+ import gradio as gr
54
+ from modules.shared_state import set_web_image, check_and_reset_tab_switch, shared_state
55
+ from modules.config_manager import load_config
56
+ from modules.ui.common import CSS_STYLES
57
+ from modules.ui.tab_settings import create_settings_tab
58
+ from modules.ui.tab_single import create_single_tab
59
+ from modules.ui.tab_batch import create_batch_tab
60
+ from modules.ui.tab_dual import create_dual_tab
61
+ from modules.ui.tab_tools import create_tools_tab
62
+ from modules.managers.rule_manager import (
63
+ read_replacement_file_content,
64
+ read_synonym_file_content,
65
+ read_addition_file_content
66
+ )
67
+ from modules.managers.localization_manager import get_str
68
+
69
+ # Tagger modülleri
70
+ try:
71
+ from modules.tagger import run_joint_classifier, cl_tagger_instance
72
+ except Exception as e:
73
+ print(f"⚠️ Tagger modülleri yüklenemedi: {e}")
74
+ run_joint_classifier = None
75
+ cl_tagger_instance = None
76
 
77
+ # Klasör Sabitleri
78
+ KATEGORILER_KLASORU = "data/rules/kategoriler"
79
+ ALT_KATEGORILER_KLASORU = "data/rules/alt_kategoriler"
80
+ REPLACEMENT_RULES_KLASORU = "data/rules/replacement_rules"
81
+ SYNONYM_RULES_KLASORU = "data/rules/synonym_rules"
82
+ ADDITION_RULES_KLASORU = "data/rules/addition_rules"
83
+ CONFIGLIST_KLASORU = "data/rules/configlist"
 
 
 
 
 
 
 
84
 
85
+ OS_ENV_HF_TOKEN = os.environ.get("HF_TOKEN")
86
 
87
+ def create_ui():
88
+ # Ayarları yükle
89
+ app_config = load_config()
90
+
91
+ # Tema Ayarını Uygula
92
+ current_theme_name = app_config.get("general_settings", {}).get("theme", "Default")
93
+ theme_object = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
+ if current_theme_name == "Soft":
96
+ theme_object = gr.themes.Soft()
97
+ elif current_theme_name == "Glass":
98
+ theme_object = gr.themes.Glass()
99
+ elif current_theme_name == "Monochrome":
100
+ theme_object = gr.themes.Monochrome()
101
+
102
+ with gr.Blocks(title=get_str("app_title"), css=CSS_STYLES, theme=theme_object) as demo:
103
 
104
+ # Uyarı mesajları
105
+ if OS_ENV_HF_TOKEN is None or run_joint_classifier is None:
106
+ gr.Markdown("""<div style='background-color:#fff3cd; color:#856404; padding:10px; border-radius:8px; border:1px solid #ffeeba; margin-bottom: 20px;'>⚠️ **UYARI:** Joint Tagger modeli başlatılamadı veya 'HF_TOKEN' ortam değişkeni ayarlanmamış.</div>""")
107
 
108
+ if cl_tagger_instance is None or (hasattr(cl_tagger_instance, 'session') and cl_tagger_instance.session is None):
109
+ gr.Markdown("""<div style='background-color:#f8d7da; color:#721c24; padding:10px; border-radius:8px; border:1px solid #f5c6cb; margin-bottom: 20px;'>❌ **HATA:** CL Tagger modeli başlatılamadı.</div>""")
110
+
111
+ # ANA TABS
112
+ with gr.Tabs() as tabs_ana_panel:
113
 
114
+ # 1. AYARLAR
115
+ settings_components = create_settings_tab(app_config)
116
 
117
+ # 2. TEKİL ETİKETLEME
118
+ single_components = create_single_tab(settings_components)
119
+
120
+ # 3. DUAL ETİKETLEME
121
+ dual_components = create_dual_tab(settings_components)
122
+
123
+ # 4. TOPLU ETİKETLEME
124
+ batch_components = create_batch_tab(settings_components)
125
+
126
+ # 5. ARAÇLAR
127
+ tools_components = create_tools_tab(app_config)
128
+
129
+ # --- ANA SEKME KONTROL DÖNGÜSÜ ---
130
+ def control_tab_switch():
131
+ if check_and_reset_tab_switch():
132
+ return gr.Tabs(selected="tab_single")
133
+ return gr.update()
134
+
135
+ main_loop_btn = gr.Button("Main Loop", visible=False, elem_id="main_loop_btn")
136
+ main_loop_btn.click(
137
+ fn=control_tab_switch,
138
+ inputs=[],
139
+ outputs=[tabs_ana_panel],
140
+ show_progress="hidden"
141
  )
142
+
143
+ # --- BUTON BAĞLANTILARI ---
144
+ def transfer_ve_gecis(text):
145
+ return text, gr.Tabs(selected="tab_kategori_araclari")
146
+
147
+ if "btn_send_tekil" in single_components and "toplu_filtered_output" in single_components:
148
+ single_components["btn_send_tekil"].click(
149
+ fn=transfer_ve_gecis,
150
+ inputs=[single_components["toplu_filtered_output"]],
151
+ outputs=[tools_components["etiket_input_common"], tabs_ana_panel]
152
+ )
153
+
154
+ if "btn_send_toplu" in batch_components and "toplu_batch_combined_original_tags" in batch_components:
155
+ batch_components["btn_send_toplu"].click(
156
+ fn=transfer_ve_gecis,
157
+ inputs=[batch_components["toplu_batch_combined_original_tags"]],
158
+ outputs=[tools_components["etiket_input_common"], tabs_ana_panel]
159
+ )
160
+
161
+ if "btn_send_dual" in dual_components and "dual_combined_all_tags" in dual_components:
162
+ dual_components["btn_send_dual"].click(
163
+ fn=transfer_ve_gecis,
164
+ inputs=[dual_components["dual_combined_all_tags"]],
165
+ outputs=[tools_components["etiket_input_common"], tabs_ana_panel]
166
+ )
167
+
168
+ gr.Markdown(
169
+ f"<h1 style='text-align: center; color: #4a00e0; margin-bottom: 5px; font-size: 1.5em; font-weight: 700; text-shadow: 1px 1px 2px rgba(0,0,0,0.1);'>🚀 {get_str('app_title')}</h1>"
170
+ f"<div style='text-align: center; color: #555; font-size: 0.9em;'>{get_str('app_subtitle')}</div>"
171
+ )
172
+
173
+ # Default dosya yüklemeleri
174
+ default_replacement_path = os.path.join(REPLACEMENT_RULES_KLASORU, "varsayilan_degisiklikler.txt")
175
+ default_synonym_path = os.path.join(SYNONYM_RULES_KLASORU, "varsayilan_birlesimler.txt")
176
+ default_addition_path = os.path.join(ADDITION_RULES_KLASORU, "varsayilan_eklemeler.txt")
177
+
178
+ demo.load(fn=lambda: read_replacement_file_content(default_replacement_path) if os.path.exists(default_replacement_path) else "", outputs=tools_components["replacement_file_content"])
179
+ demo.load(fn=lambda: read_synonym_file_content(default_synonym_path) if os.path.exists(default_synonym_path) else "", outputs=tools_components["synonym_file_content"])
180
+ demo.load(fn=lambda: read_addition_file_content(default_addition_path) if os.path.exists(default_addition_path) else "", outputs=tools_components["addition_file_content"])
181
+
182
+ demo.load(None, None, None, js="""
183
+ () => {
184
+ console.log("UltraProTagger: Smart Polling Başlatıldı");
185
+ setInterval(async () => {
186
+ try {
187
+ const response = await fetch('/api/check_status');
188
+ const data = await response.json();
189
+
190
+ if (data.switch_tab) {
191
+ const btnMain = document.getElementById('main_loop_btn');
192
+ if (btnMain) btnMain.click();
193
+ }
194
+
195
+ if (data.new_image) {
196
+ const btnTimer = document.getElementById('timer_btn');
197
+ if (btnTimer) btnTimer.click();
198
+ }
199
+ } catch (e) {
200
+ console.error("Polling hatası:", e);
201
+ }
202
+ }, 1000);
203
+ }
204
  """)
205
+
206
+ demo.queue()
207
+ return demo
208
+
209
+ # Klasörleri oluştur
210
+ folders_to_create = [
211
+ KATEGORILER_KLASORU, ALT_KATEGORILER_KLASORU,
212
+ REPLACEMENT_RULES_KLASORU, SYNONYM_RULES_KLASORU, ADDITION_RULES_KLASORU,
213
+ CONFIGLIST_KLASORU, "data/configs"
214
+ ]
215
+ for folder in folders_to_create:
216
+ os.makedirs(folder, exist_ok=True)
217
+
218
+ # Demo oluştur ve başlat
219
+ demo = create_ui()
220
+
221
+ else:
222
+ # Fallback: Basit hata mesajı
223
+ import gradio as gr
224
 
225
+ with gr.Blocks() as demo:
226
+ gr.Markdown("# ❌ Hata\nDataset'ten kod yüklenemedi. Lütfen daha sonra tekrar deneyin.")
227
 
228
  # ==================== UYGULAMA BAŞLAT ====================
229
 
230
  if __name__ == "__main__":
 
 
231
  demo.launch()
requirements.txt CHANGED
@@ -1,4 +1,25 @@
1
- # HuggingFace Space için gereksinimler
2
  gradio>=5.0.0
3
- Pillow
 
4
  numpy
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # UltraProTagger Full Application Requirements
2
  gradio>=5.0.0
3
+ torch>=2.0.0
4
+ torchvision
5
  numpy
6
+ Pillow
7
+ requests
8
+ pandas
9
+ matplotlib
10
+ timm>=0.9.0
11
+ onnxruntime
12
+ huggingface_hub>=0.21.0
13
+ safetensors
14
+ einops
15
+ google-generativeai
16
+ moviepy>=2.0.0
17
+ lark
18
+ joblib
19
+ compress-fasttext
20
+ scipy
21
+ hnswlib
22
+ msgspec
23
+ fastapi
24
+ uvicorn
25
+ pydantic