|
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): |
|
""" |
|
Automatically detect the syllable count based on vowel sounds, |
|
then return the appropriate rhyming tail. |
|
""" |
|
vowels = [phone for phone in phones if phone[0] in 'AEIOU'] |
|
syllable_count = len(vowels) |
|
if syllable_count < 1: |
|
return None |
|
return phones[-syllable_count * 2:] |
|
|
|
def get_exact_rhymes(phones): |
|
rhyming_tail = _get_rhyming_tail(phones) |
|
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))] |
|
return exact_rhymes |
|
|
|
def get_filtered_loose_rhymes(phones): |
|
""" |
|
Fallback function to find words with a similar ending sound by allowing slight variations. |
|
Applies additional filtering to avoid unrelated results. |
|
""" |
|
rhyming_tail = _get_rhyming_tail(phones) |
|
if not rhyming_tail: |
|
return [] |
|
|
|
search_pattern = " ".join(phone[:-1] + "." for phone in rhyming_tail) |
|
matches = pronouncing.search(search_pattern) |
|
|
|
|
|
filtered_rhymes = [match for match in matches if match != phones] |
|
return filtered_rhymes |
|
|
|
def find_rhymes_for_phrase(phrase): |
|
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 |
|
|
|
|
|
exact_rhymes = get_exact_rhymes(phones) |
|
|
|
|
|
if exact_rhymes: |
|
rhyming_options.append(exact_rhymes) |
|
else: |
|
loose_rhymes = get_filtered_loose_rhymes(phones) |
|
if loose_rhymes: |
|
rhyming_options.append(loose_rhymes) |
|
else: |
|
rhyming_options.append([f"{word} (No rhymes found)"]) |
|
|
|
combined_results = list(itertools.product(*rhyming_options)) |
|
unique_results = set(" ".join(combination) for combination in combined_results) |
|
|
|
|
|
return list(unique_results) |
|
|
|
|
|
def add_to_notepad(notepad, selected_rhyme): |
|
return notepad + " " + selected_rhyme |
|
|
|
|
|
with gr.Blocks() as demo: |
|
gr.Markdown("## Interactive Rhyming Generator with Notepad") |
|
|
|
|
|
phrase_input = gr.Textbox(label="Enter phrase (space-separated words)") |
|
|
|
|
|
rhyme_output = gr.Dataframe(headers=["Rhyming Phrases"], interactive=False) |
|
notepad = gr.Textbox(label="Notepad", lines=10, placeholder="Write your lyrics here...") |
|
|
|
|
|
generate_btn = gr.Button("Generate Rhymes") |
|
|
|
|
|
rhyme_output.change(add_to_notepad, inputs=[notepad, rhyme_output], outputs=notepad) |
|
|
|
|
|
generate_btn.click(find_rhymes_for_phrase, inputs=[phrase_input], outputs=rhyme_output) |
|
|
|
demo.launch() |
|
|