DEV Community

Alexey Kramin
Alexey Kramin

Posted on

5 3 2 1 1

How I built my first AI project for a couple of hours

Artificial Intelligence is here probably for ever. It becomes more and more widespread and usual, like personal computers or smartphones. And we won’t be able to imagine our lives without it very soon. To use it as a developer in your projects becomes incredibly easy too. I developed a simple tool using the OpenAI NPM package, and I’m going to share my approach. Let’s go.

Idea

The main idea is pretty simple. I saw that many people on Twitter share their achievements, like MRR, subscribers numbers, or progress like lists, with emojis. For example:

🧚‍♂️ be fairy
👑 be gorgeous
🦄 be unique
🐳 be a whale
🦧 be funny

I decided to create a tool that looks for appropriate emoji according to text provided.

Implementation

Let’s start from the backend. I’m using Node.js so first of all I need to install OpenAI npm package. Then to use the package you need to obtain your API-key from open AI website.
When you finish all the preparation it’s time to get you hands dirty. Init OpenAI package:

const { Configuration, OpenAIApi } = require('openai');
// Replace YOUR_API_KEY with your actual OpenAI API key
const API_KEY = process.env.OPENAI_API_KEY;
// Replace MODEL_ID with the ID of the model you want to use
// we are gonna use the chat completion functions so the following model id
// works there properly. Check in the API documentation if a model you wanna try
// works with selected API functions.
const MODEL_ID = 'gpt-3.5-turbo';
const configuration = new Configuration({
    apiKey: API_KEY,
});
const openai = new OpenAIApi(configuration);
Enter fullscreen mode Exit fullscreen mode

When we initialised the OpenAI object, we can call the API then:

const completion = await openai.createChatCompletion({
    model: MODEL_ID,
    messages: [{ "role": "user", "content": `generate exactly 5 funny and playful emojis for each paragraph of the input following the meaning of them. 
  Return it as JSON with an array of non empty strings containing exactly one emoji arrays.
  It shoudln't contain any additional keys in JSON. Only array of arrays. 
  Length of the array should be equal to ${count}. 
  No additional texts or explanations or extra array entities.
  The input: "${input.trim()}"` }]
});
const output = completion.data.choices[0].message.content;
Enter fullscreen mode Exit fullscreen mode

I tried to use Edits API first, but the result was not really predictable so I switched to ChatCompletion. It’s not perfect, but responses much more suitable.
Our output should look like a stringified JSON, but sometimes the AI returns not really expected response. So we need to be sure that we have a plan B if it could not be parsed properly.

let outputArray = [];
try {
  outputArray = JSON.parse(output
    .replaceAll(' ', '')
    .replaceAll('\n', '')
    .replaceAll('],]', ']]')
    .match(/\[(.|\n)*\]/g)[0] // get only array. There might be other info generated
    .trim()
  );
  outputArray = outputArray.map(arr => {
    if (arr.length) return arr;
    return getNRandomEmojis(5); // there might be an empty array
  });

  while (outputArray.length < input.length) {
    outputArray.push(getNRandomEmojis(5)); // length of any array might be less then we expeced (5)
  }
} catch (e) {
  console.error(e);
  const paragrapthsLength = input.length;
  for (let i = 0; i < paragrapthsLength; i++) { // just generate random emojis as a backup
    outputArray.push(getNRandomEmojis(5));
  }
}
Enter fullscreen mode Exit fullscreen mode

Now let’s summarise everything we did and combine it into one file. The full code of the service looks as below.

async generateResponse(input) {
  // Replace YOUR_API_KEY with your actual OpenAI API key
  const API_KEY = process.env.OPENAI_API_KEY;
  // Replace MODEL_ID with the ID of the model you want to use
  // we are gonna use the chat completion functions so the following model id
  // works there properly. Check in the API documentation if a model you wanna try
  // works with selected API functions.
  const MODEL_ID = 'gpt-3.5-turbo';

  const configuration = new Configuration({
    apiKey: API_KEY,
  });
  const openai = new OpenAIApi(configuration);

  const inputStringified = input.map(inp => inp.val.trim()).join('\n');

  const completion = await openai.createChatCompletion({
    model: MODEL_ID,
    messages: [{ "role": "user", "content": getMessageContent(inputStringified, input.length) }]
  });

  const output = completion.data.choices[0].message.content;

  let outputArray = [];
  try {
    outputArray = JSON.parse(output
      .replaceAll(' ', '')
      .replaceAll('\n', '')
      .replaceAll('],]', ']]')
      .match(/\[(.|\n)*\]/g)[0] // get only array. There might be other info generated
      .trim()
    );
    outputArray = outputArray.map(arr => {
      if (arr.length) return arr;
      return getNRandomEmojis(5);
    });

    while (outputArray.length < input.length) {
      outputArray.push(getNRandomEmojis(5));
    }
  } catch (e) {
    console.error(e);
    const paragrapthsLength = input.length;
    for (let i = 0; i < paragrapthsLength; i++) {
      outputArray.push(getNRandomEmojis(5));
    }
  }

  return outputArray;
}

function getMessageContent(input, count) {
  return `generate exactly 5 funny and playful emojis for each paragraph of the input following the meaning of them. 
  Return it as JSON with an array of non empty strings containing exactly one emoji arrays.
  It shoudln't contain any additional keys in JSON. Only array of arrays. 
  Length of the array should be equal to ${count}. 
  No additional texts or explanations or extra array entities.
  The input: "${input.trim()}"`;
}

function getNRandomEmojis(n) {
  const res = [];
  for (let i = 0; i < n; i++) {
    res.push(getRandomEmoji());
  }
  return res;
}

function getRandomEmoji() {
  const emojis = [
    '😄', '😃', '😀', '😊', '😔', '😉', '😍', '😘', '😚', '😗', '😙', '😜', '😝', '😛', '😳', '😁', '😔', '😌', '😒', '😞', '😣', '😢', '😂', '😭', '😪', '😥', '😰', '😅', '😓', '😩', '😫', '😨', '😱', '😠', '😡', '😤', '😖', '😆', '😋', '😷', '😎', '😴', '😵', '😲', '😟', '😦', '😧', '😈', '👿', '😮', '😬', '😐', '😕', '😯', '😶', '😇', '😏', '😑', '👲', '👳', '👮', '👷', '💂', '👶', '👦', '👧', '👨', '👩', '👴', '👵', '👱', '👼', '👸', '😺', '😸', '😻', '😽', '😼', '🙀', '😿', '😹', '😾', '👹', '👺', '🙈', '🙉', '🙊', '💀', '👽', '💩', '🔥', '', '🌟', '💫', '💥', '💢', '💦', '💧', '💤', '💨', '👂', '👀', '👃', '👅', '👄', '👍', '👎', '👌', '👊', '', '', '👋', '', '👐', '👆', '👇', '👉', '👈', '🙌', '🙏', '', '👏', '💪', '🚶', '🏃', '💃', '👫', '👪', '👬', '👭', '💏', '💑', '👯', '🙆', '🙅', '💁', '🙋', '💆', '💇', '💅', '👰', '🙎', '🙍', '🙇', '🎩', '👑', '👒', '👟', '👞', '👡', '👠', '👢', '👕', '👔', '👚', '👗', '🎽', '👖', '👘', '👙', '💼', '👜', '👝', '👛', '👓', '🎀', '🌂', '💄', '💛', '💙', '💜', '💚', '', '💔', '💗', '💓', '💕', '💖', '💞', '💘', '💌', '💋', '💍', '💎', '👤', '👥', '💬', '👣', '💭', '🐶', '🐺', '🐱', '🐭', '🐹', '🐰', '🐸', '🐯', '🐨', '🐻', '🐷', '🐽', '🐮', '🐗', '🐵', '🐒', '🐴', '🐑', '🐘', '🐼', '🐧', '🐦', '🐤', '🐥', '🐣', '🐔', '🐍', '🐢', '🐛', '🐝', '🐜', '🐞', '🐌', '🐙', '🐚', '🐠', '🐟', '🐬', '🐳', '🐋', '🐄', '🐏', '🐀', '🐃', '🐅', '🐇', '🐉', '🐎', '🐐', '🐓', '🐕', '🐖', '🐁', '🐂', '🐲', '🐡', '🐊', '🐫', '🐪', '🐆', '🐈', '🐩', '🐾', '💐', '🌸', '🌷', '🍀', '🌹', '🌻', '🌺', '🍁', '🍃', '🍂', '🌿', '🌾', '🍄', '🌵', '🌴', '🌲', '🌳', '🌰', '🌱', '🌼', '🌐', '🌞', '🌝', '🌚', '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘', '🌜', '🌛', '🌙', '🌍', '🌎', '🌏', '🌋', '🌌', '🌠', '', '', '', '', '', '', '', '', '🌀', '🌁', '🌈', '🌊', '🎍', '💝', '🎎', '🎒', '🎓', '🎏', '🎆', '🎇', '🎐', '🎑', '🎃', '👻', '🎅', '🎄', '🎁', '🎋', '🎉', '🎊', '🎈', '🎌', '🔮', '🎥', '📷', '📹', '📼', '💿', '📀', '💽', '💾', '💻', '📱', '', '📞', '📟', '📠', '📡', '📺', '📻', '🔊', '🔉', '🔈', '🔇', '🔔', '🔕', '📢', '📣', '', '', '', '', '🔓', '🔒', '🔏', '🔐', '🔑', '🔎', '💡', '🔦', '🔆', '🔅', '🔌', '🔋', '🔍', '🛁', '🛀', '🚿', '🚽', '🔧', '🔩', '🔨', '🚪', '🚬', '💣', '🔫', '🔪', '💊', '💉', '💰', '💴', '💵', '💷', '💶', '💳', '💸', '📲', '📧', '📥', '📤', '', '📩', '📨', '📯', '📫', '📪', '📬', '📭', '📮', '📦', '📝', '📄', '📃', '📑', '📊', '📈', '📉', '📜', '📋', '📅', '📆', '📇', '📁', '📂', '', '📌', '📎', '', '', '📏', '📐', '📕', '📗', '📘', '📙', '📓', '📔', '📒', '📚', '📖', '🔖', '📛', '🔬', '🔭', '📰', '🎨', '🎬', '🎤', '🎧', '🎼', '🎵', '🎶', '🎹', '🎻', '🎺', '🎷', '🎸', '👾', '🎮', '🃏', '🎴', '🀄', '🎲', '🎯', '🏈', '🏀', '', '', '🎾', '🎱', '🏉', '🎳', '', '🚵', '🚴', '🏁', '🏇', '🏆', '🎿', '🏂', '🏊', '🏄', '🎣', '', '🍵', '🍶', '🍼', '🍺', '🍻', '🍸', '🍹', '🍷', '🍴', '🍕', '🍔', '🍟', '🍗', '🍖', '🍝', '🍛', '🍤', '🍱', '🍣', '🍥', '🍙', '🍘', '🍚', '🍜', '🍲', '🍢', '🍡', '🍳', '🍞', '🍩', '🍮', '🍦', '🍨', '🍧', '🎂', '🍰', '🍪', '🍫', '🍬', '🍭', '🍯', '🍎', '🍏', '🍊', '🍋', '🍒', '🍇', '🍉', '🍓', '🍑', '🍈', '🍌', '🍐', '🍍', '🍠', '🍆', '🍅', '🌽', '🏠', '🏡', '🏫', '🏢', '🏣', '🏥', '🏦', '🏪', '🏩', '🏨', '💒', '', '🏬', '🏤', '🌇', '🌆', '🏯', '🏰', '', '🏭', '🗼', '🗾', '🗻', '🌄', '🌅', '🌃', '🗽', '🌉', '🎠', '🎡', '', '🎢', '🚢', '', '🚤', '🚣', '', '🚀', '', '💺', '🚁', '🚂', '🚊', '🚉', '🚞', '🚆', '🚄', '🚅', '🚈', '🚇', '🚝', '🚋', '🚃', '🚎', '🚌', '🚍', '🚙', '🚘', '🚗', '🚕', '🚖', '🚛', '🚚', '🚨', '🚓', '🚔', '🚒', '🚑', '🚐', '🚲', '🚡', '🚟', '🚠', '🚜', '💈', '🚏', '🎫', '🚦', '🚥', '', '🚧', '🔰', '', '🏮', '🎰', '', '🗿', '🎪', '🎭', '📍', '🚩', '', '', '', '', '🔠', '🔡', '🔤', '', '', '', '', '', '', '🔄', '', '', '🔼', '🔽', '', '', '', '', '', '', '', '', '', '🆗', '🔀', '🔁', '🔂', '🆕', '🆙', '🆒', '🆓', '🆖', '📶', '🎦', '🈁', '🈯', '🈳', '🈵', '🈴', '🈲', '🉐', '🈹', '🈺', '🈶', '🈚', '🚻', '🚹', '🚺', '🚼', '🚾', '🚰', '🚮', '🅿', '', '🚭', '🈷', '🈸', '🈂', '', '🛂', '🛄', '🛅', '🛃', '🉑', '', '', '🆑', '🆘', '🆔', '🚫', '🔞', '📵', '🚯', '🚱', '🚳', '🚷', '🚸', '', '', '', '', '', '', '💟', '🆚', '📳', '📴', '🅰', '🅱', '🆎', '🅾', '💠', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '🔯', '🏧', '💹', '💲', '💱', '©', '®', '', '', '', '🔝', '🔚', '🔙', '🔛', '🔜', '', '', '', '', '', '', '🔃', '🕛', '🕧', '🕐', '🕜', '🕑', '🕝', '🕒', '🕞', '🕓', '🕟', '🕔', '🕠', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚', '🕡', '🕢', '🕣', '🕤', '🕥', '🕦', '', '', '', '', '', '', '', '', '💮', '💯', '', '', '🔘', '🔗', '', '🔱', '🔲', '🔳', '', '', '', '', '', '', '🔺', '', '', '', '', '🔴', '🔵', '🔻', '🔶', '🔷', '🔸', '🔹'
  ];
  return emojis[Math.floor(Math.random() * emojis.length)];
}
Enter fullscreen mode Exit fullscreen mode

Your front-end might look as you prefer. Example of mine is on the GIF

Emoji generator result of work

The tool itself - Emoji Me

Instead of a conclusion.

It’s was a tiny example of an AI application for some routine automations, but it’s a step into very promising and intriguing AI world. There are so much interesting to discover so do it and enjoy.


If you like the article, follow me on social media ❤️

Twitter

LinkedIn

API Trace View

How I Cut 22.3 Seconds Off an API Call with Sentry

Struggling with slow API calls? Dan Mindru walks through how he used Sentry's new Trace View feature to shave off 22.3 seconds from an API call.

Get a practical walkthrough of how to identify bottlenecks, split tasks into multiple parallel tasks, identify slow AI model calls, and more.

Read more →

Top comments (0)

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay