import gradio as gr import torch from transformers import AutoTokenizer, AutoModelForSeq2SeqLM from sentence_transformers import SentenceTransformer, util import numpy as np import requests import gradio.themes as grthemes import config # ---------------------- # Paraphrasing Model Setup # ---------------------- PARAPHRASE_MODEL_NAME = "Vamsi/T5_Paraphrase_Paws" paraphrase_tokenizer = AutoTokenizer.from_pretrained(PARAPHRASE_MODEL_NAME) paraphrase_model = AutoModelForSeq2SeqLM.from_pretrained(PARAPHRASE_MODEL_NAME) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") paraphrase_model = paraphrase_model.to(device) # ---------------------- # Semantic Similarity Model # ---------------------- similarity_model = SentenceTransformer('all-MiniLM-L6-v2') # ---------------------- # Tone Templates # ---------------------- tone_templates = { "Academic": "Paraphrase the following text in a formal, academic tone:", "Casual": "Paraphrase the following text in a casual, conversational tone:", "Friendly": "Paraphrase the following text in a friendly, approachable tone:", "Stealth": "Paraphrase the following text to bypass AI detectors and sound as human as possible:", } # ---------------------- # Paraphrasing Function # ---------------------- def paraphrase(text, tone): prompt = tone_templates[tone] + " " + text input_ids = paraphrase_tokenizer.encode(prompt, return_tensors="pt", max_length=256, truncation=True).to(device) outputs = paraphrase_model.generate( input_ids, do_sample=True, top_k=120, top_p=0.95, temperature=0.7, repetition_penalty=1.2, max_length=256, num_return_sequences=1 ) paraphrased = paraphrase_tokenizer.decode(outputs[0], skip_special_tokens=True) return paraphrased # ---------------------- # Semantic Similarity Function # ---------------------- def semantic_similarity(text1, text2): emb1 = similarity_model.encode(text1, convert_to_tensor=True) emb2 = similarity_model.encode(text2, convert_to_tensor=True) sim = util.pytorch_cos_sim(emb1, emb2).item() return sim # ---------------------- # Real AI Detection (Winston AI API) # ---------------------- def check_ai_score(text): api_key = config.WINSTON_AI_API_KEY api_url = config.WINSTON_AI_API_URL if not api_key: return None, "No API key set. Please add your Winston AI API key to config.py." headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } data = {"text": text, "sentences": False} try: response = requests.post(api_url, headers=headers, json=data, timeout=30) if response.status_code == 200: result = response.json() # Winston AI returns a 'score' (0-100, higher = more human) score = result.get("score", None) if score is not None: ai_prob = 1.0 - (score / 100.0) return ai_prob, None else: return None, "No score in Winston AI response." else: return None, f"Winston AI error: {response.status_code} {response.text}" except Exception as e: return None, f"Winston AI exception: {str(e)}" # ---------------------- # Humanization Score & Rating # ---------------------- def humanization_score(sim, ai_prob): # Lower similarity and lower AI probability = more human score = (1.0 - sim) * 0.5 + (1.0 - ai_prob) * 0.5 return score def humanization_rating(score): if score < 0.7: return f"⚠️ Still AI-like ({score:.2f})" elif score < 0.85: return f"👍 Acceptable ({score:.2f})" else: return f"✅ Highly Humanized ({score:.2f})" # ---------------------- # Main Processing Function # ---------------------- def process(text, tone): if not text.strip(): return "", "", 0.0, "", 0.0, "" # Pre-humanization AI detection pre_ai_prob, pre_err = check_ai_score(text) if pre_ai_prob is None: return "", f"AI Detection Error: {pre_err}", 0.0, "", 0.0, "" # Paraphrase try: paraphrased = paraphrase(text, tone) except Exception as e: return f"[Paraphrasing error: {str(e)}]", "", 0.0, "", 0.0, "" # Post-humanization AI detection post_ai_prob, post_err = check_ai_score(paraphrased) if post_ai_prob is None: return paraphrased, f"AI Detection Error: {post_err}", 0.0, "", 0.0, "" # Semantic similarity sim = semantic_similarity(text, paraphrased) # Humanization score score = humanization_score(sim, post_ai_prob) rating = humanization_rating(score) ai_score_str = f"Pre: {100*(1-pre_ai_prob):.1f}% human | Post: {100*(1-post_ai_prob):.1f}% human" return ( paraphrased, # gr.Textbox (string) ai_score_str, # gr.Markdown (string) sim, # gr.Number (float) rating, # gr.Markdown (string) score * 100, # gr.Number (float) "" ) # ---------------------- # Gradio UI # ---------------------- custom_theme = grthemes.Base( primary_hue="blue", secondary_hue="blue", neutral_hue="slate" ) with gr.Blocks(theme=custom_theme, title="AI Humanizer - Made by Taha") as demo: gr.Markdown(""" # 🧠 AI Humanizer
Rewrite AI text to sound 100% human Made by Taha
""", elem_id="header") with gr.Row(): with gr.Column(): text_in = gr.Textbox(label="Paste AI-generated text here", lines=8, placeholder="Paste your text...", elem_id="input-box") tone = gr.Dropdown(["Academic", "Casual", "Friendly", "Stealth"], value="Stealth", label="Tone Selector") btn = gr.Button("Humanize", elem_id="humanize-btn") with gr.Column(): text_out = gr.Textbox(label="Humanized Output", lines=8, interactive=False, elem_id="output-box") ai_scores = gr.Markdown("", elem_id="ai-scores") sim_score = gr.Number(label="Similarity (0=very different, 1=very similar)", interactive=False) rating = gr.Markdown("", elem_id="rating") human_score = gr.Number(label="Humanization Score (%)", interactive=False) btn.click( process, inputs=[text_in, tone], outputs=[text_out, ai_scores, sim_score, rating, human_score, gr.Textbox(visible=False)], api_name="humanize" ) gr.Markdown("""
Made by Taha | Free for unlimited use | Optimized for students and creators
""", elem_id="footer") demo.launch()