Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -397,8 +397,8 @@ class SelectiveGrammarFixer:
|
|
| 397 |
|
| 398 |
result = ' '.join(fixed_sentences)
|
| 399 |
|
| 400 |
-
# Add natural human variations
|
| 401 |
-
|
| 402 |
|
| 403 |
return result
|
| 404 |
|
|
@@ -528,6 +528,120 @@ class EnhancedDipperHumanizer:
|
|
| 528 |
# Initialize human variations handler
|
| 529 |
self.human_variations = HumanLikeVariations()
|
| 530 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 531 |
def preserve_keywords(self, text, keywords):
|
| 532 |
"""Mark keywords to preserve them during paraphrasing"""
|
| 533 |
if not keywords:
|
|
|
|
| 397 |
|
| 398 |
result = ' '.join(fixed_sentences)
|
| 399 |
|
| 400 |
+
# Add natural human variations (but we need to reference the main class method)
|
| 401 |
+
# This will be called from the smart_fix method instead
|
| 402 |
|
| 403 |
return result
|
| 404 |
|
|
|
|
| 528 |
# Initialize human variations handler
|
| 529 |
self.human_variations = HumanLikeVariations()
|
| 530 |
|
| 531 |
+
def add_natural_human_patterns(self, text):
|
| 532 |
+
"""Add natural human writing patterns that Originality AI associates with human text"""
|
| 533 |
+
sentences = self.split_into_sentences_advanced(text)
|
| 534 |
+
result_sentences = []
|
| 535 |
+
|
| 536 |
+
for i, sentence in enumerate(sentences):
|
| 537 |
+
if not sentence.strip():
|
| 538 |
+
continue
|
| 539 |
+
|
| 540 |
+
# Natural contractions throughout
|
| 541 |
+
sentence = self.apply_contractions(sentence)
|
| 542 |
+
|
| 543 |
+
# Add natural speech patterns (15% chance)
|
| 544 |
+
if random.random() < 0.15 and len(sentence.split()) > 10:
|
| 545 |
+
# Natural interruptions that humans actually use
|
| 546 |
+
if random.random() < 0.5:
|
| 547 |
+
# Add "you know" or "I mean" naturally
|
| 548 |
+
words = sentence.split()
|
| 549 |
+
if len(words) > 6:
|
| 550 |
+
pos = random.randint(3, len(words)-3)
|
| 551 |
+
if random.random() < 0.5:
|
| 552 |
+
words.insert(pos, "you know,")
|
| 553 |
+
else:
|
| 554 |
+
words.insert(pos, "I mean,")
|
| 555 |
+
sentence = ' '.join(words)
|
| 556 |
+
else:
|
| 557 |
+
# Start with natural opener
|
| 558 |
+
openers = ["Look,", "See,", "Thing is,", "Honestly,", "Actually,"]
|
| 559 |
+
sentence = random.choice(openers) + " " + sentence[0].lower() + sentence[1:]
|
| 560 |
+
|
| 561 |
+
# Add subtle errors that humans make (8% chance)
|
| 562 |
+
if random.random() < 0.08:
|
| 563 |
+
words = sentence.split()
|
| 564 |
+
if len(words) > 5:
|
| 565 |
+
# Common comma omissions
|
| 566 |
+
if ", and" in sentence and random.random() < 0.3:
|
| 567 |
+
sentence = sentence.replace(", and", " and", 1)
|
| 568 |
+
# Double words occasionally
|
| 569 |
+
elif random.random() < 0.2:
|
| 570 |
+
idx = random.randint(1, len(words)-2)
|
| 571 |
+
if words[idx].lower() in ['the', 'a', 'to', 'in', 'on', 'at']:
|
| 572 |
+
words.insert(idx+1, words[idx])
|
| 573 |
+
sentence = ' '.join(words)
|
| 574 |
+
|
| 575 |
+
# Natural sentence combinations (20% chance)
|
| 576 |
+
if i < len(sentences) - 1 and random.random() < 0.2:
|
| 577 |
+
next_sent = sentences[i+1].strip()
|
| 578 |
+
if next_sent and len(sentence.split()) + len(next_sent.split()) < 25:
|
| 579 |
+
# Natural connectors based on content
|
| 580 |
+
if any(w in next_sent.lower() for w in ['but', 'however', 'although']):
|
| 581 |
+
sentence = sentence.rstrip('.') + ", but " + next_sent[0].lower() + next_sent[1:]
|
| 582 |
+
sentences[i+1] = "" # Mark as processed
|
| 583 |
+
elif any(w in next_sent.lower() for w in ['also', 'too', 'as well']):
|
| 584 |
+
sentence = sentence.rstrip('.') + " and " + next_sent[0].lower() + next_sent[1:]
|
| 585 |
+
sentences[i+1] = "" # Mark as processed
|
| 586 |
+
|
| 587 |
+
result_sentences.append(sentence)
|
| 588 |
+
|
| 589 |
+
return ' '.join([s for s in result_sentences if s])
|
| 590 |
+
|
| 591 |
+
def vary_sentence_start(self, sentence):
|
| 592 |
+
"""Vary sentence beginning to avoid repetitive patterns"""
|
| 593 |
+
if not sentence:
|
| 594 |
+
return sentence
|
| 595 |
+
|
| 596 |
+
words = sentence.split()
|
| 597 |
+
if len(words) < 5:
|
| 598 |
+
return sentence
|
| 599 |
+
|
| 600 |
+
# Different ways to start sentences naturally
|
| 601 |
+
variations = [
|
| 602 |
+
lambda s: "When " + s[0].lower() + s[1:] + ", it makes sense.",
|
| 603 |
+
lambda s: "If you think about it, " + s[0].lower() + s[1:],
|
| 604 |
+
lambda s: s + " This is important.",
|
| 605 |
+
lambda s: "The thing about " + words[0].lower() + " " + ' '.join(words[1:]) + " is clear.",
|
| 606 |
+
lambda s: "What's interesting is " + s[0].lower() + s[1:],
|
| 607 |
+
lambda s: s, # Keep original sometimes
|
| 608 |
+
]
|
| 609 |
+
|
| 610 |
+
# Pick a random variation
|
| 611 |
+
variation = random.choice(variations)
|
| 612 |
+
try:
|
| 613 |
+
return variation(sentence)
|
| 614 |
+
except:
|
| 615 |
+
return sentence
|
| 616 |
+
|
| 617 |
+
def apply_contractions(self, text):
|
| 618 |
+
"""Apply common contractions to make text more natural"""
|
| 619 |
+
contractions = {
|
| 620 |
+
"it is": "it's", "that is": "that's", "there is": "there's",
|
| 621 |
+
"he is": "he's", "she is": "she's", "what is": "what's",
|
| 622 |
+
"where is": "where's", "who is": "who's", "how is": "how's",
|
| 623 |
+
"cannot": "can't", "will not": "won't", "do not": "don't",
|
| 624 |
+
"does not": "doesn't", "did not": "didn't", "could not": "couldn't",
|
| 625 |
+
"should not": "shouldn't", "would not": "wouldn't", "is not": "isn't",
|
| 626 |
+
"are not": "aren't", "was not": "wasn't", "were not": "weren't",
|
| 627 |
+
"have not": "haven't", "has not": "hasn't", "had not": "hadn't",
|
| 628 |
+
"I am": "I'm", "you are": "you're", "we are": "we're",
|
| 629 |
+
"they are": "they're", "I have": "I've", "you have": "you've",
|
| 630 |
+
"we have": "we've", "they have": "they've", "I will": "I'll",
|
| 631 |
+
"you will": "you'll", "he will": "he'll", "she will": "she'll",
|
| 632 |
+
"we will": "we'll", "they will": "they'll", "I would": "I'd",
|
| 633 |
+
"you would": "you'd", "he would": "he'd", "she would": "she'd",
|
| 634 |
+
"we would": "we'd", "they would": "they'd", "could have": "could've",
|
| 635 |
+
"should have": "should've", "would have": "would've", "might have": "might've",
|
| 636 |
+
"must have": "must've", "there has": "there's", "here is": "here's",
|
| 637 |
+
"let us": "let's", "that will": "that'll", "who will": "who'll"
|
| 638 |
+
}
|
| 639 |
+
|
| 640 |
+
for full, contr in contractions.items():
|
| 641 |
+
text = re.sub(r'\b' + full + r'\b', contr, text, flags=re.IGNORECASE)
|
| 642 |
+
|
| 643 |
+
return text
|
| 644 |
+
|
| 645 |
def preserve_keywords(self, text, keywords):
|
| 646 |
"""Mark keywords to preserve them during paraphrasing"""
|
| 647 |
if not keywords:
|