File size: 3,234 Bytes
e0171fd
 
b054a29
24d2316
e0171fd
24d2316
e0171fd
 
 
 
 
 
 
 
b054a29
c14d215
 
b054a29
c14d215
 
6b49f37
fa2e050
 
 
 
 
6b49f37
 
 
 
fa2e050
6b49f37
 
 
 
c14d215
 
 
24d2316
6b49f37
 
 
 
b054a29
 
 
 
 
c14d215
 
 
b054a29
c14d215
 
6b49f37
 
b054a29
6b49f37
 
 
c14d215
6b49f37
 
 
 
 
b054a29
e14c302
b054a29
 
e14c302
 
 
 
 
b054a29
e14c302
b054a29
 
 
e0171fd
24d2316
c14d215
b054a29
c14d215
b054a29
bad4777
c14d215
 
e14c302
c14d215
e0171fd
24d2316
 
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
import pronouncing
import string
import itertools
import gradio as gr

CONSONANTS = set(string.ascii_uppercase) - set('AEIOU')

def get_phones(word):
    phones_for_word = pronouncing.phones_for_word(word)
    if not phones_for_word:
        return None
    phones = phones_for_word[0].split()
    return phones

def _get_rhyming_tail(phones, syllable_count=1):
    vowels = [phone for phone in phones if phone[0] in 'AEIOU']
    if len(vowels) < syllable_count:
        return None  # Not enough syllables for the rhyme
    return phones[-syllable_count * 2:]

def get_exact_rhymes(phones, syllable_count=1):
    rhyming_tail = _get_rhyming_tail(phones, syllable_count)
    if not rhyming_tail:
        return []
    
    rhyming_tail_str = " ".join(rhyming_tail)
    matches = pronouncing.search(rhyming_tail_str + "$")
    
    exact_rhymes = [match for match in matches if rhyming_tail == _get_rhyming_tail(get_phones(match), syllable_count)]
    return exact_rhymes

def get_loose_rhymes(phones, syllable_count=1):
    """
    Fallback function to find words with a similar ending sound by allowing slight variations.
    """
    rhyming_tail = _get_rhyming_tail(phones, syllable_count)
    if not rhyming_tail:
        return []
    
    # Allow for near matches by replacing the last character in each phoneme with a wildcard
    search_pattern = " ".join(phone[:-1] + "." for phone in rhyming_tail)
    matches = pronouncing.search(search_pattern)
    return matches

def find_rhymes_for_phrase(phrase, syllable_count=1):
    words = phrase.split()
    rhyming_options = []

    for word in words:
        phones = get_phones(word)
        if phones is None:
            rhyming_options.append([f"{word} (Not recognized)"])
            continue
        
        # Try to find exact rhymes first
        exact_rhymes = get_exact_rhymes(phones, syllable_count)
        
        # If no exact rhymes are found, fallback to looser rhymes
        if exact_rhymes:
            rhyming_options.append(exact_rhymes)
        else:
            loose_rhymes = get_loose_rhymes(phones, syllable_count)
            if loose_rhymes:
                rhyming_options.append(loose_rhymes)
            else:
                rhyming_options.append([f"{word} (No rhymes found)"])
    
    # Generate all possible combinations of rhyming words
    combined_results = list(itertools.product(*rhyming_options))
    
    # Remove duplicates
    unique_results = set(" ".join(combination) for combination in combined_results)
    
    # Format combined results as rhyming lines
    if unique_results:
        result_str = f"Rhyming combinations for '{phrase}':\n"
        result_str += "\n".join(unique_results)
        return result_str
    else:
        return f"No rhyming combinations found for '{phrase}'"

# Gradio interface
iface = gr.Interface(
    fn=lambda phrase, syllables: find_rhymes_for_phrase(phrase, syllables), 
    inputs=[
        gr.Textbox(label="Enter phrase (space-separated words)"), 
        gr.Slider(1, 3, step=1, label="Number of Syllables")
    ], 
    outputs="text", 
    description="Enter a phrase with any number of words to find multisyllabic rhyming combinations."
)

if __name__ == "__main__":
    iface.launch()