Download safety.py from FincH12/Automation_Threads_EU: direct link, hf CLI and curl.
- Browser
- Download file 10.1 kB
-
https://huggingface.co/spaces/FincH12/Automation_Threads_EU/resolve/main/safety.py
- Command line
-
hf download hf://spaces/FincH12/Automation_Threads_EU/safety.py
-
curl -L -o safety.py https://huggingface.co/spaces/FincH12/Automation_Threads_EU/resolve/main/safety.py
10.1 kB
| # -*- coding: utf-8 -*- | |
| import requests | |
| import json | |
| from config import GEMINI_API_BASE, GEMINI_MODEL | |
| # Список базовых локальных стоп-слов или подозрительных спам-маркеров | |
| SPAM_TRIGGER_WORDS = [ | |
| "купити зараз", "купи дешево", "безкоштовні гроші", "free money", "click here", | |
| "клікни сюди", "заробіток без вкладень", "швидкий прибуток", "найкраща ціна", | |
| "гарантований дохід", "розіграш айфонів", "iphone giveaway" | |
| ] | |
| def local_safety_check(text): | |
| """ | |
| Проверяет текст на наличие базовых спам-маркеров (регистронезависимо). | |
| """ | |
| text_lower = text.lower() | |
| for word in SPAM_TRIGGER_WORDS: | |
| if word in text_lower: | |
| return False, f"Обнаружено локальное стоп-слово: '{word}'" | |
| return True, "Локальный тест безопасности пройден." | |
| def gemini_compliance_audit(text): | |
| """ | |
| Использует gemini-web2api для комплексного аудита текста на триггер-слова, | |
| токсичность или спам-маркеры Meta Safety Compliance. | |
| Если текст не проходит аудит, возвращает перефразированную безопасную версию. | |
| """ | |
| prompt = f""" | |
| Проаналізуй наступний текст для публікації в мережі Threads на відповідність правилам безпеки (Meta Safety Compliance): відсутність спаму, агресивного маркетингу, заборонених слів чи клікбейту, який може призвести до тіньового бану (Shadowban). | |
| Текст: | |
| \"\"\"{text}\"\"\" | |
| Якщо текст повністю безпечний і відповідає правилам, поверни його без змін у форматі JSON: | |
| {{"status": "safe", "text": "оригінальний текст"}} | |
| Якщо текст містить небезпечні слова, спам-триггери чи підозрілі конструкції, перефразуй його безпечною та природною українською мовою та поверни у форматі JSON: | |
| {{"status": "rewritten", "text": "новий безпечний текст"}} | |
| Повертай ТІЛЬКИ чистий JSON-об'єкт, без маркдауну та зайвого тексту. | |
| """ | |
| headers = {"Content-Type": "application/json"} | |
| payload = { | |
| "model": GEMINI_MODEL, | |
| "messages": [{"role": "user", "content": prompt}], | |
| "temperature": 0.2 | |
| } | |
| try: | |
| response = requests.post(f"{GEMINI_API_BASE}/chat/completions", headers=headers, json=payload, timeout=30) | |
| if response.status_code == 200: | |
| result_json = response.json() | |
| content = result_json["choices"][0]["message"]["content"].strip() | |
| import re | |
| match = re.search(r'\{.*\}', content, re.DOTALL) | |
| if match: | |
| content = match.group(0) | |
| parsed = json.loads(content) | |
| return parsed.get("text", text) | |
| else: | |
| print(f"[Safety Warning] Ошибка Gemini API ({response.status_code}). Возвращен исходный текст.") | |
| return text | |
| except Exception as e: | |
| print(f"[Safety Exception] Ошибка при аудите контента: {e}. Возвращен исходный текст.") | |
| return text | |
| def filter_and_correct_content(text): | |
| """ | |
| Полный цикл проверки безопасности контента: | |
| 1. Локальный аудит по стоп-словам. | |
| 2. Семантический аудит через Gemini с автокоррекцией. | |
| """ | |
| # 1. Локальный быстрый чек | |
| is_local_safe, reason = local_safety_check(text) | |
| if not is_local_safe: | |
| print(f"[Safety Audit] {reason}. Запуск автоматической коррекции через Gemini...") | |
| # 2. Семантический чек и автокоррекция | |
| corrected_text = gemini_compliance_audit(text) | |
| return corrected_text | |
| def evaluate_image_with_vlm(image_path, text_context=""): | |
| """ | |
| Использует мультимодальную модель Llama-3.2-11b-Vision через Nvidia NIM | |
| для оценки качества сгенерированного изображения. Возвращает структурированный вердикт. | |
| """ | |
| import os | |
| import base64 | |
| import json | |
| from config import NVIDIA_NIM_API_KEY | |
| if not os.path.exists(image_path): | |
| print(f"[VLM Safety] Файл изображения {image_path} не найден для оценки.") | |
| return {"is_perfect": True, "issue_detected": None, "bg_prompt_improvement": "", "criticism": "Файл не найден"} | |
| try: | |
| with open(image_path, "rb") as image_file: | |
| encoded_image = base64.b64encode(image_file.read()).decode('utf-8') | |
| headers = { | |
| "Authorization": f"Bearer {NVIDIA_NIM_API_KEY}", | |
| "Content-Type": "application/json" | |
| } | |
| prompt_text = ( | |
| "Перед тобой сгенерированный пост-карточка для соцсети Threads (кириллица, украинский язык).\n" | |
| "Проанализируй изображение и верни строго JSON-объект с результатами анализа читаемости и дизайна.\n" | |
| "Будь ОБЪЕКТИВЕН и РЕАЛИСТИЧЕН: белый или очень светлый текст на темной или полупрозрачной темно-серой подложке панели является ИДЕАЛЬНО ЧИТАЕМЫМ. Не придирайся к мелочам. Ставь 'is_perfect': true во всех случаях, кроме критических дефектов (текст физически нечитаем, буквы накладываются друг на друга в кашу, или картинка сломана).\n" | |
| "Формат JSON:\n" | |
| "{\n" | |
| " \"is_perfect\": true или false,\n" | |
| " \"issue_detected\": \"описание проблемы на русском языке (коротко) или null\",\n" | |
| " \"bg_prompt_improvement\": \"дополнительные ключевые слова на английском языке для улучшения промпта фона (например, 'darker gradients, vibrant lighting, smooth empty space'), чтобы решить проблему. НЕ ПРОСИ делать фон сплошным или полностью черным, фон должен оставаться высокодетализированным, кинематографичным и ярким!\",\n" | |
| " \"criticism\": \"вердикт на русском языке (1-2 предложения)\"\n" | |
| "}\n" | |
| f"Контекст поста: '{text_context}'.\n" | |
| "Возвращай ТОЛЬКО чистый JSON-объект без маркдаун-разметки ```json." | |
| ) | |
| payload = { | |
| "model": "meta/llama-3.2-11b-vision-instruct", | |
| "messages": [ | |
| { | |
| "role": "user", | |
| "content": [ | |
| {"type": "text", "text": prompt_text}, | |
| { | |
| "type": "image_url", | |
| "image_url": { | |
| "url": f"data:image/png;base64,{encoded_image}" | |
| } | |
| } | |
| ] | |
| } | |
| ], | |
| "max_tokens": 350, | |
| "temperature": 0.1 | |
| } | |
| print(f"[VLM Safety] Аудит изображения {os.path.basename(image_path)} через Llama-3.2-Vision...") | |
| response = requests.post("https://integrate.api.nvidia.com/v1/chat/completions", headers=headers, json=payload, timeout=40) | |
| if response.status_code == 200: | |
| res_data = response.json() | |
| content = res_data['choices'][0]['message']['content'].strip() | |
| # Очищаем markdown-теги json | |
| if content.startswith("```"): | |
| content = content.split("```")[1] | |
| if content.startswith("json"): | |
| content = content[4:].strip() | |
| content = content.strip("`").strip() | |
| parsed = json.loads(content) | |
| print(f"\n=== [VLM ВЕРДИКТ ДЛЯ {os.path.basename(image_path)}] ===") | |
| print(f"Идеально: {parsed.get('is_perfect')}") | |
| print(f"Проблема: {parsed.get('issue_detected')}") | |
| print(f"Рекомендация: {parsed.get('bg_prompt_improvement')}") | |
| print(f"Критика: {parsed.get('criticism')}") | |
| print("==================================================\n") | |
| return parsed | |
| else: | |
| print(f"[VLM Safety Warning] Ошибка Nvidia NIM VLM API ({response.status_code}): {response.text}") | |
| return {"is_perfect": True, "issue_detected": None, "bg_prompt_improvement": "", "criticism": "Ошибка API"} | |
| except Exception as e: | |
| print(f"[VLM Safety Exception] Ошибка при парсинге вердикта VLM: {e}") | |
| return {"is_perfect": True, "issue_detected": None, "bg_prompt_improvement": "", "criticism": "Исключение при парсинге"} | |