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'