This project discusses my eclectic, carefully curated deck of English vocab words that are both useful and mostly advanced/not very common. Many of the words in the deck are taken from Webster's words of the Day page, but lots are also from my readings/experiences too. They're all words that I did not originally know and that I believe are genuinely useful, even if they are indeed a bit esoteric. I've made a custom, styled template for the deck inspired by Webster dictionary, and have also put together images and audio for each card.
As I encounter new, unknown words, I've stored them away in a Google Keep backlog. I've gotten into the habit of allocating a corner of my loose leaf that I use for notes for vocab words that I don't yet know, and stay up to date with the Merriam-Webster word of the day. Since I don't want to commit completely useless words into my lexicon for no reason, I do some vetting, checking their usage over time, recent usage, and the applicability of the word, before batch adding words to my spaced-repetition flashcard deck.
Spaced repetition is a special evidence-based flashcard studying method wherein cards are automatically shown to you at specific intervals based on your response to remembering the card, as to show you the card at the moment before you are predicted to forget it. That is, the more you forget a card, the more often you will encounter the card, and the better you get at remembering it, the longer the interval gaps become. The end result: the more you review, the longer it takes to forget. Not only is retention boosted, but study time is better optimized.
Generally these days spaced repetition is implemented with software, but that does not necessarily need to be the case. 'Leitner boxes' are an implementation of spaced repetition with physical flashcards and boxes to store them in based on proficiency. After reviewing cards, the cards move to boxes based on your ability to recall them, and the easier to remember cards end up being reviewed less often.
Although approaches like this do work, I highly recommend using software to manage the spaced repetition for you, since they can provide greater configurability, allow you to track your progress over time, and manage everything for you, so that you can spend your time actually reviewing cards rather than handling technicalities. There are a large variety of both free and paid applications for the task, but my go-to is Anki Flashcards. It's completely open source, easy to use, highly configurable, extendable, and has lots of community support, decks, and add-ons. It's completely free to use their website, desktop app, and android app, but their iPhone app is $25 (and worth every penny).
A copy of the deck can be downloaded here. I will try to frequently update the link with new cards as I add them, and Anki Flashcards should automatically merge in the new ones when you install updated decks.
With my deck building up in size, and my appetite for words evergrowing, I knew I'd need a better way to create flashcards. For each flashcard, there are 9 different fields: word, definitions, examples, synonyms, notes, images, pronunciation, audio, and part of speech. All fields are needed for every card except notes, which is reserved for when an important note is needed to provide context for a word. While this may have been fine for the first 100 cards, I hope to grow at a much higher rate, and also thought that automatic card generation would be a fun next step. I'd still curate the words, but a bot would help create the cards.
The first step of figuring out how to automate would be to determine where and how to fetch card information. While indeed many dictionary APIs, including free options, already exist, such as webster's, I wanted something that would provide me unique examples for the word, and compile all the data in one place. Additionally, I needed to implement some sort of image generation/location system to find an image to help remember the word, along with adding text to speech so that my flashcard software could read me the word.
Over the past month, I've come to find that OpenAI's ChatGTP has been particularly useful for curating these specific things, and their DALLE image generator has been able to create good-enough images for memorizing words. Since they have extremely cheap and easy to use APIs for the services, and I've been wanting to learn how to implement NLP into software anyway, I chose to implement OpenAI's AI to generate word images and metadata. For text to speech, I chose Google text to speech, given it's robustness and popularity.
With ChatGTP's API, you have the option of providing a "system message" to the bot before querying it. For this, I wanted a bot that would both write poetically and in interesting/helpful ways, but also provide output in as a valid JSON. For this, I wrote up the following message to teach the bot how to behave and function.
You are a very skillful poet with a large lexicon. Your goal is to help people improve their vocab in a fun and helpful way. People will provide you a single word input, and you will reply with various pieces of information, separated by two newlines. Ensure it is a valid json. Follow the following template exactly. If the word appears misspelt, take your best guess as to what the word is. If you are totally unsure, respond "na".
{
"word": {Word provided, or, if provided word misspelt, your best guess.},
"part_of_speech": {Part of speech of the word.},
"pronunciation": {The phonetic pronunciation of the word, using dashes as separators and only ascii characters. Aim for clarity.},
"definitions": [<Definitions here, separated by commas, in order of popularity. Include the top definition, along with up to 3 other popular definitions as needed, but aim for as few as possible. Ensure each definition is clear and longer than 4 words. The word itself shouldn't show up in any of the definitions. Make them clear, but not overly textbooky.>],
"synonyms": [<4-5 synonyms here, separated by commas, each embedded in quotes, in order of helpfulness. Synonyms should be only single words each, and they shouldn't be totally obscure.],
"examples": [<4-5 examples here, separated by commas, each embedded in quotes, in order of popularity. Each example should not start with a proper noun, and the ending period should be left out (if it is multiple sentences only the last one should lack a period). For the specific requested word, embed it in single asterisks. The examples should be upbeat, make sense and sound eloquent and good, and help demonstrate the word definition. Ensure that they are fully lowercase, except proper nouns.>]
}
Additional important instructions:
1) If passed a conjugated verb, standardize it to be imperative.
2) If passed a declined noun, standardize it to be singular.
3) Be lively, friendly, clear, and as helpful as possible. Be slightly poetic and convivial.
Images also require a prompt, but for the image I decided that the best person to write a prompt would AI itself. So, for the images, I prompted GPT to write a prompt for DALLE using the following template.
Provide {count} brief, different bits of imagery that capture a common occurrence of \"{word}\" These descriptions should: - NOT use the word \"{word}.\"\n- NOT involve humans.\n- BE 300 characters or less.
1{ 2 "word": "Conflate", 3 "part_of_speech": "verb", 4 "pronunciation": "kuhn-fleyt", 5 "definitions": [ 6 "to bring together; meld or fuse", 7 "to confuse or mix up" 8 ], 9 "synonyms": [ 10 "blend", 11 "merge", 12 "combine", 13 "unify", 14 "amalgamate" 15 ], 16 "examples": [ 17 "Let's *conflate* our ideas to create something truly original", 18 "Don't *conflate* this issue with others that are irrelevant", 19 "The author often *conflates* fact and fiction in his stories", 20 "The sensation of nostalgia and longing were *conflated* in her heart" 21 ] 22}
After using Anki for a while for this project though, I decided that it'd be fun to try to generate actual physical flashcards of my own. Now that I had the ability to generate all the different pieces of flashcards, I spent a significant amount of time figuring out how to render them into actual flashcard images. After much experimentation, I decided to code custom SVG templates, which I write more about here. The general idea is that SVG files are really just definitions of paths, lines, shapes, and colors. Instead of using a program like Illustrator to generate them for me, I hand-wrote a flashcard-style SVG in a text editor, and then added fields that could be swapped out for dynamic content (including image sources!). As I worked on this I was also able to fine tune the image generation to allow for more accurate to the word images. Here's some examples...
Although the software tool I initially was working on was a basic script to help me create new Anki flashcards, I'm now working on a much larger-scale project to generate templated PDF flashcards that can be (eventually) professionally printed out. At the moment I do have a working script for the program, which can be found here, but I'm in the process of porting it over to Django. The current port allows you to generate flashcards via a simple endpoint by submitting a list of words and styles, placing the output PDFs and images used for the flashcards into S3 (AWS storage) automatically.
While my API implementation enables concurrent flashcard generation server-side, but, as it turns out, flashcard generation is extremely IO-bound. It takes 20 seconds worth of waiting to gather all the needed resources for a given card, including AI-generated images and dictionary entries, no matter what. However, since most of that time is spent waiting, multiple cards can be generated on other threads at the same time. My goal is to be able to send a request to generate as many flashcards as you'd want and get back a task ID, which you could then use to get the generated flashcards later.
For this, I've been looking into using some sort of task queue system with workers, although I may just use threading and implement my own task ID model for my database. Part of what makes the flashcard generation annoying to distribute is that it can't run on lambdas serverless-ly because of the cold start of chromedriver. Since I'm using serelium to render the PDFs, it'd take a long time for a serverless function to set up to perform the render, as opposed to a dedicated server always having a chromedriver running.
The next step for this chapter of the project, after further refining the API, is to create an actual UI. My plan is to eventually integrate with Twilio so that you can text a phone number a word whenever you come across it in daily life, and then at the end of each month a deck of flashcards could automatically be generated, printed, and sent to you. Updates will be posted here as the project progresses.