File size: 3,792 Bytes
1e184ae d1b3ff3 84eeede 1e184ae 84eeede 1e184ae d1b3ff3 1e184ae 3f1e602 84eeede d1b3ff3 1e184ae d1b3ff3 84eeede 3f1e602 84eeede 3f1e602 84eeede 3f1e602 84eeede 1e184ae 84eeede 1e184ae 84eeede d1b3ff3 1e184ae 84eeede 1e184ae 84eeede 1e184ae 84eeede 1e184ae 84eeede 1e184ae | 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 | """
DIPPER Paraphrase API — HuggingFace Spaces deployment (GPU-enabled).
Uses google/t5-efficient-large-nl32 tokenizer with SamSJackson/paraphrase-dipper-no-ctx model.
"""
import gradio as gr
import torch
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
import time
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"[DIPPER] Device: {device}")
print("[DIPPER] Loading model...")
t0 = time.time()
# CRITICAL: tokenizer must come from the base model, NOT from SamSJackson repo (which has broken vocab=104)
tokenizer = AutoTokenizer.from_pretrained("google/t5-efficient-large-nl32")
model = AutoModelForSeq2SeqLM.from_pretrained("SamSJackson/paraphrase-dipper-no-ctx")
model = model.to(device)
model.eval()
print(f"[DIPPER] Model loaded in {time.time()-t0:.1f}s on {device}")
print(f"[DIPPER] Tokenizer vocab: {tokenizer.vocab_size}, Model params: {sum(p.numel() for p in model.parameters())/1e6:.1f}M")
# Self-test
test_input = "lexical = 40, order = 40 This is a test sentence about machine learning and artificial intelligence."
test_ids = tokenizer(test_input, return_tensors="pt", max_length=512, truncation=True)
test_ids = {k: v.to(device) for k, v in test_ids.items()}
with torch.no_grad():
test_out = model.generate(**test_ids, max_new_tokens=128, top_p=0.75, do_sample=True)
test_result = tokenizer.decode(test_out[0], skip_special_tokens=True)
print(f"[DIPPER] Self-test result: '{test_result}'")
def paraphrase(text: str, lex: int = 40, order: int = 40) -> str:
"""Paraphrase a single paragraph using DIPPER."""
if not text or not text.strip():
return ""
text = text.strip()
prefix = f"lexical = {lex}, order = {order} "
input_text = prefix + text
inputs = tokenizer(input_text, return_tensors="pt", max_length=1000, truncation=True)
inputs = {k: v.to(device) for k, v in inputs.items()}
t0 = time.time()
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=500,
top_p=0.75,
do_sample=True
)
elapsed = time.time() - t0
result = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(f"[DIPPER] {len(text)} -> {len(result)} chars in {elapsed:.1f}s")
return result
def batch_paraphrase(text: str, lex: int = 40, order: int = 40) -> str:
"""Paraphrase multi-paragraph text by processing each paragraph separately."""
if not text or not text.strip():
return ""
paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
results = []
for i, para in enumerate(paragraphs):
print(f"[DIPPER] Paragraph {i+1}/{len(paragraphs)}")
result = paraphrase(para, lex=lex, order=order)
results.append(result)
return '\n\n'.join(results)
# Gradio interface
with gr.Blocks(title="DIPPER Paraphrase API") as demo:
gr.Markdown("# DIPPER Paraphrase API\nRewrite text to bypass AI detection. Use the API endpoint for programmatic access.")
gr.Markdown(f"**Device:** {device} | **Tokenizer:** google/t5-efficient-large-nl32 | **Model:** SamSJackson/paraphrase-dipper-no-ctx (972M)")
with gr.Row():
with gr.Column():
input_text = gr.Textbox(label="Input Text", lines=10, placeholder="Paste text here...")
lex_slider = gr.Slider(0, 100, value=40, step=10, label="Lexical Control (40=optimal)")
ord_slider = gr.Slider(0, 100, value=40, step=10, label="Order Control (40=optimal)")
btn = gr.Button("Paraphrase", variant="primary")
with gr.Column():
output_text = gr.Textbox(label="Paraphrased Text", lines=10)
btn.click(fn=batch_paraphrase, inputs=[input_text, lex_slider, ord_slider], outputs=output_text)
demo.launch()
|