Generate Rhyming Word

parent:
poetry

Related:


Introduction:

need to get end of word and rhyme. Might be better ways to get it but here's one way to skin this cat. Here's the initial setup; the code's also a gist at https://gist.github.com/brockmanmatt/ce9a2a83a55d9abefc5ca95aa2af8ee0. Load the key however you want.

import openai, json, pandas as pd
openai.api_key = "KEY GOES HERE"

#arguments to send the API
kwargs = {
"engine":"davinci",
"temperature":0,
"max_tokens":150,
"stop":"\n\n",
}

Get end of word

So actually getting the end part of a word seems to require quite a few examples; this may change but for now, 0 shot does not seem to work, nor just just a few examples.

Trying with just a few examples:

def getEndOfWord(someWord, verbose=False):
  """
  Get the last part of a word that I'll need to rhyme
  """
  prompt = ""
  prompt += "full: turtle\n"
  prompt += "ending: tle\n\n"

  prompt += "full: apple\n"
  prompt += "ending: ple\n\n"

  prompt += "full: training\n"
  prompt += "ending: ing\n\n"

  prompt += "full: {}\n".format(someWord)
  prompt += "ending:"

  r = openai.Completion.create(prompt=prompt, **kwargs)["choices"][0]["text"].strip()
  return r

This fails easily;

>> getEndOfWord("hamper")
'per'
>> getEndOfWord("attica")
'cia'

So if we add more examples it does better. It might be possible to optimize the context.

def getEndOfWord(someWord, verbose=False):
  """
  Get the last part of a word that I'll need to rhyme
  """
  prompt = ""
  prompt += "full: turtle\n"
  prompt += "ending: tle\n\n"

  prompt += "full: apple\n"
  prompt += "ending: ple\n\n"

  prompt += "full: training\n"
  prompt += "ending: ing\n\n"

  prompt += "full: whopper\n"
  prompt += "ending: per\n\n"

  prompt += "full: balderdash\n"
  prompt += "ending: ash\n\n"

  prompt += "full: clause\n"
  prompt += "ending: ause\n\n"

  prompt += "full: higher\n"
  prompt += "ending: er\n\n"

  prompt += "full: small\n"
  prompt += "ending: all\n\n"

  prompt += "full: pernicious\n"
  prompt += "ending: us\n\n"

  prompt += "full: {}\n".format(someWord)
  prompt += "ending:"

  if verbose:
    print(prompt)

  r = openai.Completion.create(prompt=prompt, **kwargs)["choices"][0]["text"].strip()
  return r

And this seems to work better, e.g.
>> getEndOfWord("hamper")
'per'
>> getEndOfWord("attica")
'ica'

Getting a word that ends with an ending

So to help it out with getting the ending to a word, we can do some fill in the blak!

def fillInWord(letter, ending, temp=0, verbose=False):
  """
  generate a word that ends with the ending and starts with a letter
  """
  prompt = ""
  prompt += "Guess: t__ial\n"
  prompt += "Answer: trivial\n\n"

  prompt += "Guess: c__ury\n"
  prompt += "Answer: century\n\n"

  prompt += "Guess: a__al\n"
  prompt += "Answer: animal\n\n"

  prompt += "Guess: a__le\n"
  prompt += "Answer: able\n\n"

  prompt += "Guess: t__ble\n"
  prompt += "Answer: table\n\n"

  prompt += "Guess: {}__{}\n".format(letter, ending)
  prompt += "Answer:"

  if verbose:
    print(prompt)

  myKwargs = kwargs.copy()
  myKwargs["temperature"] = int(temp)
  #print(kwargs)
  #print(myKwargs)

  r = openai.Completion.create(prompt=prompt, **myKwargs)["choices"][0]["text"].strip()
  return r

This often works

>> fillInWord("a", "ing", temp=1)
'aching'
>> fillInWord("f", "ing", temp=1)
'fighting'

And we can nest the two functions above to get the end of a word + get a word that rhymes with it

>> fillInWord("a", getEndOfWord("hamper"))
'after'

Generating a word to match

So since can get the ending of a word and generate a word that ends with an ending with a given starting character, we can just try generating a rhyming word for each letter f the alphabet. (I guess for actual poetry we'd want to make sure that the context matters too but I leave that to someone else to figure out).

So here we can (try to) generate a rhyming word for each letter of the alphabet for a target word.

import string
def getPossibleWordChoices(ending, temp=0):
  choices = []
  for x in string.ascii_lowercase:
    choices.append(fillInWord(x, ending, temp=temp))
  return choices

>> getPossibleWordChoices("lousy")
['ally', 'barely', 'clearly', 'daily', 'easily', 'fly', 'gently', 'holy', 'illy', 'July', 'quickly', 'lovely', 'million', 'nicely', 'only', 'play', 'quickly', 'really', 'slyly', 'truly', 'ugly', 'valley', 'weekly', 'xylophone', 'yearly', 'zealously']

And then we can use semantic similarity to a context to generate the best match to a target context. This is kind of what I do when I try to rhyme which is why I did this this way.

def generateRelevantWord(context, wordToRhyme, verbose=False):
  """
  return semantic the possibleWord with highest semantic similarity to context
  """
  possibleWords = getPossibleWordChoices(getEndOfWord(wordToRhyme))
  if verbose:
    print(possibleWords)
  scores = openai.Engine("davinci").search(
  documents=[x for x in possibleWords],
  query=context
  )

  return max([(scores["data"][i]["score"], possibleWords[i]) for i in range(len(possibleWords))])[1]

>> generateRelevantWord("I want to go to sleep but I'm not sure that's a good idea", "lousy")
'quickly'
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License