Spaces:
Running
Running
| import gradio as gr | |
| from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, AutoModelForSequenceClassification | |
| import os | |
| from huggingface_hub import login | |
| import torch | |
| # Authenticate with Hugging Face token | |
| HUGGINGFACE_TOKEN = os.getenv("HF_TOKEN") | |
| login(token=HUGGINGFACE_TOKEN) | |
| # Load Phi-4 Mini | |
| phi_id = "microsoft/phi-4-mini-instruct" | |
| phi_tokenizer = AutoTokenizer.from_pretrained(phi_id, token=HUGGINGFACE_TOKEN) | |
| phi_model = AutoModelForCausalLM.from_pretrained(phi_id, torch_dtype="auto", device_map="auto", token=HUGGINGFACE_TOKEN) | |
| phi_pipe = pipeline("text-generation", model=phi_model, tokenizer=phi_tokenizer) | |
| # Load T5 for paraphrasing | |
| t5_pipe = pipeline("text2text-generation", model="google-t5/t5-base") | |
| # Load AI Detector | |
| detector_id = "openai-community/roberta-base-openai-detector" | |
| detector_tokenizer = AutoTokenizer.from_pretrained(detector_id) | |
| detector_model = AutoModelForSequenceClassification.from_pretrained(detector_id) | |
| # ===== Helper: Circular HTML Visualization ===== | |
| def circular_html(ai_percent): | |
| color = ( | |
| "#4caf50" if ai_percent < 30 else | |
| "#2196f3" if ai_percent < 60 else | |
| "#f44336" if ai_percent < 90 else | |
| "#e91e63" | |
| ) | |
| text_color = "#fff" if ai_percent > 50 else "#222" | |
| return f""" | |
| <div style="display: flex; flex-direction: column; align-items: center; margin-top: 15px;"> | |
| <div style="font-size: 20px; font-weight: 500; margin-bottom: 12px; color: {text_color};"> | |
| AI Likelihood | |
| </div> | |
| <div style=" | |
| width: 180px; | |
| height: 180px; | |
| border-radius: 50%; | |
| background: conic-gradient({color} {ai_percent}%, #33333333 {ai_percent}%); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 32px; | |
| font-weight: bold; | |
| color: {text_color}; | |
| border: 6px solid rgba(255,255,255,0.1); | |
| box-shadow: 0 0 15px rgba(0,0,0,0.2); | |
| "> | |
| {ai_percent}% | |
| </div> | |
| </div> | |
| """ | |
| # ===== Chunking for Large Input Support ===== | |
| def chunk_text(text, max_tokens=300): | |
| paragraphs = text.split("\n\n") | |
| chunks, current = [], "" | |
| for para in paragraphs: | |
| if len(current.split()) + len(para.split()) < max_tokens: | |
| current += para + "\n\n" | |
| else: | |
| chunks.append(current.strip()) | |
| current = para + "\n\n" | |
| if current.strip(): | |
| chunks.append(current.strip()) | |
| return chunks | |
| # ===== Phi Prompt Wrapper ===== | |
| def generate_phi_prompt(text, instruction): | |
| chunks = chunk_text(text) | |
| outputs = [] | |
| for chunk in chunks: | |
| prompt = f"{instruction}\n{chunk}\nResponse:" | |
| result = phi_pipe(prompt, max_new_tokens=256, do_sample=False, temperature=0.3)[0]["generated_text"] | |
| outputs.append(result.split("Response:")[1].strip() if "Response:" in result else result.strip()) | |
| return "\n\n".join(outputs) | |
| # ===== Writing Tools ===== | |
| def fix_grammar(text): | |
| return generate_phi_prompt(text, "Correct all grammar and punctuation errors in the following text. Provide only the corrected version:") | |
| def improve_tone(text): | |
| return generate_phi_prompt(text, "Rewrite the following text to sound more formal, polite, and professional:") | |
| def improve_fluency(text): | |
| return generate_phi_prompt(text, "Rewrite the following to improve its clarity, sentence flow, and natural fluency:") | |
| def paraphrase(text): | |
| chunks = chunk_text(text, max_tokens=60) | |
| return "\n\n".join( | |
| t5_pipe("paraphrase this sentence: " + chunk, max_length=128, num_beams=5, do_sample=False)[0]["generated_text"] | |
| for chunk in chunks | |
| ) | |
| # ===== Apply Enhancements Based on Checkboxes ===== | |
| def apply_selected_enhancements(text, fix, tone, fluency, para): | |
| result = text | |
| if fix: | |
| result = fix_grammar(result) | |
| if tone: | |
| result = improve_tone(result) | |
| if fluency: | |
| result = improve_fluency(result) | |
| if para: | |
| result = paraphrase(result) | |
| return result | |
| # ===== AI Detection and Visualization ===== | |
| def detect_ai_percent(text): | |
| inputs = detector_tokenizer(text, return_tensors="pt", truncation=True, padding=True) | |
| with torch.no_grad(): | |
| logits = detector_model(**inputs).logits | |
| probs = torch.softmax(logits, dim=1).squeeze() | |
| ai_score = round(probs[1].item() * 100, 2) | |
| label = "Likely AI-Generated" if ai_score > 50 else "Likely Human" | |
| return label, circular_html(ai_score) | |
| # ===== Rewrite for Human-Like Text ===== | |
| def rewrite_to_human(text): | |
| return generate_phi_prompt(text, "Rewrite the following text so that it is indistinguishable from human writing and avoids AI detection. Be natural and fluent:") | |
| # ===== File Handling ===== | |
| def load_file(file_obj): | |
| if file_obj is None: | |
| return "" | |
| return file_obj.read().decode("utf-8") | |
| def save_file(text): | |
| path = "/tmp/output.txt" | |
| with open(path, "w", encoding="utf-8") as f: | |
| f.write(text) | |
| return path | |
| # ===== Gradio Interface ===== | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# ✍️ AI Writing Assistant + Circular AI Detector") | |
| gr.Markdown("Fix grammar, tone, fluency, paraphrase, and detect AI content with a modern circular progress view.") | |
| with gr.Row(): | |
| file_input = gr.File(label="📂 Upload .txt File", file_types=[".txt"]) | |
| load_btn = gr.Button("📥 Load Text") | |
| input_text = gr.Textbox(lines=12, label="Input Text") | |
| load_btn.click(fn=load_file, inputs=file_input, outputs=input_text) | |
| gr.Markdown("## ✅ Select Enhancements to Apply") | |
| with gr.Row(): | |
| check_fix = gr.Checkbox(label="✔️ Fix Grammar") | |
| check_tone = gr.Checkbox(label="🎯 Improve Tone") | |
| check_fluency = gr.Checkbox(label="🔄 Improve Fluency") | |
| check_paraphrase = gr.Checkbox(label="🌀 Paraphrase") | |
| run_selected = gr.Button("🚀 Run Selected Enhancements") | |
| output_text = gr.Textbox(lines=12, label="Output") | |
| run_selected.click( | |
| fn=apply_selected_enhancements, | |
| inputs=[input_text, check_fix, check_tone, check_fluency, check_paraphrase], | |
| outputs=output_text | |
| ) | |
| gr.Markdown("## 🕵️ AI Detection") | |
| detect_btn = gr.Button("Detect AI Probability") | |
| ai_summary = gr.Textbox(label="AI Summary", interactive=False) | |
| ai_circle = gr.HTML() | |
| detect_btn.click(fn=detect_ai_percent, inputs=input_text, outputs=[ai_summary, ai_circle]) | |
| gr.Markdown("## 🔁 Rewrite to Reduce AI Probability") | |
| rewrite_btn = gr.Button("Rewrite as Human") | |
| rewritten_text = gr.Textbox(lines=12, label="Rewritten Text") | |
| rewrite_btn.click(fn=rewrite_to_human, inputs=input_text, outputs=rewritten_text) | |
| gr.Markdown("## 📤 Download Output") | |
| download_btn = gr.Button("💾 Download Output") | |
| download_file = gr.File(label="Click to download", interactive=True) | |
| download_btn.click(fn=save_file, inputs=output_text, outputs=download_file) | |
| demo.launch() |