import os import tempfile import gradio as gr from PIL import Image # Import Tagger Processors from modules.taggers.joint import JointTaggerProcessor, run_joint_classifier from modules.taggers.cl import CLTaggerProcessor from modules.taggers.pixai import PixaiTaggerProcessor from modules.taggers.anime import AnimeTaggerProcessor from modules.taggers.gemini import GeminiTaggerProcessor # Import Managers and Utils from modules.managers.category_manager import kategori_sozlugu_yukle, kategorizelendir_ileri from modules.tagger_refinement import rafine_etiketler from modules.utils.tag_utils import unique_and_sort_tags from modules.managers.rule_manager import apply_additions # --- CL Tagger Modülünü İçe Aktarma --- try: from modules.cl_tagger_module import CLTagger except ImportError: try: from .cl_tagger_module import CLTagger # Fallback for relative import except ImportError: print("cl_tagger_module.py bulunamadı.") CLTagger = None # Global Instance Variables cl_tagger_instance = None try: if CLTagger: cl_tagger_instance = CLTagger() print("CL Tagger (ONNX) başarıyla yüklendi.") except Exception as e: print(f"CL Tagger (ONNX) yüklenirken hata: {e}") cl_tagger_instance = None # --- Ortak İşleme Fonksiyonu --- def _process_single_image( image, joint_thresh, use_joint, cl_gen_thresh, cl_char_thresh, use_cl_tagger, pixai_general_thresh, pixai_char_thresh, use_pixai_tagger, animetagger_model, animetagger_thresh, use_animetagger, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, sort_order="Alfabetik", device: str = "Auto", context_weight: float = 0.0, enable_cat_for_gemini=False, selected_cats_for_gemini=None ): if image is None: return "", "", "", "⚠️ Resim yüklenmedi.", [] alert_messages = [] all_tags = set() all_raw_tags_for_original_sort = [] gemini_result_text = "" current_joint_processor = JointTaggerProcessor(replacement_file_path, synonym_file_path, addition_file_path) current_cl_tagger_processor = CLTaggerProcessor(cl_tagger_instance, replacement_file_path, synonym_file_path, addition_file_path) current_pixai_processor = PixaiTaggerProcessor(replacement_file_path, synonym_file_path, addition_file_path) current_animetagger_processor = AnimeTaggerProcessor(replacement_file_path, synonym_file_path, addition_file_path) current_gemini_processor = GeminiTaggerProcessor() if use_joint: j_raw, j_alert, j_order = current_joint_processor.predict(image, joint_thresh, replacement_file_path, synonym_file_path, addition_file_path, sort_order, device) if "Hata" not in j_raw and "❌" not in j_alert: all_tags.update(t.strip() for t in j_raw.split(',') if t.strip()) all_raw_tags_for_original_sort.extend(j_order) else: alert_messages.append(f"Joint: {j_alert}") if use_cl_tagger: cl_raw, cl_alert, cl_order = current_cl_tagger_processor.predict(image, cl_gen_thresh, cl_char_thresh, replacement_file_path, synonym_file_path, addition_file_path, sort_order) if "Hata" not in cl_raw and "❌" not in cl_alert: all_tags.update(t.strip() for t in cl_raw.split(',') if t.strip()) all_raw_tags_for_original_sort.extend(cl_order) else: alert_messages.append(f"CL: {cl_alert}") if use_pixai_tagger: p_raw, p_alert, p_order = current_pixai_processor.predict(image, pixai_general_thresh, pixai_char_thresh, replacement_file_path, synonym_file_path, addition_file_path, "Orijinal", device) if "Hata" not in p_raw and "❌" not in p_alert: all_tags.update(t.strip() for t in p_raw.split(',') if t.strip()) all_raw_tags_for_original_sort.extend(p_order) else: alert_messages.append(f"PixAI: {p_alert}") if use_animetagger: a_raw, a_alert, a_order = current_animetagger_processor.predict(image, animetagger_model, animetagger_thresh, replacement_file_path, synonym_file_path, addition_file_path, "Orijinal", device) if "Hata" not in a_raw and "❌" not in a_alert: all_tags.update(t.strip() for t in a_raw.split(',') if t.strip()) all_raw_tags_for_original_sort.extend(a_order) else: alert_messages.append(f"AnimeTagger: {a_alert}") combined_final_tags_string = unique_and_sort_tags(", ".join(list(all_tags)), sort_order, original_order_ref=all_raw_tags_for_original_sort) refined_final_tags_string = rafine_etiketler(combined_final_tags_string, context_weight) refined_final_tags_string = apply_additions(refined_final_tags_string, addition_file_path) if use_gemini: active_prompt = gemini_prompt_vision if gemini_mode == "Tags": active_prompt = gemini_prompt_tags elif gemini_mode == "Vision + Tags": active_prompt = gemini_prompt_hybrid tags_content_for_gemini = "" if gemini_mode in ["Tags", "Vision + Tags"]: source_tags = refined_final_tags_string if refined_final_tags_string else combined_final_tags_string if enable_cat_for_gemini and selected_cats_for_gemini: tags_content_for_gemini = kategorizelendir_ileri(source_tags, selected_cats_for_gemini, kategori_sozlugu_yukle()) else: tags_content_for_gemini = source_tags g_text, g_alert = current_gemini_processor.predict( image, gemini_api_key, active_prompt, gemini_mode, tags_content_for_gemini, gemini_model_id, gemini_system_instruction ) if "❌" in g_alert or "⚠️" in g_alert: alert_messages.append(f"Gemini: {g_alert}") else: gemini_result_text = g_text final_alert = "✅ İşlem tamamlandı!" if not alert_messages else "❌ Hatalar: " + "; ".join(alert_messages) return combined_final_tags_string, refined_final_tags_string, gemini_result_text, final_alert, all_raw_tags_for_original_sort # --- Ana Etiketleme Fonksiyonları --- def toplu_islem( image, joint_thresh, use_joint, cl_gen_thresh, cl_char_thresh, use_cl_tagger, pixai_general_thresh, pixai_char_thresh, use_pixai_tagger, animetagger_model, animetagger_thresh, use_animetagger, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, enable_categorization, selected_categories, sort_order="Alfabetik", device: str = "Auto", context_weight: float = 0.0 ): final_tags_string, refined_tags_string, gemini_out, alert_message, _ = _process_single_image( image, joint_thresh, use_joint, cl_gen_thresh, cl_char_thresh, use_cl_tagger, pixai_general_thresh, pixai_char_thresh, use_pixai_tagger, animetagger_model, animetagger_thresh, use_animetagger, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, sort_order, device, context_weight, enable_cat_for_gemini=enable_categorization, selected_cats_for_gemini=selected_categories ) source_for_cat = refined_tags_string if refined_tags_string else final_tags_string categorized_tags_output = kategorizelendir_ileri(source_for_cat, selected_categories, kategori_sozlugu_yukle()) if (enable_categorization and selected_categories) else "" parts = [] if categorized_tags_output: parts.append(categorized_tags_output) if gemini_out: parts.append(gemini_out) combined_cat_gem = ", ".join(parts) return alert_message, final_tags_string, refined_tags_string, categorized_tags_output, gemini_out, combined_cat_gem def toplu_islem_batch( progress=gr.Progress(), images=None, joint_thresh=0.25, use_joint=True, cl_gen_thresh=0.55, cl_char_thresh=0.60, use_cl_tagger=True, pixai_general_thresh=0.30, pixai_char_thresh=0.85, use_pixai_tagger=False, animetagger_model="MobileNet V4 (Hızlı)", animetagger_thresh=0.35, use_animetagger=False, use_gemini=False, gemini_api_key="", gemini_mode="Vision", gemini_model_id="gemini-2.5-flash", gemini_prompt_vision="", gemini_prompt_tags="", gemini_prompt_hybrid="", gemini_system_instruction="", replacement_file_path="", synonym_file_path="", addition_file_path="", enable_categorization=False, selected_categories=None, sort_order="Alfabetik", device: str = "Auto", context_weight: float = 0.0 ): if not images: return "⚠️ Resim yüklenmedi.", "", None, "", "", "", "" all_final, all_refined, all_cat, all_orig, all_gemini, results_html, alerts = [], [], [], [], [], [], [] total = len(images) for i, img_obj in enumerate(images): progress(i / total, desc=f"İşleniyor: {os.path.basename(img_obj.name)} ({i+1}/{total})") try: image = Image.open(img_obj.name) except Exception as e: alerts.append(f"{img_obj.name}: Okuma hatası: {e}"); continue comb, ref, gem_out, alert, orig = _process_single_image( image, joint_thresh, use_joint, cl_gen_thresh, cl_char_thresh, use_cl_tagger, pixai_general_thresh, pixai_char_thresh, use_pixai_tagger, animetagger_model, animetagger_thresh, use_animetagger, use_gemini, gemini_api_key, gemini_mode, gemini_model_id, gemini_prompt_vision, gemini_prompt_tags, gemini_prompt_hybrid, gemini_system_instruction, replacement_file_path, synonym_file_path, addition_file_path, sort_order, device, context_weight, enable_cat_for_gemini=enable_categorization, selected_cats_for_gemini=selected_categories ) if "❌" in alert or "⚠️" in alert: alerts.append(f"{img_obj.name}: {alert}") else: all_final.append(comb); all_refined.append(ref); all_orig.extend(orig) if gem_out: all_gemini.append(f"--- {os.path.basename(img_obj.name)} ---\n{gem_out}") source = ref if ref else comb cat_out = kategorizelendir_ileri(source, selected_categories, kategori_sozlugu_yukle()) if (enable_categorization and selected_categories) else "" if cat_out: all_cat.append(cat_out) html_part = f"