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()