現今,越來越多的企業選擇透過 WhatsApp 使用聊天機械人,以與顧客互動、了解他們的需求,以及蒐集所需的資料。然而,他們在蒐集和整理資料時,往往面臨著諸多效率方面的挑戰。在這種情況下,WhatsApp Flows 便能大派用場。
只需將聊天機械人與 WhatsApp Flows 整合,企業便可以更高效地解讀收到的顧客資料。如此一來,聊天機械人能夠根據對話情景,啟動專為蒐集資料而設的特定 Flows 流程。
在本教學導覽中,您將使用 Llama 2 和 Python 來構建聊天機械人,並將其連結至 WhatsApp Flows,以提升其資料蒐集能力。在這個過程中,您將可見證 WhatsApp Flows 如何提升聊天機械人體驗的易用性,並提高顧客資料蒐集的準確性和效率。
聊天機械人會使用 WhatsApp Flows 來回覆用戶的要求和提示,以便蒐集資料。以本文所用的虛構西班牙酒店為例,它可讓用戶與聊天機械人交談、搜尋酒店所提供的服務之資訊,並聯絡酒店以尋求支援。
聊天機械人將配搭使用簡單的 if
陳述式和標準 Llama 2 模型,以便系統存取充足的常識知識庫。
第 1 部分:
使用 WhatsApp 管理工具的流程建造工具來建立 Flows 流程。
第 2 部分:
將 Llama 2 模型從 GGML 轉換為 GGUF。
在這部分,您需要使用流程建造工具來建立一些 Flows 流程。或者,您可以使用 Flows API;本文對此不作詳細闡述。
若要採取本部分的步驟,請確保您具備下列條件:
已安裝 ngrok。
最後,確保您已完成使用 Flows 所需執行的步驟。您亦可預覽完整專案程式碼。
首先,前往您 WhatsApp Business 帳戶的「流程」頁面。若這是您首次與 Flows 互動,您應該會看到一個標題為「開始建立流程」的按鈕。否則,此頁面右上方會顯示「建立流程」按鈕。
點擊畫面所顯示的按鈕以開啟對話框,並在當中輸入您 Flows 流程的一些詳細資訊:
首先,您需要建立一個 Flows 流程,讓用戶用來搜尋酒店所提供的服務之資訊。
在「名稱」欄位中輸入所需名稱。接著,在「類別」下拉式選單中,選擇「註冊」,並將「範本」下拉式選單設為「無」。點擊「提交」。
在下一個頁面中,畫面左側將顯示編輯工具,右側則會顯示預覽畫面。
將編輯工具的內容替換為您 Flows 流程的 JSON 標記。您可以查閱開發人員文件,進一步了解 Flow JSON。
儲存 Flows 流程;您的預覽畫面應與下圖相似:
此 Flows 流程包含一個畫面,用戶可在當中輸入其詳細資訊、選擇感興趣的服務,以及查閱一則選用的額外訊息。當用戶點擊「提交」時,這個 Flows 流程便會關閉,並將收到的資料傳送至您企業以供處理。傳輸此類資料的方法之一便是使用端點。不過,此專案不會用到端點。這些資料會傳送至支援聊天機械人的同一個 Webhook。
您可以使用各個動作來執行此傳輸程序。您需要使用 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" } } ...
在此程式碼片段中,用戶的按鈕點擊動作會觸發 on-click-action
,以擷取裝載中的資料。接著,它會將裝載傳送至 Webhook 伺服器,並透過 complete
動作關閉 Flows 流程。
您可以沿用分配任何變數的方法來分配 payload
鍵。相應的值可代表資料物件或 Flows 流程元件的名稱(類似 HTML 表格的名稱屬性)。
現在,您應會查看運作中的 Flows 流程,並使用「互動式預覽」切換按鈕來模擬真實的用戶體驗:
測試之後,您便可發佈目前仍處於「草稿」狀態的 Flows 流程。若要發佈此 Flows 流程,請開啟「儲存」右側的選單並點擊「發佈」。這個 Flows 流程現已準備就緒並可供使用。
現在,您需要建立「聯絡我們」Flows 流程。
首先,重複執行上文所述的初始 Flows 流程建立程序,但將類別設為「聯絡我們」。將編輯工具的內容替換為這個 JSON 標記,以顯示以下畫面:
發佈此 Flows 流程並繼續執行下一部分,以設定聊天機械人。該部分會用到 send_message
、flow_details
和 flow_reply_processor
這 3 個函數;這些函數包含將 Flows 流程傳送給用戶的必要邏輯。該部分亦會提及處理傳入 Flows 流程裝載的邏輯。因此,即使您已構建聊天機械人,我們仍建議您仔細查閱該部分的內容。
接下來,您需要配置聊天機械人並將其整合到您的 Flows 流程。
在繼續操作之前,請確保您具備下列條件:
擁有 Python 的基本知識和最新版本。
已下載 HuggingFace 版本 Llama 2。HuggingFace Llama 2 模型無需使用任何其他工具或專用硬件。您亦可使用官方版本 Llama 2,但您將需進行額外設定。
擁有您帳戶的存取憑證和手機號碼編號。
擁有程式碼編輯工具。
聊天機械人將透過一組預先定義的指令碼來運作;該組指令碼旨在根據用戶輸入的內容,為其提供相應的協助。在初次互動時,聊天機械人會根據用戶的訊息,提供個人化問候語文字,以及一個文字選單。這些選項可迎合特定需求:酒店所提供的查詢服務、聯絡酒店的客戶服務人員,或與由 Llama 支援的聊天機械人互動。
使用英數字元回覆時,系統會將用戶連結至相應的服務或動作。然而,任何其他回覆均將觸發預設聊天機械人功能,以協助處理一般查詢,或根據進一步對話,引導用戶取得可用服務。
首先,在終端上運行以下指令以建立虛擬環境:
python -m venv venv
啟用此環境:
source venv/bin/activate
接著,安裝所需套件:
pip install requests flask llama-cpp-python python-dotenv
您需要使用 Flask
來建立路線並與 API 互動、使用 requests
來傳送互聯網要求、使用 llama-cpp-python
來與模型互動,並使用 python-dotenv
來載入環境變數。
接下來,建立名為 .env
的環境檔案和下列內容,以分配相應的值;VERIFY_TOKEN
可使用任何字串。
TOKEN = ACCESS_TOKEN = PHONE_NUMBER_ID =
在同一個目錄中,建立名為 main.py
的檔案,並開始新增您需要使用的套件:
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
現在,初始化變數和類別。此程式碼片段亦會啟動 Flask 並呼叫 load_dotenv()
方法,以助載入變數:
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 會用於儲存酒店所提供的各項服務。code_prompt_texts
清單包含與用戶的輸入選擇相應的選項;這些選項分別是「1」、「2」、「是」和「否」,可使用下方函數來指定。下方函數有助將用戶的回覆配對至相應的選項。
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
程式碼會將字串轉換為小楷字母,以免運行條件式邏輯時出現配對錯誤的情形。match…case
架構會將用戶輸入的提示配對至輸出項目。舉例來說,用戶輸入「1」時將觸發 "Contact us"
功能。
接下來,以下函數包含使用 Python RegEx 套件 re
的 if
陳述式,以從顧客訊息當中搜尋特定字詞,從而判斷向用戶傳送哪類回覆:
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)
現在,訊息(如 "Hello there"
)將會觸發 send_message
方法,當中第二個引數為 SEND_GREETINGS_AND_PROMPT
。以下是 send_message
方法;視乎具體情況,替換 <xxx>
之間的內容。
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")
若訊息是簡單的問候語(SEND_GREETINGS_AND_PROMPT
),回覆將包含額外的提示(greetings_text_body
)。
同樣地,當用戶詢問關於酒店所提供服務的問題時,傳送給用戶的文字訊息(service_intro_text
)便會包含相關服務。除了這些服務外,該訊息還會包含一則提示,提醒用戶選擇是否想與客戶服務人員交流。
若輸入內容需要聊天機械人作出回覆(CHATBOT
),則您需要初始化該模型、為其提供訊息內容,並處理需要傳回給用戶的回覆。FLOW_RESPONSE
會顯示 Flows 流程所擷取的回覆。
CONTACT_US
和 TALK_TO_AN_AGENT
等其他選項則會將 Flows 流程裝載傳送至用戶。Flows 流程裝載來自 flow_details
函數,其主體如下所示。此裝載包含 Flows 流程的必要詳情,包括 FLOW_ID
;您可以從 WhatsApp Business 帳戶的「流程」頁面獲取此類資訊。此外,您也可以在環境變數中定義這些編號。
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
此方法可產生隨機 UUID 以建立 action.parameters.flow_token
。系統會將 action.parameters.flow_action_payload.screen
傳遞為參數(screen_id
)。在理想情況下,它應代表執行 action.parameters.flow_cta
時,您想要向用戶顯示的初始畫面之編號。
最後,新增 Webhook 路線。當您在 Meta for Developers 將 Webhook 加至自家應用程式時,程式碼便會發起 Webhook GET
要求。若要求成功,系統便會傳回要求的 hub.challenge
。
@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)
POST
要求會使用上文所述的 user_message_processor
方法來擷取並處理訊息裝載。由於此程式碼僅用於處理訊息裝載,因此擷取任何其他裝載時會出現錯誤。因此,您可使用 if
陳述式來檢查是否存在 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)
此外,您可以使用名為 flow_reply_processor
的協助工具函數,從 Flows 流程中擷取回覆並將其傳回給用戶:
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)
此函數會使用 flow_key
鍵來區分這兩個 Flows 流程,並相應地擷取回覆,同時傳遞正確的首個畫面編號。
在執行程式碼前,將其與完整版本加以比較,並確認所有元素均為一致。
在繼續操作之前,先從您的終端執行此指令:
flask --app main run --port 5000
若執行成功,您應該會看到下列訊息:
* Running on http://127.0.0.1:5000
接下來,執行 ngrok http 5000
以取得與您應用程式相應的網址。複製此連結。
接著,前往您的 Meta for Developers 開發人員帳戶,點擊左側導覽面板中「WhatsApp」下方的「配置」選單:
在「Webhook」小卡片中,點擊「編輯」。
然後,在所開啟對話框的「回調網址」欄位中,貼上所複製的網址並附上 /webhook
。
在「驗證憑證」欄位中,加入 .env
檔案的 TOKEN
變數所提供的憑證。點擊「驗證並儲存」以關閉對話框。
現在,在同一個小卡片中,點擊「管理」並檢查「訊息」欄位。該小卡片應如下所示:
Webhook 現已就緒。
您可以向自己的帳戶號碼傳送一則訊息,如「您好」。您應該會收到正確的回覆。嘗試使用選單所顯示的提示來回覆,以測試 Flows 流程:
以下是另一個螢幕截圖,當中顯示了聊天機械人的回覆。用戶要求簡單地翻譯一些內容,而聊天機械人可以做到這一點。
WhatsApp Flows 是一款供企業蒐集結構化資料的強大工具,有助改善顧客互動,並簡化企業與消費者之間的溝通交流。建立 Flows 流程的方式之一是使用 WhatsApp 管理工具的流程建造工具;該工具提供簡單易用的 Flows 流程設計介面。
本文的示範應用程式概要地介紹了如何利用 WhatsApp Flows,從而改善顧客互動及進行以資料為本的分析。若要用於更具體的專業用途,您亦可配置 Llama 2 和 WhatsApp Flows,將聊天機械人連結至自訂模型,或者使用專有資料來源來予以訓練,使其能夠回答有關您商品及其他功能的自然語言問題。
立即使用 WhatsApp Flows,改進顧客互動體驗並簡化應用程式的資料蒐集流程。立即試用。