Build Your Own Chatbot with AWS Bedrock and NestJS: A Step-by-Step Guide
Integrating a Generative AI model from AWS Bedrock into a NestJS-based chatbot API offers a powerful approach to building interactive applications. This guide simplifies the process, guiding you step-by-step from setting up your environment to creating a fully functional chatbot API in NestJS using TypeScript.
Step-by-Step Guide: Using a base model from AWS Bedrock with NestJS and AWS SDK
Prerequisites:
AWS Account with access to AWS Bedrock.
Node.js and yarn (…or npm) installed on your local machine.
Basic understanding of NestJS, TypeScript, and RESTful APIs.
Step 1: Select a base model from AWS Bedrock
Access AWS Bedrock:
- Log into your AWS Management Console and search for AWS Bedrock. It provides various foundation models like Anthropic, Stability AI, and others.
Request access and get Model ID:
Browse the available models in the AWS Bedrock console.
Select which one you’ll be using based on your necessities and request access to it.
Note the model's ID that you wish to use (e.g.,
amazon.titan-text-premier-v1:0
or a similar identifier). You can refer to this page to find it.
Step 2: Create a NestJS project
Create a New NestJS Project:
npm i -g @nestjs/cli nest new nest-bedrock-chatbot cd nest-bedrock-chatbot
Install Required Dependencies: We need
AWS SDK
to interact with bedrock anddotenv
to secure our credentials.yarn add @aws-sdk/client-bedrock-runtime dotenv
Step 3: Set up environment variables
Create a
.env
file in your project root with the following details:BEDROCK_MODEL_ID=bedrock-model-id AWS_ACCESS_KEY_ID=your-aws-access-key AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key AWS_REGION=your-aws-region CUSTOM_PROMPT="This is where you tell the model how to act and how to answer."
Refer to this documentation regarding the creation of access keys.
Configure dotenv (
src/main.ts
):import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import * as dotenv from 'dotenv'; dotenv.config(); async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); } bootstrap();
Step 4: Create the service to communicate with AWS Bedrock
Create a new service in NestJS that will handle requests to the AWS Bedrock endpoint.
Generate the Service:
nest g service bedrock
Implement the Bedrock Service (
src/bedrock/bedrock.service.ts
):import { Injectable } from '@nestjs/common'; import { BedrockRuntimeClient, InvokeModelCommand, } from '@aws-sdk/client-bedrock-runtime'; @Injectable() export class BedrockService { private readonly client: BedrockRuntimeClient; private readonly customPrompt: string; constructor() { this.client = new BedrockRuntimeClient({ region: process.env.AWS_REGION, credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID!, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!, }, }); this.customPrompt = process.env.CUSTOM_PROMPT || ''; } async getResponseFromModel(userInput: string): Promise<string> { const body = { inputText: `${this.customPrompt}\n${userInput}`, }; try { const command = new InvokeModelCommand({ modelId: process.env.BEDROCK_MODEL_ID, body: JSON.stringify(body), }); const response = await this.client.send(command); return this.extractResponse(response.body); } catch (error) { console.error('Error interacting with AWS Bedrock:', error); throw new Error('Failed to get a response from the model'); } } extractResponse(data: any): string { const responseBody = new TextDecoder().decode(data); const parsedBody = JSON.parse(responseBody); return parsedBody.results[0].outputText; } }
Note that the structure of the command body depends on the model.
Step 5: Create the controller to handle requests
Generate the Controller:
nest g controller chatbot
Implement the Chatbot Controller (
src/chatbot/chatbot.controller.ts
):
This endpoint will require a body such as{ “prompt”: “Who are you?“ }
and will return a json{ “answer”: “I’m a chatbot” }
.import { Body, Controller, Post } from '@nestjs/common'; import { BedrockService } from 'src/bedrock/bedrock.service'; @Controller('chatbot') export class ChatbotController { constructor(private readonly bedrockService: BedrockService) {} @Post('ask') async askModel( @Body() { prompt }: { prompt: string }, ): Promise<{ answer: string }> { const answer = await this.bedrockService.getResponseFromModel(prompt); return { answer }; } }
Step 6: Test Your Chatbot API
Start the NestJS Application:
npm run start:dev
Test the API Using Postman or Curl:
Make a
POST
request tohttp://localhost:3000/chatbot/ask
curl --location 'localhost:3000/chatbot/ask' \ --header 'Content-Type: application/json' \ --data '{ "prompt": "Who are you?" }'
You should receive a response with the chatbot’s answer based on your custom prompt and user input.
Additional Tips:
Input Validation: Use NestJS DTOs, ValidationPipe, class-transformer, and class-validator to ensure clean inputs.
Error Handling: Enhance error handling for network issues and invalid Bedrock responses.
Custom Prompts: Adjust
CUSTOM_PROMPT
dynamically based on user inputs, allowing for more personalized chatbot interactions.
This guide has walked you through integrating AWS Bedrock models into a NestJS-based chatbot API, allowing you to harness the power of Generative AI without the complexity of deploying custom models. By customizing prompts and refining input/output handling, you can create highly interactive, responsive chatbots tailored to your needs.
Shoutout to Vithor Varela for inspiring me!
Subscribe to my newsletter
Read articles from Wiljeder Filho directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Wiljeder Filho
Wiljeder Filho
Coding stuff