Spaces:
Running
Running
import gradio as gr | |
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, pipeline | |
import torch | |
import random | |
import re | |
import warnings | |
import math | |
from collections import Counter | |
warnings.filterwarnings("ignore") | |
# Import NLTK with error handling | |
try: | |
import nltk | |
import textstat | |
from nltk.corpus import wordnet | |
from nltk.tokenize import sent_tokenize, word_tokenize | |
NLTK_AVAILABLE = True | |
except ImportError as e: | |
print(f"NLTK import error: {e}") | |
NLTK_AVAILABLE = False | |
# Fallback imports | |
import textstat | |
# Download required NLTK data if available | |
if NLTK_AVAILABLE: | |
try: | |
nltk.data.find('tokenizers/punkt_tab') | |
except LookupError: | |
print("Downloading punkt_tab...") | |
nltk.download('punkt_tab') | |
try: | |
nltk.data.find('tokenizers/punkt') | |
except LookupError: | |
print("Downloading punkt...") | |
nltk.download('punkt') | |
try: | |
nltk.data.find('corpora/wordnet') | |
except LookupError: | |
print("Downloading wordnet...") | |
nltk.download('wordnet') | |
try: | |
nltk.data.find('corpora/omw-1.4') | |
except LookupError: | |
print("Downloading omw-1.4...") | |
nltk.download('omw-1.4') | |
# Load multiple models for diverse paraphrasing | |
models = { | |
"t5_paraphrase": { | |
"model_name": "Vamsi/T5_Paraphrase_Paws", | |
"tokenizer": None, | |
"model": None | |
}, | |
"pegasus": { | |
"model_name": "tuner007/pegasus_paraphrase", | |
"tokenizer": None, | |
"model": None | |
} | |
} | |
# Initialize models | |
for key, model_info in models.items(): | |
try: | |
model_info["tokenizer"] = AutoTokenizer.from_pretrained(model_info["model_name"]) | |
model_info["model"] = AutoModelForSeq2SeqLM.from_pretrained(model_info["model_name"]) | |
print(f"Loaded {key} model successfully") | |
except Exception as e: | |
print(f"Failed to load {key}: {e}") | |
class AdvancedHumanizer: | |
def __init__(self): | |
self.transition_words = [ | |
"However", "Nevertheless", "Furthermore", "Moreover", "Additionally", | |
"Consequently", "Therefore", "Thus", "In contrast", "Similarly", | |
"On the other hand", "Meanwhile", "Subsequently", "Notably", | |
"Importantly", "Significantly", "Interestingly", "Remarkably" | |
] | |
self.hedging_phrases = [ | |
"appears to", "seems to", "tends to", "suggests that", "indicates that", | |
"may well", "might be", "could be", "potentially", "presumably", | |
"arguably", "to some extent", "in many cases", "generally speaking" | |
] | |
self.academic_connectors = [ | |
"In light of this", "Building upon this", "This finding suggests", | |
"It is worth noting that", "This observation", "These results", | |
"The evidence indicates", "This approach", "The data reveals" | |
] | |
def add_natural_variations(self, text): | |
"""Add natural linguistic variations to make text less robotic""" | |
if NLTK_AVAILABLE: | |
sentences = sent_tokenize(text) | |
else: | |
# Fallback: simple sentence splitting | |
sentences = [s.strip() for s in text.split('.') if s.strip()] | |
varied_sentences = [] | |
for i, sentence in enumerate(sentences): | |
if not sentence.endswith('.') and NLTK_AVAILABLE: | |
sentence += '.' | |
elif not sentence.endswith('.') and not NLTK_AVAILABLE: | |
sentence += '.' | |
# Randomly add hedging language | |
if random.random() < 0.3 and not any(phrase in sentence.lower() for phrase in self.hedging_phrases): | |
hedge = random.choice(self.hedging_phrases) | |
if sentence.startswith("The ") or sentence.startswith("This "): | |
sentence = sentence.replace("The ", f"The {hedge} ", 1) | |
sentence = sentence.replace("This ", f"This {hedge} ", 1) | |
# Add transitional phrases for flow | |
if i > 0 and random.random() < 0.4: | |
connector = random.choice(self.academic_connectors) | |
sentence = f"{connector}, {sentence.lower()}" | |
varied_sentences.append(sentence) | |
return " ".join(varied_sentences) | |
def diversify_vocabulary(self, text): | |
"""Replace common words with synonyms for variation""" | |
if not NLTK_AVAILABLE: | |
# Fallback: simple word replacements | |
replacements = { | |
"significant": "notable", "important": "crucial", "demonstrate": "show", | |
"utilize": "use", "implement": "apply", "generate": "create", | |
"facilitate": "help", "optimize": "improve", "analyze": "examine" | |
} | |
result = text | |
for old, new in replacements.items(): | |
result = re.sub(r'\b' + old + r'\b', new, result, flags=re.IGNORECASE) | |
return result | |
words = word_tokenize(text) | |
result = [] | |
for word in words: | |
if word.isalpha() and len(word) > 4 and random.random() < 0.2: | |
synonyms = [] | |
for syn in wordnet.synsets(word): | |
for lemma in syn.lemmas(): | |
if lemma.name() != word and '_' not in lemma.name(): | |
synonyms.append(lemma.name()) | |
if synonyms: | |
replacement = random.choice(synonyms[:3]) # Use top 3 synonyms | |
result.append(replacement) | |
else: | |
result.append(word) | |
else: | |
result.append(word) | |
return " ".join(result) | |
def adjust_sentence_structure(self, text): | |
"""Modify sentence structures for more natural flow""" | |
if NLTK_AVAILABLE: | |
sentences = sent_tokenize(text) | |
else: | |
# Fallback: simple sentence splitting | |
sentences = [s.strip() + '.' for s in text.split('.') if s.strip()] | |
modified = [] | |
for sentence in sentences: | |
# Randomly split long sentences | |
if len(sentence.split()) > 20 and random.random() < 0.4: | |
words = sentence.split() | |
mid_point = len(words) // 2 | |
# Find a good breaking point near the middle | |
for i in range(mid_point - 3, mid_point + 3): | |
if i < len(words) and words[i].rstrip('.,').lower() in ['and', 'but', 'which', 'that']: | |
part1 = " ".join(words[:i]) + "." | |
part2 = " ".join(words[i+1:]) | |
if part2: | |
part2 = part2[0].upper() + part2[1:] | |
modified.extend([part1, part2]) | |
break | |
else: | |
modified.append(sentence) | |
else: | |
modified.append(sentence) | |
return " ".join(modified) | |
def paraphrase_with_multiple_models(self, text, chunk_size=300): | |
"""Use multiple models to paraphrase different parts of the text""" | |
# Check if any models are available | |
available_models = [k for k, v in models.items() if v["model"] is not None] | |
if not available_models: | |
# No models available, use fallback humanization | |
return self.fallback_humanization(text) | |
if len(text) <= chunk_size: | |
return self.paraphrase_single_chunk(text) | |
# Split into chunks | |
if NLTK_AVAILABLE: | |
sentences = sent_tokenize(text) | |
else: | |
sentences = [s.strip() + '.' for s in text.split('.') if s.strip()] | |
chunks = [] | |
current_chunk = "" | |
for sentence in sentences: | |
if len(current_chunk + sentence) <= chunk_size: | |
current_chunk += sentence + " " | |
else: | |
if current_chunk: | |
chunks.append(current_chunk.strip()) | |
current_chunk = sentence + " " | |
if current_chunk: | |
chunks.append(current_chunk.strip()) | |
# Paraphrase each chunk with different models | |
paraphrased_chunks = [] | |
for i, chunk in enumerate(chunks): | |
paraphrased = self.paraphrase_single_chunk(chunk, model_choice=i % len(available_models)) | |
paraphrased_chunks.append(paraphrased) | |
return " ".join(paraphrased_chunks) | |
def fallback_humanization(self, text): | |
"""Fallback humanization when no AI models are available""" | |
# Use the vocabulary diversification and natural variations | |
result = self.diversify_vocabulary(text) | |
result = self.add_natural_variations(result) | |
return result | |
def paraphrase_single_chunk(self, text, model_choice=0): | |
"""Paraphrase a single chunk of text""" | |
available_models = [k for k, v in models.items() if v["model"] is not None] | |
if not available_models: | |
# No models available, use fallback | |
return self.fallback_humanization(text) | |
model_key = available_models[model_choice % len(available_models)] | |
model_info = models[model_key] | |
try: | |
if model_key == "t5_paraphrase": | |
input_ids = model_info["tokenizer"].encode( | |
f"paraphrase: {text}", | |
return_tensors="pt", | |
max_length=512, | |
truncation=True | |
) | |
outputs = model_info["model"].generate( | |
input_ids=input_ids, | |
max_length=len(text.split()) + 50, | |
num_beams=5, | |
num_return_sequences=1, | |
temperature=1.2, | |
top_k=50, | |
top_p=0.92, | |
do_sample=True, | |
early_stopping=True | |
) | |
result = model_info["tokenizer"].decode(outputs[0], skip_special_tokens=True) | |
elif model_key == "pegasus": | |
input_ids = model_info["tokenizer"].encode( | |
text, | |
return_tensors="pt", | |
max_length=512, | |
truncation=True | |
) | |
outputs = model_info["model"].generate( | |
input_ids=input_ids, | |
max_length=len(text.split()) + 30, | |
num_beams=4, | |
temperature=1.1, | |
top_p=0.9, | |
do_sample=True | |
) | |
result = model_info["tokenizer"].decode(outputs[0], skip_special_tokens=True) | |
return result if result and len(result) > 10 else self.fallback_humanization(text) | |
except Exception as e: | |
print(f"Error with {model_key}: {e}") | |
return self.fallback_humanization(text) | |
class AIDetector: | |
def __init__(self): | |
"""Initialize AI detection patterns and thresholds""" | |
# Common AI-generated text patterns | |
self.ai_phrases = [ | |
"demonstrates significant", "substantial improvements", "comprehensive analysis", | |
"furthermore", "moreover", "additionally", "consequently", "therefore", | |
"implementation of", "utilization of", "optimization of", "enhancement of", | |
"facilitate", "demonstrate", "indicate", "substantial", "comprehensive", | |
"significant improvements", "notable enhancements", "effective approach", | |
"robust methodology", "systematic approach", "extensive evaluation", | |
"empirical results", "experimental validation", "performance metrics", | |
"benchmark datasets", "state-of-the-art", "cutting-edge", "novel approach", | |
"innovative solution", "groundbreaking", "revolutionary", "paradigm shift" | |
] | |
# Academic buzzwords that AI overuses | |
self.overused_academic_words = [ | |
"significant", "substantial", "comprehensive", "extensive", "robust", | |
"novel", "innovative", "efficient", "effective", "optimal", "superior", | |
"enhanced", "improved", "advanced", "sophisticated", "cutting-edge", | |
"state-of-the-art", "groundbreaking", "revolutionary", "paradigm" | |
] | |
# Transition words AI uses excessively | |
self.excessive_transitions = [ | |
"furthermore", "moreover", "additionally", "consequently", "therefore", | |
"thus", "hence", "nevertheless", "nonetheless", "however" | |
] | |
# Formal structures AI tends to overuse | |
self.formal_patterns = [ | |
r"the implementation of \w+", | |
r"the utilization of \w+", | |
r"in order to \w+", | |
r"it is important to note that", | |
r"it should be emphasized that", | |
r"it can be observed that", | |
r"the results demonstrate that", | |
r"the findings indicate that" | |
] | |
def calculate_ai_probability(self, text): | |
"""Calculate the probability that text is AI-generated""" | |
if not text or len(text.strip()) < 50: | |
return {"probability": 0, "confidence": "Low", "details": {"error": "Text too short for analysis"}} | |
scores = {} | |
# 1. Check for AI phrases | |
scores['ai_phrases'] = self._check_ai_phrases(text) | |
# 2. Check vocabulary repetition | |
scores['vocab_repetition'] = self._check_vocabulary_repetition(text) | |
# 3. Check sentence structure patterns | |
scores['structure_patterns'] = self._check_structure_patterns(text) | |
# 4. Check transition word overuse | |
scores['transition_overuse'] = self._check_transition_overuse(text) | |
# 5. Check formal pattern overuse | |
scores['formal_patterns'] = self._check_formal_patterns(text) | |
# 6. Check sentence length consistency | |
scores['sentence_consistency'] = self._check_sentence_consistency(text) | |
# 7. Check readability patterns | |
scores['readability'] = self._check_readability_patterns(text) | |
# Calculate weighted final score | |
weights = { | |
'ai_phrases': 0.2, | |
'vocab_repetition': 0.15, | |
'structure_patterns': 0.15, | |
'transition_overuse': 0.15, | |
'formal_patterns': 0.15, | |
'sentence_consistency': 0.1, | |
'readability': 0.1 | |
} | |
final_score = sum(scores[key] * weights[key] for key in weights) | |
final_score = min(100, max(0, final_score)) # Clamp between 0-100 | |
# Determine confidence level | |
if final_score >= 80: | |
confidence = "Very High" | |
verdict = "Likely AI-Generated" | |
elif final_score >= 60: | |
confidence = "High" | |
verdict = "Probably AI-Generated" | |
elif final_score >= 40: | |
confidence = "Medium" | |
verdict = "Possibly AI-Generated" | |
elif final_score >= 20: | |
confidence = "Low" | |
verdict = "Probably Human-Written" | |
else: | |
confidence = "Very Low" | |
verdict = "Likely Human-Written" | |
return { | |
"probability": round(final_score, 1), | |
"confidence": confidence, | |
"verdict": verdict, | |
"details": { | |
"ai_phrases_score": round(scores['ai_phrases'], 1), | |
"vocabulary_repetition": round(scores['vocab_repetition'], 1), | |
"structure_patterns": round(scores['structure_patterns'], 1), | |
"transition_overuse": round(scores['transition_overuse'], 1), | |
"formal_patterns": round(scores['formal_patterns'], 1), | |
"sentence_consistency": round(scores['sentence_consistency'], 1), | |
"readability_score": round(scores['readability'], 1) | |
} | |
} | |
def _check_ai_phrases(self, text): | |
"""Check for common AI-generated phrases""" | |
text_lower = text.lower() | |
phrase_count = sum(1 for phrase in self.ai_phrases if phrase in text_lower) | |
words = len(text.split()) | |
if words == 0: | |
return 0 | |
# Score based on phrase density | |
density = (phrase_count / words) * 1000 # Per 1000 words | |
return min(100, density * 10) # Scale to 0-100 | |
def _check_vocabulary_repetition(self, text): | |
"""Check for repetitive vocabulary typical of AI""" | |
words = [word.lower().strip('.,!?;:') for word in text.split() if word.isalpha()] | |
if len(words) < 10: | |
return 0 | |
word_counts = Counter(words) | |
overused_count = sum(1 for word in self.overused_academic_words if word_counts.get(word, 0) > 1) | |
# Calculate repetition score | |
total_overused_words = len(self.overused_academic_words) | |
repetition_ratio = overused_count / total_overused_words if total_overused_words > 0 else 0 | |
return min(100, repetition_ratio * 200) # Scale to 0-100 | |
def _check_structure_patterns(self, text): | |
"""Check for repetitive sentence structures""" | |
if NLTK_AVAILABLE: | |
sentences = sent_tokenize(text) | |
else: | |
sentences = [s.strip() for s in text.split('.') if s.strip()] | |
if len(sentences) < 3: | |
return 0 | |
# Check for similar sentence starters | |
starters = [s.split()[:3] for s in sentences if len(s.split()) >= 3] | |
starter_counts = Counter([' '.join(starter) for starter in starters]) | |
repeated_starters = sum(1 for count in starter_counts.values() if count > 1) | |
repetition_ratio = repeated_starters / len(sentences) if len(sentences) > 0 else 0 | |
return min(100, repetition_ratio * 150) # Scale to 0-100 | |
def _check_transition_overuse(self, text): | |
"""Check for excessive use of transition words""" | |
text_lower = text.lower() | |
transition_count = sum(1 for transition in self.excessive_transitions if transition in text_lower) | |
words = len(text.split()) | |
if words == 0: | |
return 0 | |
# Score based on transition density | |
density = (transition_count / words) * 100 # Percentage | |
return min(100, density * 20) # Scale to 0-100 | |
def _check_formal_patterns(self, text): | |
"""Check for overly formal patterns typical of AI""" | |
pattern_count = 0 | |
text_lower = text.lower() | |
for pattern in self.formal_patterns: | |
matches = re.findall(pattern, text_lower) | |
pattern_count += len(matches) | |
words = len(text.split()) | |
if words == 0: | |
return 0 | |
density = (pattern_count / words) * 1000 # Per 1000 words | |
return min(100, density * 15) # Scale to 0-100 | |
def _check_sentence_consistency(self, text): | |
"""Check for unnaturally consistent sentence lengths""" | |
if NLTK_AVAILABLE: | |
sentences = sent_tokenize(text) | |
else: | |
sentences = [s.strip() for s in text.split('.') if s.strip()] | |
if len(sentences) < 5: | |
return 0 | |
lengths = [len(s.split()) for s in sentences] | |
avg_length = sum(lengths) / len(lengths) | |
# Calculate variance | |
variance = sum((length - avg_length) ** 2 for length in lengths) / len(lengths) | |
std_dev = math.sqrt(variance) | |
# Low variance indicates AI (unnaturally consistent) | |
consistency_score = 100 - min(100, std_dev * 10) # Invert score | |
return max(0, consistency_score - 20) # Adjust threshold | |
def _check_readability_patterns(self, text): | |
"""Check readability patterns that suggest AI generation""" | |
try: | |
# Simple readability metrics | |
words = text.split() | |
sentences = len([s for s in text.split('.') if s.strip()]) | |
if sentences == 0: | |
return 0 | |
avg_words_per_sentence = len(words) / sentences | |
# AI tends to have very consistent, moderate sentence lengths | |
if 15 <= avg_words_per_sentence <= 25: | |
return 30 # Moderate AI indicator | |
elif 25 < avg_words_per_sentence <= 35: | |
return 50 # Higher AI indicator | |
else: | |
return 10 # More natural variation | |
except: | |
return 0 | |
# Initialize AI detector | |
ai_detector = AIDetector() | |
# Initialize humanizer | |
humanizer = AdvancedHumanizer() | |
def detect_ai_text(input_text): | |
"""Detect if text is AI-generated""" | |
if not input_text.strip(): | |
return "Please enter some text to analyze." | |
result = ai_detector.calculate_ai_probability(input_text) | |
# Format the output | |
output = f""" | |
## π€ AI Detection Analysis | |
**Overall Assessment:** {result['verdict']} | |
**AI Probability:** {result['probability']}% | |
**Confidence Level:** {result['confidence']} | |
### π Detailed Breakdown: | |
- **AI Phrases Score:** {result['details']['ai_phrases_score']}% | |
- **Vocabulary Repetition:** {result['details']['vocabulary_repetition']}% | |
- **Structure Patterns:** {result['details']['structure_patterns']}% | |
- **Transition Overuse:** {result['details']['transition_overuse']}% | |
- **Formal Patterns:** {result['details']['formal_patterns']}% | |
- **Sentence Consistency:** {result['details']['sentence_consistency']}% | |
- **Readability Score:** {result['details']['readability_score']}% | |
### π‘ Interpretation: | |
- **0-20%:** Likely human-written with natural variations | |
- **21-40%:** Possibly AI-generated or heavily edited | |
- **41-60%:** Probably AI-generated with some humanization | |
- **61-80%:** Likely AI-generated with minimal editing | |
- **81-100%:** Very likely raw AI-generated content | |
### π‘οΈ Tips to Improve: | |
- Add more natural vocabulary variations | |
- Use varied sentence structures | |
- Include personal insights or examples | |
- Reduce formal academic buzzwords | |
- Add natural transitions and flow | |
""" | |
return output | |
def humanize_academic_text(input_text, humanization_level="Moderate"): | |
""" | |
Advanced humanization with multiple techniques | |
""" | |
if not input_text.strip(): | |
return "Please enter some text to humanize." | |
# Step 1: Initial paraphrasing with multiple models | |
paraphrased = humanizer.paraphrase_with_multiple_models(input_text) | |
# Apply different levels of humanization | |
if humanization_level == "Light": | |
# Minimal changes - just paraphrasing | |
result = paraphrased | |
elif humanization_level == "Moderate": | |
# Add natural variations and some vocabulary changes | |
result = humanizer.add_natural_variations(paraphrased) | |
result = humanizer.diversify_vocabulary(result) | |
else: # Heavy | |
# Apply all techniques | |
result = humanizer.add_natural_variations(paraphrased) | |
result = humanizer.diversify_vocabulary(result) | |
result = humanizer.adjust_sentence_structure(result) | |
# Clean up formatting | |
result = re.sub(r'\s+', ' ', result).strip() | |
result = re.sub(r'\s+([.,!?;:])', r'\1', result) | |
# Ensure proper capitalization | |
if NLTK_AVAILABLE: | |
sentences = sent_tokenize(result) | |
else: | |
sentences = [s.strip() for s in result.split('.') if s.strip()] | |
formatted_sentences = [] | |
for sentence in sentences: | |
if sentence: | |
sentence = sentence[0].upper() + sentence[1:] if len(sentence) > 1 else sentence.upper() | |
if not sentence.endswith(('.', '!', '?')): | |
sentence += '.' | |
formatted_sentences.append(sentence) | |
final_result = " ".join(formatted_sentences) | |
return final_result if final_result else "Error processing text. Please try again." | |
# Create Gradio interface with tabs for both humanization and AI detection | |
with gr.Blocks(theme="soft", title="AI Text Humanizer & Detector") as demo: | |
gr.Markdown(""" | |
# π€β‘οΈπ¨ AI Text Humanizer & Detector Pro | |
**Complete solution for AI text processing - Humanize AND Detect AI-generated content** | |
Transform robotic AI text into natural, human-like writing, then verify the results with our built-in AI detector. | |
""") | |
with gr.Tabs(): | |
# Humanization Tab | |
with gr.TabItem("π Text Humanizer"): | |
gr.Markdown("### Transform AI text into natural, human-like writing") | |
with gr.Row(): | |
with gr.Column(): | |
humanize_input = gr.Textbox( | |
lines=10, | |
placeholder="Enter machine-generated or robotic academic text here...", | |
label="Raw Input Text", | |
info="Paste your AI-generated text that needs to be humanized" | |
) | |
humanization_level = gr.Radio( | |
choices=["Light", "Moderate", "Heavy"], | |
value="Moderate", | |
label="Humanization Level", | |
info="Light: Basic paraphrasing | Moderate: Natural variations + vocabulary | Heavy: All techniques" | |
) | |
humanize_btn = gr.Button("π Humanize Text", variant="primary", size="lg") | |
with gr.Column(): | |
humanize_output = gr.Textbox( | |
label="Humanized Academic Output", | |
lines=10, | |
show_copy_button=True, | |
info="Copy this natural, human-like text" | |
) | |
# Examples for humanizer | |
gr.Examples( | |
examples=[ | |
[ | |
"The implementation of artificial intelligence algorithms demonstrates significant improvements in computational efficiency and accuracy metrics across various benchmark datasets.", | |
"Moderate" | |
], | |
[ | |
"Machine learning models exhibit superior performance characteristics when evaluated against traditional statistical approaches in predictive analytics applications.", | |
"Heavy" | |
] | |
], | |
inputs=[humanize_input, humanization_level], | |
outputs=humanize_output, | |
fn=humanize_academic_text | |
) | |
# AI Detection Tab | |
with gr.TabItem("π΅οΈ AI Detector"): | |
gr.Markdown("### Analyze text to detect if it's AI-generated") | |
with gr.Row(): | |
with gr.Column(): | |
detect_input = gr.Textbox( | |
lines=10, | |
placeholder="Paste text here to check if it's AI-generated...", | |
label="Text to Analyze", | |
info="Enter any text to check its AI probability" | |
) | |
detect_btn = gr.Button("π Analyze Text", variant="secondary", size="lg") | |
with gr.Column(): | |
detect_output = gr.Markdown( | |
label="AI Detection Results", | |
value="Analysis results will appear here..." | |
) | |
# Examples for detector | |
gr.Examples( | |
examples=[ | |
["The implementation of machine learning algorithms demonstrates significant improvements in computational efficiency and accuracy metrics across various benchmark datasets. Furthermore, these results indicate substantial enhancements in performance."], | |
["I love going to the coffee shop on weekends. The barista there makes the best cappuccino I've ever had, and I always end up chatting with other customers about random stuff."], | |
["The comprehensive analysis reveals that the optimization of neural network architectures facilitates enhanced performance characteristics in predictive analytics applications."] | |
], | |
inputs=[detect_input], | |
outputs=detect_output, | |
fn=detect_ai_text | |
) | |
# Combined Analysis Tab | |
with gr.TabItem("π Humanize & Test"): | |
gr.Markdown("### Humanize text and immediately test the results") | |
with gr.Column(): | |
combined_input = gr.Textbox( | |
lines=8, | |
placeholder="Enter AI-generated text to humanize and test...", | |
label="Original AI Text", | |
info="This will be humanized and then tested for AI detection" | |
) | |
combined_level = gr.Radio( | |
choices=["Light", "Moderate", "Heavy"], | |
value="Moderate", | |
label="Humanization Level" | |
) | |
combined_btn = gr.Button("π Humanize & Analyze", variant="primary", size="lg") | |
with gr.Row(): | |
with gr.Column(): | |
combined_humanized = gr.Textbox( | |
label="Humanized Text", | |
lines=8, | |
show_copy_button=True | |
) | |
with gr.Column(): | |
combined_analysis = gr.Markdown( | |
label="AI Detection Analysis", | |
value="Analysis will appear here..." | |
) | |
# Settings & Info Tab | |
with gr.TabItem("βΉοΈ Info & Settings"): | |
gr.Markdown(""" | |
### π― How to Use: | |
**Humanizer:** | |
1. Paste your AI-generated text | |
2. Choose humanization level | |
3. Get natural, human-like output | |
**AI Detector:** | |
1. Paste any text | |
2. Get detailed AI probability analysis | |
3. See breakdown of detection factors | |
**Combined Mode:** | |
1. Humanize and test in one step | |
2. Perfect for optimizing results | |
3. Iterate until satisfied | |
### π§ Features: | |
**Humanization:** | |
- β Multiple AI models for paraphrasing | |
- β Natural vocabulary variations | |
- β Sentence structure optimization | |
- β Academic tone preservation | |
- β Three intensity levels | |
**AI Detection:** | |
- π Advanced pattern recognition | |
- π Detailed scoring breakdown | |
- π― Multiple detection criteria | |
- π Confidence assessment | |
- π‘ Improvement suggestions | |
### βοΈ Ethical Usage: | |
This tool is for improving writing quality and understanding AI detection. | |
Use responsibly and maintain academic integrity. | |
""") | |
# Event handlers | |
humanize_btn.click( | |
fn=humanize_academic_text, | |
inputs=[humanize_input, humanization_level], | |
outputs=humanize_output | |
) | |
detect_btn.click( | |
fn=detect_ai_text, | |
inputs=[detect_input], | |
outputs=detect_output | |
) | |
def combined_process(text, level): | |
"""Humanize text and then analyze it""" | |
if not text.strip(): | |
return "Please enter text to process.", "No analysis available." | |
# First humanize | |
humanized = humanize_academic_text(text, level) | |
# Then analyze | |
analysis = detect_ai_text(humanized) | |
return humanized, analysis | |
combined_btn.click( | |
fn=combined_process, | |
inputs=[combined_input, combined_level], | |
outputs=[combined_humanized, combined_analysis] | |
) | |
if __name__ == "__main__": | |
demo.launch( | |
share=False, | |
debug=True, | |
show_error=True, | |
server_name="127.0.0.1", | |
server_port=7860 | |
) | |