Software Development

Crafting a Customized Sports activities Exercise Service – Insta News Hub

Crafting a Customized Sports activities Exercise Service – Insta News Hub

Enter the realm of Synthetic Intelligence (AI), the place machine studying fashions and clever algorithms are revolutionizing how we work together with information, make selections, and predict outcomes. The fusion of AI with Node.js opens a portal to a mess of prospects, remodeling the panorama of internet providers throughout varied domains, together with sports activities and health.

Lifecycle

On the base of the appliance, we going to have some sports activities exercise day by day ideas which shall be generated primarily based on AI. Which means we do an exercise that AI instructed, then we’ve to ask AI once more about ideas. Then we get a response from AI on our software and expose it for the subsequent day. Then customers will see that new suggestion plan many times daily.

Crafting a Customized Sports activities Exercise Service – Insta News Hub

Lifecycle of sports activities exercise era

Additionally, we going to restrict sports activities actions across the prospects that may be achieved individually by the consumer.

Some possible sports activities that the user can do

Some potential sports activities actions that the consumer can do

Let’s say soccer or hockey will be carried out by the consumer, but it surely’s a workforce sport and requires some further immediate setup for AI era. We going to focus particularly on solo exercise which going to deliver us simplicity initially.

Setup OpenAI API

The trail goes to be fairly easy. In our case, we going to make use of OpenAI API and a Node.js surroundings. That is normally simple to seek out from the primary dashboard or menu.

For those who’re a brand new consumer or haven’t used the API earlier than, you might want to use for entry. This might contain filling out a kind the place you clarify how you propose to make use of the API.

OpenAI might need completely different plans, together with free or paid choices, relying on utilization limits and extra options. For many paid plans, you’ll must enter billing info.

As soon as your account is about up and you’ve got API entry, you’ll be given an API key. This key’s a protracted string of characters that uniquely identifies your account.

Let’s go to OpenAI and navigate to the API part. Navigate to https://platform.openai.com/api-keys. From the listing of api-keys take what you going to make use of. That key seems to be one thing like this:

OPENAI_API_KEY="sk-PMCRj7YiTV9e8OdTV26AI7BhcdkFJYZ3lu0p00H3217315y84"

Along with your API key, you can begin making requests to the OpenAI API. In your code, you’ll usually set this key in your HTTP headers or in a configuration file to authenticate your API requests.

Right here you possibly can see how we going to proceed:

Service building process

Service constructing course of

Select the OpenAI Mannequin

The perfect mannequin could be one from the GPT-4 sequence with the flexibility to course of and generate textual content primarily based on an unlimited vary of knowledge. However in our case, I going to make use of gpt-3.5-turbo. This mannequin is tremendous quick and optimized for quicker response. Additionally, it’s designed to be more cost effective making it an acceptable alternative for purposes that require frequent and huge numbers of API calls.

Setting Node.js Surroundings

Let’s generate a easy node software with express framework. For that, I’m utilizing create-node-application, but it surely’s as much as you which of them generator to make use of or set it up by your self. We’d like an surroundings and entry level from the place we going to reveal endpoints.

npx create-node-application sports_activity_servise -fw=categorical

The undertaking ought to have a `src` file with `index.ts` which must be a easy default setup for launching the server.

App listening at http://localhost:3000

If you’ll be able to get Whats up world by accessing that URL, then every part is ok.

Let’s check out the construction of the service.

Schema of the application

Schema of the appliance

Now we have to set up dependencies. Run npm i --save openai and confirm in your bundle.json that the bundle has been put in.

OpenAI package in the package.json

OpenAI bundle within the bundle.json

The subsequent step is to confirm the surroundings variables. For that, we’ve to create .env within the root of sports_activity_servise and add the next values:

Environment variables for sports activity service

Surroundings variables for sports activities exercise service

Now, we will make the most of these values in our software, due to the dotenvbundle. Let’s use the OPENAI_API_KEY we obtained from the platform. To do that, we have to create src/config/index.ts and add the next code:

import OpenAI from 'openai';

export const openai = new OpenAI({
  apiKey: course of.env.OPENAI_API_KEY,
});

This configuration will grant us entry to the OpenAI interface, which we plan to make the most of inside our controllers.

Utilization of the OpenAI With Node.js

To precisely counsel a sports activities exercise, it’s important to assemble particular details about the consumer. In our database, we intention to gather primary consumer indicators and a historical past of actions they’ve undertaken for the reason that final suggestion supplied by the service. Let’s evaluate the schema.

Result of sports activity based on indicators and history of activities

Results of sports activities exercise primarily based on indicators and historical past of actions

As you possibly can see, the end result is at all times influenced by historical past. Nonetheless, this outcome will be enhanced via varied components. The ultimate suggestion will be affected by the present climate, exercise frequency, companions, residing space, life-style, and accessibility, amongst others. We’ll focus on a choose few of those components to simplify the method.

Schema of building the prompt for OpenAI

Schema of constructing the immediate for OpenAI

We have to assemble a concise immediate that clearly communicates to OpenAI our requirement for a response detailing right now’s exercise.

As beforehand talked about, we’ll make the most of Knex for database interactions. For steering on organising the database, executing migrations, and seeding, please consult with my different article: How to Create Node.js Server With Postgres and Knex on Express.

Let’s develop the required migrations for our database:

knex migrate:make create_users_table -x ts
knex migrate:make create_indicators_table -x ts
knex migrate:make create_activities_table -x ts

Then fill them up one after the other:

{
await knex.schema.createTable(tableName, perform (desk) {
desk.increments(‘id’).main();
desk.string(‘first_name’).notNullable();
desk.string(‘last_name’).notNullable();
desk.string(‘username’).notNullable();
desk.string(‘e mail’).notNullable();
desk.string(‘password’).notNullable();
desk.timestamps(true, true);
});
}

export async perform down(knex: Knex): Promise {
await knex.schema.dropTable(tableName);
}” data-lang=”software/typescript”>

import { Knex } from 'knex';

const tableName="customers";

export async perform up(knex: Knex): Promise<void> {
  await knex.schema.createTable(tableName, perform (desk) {
    desk.increments('id').main();
    desk.string('first_name').notNullable();
    desk.string('last_name').notNullable();
    desk.string('username').notNullable();
    desk.string('e mail').notNullable();
    desk.string('password').notNullable();
    desk.timestamps(true, true);
  });
}

export async perform down(knex: Knex): Promise<void> {
  await knex.schema.dropTable(tableName);
}

Customers desk migration file

{
await knex.schema.createTable(tableName, perform (desk) {
desk.increments(‘id’).main();
desk.integer(‘age’).notNullable();
desk.integer(‘weight’).notNullable();
desk.integer(‘top’).notNullable();
desk.enu(‘life_style’, Object.values(LifeStyle)).notNullable();
desk.integer(‘user_id’).unsigned().notNullable();
desk.overseas(‘user_id’).references(‘id’).inTable(‘customers’).onDelete(‘CASCADE’);
desk.timestamps(true, true);
});
}

export async perform down(knex: Knex): Promise {
await knex.schema.dropTable(tableName);
}” data-lang=”software/typescript”>

import { Knex } from 'knex';
import { LifeStyle } from '../../src/constants/indicators';

const tableName="indicators";

export async perform up(knex: Knex): Promise<void> {
  await knex.schema.createTable(tableName, perform (desk) {
    desk.increments('id').main();
    desk.integer('age').notNullable();
    desk.integer('weight').notNullable();
    desk.integer('top').notNullable();
    desk.enu('life_style', Object.values(LifeStyle)).notNullable();
    desk.integer('user_id').unsigned().notNullable();
    desk.overseas('user_id').references('id').inTable('customers').onDelete('CASCADE');
    desk.timestamps(true, true);
  });
}

export async perform down(knex: Knex): Promise<void> {
  await knex.schema.dropTable(tableName);
}

Indicators desk migration file

The migration for actions will embody a boolean flag to point completion. That is crucial to find out the suitable timing for sending one other suggestion.

import { Knex } from 'knex';
import { actions } from '../../src/constants/actions';

export async perform up(knex: Knex): Promise<void> {
  await knex.schema.createTable('actions', perform (desk) {
    desk.increments('id').main();
    desk.enu('activity_type', Object.values(actions)).notNullable();
    desk.string('length').notNullable();
    desk.boolean('is_completed').defaultTo(false).notNullable();
    desk.integer('user_id').unsigned().notNullable();
    desk.overseas('user_id').references('id').inTable('customers').onDelete('CASCADE');
    desk.timestamps(true, true);
  });
}

export async perform down(knex: Knex): Promise<void> {
  await knex.schema.dropTable('actions');
}

Actions desk migration file

Subsequent, execute knex migrate:newest to include all the required fields into the database. Following this, to populate the database with preliminary information, execute the seeding command:

knex seed:make 01-users -x ts
knex seed:make 02-indicators -x ts

With the next information:

[] = [
…Array(10).keys(),
].map(() => ({
e mail: faker.web.e mail().toLowerCase(),
first_name: faker.particular person.firstName(),
last_name: faker.particular person.lastName(),
username: faker.web.userName().toLowerCase(),
}));
const testUser = {
e mail: course of.env.TEST_USER_EMAIL as string,
first_name: course of.env.TEST_USER_FIRST_NAME as string,
last_name: course of.env.TEST_USER_LAST_NAME as string,
username: course of.env.TEST_USER_USERNAME as string,
};
customers.push(testUser);
const hashed_password = await bcrypt.hash(defaultPassword, 10);
await knex(tableName).insert(customers.map(consumer => ({ …consumer, password: hashed_password })));
};” data-lang=”software/typescript”>

require('dotenv').config();
import { Knex } from 'knex';
import * as course of from 'course of';
import bcrypt from 'bcrypt';
import { faker } from '@faker-js/faker';
import { Position, Consumer } from '../../src/@varieties';

const tableName="customers";
const defaultPassword = course of.env.DEFAULT_PASSWORD as string;

exports.seed = async perform (knex: Knex) {
  await knex(tableName).del();
  const customers: Omit<Consumer, 'id' | 'password' | 'created_at' | 'updated_at'>[] = [
    ...Array(10).keys(),
  ].map(() => ({
    e mail: faker.web.e mail().toLowerCase(),
    first_name: faker.particular person.firstName(),
    last_name: faker.particular person.lastName(),
    username: faker.web.userName().toLowerCase(),
  }));
  const testUser = {
    e mail: course of.env.TEST_USER_EMAIL as string,
    first_name: course of.env.TEST_USER_FIRST_NAME as string,
    last_name: course of.env.TEST_USER_LAST_NAME as string,
    username: course of.env.TEST_USER_USERNAME as string,
  };
  customers.push(testUser);
  const hashed_password = await bcrypt.hash(defaultPassword, 10);
  await knex(tableName).insert(customers.map(consumer => ({ ...consumer, password: hashed_password })));
};

01-users.ts — customers seed

{
return {
id: index + 1,
age: faker.quantity.int({ min: 14, max: 60 }),
weight: faker.quantity.int({ min: 50, max: 110 }),
top: faker.quantity.int({ min: 140, max: 220 }),
life_style: lifeStyleValues[faker.number.int({ min: 0, max: lifeStyleValues.length – 1 })],
user_id: consumer.id,
};
});

await knex(tableName).insert(indicators);
};” data-lang=”software/typescript”>

import { faker } from '@faker-js/faker';
import { Knex } from 'knex';
import { LifeStyle } from '../../src/constants/indicators';

const tableName="indicators";

exports.seed = async perform (knex: Knex) {
  await knex(tableName).del();
  const lifeStyleValues = Object.values(LifeStyle);

  const usersIds = await knex('customers').choose('id');
  const indicators = usersIds.map((consumer, index) => {
    return {
      id: index + 1,
      age: faker.quantity.int({ min: 14, max: 60 }),
      weight: faker.quantity.int({ min: 50, max: 110 }),
      top: faker.quantity.int({ min: 140, max: 220 }),
      life_style: lifeStyleValues[faker.number.int({ min: 0, max: lifeStyleValues.length - 1 })],
      user_id: consumer.id,
    };
  });

  await knex(tableName).insert(indicators);
};

02-indicators.ts — Indicators Seed

As you possibly can observe, the symptoms for the consumer are fairly primary. Moreover, whereas the immediate may embody a historical past of actions for extra context, we’ll omit this step for the preliminary seeding course of. As soon as all of the information are ready, merely execute knex seed:run to populate the database. At this stage, our database is absolutely ready.

Now within the src folder create a index.ts as an entry level for our service:

import * as course of from 'course of';
require('dotenv').config();
import categorical from 'categorical';
import bodyParser from 'body-parser';
import cors from 'cors';
import { router } from 'src/routes';
import { connectToRedis } from 'src/redis';

const app = categorical();
const PORT = course of.env.PORT || 9999;

app.use(bodyParser.json());
app.use(cors());
app.use('/api/v1', router);

(async () => {
  attempt {
    await connectToRedis();

    app.hear(PORT, async () => {
      console.log(`Server is operating on port ${PORT}`);
    });
  } catch (error) {
    console.error('Failed to begin server:', error);
    course of.exit(1);
  }
})();

Entrypoint for service

Routing

Earlier than we proceed to assemble controllers, let’s study the routing setup which we getting from src/routes/index.ts.

import { Router } from 'categorical';
import { authRouter } from 'src/routes/authRouter';
import { sessionController } from 'src/controllers/sessionController';
import { authMiddleware } from 'src/middlewares/authMiddleware';
import { userRouter } from 'src/routes/userRouter';
import { suggestionRouter } from 'src/routes/suggestionRouter';
import { indicatorRouter } from 'src/routes/indicatorRouter';

export const router = Router({ mergeParams: true });

router.use('/auth', authRouter);
router.use(authMiddleware);
router.get('/session', sessionController);

router.use('/consumer', userRouter);
router.use('/suggestion', suggestionRouter);
router.use('/indicator', indicatorRouter);

Routes for software

To take care of focus and keep away from diverging from our present context, we’ll bypass the setup of Redis and the authentication phase. For an in-depth exploration of those areas, please seek the advice of my different articles on authentication in Node.js purposes.

From middleware authMiddleware within the following iterations we going to acquire consumer session: req.consumer = userSession. This session consists solely of an identifier, with no further info.

export kind UserSession = {
  id: quantity;
}

We’ll make the most of that ID to retrieve the consumer and all important information required for the immediate. Keep in mind, our goal is to assemble a immediate tailor-made for OpenAI.

Ideas we going to get from suggestionRouter which comprise get and publish endpoints.

import { Router } from 'categorical';
import { getSuggestionController } from 'src/controllers/suggestion/getSuggestionController';
import { finishLastSuggestionController } from 'src/controllers/suggestion/finishLastSuggestionController';

export const suggestionRouter = Router({ mergeParams: true });

suggestionRouter.get("https://dzone.com/", getSuggestionController);
suggestionRouter.publish('/end', finishLastSuggestionController);

Router for ideas

The ultimate element is the indicatorRouter, which homes a single controller:

import { Router } from 'categorical';
import { updateIndicatorController } from 'src/controllers/indicators/updateIndicatorController';

export const indicatorRouter = Router({ mergeParams: true });

indicatorRouter.publish("https://dzone.com/", updateIndicatorController);

Router for indicators

Fashions

Now, it’s time to discover the performance of fashions and easy methods to handle them. For extra detailed info on creating modules, I’ve supplied an in-depth clarification in one other article: Crafting Database Models with Knex.js and PostgreSQL. You may examine there easy methods to construct primary Mannequin and use it for different fashions. We have to have 3 further fashions within the folder src/fashions:

(information: Payload) {
return tremendous.insert({
…information,
function: Position.Consumer,
});
}

public static findByEmail(e mail: string): Promise {
return this.findOneBy<
{
e mail: string;
},
Consumer
>({ e mail });
}

public static findByUsername(username: string): Promise {
return this.findOneBy<
{
username: string;
},
Consumer
>({ username });
}
}” data-lang=”software/typescript”>

import { Mannequin } from 'src/fashions/Mannequin';
import { Position, Consumer, DefaultUserData } from 'src/@varieties';

export class UserModel extends Mannequin {
  static tableName="customers";

  public static async create<Payload>(information: Payload) {
    return tremendous.insert<Payload & DefaultUserData>({
      ...information,
      function: Position.Consumer,
    });
  }

  public static findByEmail(e mail: string): Promise<Consumer | null> {
    return this.findOneBy<
      {
        e mail: string;
      },
      Consumer
    >({ e mail });
  }

  public static findByUsername(username: string): Promise<Consumer | null> {
    return this.findOneBy<
      {
        username: string;
      },
      Consumer
    >({ username });
  }
}

Consumer mannequin

({
user_id: userId,
});
}

public static async updateByUserId(userId: quantity, information: Partial) {
return this.updateBy<
{
user_id: quantity;
},
Partial
>(
{
user_id: userId,
},
information
);
}
}” data-lang=”software/typescript”>

import { Mannequin } from 'src/fashions/Mannequin';
import kind { Indicator } from 'src/@varieties';

export class IndicatorModel extends Mannequin {
  static tableName="indicators";

  public static async findAllByUserId(userId: quantity) {
    return this.findAllBy<
      {
        user_id: quantity;
      },
      Indicator
    >({
      user_id: userId,
    });
  }

  public static async updateByUserId(userId: quantity, information: Partial<Indicator>) {
    return this.updateBy<
      {
        user_id: quantity;
      },
      Partial<Indicator>
    >(
      {
        user_id: userId,
      },
      information
    );
  }
}

Indicator mannequin

({
user_id: userId,
});
}
}” data-lang=”software/typescript”>

import { Mannequin } from 'src/fashions/Mannequin';
import kind { Exercise } from 'src/@varieties';

export class ActivityModel extends Mannequin {
  static tableName="actions";

  public static async findAllByUserId(userId: quantity) {
    return this.findAllBy<
      {
        user_id: quantity;
      },
      Exercise
    >({
      user_id: userId,
    });
  }
}

Exercise mannequin

All these fashions inherit from a base mannequin, which offers a set of instruments for get, set, or delete strategies. Now, we’re ready to include these fashions into our controllers.

Expectations From the Immediate

Now, let’s step again from the core implementation particulars and concentrate on the end result we anticipate from OpenAI.

  1. It must be a GET endpoint that returns the outcome to us. Our route: localhost:9999/api/v1/suggestion
  2. The outcome must be a JSON object with the particular keys that we predict within the response.
  3. It ought to return the kind of exercise in a format that we will simply acknowledge.

Let’s evaluate the response from Postman depicted on this picture.

Postman Response on suggestion route

Postman Response on suggestion route

The kind of response we intention to explain will resemble the next:: Promise<Suggestion>

export kind Exercise = {
  id: quantity;
  activity_type: string;
  is_completed: boolean;
  length: quantity;
  created_at: Date;
};

export kind ActivityDescription = {
  description: string;
  water_consume: quantity;
  distance?: quantity;
  plan: string[];
};

export kind Suggestion = Exercise & ActivityDescription;

So, meaning, that we have to create a perform: getSportActivitySuggestionwhich going to return to us a promise with suggestion information.

However how often ought to we anticipate to obtain this suggestion? One in all method is to both use a timer or wait till the completion of the final suggestion, as indicated by a POST request from the shopper with new indicators after the final exercise. Right here’s the schema:

Lifecircle of suggestion and update indicators.

Lifecircle of suggestion and replace indicators.

When a shopper sends a request for a suggestion, the shopper app also needs to specify the timing for the subsequent request. This could happen instantly after updating the symptoms, serving as a sign to the shopper that it’s time to hunt a brand new suggestion, relying on the interval elapsed for the reason that final suggestion.

Get Ideas for Sport Exercise

Now, we have to develop a controller to handle the suggestion outcomes. To do that, create src/controllers/getSuggestionController and insert the next code:

import { Request, Response } from 'categorical';
import { IndicatorModel } from 'src/fashions/IndicatorModel';
import { ActivityModel } from 'src/fashions/ActivityModel';
import { getSportActivitySuggestion } from 'src/helpers/getSportActivitySuggestion';

export const getSuggestionController = async (req: Request, res: Response) => {
  attempt {
    const [indicator] = await IndicatorModel.findAllByUserId(req.consumer.id);
    const [lastActivity] = await ActivityModel.findAllByUserId(req.consumer.id);

    if (lastActivity && !lastActivity.is_completed) {
      res.json({
        information: lastActivity,
      });
      return;
    }

    const outcome = await getSportActivitySuggestion(indicator, lastActivity);

    await ActivityModel.insert({
      activity_type: outcome.activity_type,
      length: outcome.length,
      is_completed: false,
      user_id: req.consumer.id,
    });

    res.json({
      information: outcome,
    });
  } catch (error: unknown) {
    console.log(error);
    res.standing(500).json({
      message: 'Inside Server Error',
    });
  }
};

getSuggestionController.ts

Upon receiving a suggestion, we should confirm the standing is_completed of the final exercise to keep away from making pointless requests to the OpenAI API if an exercise is already in progress. If there aren’t any energetic actions, we get hold of a suggestion via our getSportActivitySuggestion helper perform. Subsequent, we should log the exercise within the database below the consumer’s ID with the suitable standing, enabling its retrieval for future suggestion requests. Finally, we return that outcome.

To acquire a suggestion from the helper, we should craft an acceptable immediate message for the OpenAI API payload. Let’s delve into the processes executed by our helper perform.

import { Indicator, Exercise, ActivityDescription } from 'src/@varieties';
import { actions } from 'src/constants/actions';
import { openai } from 'src/configs/openai';

export async perform getSportActivitySuggestion(
  indicator: Indicator,
  lastActivity?: Exercise
): Promise<Exercise & ActivityDescription> {
  const systemPrompt = `
    You can be supplied with indicators as age, weight, top, life-style
    and former exercise kind with length if the exist,
    and your process is to return sports activities exercise plan in JSON format is determined by these indicators.
    The plan ought to embody the kind of exercise, the length in minutes, a superb description
    of easy methods to do the exercise, the really helpful water consumption in milliliters,
    and the plan like step-by-step what to do in the course of the exercise.
    
    Instance of the response:
    {
      "activity_type": $ '),
      "length": 30,
      "description": "A steady run at a reasonable tempo to enhance cardiovascular endurance.",
      "water_consume": 500
      "distance": 3000,
      "explanation_why": "The reason why this exercise is nice for you primarily based on you earlier exercise and indicators",
      "plan: ["First step description", "Second step description", "Third step description"]
    }
  `;

  const lastActivityMessage = lastActivity
    ? `
      - Final exercise kind: ${lastActivity.activity_type}
      - Final exercise length: ${lastActivity.length}
      `
    : '';

  const userPrompt = `
  - Age: ${indicator.age}
  - Weight: ${indicator.weight}
  - Peak: ${indicator.top}
  - Way of life: ${indicator.life_style}
  ${lastActivityMessage}
  `;

  const completion = await openai.chat.completions.create({
    messages: [
      { role: 'system', content: systemPrompt },
      { role: 'user', content: userPrompt },
    ],
    mannequin: 'gpt-3.5-turbo',
    temperature: 0.9,
  });

  return JSON.parse(completion.decisions[0].message.content material || '{}');
}

The helper perform makes use of the OpenAI API to generate completions primarily based on a conversation-like construction.

Basically, we’re crafting acceptable messages to create completions, simulating a dialog, and instructing the system on easy methods to assemble the response precisely. We incorporate all of the parameters of indicators, an instance of the response, and particulars from the final accomplished exercise. The perform openai.chat.completions.create() signifies that we have to create completion and generate textual content for instance. On the property messages yow will discover function which will be system the place we offer directions and consumerwhich symbolize enter from the consumer. And content material the content material of the message, which may very well be a immediate or consumer enter. The mannequin specifies the mannequin for use for producing the completion, which is a selected model of the GPT-3.5 mannequin optimized for velocity and efficiency, in our case most least expensive one. The final parameter is temperature which controls the randomness of the generated textual content. The next temperature results in extra various outputs, whereas a decrease temperature produces extra conservative, predictable outcomes. Right here, it’s set to 0.9, indicating a reasonable stage of randomness. Lastly, we merely parse the JSON from the completion outcome.

The worth fro gpt-3.5-turbo is determined by the supplier and the phrases of use. Usually, pricing for utilizing fashions like GPT-3.5 Turbo relies on components such because the variety of requests made, the complexity of the requests, and any further providers supplied. It’s greatest to examine with the particular supplier of the mannequin for correct pricing info.

We have to create a controller that shall be liable for ending the final exercise:

import { Request, Response } from 'categorical';
import { ActivityModel } from 'src/fashions/ActivityModel';

export const finishLastSuggestionController = async (req: Request, res: Response) => {
  attempt {
    const [lastActivity] = await ActivityModel.findAllByUserId(req.consumer.id);
    await ActivityModel.updateOneById(lastActivity.id, {
      is_completed: true,
    });

    res.json({
      id: lastActivity.id,
    });
  } catch (error: unknown) {
    console.log(error);
    res.standing(500).json({
      message: 'Inside Server Error',
    });
  }
};

End the final exercise

And replace the symptoms contained inside the POST request.

import { Request, Response } from 'categorical';
import { IndicatorModel } from 'src/fashions/IndicatorModel';

export const updateIndicatorController = async (req: Request, res: Response) => {
  attempt {
    const { id } = await IndicatorModel.updateByUserId(req.consumer.id, {
      age: req.physique.age,
      weight: req.physique.weight,
      top: req.physique.top,
      life_style: req.physique.life_style,
    });

    res.json({
      id,
    });
  } catch (error: unknown) {
    console.log(error);
    res.standing(500).json({
      message: 'Inside Server Error',
    });
  }
};

Replace indicators controller

We are able to replace indicators utilizing metrics from any shopper that makes use of this service, equivalent to Apple iPhones or Android telephones, which offer ample information. By leveraging this endpoint, we will increase the schema with further parameters to boost precision.

On the conclusion of this course of, I want to illustrate the results of the desk of ideas within the database that you’ll get hold of after finishing all of those steps:

Result of suggestions in the database

Results of ideas within the database

Conclusion

In abstract, harnessing OpenAI for sports activities exercise ideas presents a strong resolution to raise consumer engagement and encourage energetic existence. The refinement of indicators holds immense potential to boost the readability and effectiveness of immediate messages, paving the way in which for extra customized and compelling consumer experiences. On the core of this text lies the pivotal idea of speaking with the OpenAI API, setting up immediate messages, and parsing the resultant information. These elementary processes kind the spine of our software, driving its capacity to generate tailor-made sports activities exercise ideas and ship a seamless consumer expertise.

I belief you discovered this journey pleasing and informative. Ought to you will have any additional ideas or inquiries, please don’t hesitate to achieve out to me by way of feedback or different platforms.

Leave a Reply

Your email address will not be published. Required fields are marked *