Home >Web Front-end >JS Tutorial >WhatsApp AI Chatbot: Let&#s build one with the API

WhatsApp AI Chatbot: Let&#s build one with the API

PHPz
PHPzOriginal
2024-07-30 08:26:031017browse

Hey there, I'm Rohan, founder of Spur, a WhatsApp API & Instagram Comment/DM Automation Software.

A few weeks ago, I wrote a blog on where you should build a WhatsApp integration or not. That was a high-level article on the topic, today we'll be learning on how do you get started with the WhatsApp API?

Let's make a WhatsApp AI Chatbot

Today, we'll make a simple bot that runs on a Node server, takes in webhooks from the WhatsApp Cloud API, reads the messages & uses the
OpenAI GPT 4o to send a response.

Want to jump straight to the code? Link is at the bottom.

Get the WhatsApp Test Number & Token

This is fairly straightforward, and Meta already has a guide on this. Going forward, I'm going to assume

  1. You have created a Meta App
  2. Added the WhatsApp product
  3. Got a test number and can send messages from it

For the token, you can use the temporary token, we'll cover deploying to production in another tutorial someday.

Setting up the Node Server

if you dont have pnpm setup, this is the easiest way

corepack enable
corepack prepare pnpm@latest --activate

now we start

mkdir whatsapp-ai-bot

# intialize npm project
pnpm init

# make the server file
touch index.js

# env file
touch .env

Install the required dependencies now:

pnpm install express dotenv openai

Never commit API keys. To keep sensitive information like API keys out of the codebase, we will use environment variables. Create a .env file in the root directory of your project and add the following line:

OPENAI_API_KEY=<your-openai-api-key>

Now use the created index.js file and add the following code

import express from 'express';
import { config } from 'dotenv';
import OpenAI from 'openai';

// Load environment variables
config();

// Create a web server
const app = express();
const port = process.env.PORT || 3034;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

// Add middleware to parse JSON bodies
app.use(express.json());

// Initialize OpenAI API
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

app.get('/webhooks', (req, res) => {
  if (
    req.query['hub.mode'] === 'subscribe' &&
    req.query['hub.verify_token'] === '1234'
  ) {
    res.send(req.query['hub.challenge']);
  } else {
    res.sendStatus(400);
  }
});

app.post('/webhooks', async (req, res) => {
  const body = req.body.entry[0].changes[0];
  if (body.field !== 'messages') {
    // not from the messages webhook so dont process
    return res.sendStatus(200);
  }

  if (!body.value.messages) {
    return res.sendStatus(200);
  }

  const text = body.value.messages
    .map((message) => message.text.body)
    .join('\n\n');

  console.log(text);

  const completion = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: text }],
  });

  // Extract the response from the OpenAI completion
  const aiResponse = completion.choices[0].message.content;

  // Extract the phone number from the incoming message
  const phoneNumber = body.value.messages[0].from;

  // Prepare the message payload
  const messagePayload = {
    messaging_product: 'whatsapp',
    to: phoneNumber,
    type: 'text',
    text: {
      body: aiResponse,
    },
  };

  // Send the response back to WhatsApp
  try {
    const response = await fetch(
      `https://graph.facebook.com/v20.0/${process.env.PHONE_NUMBER_ID}/messages`,
      {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${process.env.SYSTEM_TOKEN}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(messagePayload),
      },
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    console.log('Message sent successfully');
  } catch (error) {
    console.error('Failed to send message:', error);
  }

  res.sendStatus(200);
});

and also modify the package.json to

{
  "name": "whatsapp-ai-bot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "module",
  "packageManager": "pnpm@9.6.0",
  "dependencies": {
    "dotenv": "^16.4.5",
    "express": "^4.19.2",
    "openai": "^4.53.2"
  },
  "devDependencies": {
    "nodemon": "^3.1.4"
  }
}

Understanding how the code works

Image description

  1. We first create a "GET" endpoint so that when you set the webhook in the Facebook app, the challenge passes. I've also included a value for the verify token in the .env.example value that you can use.
  2. Then comes the POST endpoint, which does the actual magic. It takes in the text, passes it onto ChatGPT and sends that response to the user.

Next Steps

This example is just the tip of the iceberg, there are so so many things you can do to improve this

  1. To implement idempotency, WhatsApp webhooks are not unique and can repeat.
  2. Add an in memory chat history
  3. Persist that memory with Redis/relational databases
  4. Leverage rich content like buttons etc. as responses (this will require OpenAI functions to build)

Conclusion

So that's about it. If you're also interested in the article I wrote about WhatsApp integration, you can check it out here.

I've also shared the code of the working example on Spur's GitHub organization.

The above is the detailed content of WhatsApp AI Chatbot: Let&#s build one with the API. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn