File size: 7,023 Bytes
dddd4a1 443c9b1 dddd4a1 443c9b1 dddd4a1 6b9d483 dddd4a1 6b9d483 bbf0867 64e5827 6b9d483 443c9b1 64e5827 6b9d483 bbf0867 443c9b1 6b9d483 5293700 6b9d483 5293700 6b9d483 5293700 6b9d483 5293700 6b9d483 5293700 6b9d483 5293700 6b9d483 bd48520 6b9d483 64e5827 6b9d483 64e5827 88051c8 64e5827 6b9d483 64e5827 88051c8 64e5827 bd48520 6b9d483 bbf0867 6b9d483 bbf0867 6b9d483 443c9b1 6b9d483 64e5827 6b9d483 64e5827 443c9b1 bbf0867 443c9b1 64e5827 bd48520 64e5827 bd48520 64e5827 bd48520 64e5827 bd48520 bbf0867 6b9d483 bbf0867 6b9d483 bbf0867 443c9b1 6b9d483 443c9b1 64e5827 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
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() |