Spaces:
Sleeping
Sleeping
Download utils.py from hizuk/purifai-api: direct link, hf CLI and curl.
- Browser
- Download file 4.92 kB
-
https://huggingface.co/spaces/hizuk/purifai-api/resolve/main/utils.py
- Command line
-
hf download hf://spaces/hizuk/purifai-api/utils.py
-
curl -L -o utils.py https://huggingface.co/spaces/hizuk/purifai-api/resolve/main/utils.py
4.92 kB
| import os | |
| import re | |
| import hashlib | |
| from supabase import create_client, Client | |
| from fastapi import HTTPException | |
| from transformers import pipeline, AutoTokenizer | |
| # ββ Thread Tuning (2-vCPU Optimization) βββββββββββββββββββββββββββββββββββββββ | |
| os.environ["OMP_NUM_THREADS"] = "2" | |
| os.environ["MKL_NUM_THREADS"] = "2" | |
| # ββ Environment Config ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| SUPABASE_URL = os.getenv("SUPABASE_URL") | |
| SUPABASE_KEY = os.getenv("SUPABASE_KEY") | |
| # ββ Supabase Client ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_supabase() -> Client: | |
| if not SUPABASE_URL or not SUPABASE_KEY: | |
| print("Warning: Supabase credentials missing.") | |
| return None | |
| return create_client(SUPABASE_URL, SUPABASE_KEY) | |
| # ββ Stable PyTorch Model Initialization ββββββββββββββββββββββββββββββββββββββ | |
| # Using the fine-tuned security model on the standard PyTorch engine | |
| HF_MODEL = "ProtectAI/deberta-v3-base-prompt-injection-v2" | |
| print(f"[PurifAI] Initializing Stable PyTorch pipeline: {HF_MODEL}") | |
| try: | |
| # We bypass ONNX and load directly into the stable transformer pipeline | |
| classifier = pipeline( | |
| "text-classification", | |
| model=HF_MODEL, | |
| tokenizer=HF_MODEL, | |
| truncation=True, | |
| max_length=512 | |
| ) | |
| print("[PurifAI] Stable PyTorch Engine loaded successfully.") | |
| except Exception as e: | |
| print(f"[PurifAI] CRITICAL: Failed to load PyTorch model: {e}") | |
| classifier = None | |
| # ββ Regexes ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| MARKETING_REGEX = re.compile( | |
| r"(unsubscribe|view in browser|manage preferences|opt-out|newsletter|privacy policy|click here to unsubscribe)", | |
| re.IGNORECASE | |
| ) | |
| HIGH_DANGER_REGEX = re.compile( | |
| r"(ignore all previous instructions|system override|jailbreak|you are now)", | |
| re.IGNORECASE | |
| ) | |
| # ββ Stable Inference Logic ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def query_huggingface(text: str): | |
| """ | |
| Runs inference locally using the stable PyTorch DeBERTa v3 model. | |
| """ | |
| if classifier is None: | |
| return {"error": "Model not loaded", "warming_up": False} | |
| try: | |
| # Run inference with strict truncation | |
| results = classifier(text, truncation=True, max_length=512) | |
| if isinstance(results, list) and len(results) > 0: | |
| prediction = results[0] | |
| label = prediction['label'] | |
| score = prediction['score'] | |
| # --- The 85% Confidence Threshold --- | |
| # If the AI thinks it's an injection but isn't 85% sure, force it to SAFE | |
| CONFIDENCE_THRESHOLD = 0.85 | |
| if label == "INJECTION" and score < CONFIDENCE_THRESHOLD: | |
| print(f"[PurifAI] Overriding INJECTION ({score:.2f}) to SAFE due to low confidence.") | |
| label = "SAFE" | |
| formatted = { | |
| label: score, | |
| "SAFE" if label == "INJECTION" else "INJECTION": 1.0 - score | |
| } | |
| return formatted | |
| return {"error": "Inference returned empty results"} | |
| except Exception as e: | |
| print(f"[PurifAI] PyTorch inference error: {str(e)}") | |
| return {"error": str(e)} | |
| # ββ Text Processing Helpers ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def clean_text(text: str) -> str: | |
| # 1. HTML Stripping | |
| cleaned = re.sub(r'<[^>]+>', ' ', text).strip() | |
| # 2. Fuzzy Deduplication | |
| fuzzy = re.sub(r'On\s+(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun).*?wrote:', '', cleaned, flags=re.IGNORECASE) | |
| fuzzy = re.sub(r'\d{1,2}:\d{2}\s*(?:AM|PM)?', '', fuzzy, flags=re.IGNORECASE) | |
| fuzzy = re.sub(r'\d{4}-\d{2}-\d{2}', '', fuzzy) | |
| return fuzzy.strip() | |
| def get_text_hash(text: str) -> str: | |
| return hashlib.sha256(text.encode('utf-8')).hexdigest() | |
| def chunk_text(text: str, chunk_size=400, overlap=50): | |
| words = text.split() | |
| if len(words) <= chunk_size: | |
| return [text] | |
| chunks = [] | |
| start = 0 | |
| while start < len(words): | |
| end = start + chunk_size | |
| chunk = ' '.join(words[start:end]) | |
| chunks.append(chunk) | |
| start = end - overlap | |
| return chunks |