Kembali ke Beranda untuk Developer

Menambahkan WhatsApp Flows ke Pengalaman Chatbot Anda

20 Maret 2024OlehGafi G & Iryna Wagner

Makin banyak bisnis yang menggunakan chatbot melalui WhatsApp untuk berinteraksi dengan pelanggan, memahami kebutuhannya, dan mengumpulkan data penting. Namun, proses pengumpulan dan pengelompokan data ini bisa menjadi tantangan dalam hal efisiensinya. Hadirlah WhatsApp Flows.

Dengan mengintegrasikan chatbot dengan WhatsApp Flows, bisnis Anda bisa menginterpretasikan informasi pelanggan yang masuk secara lebih efektif. Chatbot kemudian bisa memulai Flow tertentu yang disesuaikan untuk pengumpulan data, bergantung pada konteks percakapan.

Dalam tutorial ini, Anda akan membuat chatbot menggunakan Llama 2 dan Python, yang menghubungkannya ke WhatsApp Flows agar bisa meningkatkan kemampuan pengumpulan datanya. Dengan begitu, Anda akan mengetahui bagaimana WhatsApp Flows meningkatkan keramahan pengalaman chatbot bagi pengguna dan meningkatkan akurasi dan efisiensi pengumpulan data pelanggan.

Meningkatkan Pengalaman Chatbot dengan WhatsApp Flows

Chatbot Anda akan menanggapi permintaan dan perintah pengguna dengan WhatsApp Flows untuk pengumpulan data. Fitur ini utamanya akan memungkinkan pengguna untuk bercakap-cakap dengan chatbot, mencari informasi tentang layanan yang ditawarkan oleh hotel fiktif di Spanyol, dan menghubungi perusahaan Anda untuk mendapat dukungan.

Chatbot akan menggunakan pernyataan if sederhana bersama model Llama 2 standar untuk mengakses basis pengetahuan umum yang mencukupi.

Langkah-langkah yang Perlu Diikuti

Bagian 1:

Bagian 2:

  • Konversikan model Llama 2 dari GGML ke GGUF.

  • Tulis kode Python untuk mengintegrasikan Flow dan chatbot.
  • Buat webhook untuk mendengarkan pesan.
  • Jalankan aplikasi.

Bagian 1: Cara Membuat Flow

Di bagian ini, Anda akan menggunakan Flow Builder untuk membuat beberapa Flow. Atau, Anda bisa menggunakan Flows API, yang tidak akan dibahas di sini.

Prasyarat Bagian 1

Untuk melakukannya, pastikan Anda sudah:

Terakhir, pastikan Anda menyelesaikan langkah yang diperlukan untuk menggunakan Flow. Anda juga bisa mempratinjau kode proyek yang selesai.

Memulai

Untuk memulainya, buka halaman Flow di Akun WhatsApp Business Anda. Jika ini pertama kalinya Anda menggunakan Flow, Anda akan melihat tombol bertuliskan Mulai membangun Flow. Atau, akan ada tombol Buat Flow di kanan atas halaman.

Klik tombol yang ditampilkan untuk membuka kotak dialog tempat Anda bisa memasukkan beberapa detail tentang Flow Anda:

Memulai WhatsApp Chatbox

Flow Pertanyaan Layanan

Pertama-tama, Anda akan membuat Flow yang memungkinkan pengguna untuk mencari informasi tentang layanan yang ditawarkan oleh perusahaan hotel.

Masukkan nama di kolom Nama. Lalu, di menu pilihan Kategori, pilih Daftar, dan biarkan menu pilihan Template menjadi Tidak ada. Klik Kirim.

Halaman berikutnya menampilkan editor di sebelah kiri dan pratinjau di sebelah kanan.

Ganti isi editor dengan markup JSON untuk Flow Anda. (Anda bisa mempelajari selengkapnya tentang JSON Flow di dokumentasi developer.)

Simpan Flow dan pratinjau Anda akan mirip seperti gambar berikut:

Chatbox flow

Flow berisi satu layar yang memungkinkan pengguna untuk memasukkan detailnya, memilih layanan yang diminati, dan pesan opsional lain. Saat pengguna mengklik Kirim, Flow tertutup dan mengirimkan data yang diterima ke bisnis Anda untuk diproses. Salah satu metode transmisi data ini mencakup penggunaan endpoint. Namun, proyek ini tidak memerlukan endpoint. Data akan dikirimkan ke webhook yang sama yang mendukung chatbot.

Anda bisa mencapai transfer ini menggunakan tindakan. Anda menentukan data yang akan dikirimkan ke layar berikutnya menggunakan objek payload:

...

"on-click-action": {
    "name": "complete",
    "payload": {
        "firstname": "${form.first_name}",
        "secondname": "${form.second_name}",
        "services_interested": "${form.services_interested}",
        "additional_info": "${form.additional_info}",
        "flow_key": "agentconnect"
    }
}
...
        

Di snippet ini, tindakan pengguna yang mengklik tombol akan memicu on-click-action, yang akan merekam data di payload. Kemudian, payload akan dikirimkan ke server webhook Anda dan menutup Flow melalui tindakan complete.

Anda bisa menetapkan kode payload seperti variabel lainnya. Nilai terkait bisa merepresentasikan objek data atau nama komponen Flow (seperti atribut nama formulir HTML).

Sekarang Anda bisa melihat Flow di tindakan dan menyimulasikan pengalaman pengguna nyata yang menggunakan tombol Pratinjau interaktif:

Chatbox Interactive preview

Setelah menguji, Anda bisa menerbitkan Flow sejak masih dalam status Draf. Untuk melakukannya, buka menu di kanan Simpan dan klik Terbitkan. Flow kini siap digunakan.

Flow Hubungi Kami

Sekarang Anda akan membuat Flow "Hubungi kami".

Mulai dengan mengulangi proses pembuatan Flow awal yang sama. Untuk kategori, pilih Hubungi Kami. Ganti isi editor dengan markup JSON ini untuk merender seperti ini:

Chatbox contact us flow

Terbitkan Flow dan lanjutkan ke bagian berikutnya untuk menyiapkan chatbot. Bagian ini menampilkan tiga fungsi, send_message, flow_details, dan flow_reply_processor, yang berisi logika penting untuk mengirimkan Flow ke pengguna. Bagian ini juga mencakup logika untuk memproses payload Flow yang masuk. Oleh karena itu, kami menyarankan untuk membacanya hingga selesai meski Anda sudah membuat chatbot.

Bagian 2: Cara Menyiapkan Chatbot

Berikutnya, Anda akan mengonfigurasi chatbot dan mengintegrasikannya ke Flow Anda.

Prasyarat Bagian 2

Sebelum melanjutkan, pastikan Anda memiliki:

  • Pengetahuan dasar tentang dan versi terbaru Python

  • Versi HuggingFace dari Llama 2 yang sudah terunduh. Model HuggingFace Llama 2 tidak memerlukan alat lain atau perangkat khusus. Anda bisa menggunakan versi resmi, tetapi Anda perlu melakukan penyiapan tambahan.

  • ID token akses dan nomor telepon akun Anda

  • Editor kode

Menggunakan Python untuk Mengintegrasikan Flow dan Chatbot

Chatbot akan beroperasi melalui skrip yang sudah ditentukan yang dirancang untuk membantu pengguna berdasarkan input mereka. Saat interaksi pertama, chatbot menawarkan teks sambutan yang dipersonalisasi dan menu berbasis teks tergantung dari pesan pengguna. Opsi ini melayani kebutuhan tertentu: mengueri layanan yang ditawarkan oleh hotel, menghubungi salah satu agennya, atau berinteraksi dengan chatbot yang didukung Llama.

Menanggapi dengan karakter alfanumerik akan menghubungkan pengguna ke layanan atau tindakan terkait. Namun, semua tanggapan lain memicu fungsi chatbot default, yang membantu pertanyaan umum atau memandu pengguna melalui layanan yang ada berdasarkan percakapan selanjutnya.

Untuk memulainya, buat lingkungan virtual dengan menjalankan perintah berikut di terminal Anda:

python -m venv venv
        

Aktifkan:

source venv/bin/activate
        

Lalu, instal paket yang diperlukan:

pip install requests flask llama-cpp-python python-dotenv
        

Gunakan Flask untuk membuat rute dan berinteraksi dengan API, requests untuk mengirimkan permintaan internet, llama-cpp-python untuk berinteraksi dengan model, dan python-dotenv untuk memuat variabel lingkungan.

Selanjutnya, buat file lingkungan bernama .env dan konten berikut, yang menetapkan nilainya dengan benar. (Anda bisa menggunakan string apa pun untuk TOKEN.)

TOKEN = 
ACCESS_TOKEN = 
PHONE_NUMBER_ID = 
        

Di direktori yang sama, buat file bernama main.py dan mulai tambahkan paket yang akan Anda gunakan:

import os
import re
import time
import uuid
import requests
from dotenv import load_dotenv
from flask import Flask, request, make_response, json
from llama_cpp import Llama
        

Sekarang, inisialisasi variabel dan kelas. Snippet juga akan memulai Flask dan memanggil metode load_dotenv() untuk membantu memuat variabel:

app = Flask(__name__)

load_dotenv()
PHONE_NUMBER_ID = os.getenv('PHONE_NUMBER_ID')
url = f"https://graph.facebook.com/v18.0/{PHONE_NUMBER_ID}/messages"
TOKEN = os.getenv('TOKEN')
ACCESS_TOKEN = os.getenv('ACCESS_TOKEN')

code_prompt_texts = ["Contact us", "Chat with our chatbot", "YES", "NO"]


service_list = [
    "Accommodation Services",
    "Spa Services",
    "Dining Services",
    "Recreational Facilities",
    "Business & Conference Services",
    "Transportation Services",
    "Accessibility Services",
    "Pet-Friendly Services"
]

service_list menyimpan layanan yang ditawarkan oleh hotel. Daftar code_prompt_texts berisi opsi yang berhubungan dengan pilihan input pengguna, yang berupa, 1, 2, Y, dan N menggunakan fungsi berikut. Fungsi berikut akan membantu memetakan tanggapan pengguna ke opsi terkait.

def extract_string_from_reply(user_input):
    match user_input:
        case "1":
            user_prompt = code_prompt_texts[0].lower()
        case "2":
            user_prompt = code_prompt_texts[1].lower()
        case "Y":
            user_prompt = code_prompt_texts[2].lower()
        case "N":
            user_prompt = code_prompt_texts[3].lower()
        case _:
            user_prompt = str(user_input).lower()

    return user_prompt
        

Kode ini mengonversi string ke huruf kecil untuk mencegah kesalahan pencocokan saat menjalankan logika bersyarat. Struktur match…case mencocokkan perintah yang dimasukkan pengguna ke output. Misalnya, pengguna yang memasukkan "1" akan memicu fungsi "Contact us".

Selanjutnya, fungsi berikut ini berisi pernyataan if yang menggunakan paket Python RegEx, re, untuk mencari istilah tertentu dari pesan pengguna guna menentukan jenis tanggapan mana yang akan dikirimkan ke pengguna:

def user_message_processor(message, phonenumber, name):
    user_prompt = extract_string_from_reply(message)
    if user_prompt == "yes":
        send_message(message, phonenumber, "TALK_TO_AN_AGENT", name)
    elif user_prompt == "no":
        print("Chat terminated")
    else:
        if re.search("service", user_prompt):
            send_message(message, phonenumber, "SERVICE_INTRO_TEXT", name)

        elif re.search(
            "help|contact|reach|email|problem|issue|more|information", user_prompt
        ):
            send_message(message, phonenumber, "CONTACT_US", name)

        elif re.search("hello|hi|greetings", user_prompt):
            if re.search("this", user_prompt):
                send_message(message, phonenumber, "CHATBOT", name)

            else:
                send_message(message, phonenumber, "SEND_GREETINGS_AND_PROMPT", name)

        else:
            send_message(message, phonenumber, "CHATBOT", name)
        

Kini, pesan seperti "Hello there" akan memicu metode send_message dengan SEND_GREETINGS_AND_PROMPT sebagai argumen kedua. Di bawah ini adalah metode send_message. Ganti konten antara <xxx> dengan tepat.

def send_message(message, phone_number, message_option, name):
    greetings_text_body = (
        "\nHello "
        + name
        + ". Welcome to our hotel. What would you like us to help you with?\nPlease respond with a numeral between 1 and 2.\n\n1. "
        + code_prompt_texts[0]
        + "\n2. "
        + code_prompt_texts[1]
        + "\n\nAny other reply will connect you with our chatbot."
    )

    # loading the list's entries into a string for display to the user
    services_list_text = ""
    for i in range(len(service_list)):
        item_position = i + 1
        services_list_text = (
            f"{services_list_text} {item_position}. {service_list[i]} \n"
        )

    service_intro_text = f"We offer a range of services to ensure a comfortable stay, including but not limited to:\n\n{services_list_text}\n\nWould you like to connect with an agent to get more information about the services?\n\nY: Yes\nN: No"

    contact_flow_payload = flow_details(
        flow_header="Contact Us",
        flow_body="You have indicated that you would like to contact us.",
        flow_footer="Click the button below to proceed",
        flow_id=str("<FLOW-ID>"),
        flow_cta="Proceed",
        recipient_phone_number=phone_number,
        screen_id="CONTACT_US",
    )

    agent_flow_payload = flow_details(
        flow_header="Talk to an Agent",
        flow_body="You have indicated that you would like to talk to an agent to get more information about the services that we offer.",
        flow_footer="Click the button below to proceed",
        flow_id=str("<FLOW-ID>"),
        flow_cta="Proceed",
        recipient_phone_number=phone_number,
        screen_id="TALK_TO_AN_AGENT",
    )

    match message_option:
        case "SEND_GREETINGS_AND_PROMPT":
            payload = json.dumps(
                {
                    "messaging_product": "whatsapp",
                    "to": str(phone_number),
                    "type": "text",
                    "text": {"preview_url": False, "body": greetings_text_body},
                }
            )
        case "SERVICE_INTRO_TEXT":
            payload = json.dumps(
                {
                    "messaging_product": "whatsapp",
                    "to": str(phone_number),
                    "type": "text",
                    "text": {"preview_url": False, "body": service_intro_text},
                }
            )
        case "CHATBOT":
            LLM = Llama(
                model_path="/home/incognito/Downloads/llama-2-7b-chat.ggmlv3.q8_0.gguf.bin",
                n_ctx=2048,
            )
            # create a text prompt
            prompt = message
            # generate a response (takes several seconds)
            output = LLM(prompt)
            payload = json.dumps(
                {
                    "messaging_product": "whatsapp",
                    "to": str(phone_number),
                    "type": "text",
                    "text": {
                        "preview_url": False,
                        "body": output["choices"][0]["text"],
                    },
                }
            )
        case "CONTACT_US":
            payload = contact_flow_payload
        case "TALK_TO_AN_AGENT":
            payload = agent_flow_payload
        case "FLOW_RESPONSE":
            payload = json.dumps(
                {
                    "messaging_product": "whatsapp",
                    "to": str(phone_number),
                    "type": "text",
                    "text": {"preview_url": False, "body": message},
                }
            )

    headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer " + ACCESS_TOKEN,
    }

    requests.request("POST", url, headers=headers, data=payload)
    print("MESSAGE SENT")

Jika pesannya berupa salam sederhana (SEND_GREETINGS_AND_PROMPT), tanggapan berisi perintah tambahan (greetings_text_body).

Chatbox sample greeting

Sama halnya, saat pengguna mengajukan pertanyaan tentang layanan yang ditawarkan, pesan teks (service_intro_text) yang berisi layanan dikirimkan ke pengguna. Selain layanan, pesan ini juga berisi perintah bagi pengguna apakah mereka ingin berbicara dengan agen.

Chatbox sample offers

Jika entri mengharuskan tanggapan chatbot (CHATBOT), Anda menginisialisasi model, memasukkan konten pesan ke model, dan memproses tanggapan untuk dikirimkan kembali ke pengguna. FLOW_RESPONSE menampilkan tanggapan yang direkam Flow.

Opsi lainnya, CONTACT_US dan TALK_TO_AN_AGENT, mengirimkan payload Flow ke pengguna. Payload Flow berasal dari fungsi flow_details, yang isinya ditampilkan di bawah ini. Payload menggabungkan detail Flow esensial, termasuk FLOW_ID, yang bisa Anda ambil dari halaman Flow di akun WhatsApp Business Anda. Anda juga bisa menentukan ID ini dalam variabel lingkungan Anda.

def flow_details(flow_header, 
    flow_body, 
    flow_footer, 
    flow_id, 
    flow_cta, 
    recipient_phone_number, 
    screen_id
):
    # Generate a random UUID for the flow token
    flow_token = str(uuid.uuid4())

    flow_payload = json.dumps({
        "type": "flow",
        "header": {
            "type": "text",
            "text": flow_header
        },
        "body": {
            "text": flow_body
        },
        "footer": {
            "text": flow_footer
        },
        "action": {
            "name": "flow",
            "parameters": {
                "flow_message_version": "3",
                "flow_token": flow_token,
                "flow_id": flow_id,
                "flow_cta": flow_cta,
                "flow_action": "navigate",
                "flow_action_payload": {
                    "screen": screen_id
                }
            }
        }
    })

    payload = json.dumps({
        "messaging_product": "whatsapp",
        "recipient_type": "individual",
        "to": str(recipient_phone_number),
        "type": "interactive",
        "interactive": json.loads(flow_payload)
    })
    return payload
        

Metode ini menciptakan action.parameters.flow_token dengan membuat UUID acak. action.parameters.flow_action_payload.screen dikirimkan sebagai parameter (screen_id). Idealnya, parameter ini mewakili ID layar awal yang ingin Anda tampilkan ke pengguna saat action.parameters.flow_cta dijalankan.

Terakhir, tambahkan rute webhook. Permintaan webhook GET menginisiasi webhook ke aplikasi Anda di Meta untuk Developer. Kode ini mengembalikan hub.challenge permintaan jika berhasil.

@app.route("/webhook", methods=["GET"])
def webhook_get():
    if request.method == "GET":
        if (
            request.args.get("hub.mode") == "subscribe"
            and request.args.get("hub.verify_token") == TOKEN
        ):
            return make_response(request.args.get("hub.challenge"), 200)
        else:
            return make_response("Success", 403)
        

Permintaan POST mengekstrak dan memproses payload pesan menggunakan metode user_message_processor yang diperkenalkan sebelumnya. Karena kode ini hanya menangani payload pesan, kode ini akan memunculkan kesalahan saat menangkap payload lainnya. Untuk alasan ini, Anda bisa menggunakan pernyataan if untuk memeriksa apakah terdapat isi messages.

@app.route("/webhook", methods=["POST"])
def webhook_post():
    if request.method == "POST":
        request_data = json.loads(request.get_data())
        if (
            request_data["entry"][0]["changes"][0]["value"].get("messages")
        ) is not None:
            name = request_data["entry"][0]["changes"][0]["value"]["contacts"][0][
                "profile"
            ]["name"]
            if (
                request_data["entry"][0]["changes"][0]["value"]["messages"][0].get(
                    "text"
                )
            ) is not None:
                message = request_data["entry"][0]["changes"][0]["value"]["messages"][
                    0
                ]["text"]["body"]
                user_phone_number = request_data["entry"][0]["changes"][0]["value"][
                    "contacts"
                ][0]["wa_id"]
                user_message_processor(message, user_phone_number, name)
            else:
                # checking that there is data in a flow's response object before processing it
                if (
                    request_data["entry"][0]["changes"][0]["value"]["messages"][0][
                        "interactive"
                    ]["nfm_reply"]["response_json"]
                ) is not None:
                    flow_reply_processor(request)

    return make_response("PROCESSED", 200)
        

Selain itu, Anda bisa menggunakan fungsi bantuan yang disebut flow_reply_processor untuk mengekstrak tanggapan dari Flow dan mengirimkannya kembali kepada pengguna:

def flow_reply_processor(request):
    request_data = json.loads(request.get_data())
    name = request_data["entry"][0]["changes"][0]["value"]["contacts"][0]["profile"]["name"]
    message = request_data["entry"][0]["changes"][0]["value"]["messages"][0]["interactive"]["nfm_reply"][
        "response_json"]

    flow_message = json.loads(message)
    flow_key = flow_message["flow_key"]
    if flow_key == "agentconnect":
        firstname = flow_message["firstname"]
        reply = f"Thank you for reaching out {firstname}. An agent will reach out to you the soonest"
    else:
        firstname = flow_message["firstname"]
        secondname = flow_message["secondname"]
        issue = flow_message["issue"]
        reply = f"Your response has been recorded. This is what we received:\n\n*NAME*: {firstname} {secondname}\n*YOUR MESSAGE*: {issue}"

    user_phone_number = request_data["entry"][0]["changes"][0]["value"]["contacts"][0][
        "wa_id"]
    send_message(reply, user_phone_number, "FLOW_RESPONSE", name)
        

Fungsi ini menggunakan kode (flow_key) untuk membedakan antara dua Flow dan dengan begitu mengekstrak tanggapan yang tepat sementara meneruskan ID layar pertama yang tepat.

Sebelum menjalankan kode, bandingkan kode dengan versi lengkap dan pastikan bahwa semuanya cocok.

Cara Menyiapkan Webhook

Sebelum melanjutkan, jalankan perintah ini dari terminal Anda:

flask --app main run --port 5000 
        

Jika berhasil, Anda akan melihat pesan yang bertuliskan:

* Running on http://127.0.0.1:5000
        

Selanjutnya, jalankan ngrok http 5000 untuk mendapatkan URL yang memetakan ke aplikasi Anda. Salin tautan.

Lalu, di akun developer Anda di Meta untuk Developer, klik menu Konfigurasi di bagian WhatsApp pada panel navigasi kiri:

Chatbox configuration

Di kartu Webhook, klik Edit.

Lalu, di kolom URL Callback dari dialog yang terbuka, tempelkan URL yang disalin dan tambahkan /webhook ke dialog terebut.

Di file .env, tambahkan token dari variabel TOKEN ke kolom Verifikasi token. Klik Verifikasi dan simpan untuk menutup dialog.

Kini, dari kartu yang sama, klik Kelola dan periksa kolom pesan. Tampilan kartu akan seperti ini:

WhatsApp Chatbox webhook

Webhook kini sudah siap.

Menjalankan Aplikasi

Anda bisa mengirimkan pesan seperti "Halo" ke nomor akun Anda. Anda akan menerima tanggapan yang sesuai. Coba balas dengan perintah yang ditampilkan di menu untuk menguji Flow:

WhatsApp Chatbox running app

Di bawah ini cuplikan layar lain yang menampilkan tanggapan chatbot. Pengguna meminta terjemahan singkat, yang bisa diberikan oleh bot tersebut.

WhatsApp Chatbox running app

Kesimpulan

WhatsApp Flows berfungsi sebagai fitur yang andal bagi pelaku bisnis untuk mengumpulkan informasi terstruktur, yang bisa meningkatkan interaksi pelanggan dan menyederhanakan komunikasi antara pelaku bisnis dan konsumen. Salah satu cara membuat Flow adalah menggunakan WhatsApp Manager Flow Builder, yang menawarkan antarmuka yang ramah pengguna untuk mendesain Flow.

Aplikasi demo ini menunjukkan sekilas cara untuk memanfaatkan WhatsApp Flows agar bisa meningkatkan interaksi pelanggan dan analisis berbasis data. Untuk penggunaan yang lebih khusus, Anda juga bisa mengonfigurasi Llama 2 dan WhatsApp Flows untuk menghubungkan chatbot Anda ke model khusus atau melatihnya dengan sumber data milik Anda. Dengan begitu, chatbot bisa menjawab pertanyaan bahasa alami tentang produk Anda dan fungsi lainnya.

Manfaatkan WhatsApp Flows untuk meningkatkan interaksi pelanggan dan menyederhanakan pengumpulan data di aplikasi Anda sekarang. Coba sekarang.