DEV Community

Cover image for A Step-by-Step Guide to Create a Speaking Practice App with AWS Bedrock
Amelia Dutta
Amelia Dutta Subscriber

Posted on

A Step-by-Step Guide to Create a Speaking Practice App with AWS Bedrock

Have you ever felt that rock climbing is easier than starting a conversation? Or does an unexpected speaking invitation make your mind go blank or cause you to sweat, even in November? If so, you're not alone. This is called Glossophobia or Speaking Anxiety, which is the most common phobia. Several treatments are available, and you should consult a specialist if it affects your daily life.

In this article, we'll explore how AI can help us create an application to address this issue using AWS Bedrock.

[NOTE: This app doesn't treat the issue. It is just for developing good speaking habits and providing tips.]

Why a Speaking Practice App?

Research shows that knowing your material beforehand, rehearsing your scripts until you memorize them, and continuing to practice until you are comfortable with what you say can help treat speaking anxiety.

Why AWS Bedrock?

Amazon Bedrock is a fully managed service that provides high-performing foundation models (FMs) from top AI companies like AI21 Labs, Anthropic, Cohere, Meta, Mistral AI, Stability AI, and Amazon through a single API. It offers the capabilities needed to build generative AI applications with security, privacy, and responsible AI. It is also easy to use and beginner-friendly. By using AWS Bedrock, we can ensure our app is efficient, reliable, and easy to integrate with other AWS services.

Read More

Prerequisites

To follow along with this tutorial, you will need:

  • Basic knowledge of JavaScript/ES6
  • Node.js and npm installed on your machine
  • AWS credentials (access key ID and secret access key)
  • Familiarity with AWS Bedrock
  • Access to the Claude-v2 model

Let's Begin!

Setting Up the Project

First, let's set up our project on the local machine:

Create a new directory and navigate into it:

mkdir speaking-practice-app
cd speaking-practice-app
Enter fullscreen mode Exit fullscreen mode

Initialize a new Node.js project:

npm init -y

Install the required dependencies: Install Vite for fast development and @aws-sdk/client-bedrock-runtime for running inference using Amazon Bedrock models.

npm install vite @aws-sdk/client-bedrock-runtime

Creating the User Interface

For the next steps, you can either follow the instructions or clone the entire application from here: https://github.com/amelia2802/glossocure

Create an index.html file and add the following code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Speaking Practice App</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header>
    <h1>GLOSSOCURE</h1>
  </header>
  <main id="app">
    <section id="daily-text">
      <section class="head-component">
        <h2>Read Aloud 🔊</h2>
        <button id="getNewParagraph">Get New Paragraph</button>
      </section>
      <article id="paragraph">...</article>
    </section>
    <section class="daily-tips">
      <h3>Daily Tips 💡</h3>
      <p id="tips"></p>
    </section>
  </main>
  <script type="module" src="main.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Add CSS styling in style.css:

:root {
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  font-weight: 400;
  color-scheme: light dark;
  color: rgba(255, 255, 255, 0.968);
  background-color: #242424;
  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  margin: 0;
  display: block;
}

header {
  position: absolute;
  top: 0;
  width: 100%;
  text-align: center;
  box-shadow: 10px 0 10px rgb(243, 239, 61);
}

h1 {
  font-size: 3.2em;
  line-height: 1.1;
}

#app {
  position: absolute;
  top: 10rem;
  margin: 0 7rem;
}

.head-component {
  display: flex;
  justify-content: space-between;
}

#getNewParagraph {
  height: 100%;
  padding: 1rem;
  border-radius: 25px;
  background-color: rgb(240, 248, 151);
  font-weight: 600;
  font-family: inherit;
}

#getNewParagraph:hover, #getNewParagraph:focus {
  background-color: rgb(231, 246, 76);
  box-shadow: 1px 1px 5px rgb(249, 255, 186);
  color: black;
}

h2 {
  font-size: 1.5rem;
  font-style: oblique;
}

#paragraph {
  line-height: 27px;
}

.daily-tips {
  margin: auto;
  width: 30%;
  border: 2px dashed rgb(224, 248, 151);
  margin-top: 3rem;
  border-radius: 1rem 1rem 13%;
  text-align: center;
  padding: 0 1rem;
}
Enter fullscreen mode Exit fullscreen mode

Integrating the Frontend with the Backend

Now let's link our frontend to AWS Bedrock to fetch paragraphs and tips.

Create a main.js file & import dependencies

import './style.css';
import { BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime";
Enter fullscreen mode Exit fullscreen mode

Setting Up Constants


const modelId = 'anthropic.claude-v2';
const paragraphPrompt = "Generate a paragraph for speaking practice. Imagine you are answering an interview(news,job,entertainment) question.";
const tips = "Give daily two liner tip to overcome speaking anxiety.";
Enter fullscreen mode Exit fullscreen mode

modelId: The ID of the model we'll use from AWS Bedrock.

paragraphPrompt: A prompt that asks the model to generate a paragraph for speaking practice.

tips: A prompt that asks the model to provide daily tips for overcoming speaking anxiety.

Creating Conversation Objects & Declaring Variables

const paragraphConversation = [
  {
    role: "user",
    content: [{ text: paragraphPrompt }],
  },
];

const tipsConversation = [
  {
    role: "user",
    content: [{ text: tips }],
  },
];

let client = null;
Enter fullscreen mode Exit fullscreen mode

paragraphConversation and tipsConversation: These are the messages we send to the model. The role: "user" indicates that the prompt is from the user.

client: This variable will hold the instance of BedrockRuntimeClient.

Fetching a New Paragraph & a New Tip

async function fetchNewParagraph() {
  disableButton(true);
  showLoadingAnimation();

  try {
    const response = await client.send(new ConverseCommand({ modelId, messages: paragraphConversation }));
    console.log("Response from Bedrock (Paragraph):", response);
    const paragraph = response.output.message.content[0].text;
    document.querySelector("#paragraph").innerHTML = paragraph;
  } catch (err) {
    console.error("Error fetching new paragraph:", err);
    document.querySelector("#paragraph").innerHTML = 'An error occurred while fetching the paragraph.';
  }

  disableButton(false);
}

async function fetchNewTip() {
  try {
    const response = await client.send(new ConverseCommand({ modelId, messages: tipsConversation }));
    console.log("Response from Bedrock (Tips):", response);
    const tip = response.output.message.content[0].text;
    document.querySelector("#tips").innerHTML = tip;
  } catch (err) {
    console.error("Error fetching daily tip:", err);
    document.querySelector("#tips").innerHTML = 'Unable to fetch daily tip.';
  }
}

Enter fullscreen mode Exit fullscreen mode

fetchNewParagraph: An asynchronous function that fetches a new paragraph.

disableButton(true): Disables the button while fetching.

showLoadingAnimation(): Shows a loading spinner while fetching.

try-catch block: Attempts to fetch a new paragraph and update the DOM. If an error occurs, it logs the error and shows an error message.

fetchNewTip: Similar to fetchNewParagraph, but it fetches a tip instead.

Utility Function

function disableButton(isDisabled) {
  const paragraphButton = document.querySelector("#getNewParagraph");
  paragraphButton.disabled = isDisabled;
}
Enter fullscreen mode Exit fullscreen mode

disableButton: Enables or disables the button to prevent multiple clicks during the fetch.

Initializing the App

async function init() {
  try {
    const creds = await fetchCredentials();
    client = await createBedrockClient(creds);
    await fetchNewParagraph();
    await fetchNewTip();
  } catch (err) {
    console.error("Error initializing application:", err);
    document.querySelector("#paragraph").innerHTML = 'An error occurred while initializing the application.';
    document.querySelector("#tips").innerHTML = 'An error occurred while initializing the application.';
  }

  const paragraphButton = document.querySelector("#getNewParagraph");
  paragraphButton.addEventListener("click", fetchNewParagraph);
}
Enter fullscreen mode Exit fullscreen mode

init: An asynchronous function to initialize the app.

  • Fetches credentials and creates the Bedrock client.
  • Fetches the initial paragraph and tip.
  • Adds an event listener to the button to fetch a new paragraph when clicked.

Creating Bedrock Client

async function createBedrockClient(creds) {
  try {
    return new BedrockRuntimeClient({
      credentials: creds.credentials,
      region: creds.region,
    });
  } catch (err) {
    console.error("Error creating Bedrock client:", err);
    throw err;
  }
}
Enter fullscreen mode Exit fullscreen mode

createBedrockClient: Creates and returns a new instance of BedrockRuntimeClient with the provided credentials and region.

Fetching Credentials

async function fetchCredentials() {
  return {
    region: "us-west-2",
    credentials: {
      accessKeyId: import.meta.env.VITE_AWS_ACCESS_KEY_ID,
      secretAccessKey: import.meta.env.VITE_AWS_SECRET_ACCESS_KEY,
    },
  };
}
init();
Enter fullscreen mode Exit fullscreen mode

fetchCredentials: Returns the AWS credentials from environment variables and init(): Calls the init function to start the application.

Create a .env file & add the AWS credentials to it:

VITE_AWS_DEFAULT_REGION=us-west-2 // YOUR REGION
VITE_AWS_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY
VITE_AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY
Enter fullscreen mode Exit fullscreen mode

Running the Application

npx vite

You should now see the app running, with functionalities to fetch new paragraphs for practice and daily tips.

Homepage

Click on the Generate button and you can see a new paragraph.

Conclusion

Congratulations! You have successfully created a speaking practice app using AWS Bedrock. This app generates paragraphs for speaking practice and daily tips to overcome speaking anxiety, providing a useful tool for improving communication skills.

Top comments (0)