challenges

AI Style Generator: Part 4 (Solution)

You can find a summary of the code updates in this pull request . Read on for explanations.

1. Correct grammar

All of the work for this workshop is done in the route handler, in api/get-quote-styles/route.ts.

First I added a JSON property: corrected_quote. I added this property before the colors because it felt more fundamental to me, but the order doesn’t really matter. Here’s how I described it:

route.ts

const systemPrompt = `
You will be provided with a quotation, and your task 
is to generate:
 
 1) the same quotation but with correct spelling, 
 grammar, punctation and capitalization. 
 
 2) a hex color code that matches the mood of the 
 quotation
 
 3) a contrasting color to the hex color code that 
 matches the mood. The contrasting color should be 
 "black" or "white", whichever has the higher WCAG 
 contrast ratio compared to the color that matches 
 the mood.
 
Write your output in json with these keys: 
  "corrected_quote"
  "hex_color"
  "text_color"
`;

2. Correct gendered language

Since there’s only one corrected_quote output, I added the instructions for gendered language to the same part of the prompt. I find it very helpful to give OpenAI examples of what I want, so here’s what I added to the prompt.

route.ts

 1) the same quotation but with correct spelling, 
 grammar, punctation and capitalization. 
 Also, change any gender-specific language to 
 non-gender-specific language (for example, change 
 "men" to "people",  or change "father" to "parent").

3. Select font

First I tried asking for a Google font name for the quote:

route.ts

const systemPrompt = `
You will be provided with a quotation, and your task 
is to generate:
 
 ...
 
 4) an appropriate Google font name for the 
 quotation. This should be returned in the form of a 
 valid font name.
 
 
Write your output in json with these keys: 
  "corrected_quote"
  "hex_color"
  "text_color"
  "google_font_name"
`;

This didn’t really result in a font that actually fit the quotation, though. Here’s what I found that helped.

Guidance for the font

I asked Ask OpenAI to specify three adjectives for the quote to justify the color that it chose. I entered a quote into ChatGPT and asked for the color plus these three adjectives.

From the response I got in ChatGPT, I gave the OpenAI prompt an example of “bold, calm, professional”.

You don’t have to ask for the three adjectives in the returned JSON, but I did (I was curious!). I added a key to the JSON called description.

route.ts

const systemPrompt = `
You will be provided with a quotation, and your task 
is to generate:
 
 ...
 
 2) three adjectives that describe the quote, to be 
 returned with the key "description". For example, 
 "bold, calm, professional"
 
 3) a hex color code that matches the the three 
 adjectives selected for the quotation
 
 ...
 
 5) an appropriate Google font name for the 
 quotation, based on the adjectives you chose for the
 quote. This should be returned in the form of a 
 valid font name. 
 
Write your output in json with these keys: 
  "corrected_quote"
  "description"
  "hex_color"
  "text_color"
  "google_font_name"
`;

Unusual fonts

It helped get more appropriate fonts when I specified the that the font should match the description. Still, I found that OpenAI was giving me the same common fonts over and over. I wanted more unusual fonts, so I added that:

route.ts

const systemPrompt = `
You will be provided with a quotation, and your task 
is to generate:
 
 ...
 
 5) an appropriate Google font name for the 
 quotation, based on the adjectives you chose for the
 quote. This should be returned in the form of a 
 valid font name. Avoid common fonts like "Lato" and 
 "Roboto". Try to pick a more unusual font. 
 Examples of less common fonts: "Playfair Display", 
 "Marck Script", "Oswald", "Salsa"
 
Write your output in json with these keys: 
  "corrected_quote"
  "description"
  "hex_color"
  "text_color"
  "google_font_name"
`;

I was pretty happy with these results. Think you came up with a better prompt? Let me know by tagging me on LinkedIn or Twitter !

4. Update route return

Finally, we’ll have to update the returned value for the route to include the new data. I destructured properties from the OpenAI JSON response to send back to the client:

route.ts

export async function GET() {
  // ...
 
  const rawStyles = completion.choices[0].message.content;
  // to avoid TypeScript error with `JSON.parse`
  if (!rawStyles) {
    return NextResponse.json({
      quote: generatedQuote,
    });
  }
 
  try {
    // destructure properties
    const {
      corrected_quote,
      description,
      hex_color,
      text_color,
      google_font_name,
    } = JSON.parse(rawStyles);
 
    // return description and font name
    return NextResponse.json({
      quote: corrected_quote,
      description,
      colors: { background: hex_color, text: text_color },
      fontName: google_font_name,
    });
  } catch (error) {
    // ...
  }
}

5. View the results

Since this workshop does not include any UI updates, we can (temporarily) print the JSON reponse to the console to see the results. I chose to print the original quote too, to compare it to the updated quote and see what kind of corrections were being made.

route.ts

export async function GET() {
  const generatedQuote = getRandomQuote();
  // ...
 
  try {
    // destructure properties
    const {
      corrected_quote,
      description,
      hex_color,
      text_color,
      google_font_name,
    } = JSON.parse(rawStyles);
 
    console.log("========> ORIGINAL QUOTE", generatedQuote)
    console.log("========> OPENAI RESPONSE", {
      corrected_quote,
      description,
      hex_color,
      text_color,
      google_font_name,
    })
 
    // return description and font name
    return NextResponse.json({
      quote: corrected_quote,
      description,
      colors: { background: hex_color, text: text_color },
      fontName: google_font_name,
    });
  } catch (error) {
    // ...
  }
}

Here are some example results (Note: I temporarily defined generatedQuote at the beginning of the GET() function as a static string instead of a random quote to look at results for quotes I was interested in).

Note: I had to start up the server and click the “use random quote” button to view the results logged in the terminal.

========> ORIGINAL QUOTE No man will make great leader who wants to do it all himself, or to get all the credit for doing it.
========> OPENAI RESPONSE {
  corrected_quote: 'No person will make a great leader who wants to do it all themselves, or to get all the credit for doing it.',
  description: 'insightful, wise, empowering',
  hex_color: '#8E44AD',
  text_color: 'white',
  google_font_name: 'Cormorant Garamond'
}
========> ORIGINAL QUOTE sense of justice is noble fancy.
========> OPENAI RESPONSE {
  corrected_quote: 'A sense of justice is a noble fancy.',
  description: 'noble, dignified, serious',
  hex_color: '#3867d6',
  text_color: 'white',
  google_font_name: 'Playfair Display'
}

Up next

In the next workshop, we’ll update the UI to display the quote in the suggested font.

Workshops in this series

  1. OpenAI Node SDK
  2. Prompt engineering: color
  3. Apply color response
  4. Prompt engineering: quote cleanup and font
  5. Apply font response
  6. Quote entry (coming October 17, 2024)