Quotable NLP Synset

Swap a line's adjectives for near synonyms and listen to what breaks.

The question

How much of a line's power is the specific word, and how much is the structure holding it? Substitute only the adjectives — keep the syntax, the rhythm, the nouns — and you can hear exactly what the writer's word was doing.

Mostly what you hear is that it was doing everything.

One pass

“a great and sudden change”  →  “a outstanding and abrupt change”

How it works

  1. Pick one of fourteen authors at random — Fitzgerald, Wolfe, McCarthy, Keats, Eliot, Steinbeck, Yeats, Hemingway, Brooke, Milton, Lewis, Nietzsche, Shelley, Byron — and scrape a quote.
  2. POS-tag the line with TextBlob.
  3. Touch only JJ, JJR, JJS — adjective, comparative, superlative. Everything else passes through untouched, which is what keeps the sentence's shape and makes the swap audible.
  4. For each adjective, walk its WordNet synsets and take the first lemma that is not the word itself.
  5. Reassemble and print both lines.
main.py — the substitution
for word in blob.pos_tags:
    if word[1] in ['JJ', 'JJR', 'JJS']:
        for synset in word[0].synsets:
            if synset.lemmas()[0].name() != word[0]:
                quote = quote.replace(word[0], synset.lemmas()[0].name())
                break

Two things in there decide the whole result. The break takes WordNet's first sense and stops — no disambiguation, no check that the sense fits the sentence, so “great” becomes “outstanding” rather than “large” on nothing but ordering. And quote.replace is a string replace, not a token replace: an adjective that also appears inside another word gets hit there too. Both are the kind of thing you would fix in an hour, and neither is why the experiment answers its question — even a correct synonym lands wrong, which is the finding.

The sibling: Quotable

The scraper this runs on, QuoteFetch.py, is shared with Quotable ↗ — a 2019 bot that picked one of the same authors at random each day and texted you a line of theirs. It sent through the carriers' free email-to-SMS gateways (@vtext.com for Verizon, @txt.att.net for AT&T), so there was no Twilio account and no per-message cost. MIMEText truncates past roughly 120 characters, so anything longer went out as two messages two seconds apart — a bisected Fitzgerald line beats a severed one.

Its real flaw is worth naming because it is the reason both are archival: the scrape walks the page by indexlist(list(list(...children)[1])[2])[13] — rather than by selector. It works until the markup shifts by one element, which it since has. The substitution itself still runs fine on any string you hand it.

Where it went

Built in the same week of 2019 as Novel Sentiment Analysis, both poking at the same question: whether anything measurable survives when you take prose apart. The answer that stuck came much later, from Literature Mutations — not from single words, but from which words a whole book chooses that its neighbours don't.

Quotable_NLP_Synset on GitHub ↗