يستخدم الآن المزيد من الأنشطة التجارية البرامج التلقائية للدردشة عبر واتساب أكثر من أي وقت مضى؛ للتفاعل مع العملاء ومعرفة احتياجاتهم وجمع البيانات الأساسية. ومع ذلك، قد تشكِّل عملية جمع وتنظيم البيانات هذه تحديات فيما يتعلق بالكفاءة. الدخول إلى WhatsApp Flows.
يتيح دمج البرامج التلقائية للدردشة مع WhatsApp Flows للأنشطة التجارية تفسير معلومات العملاء الواردة بفعالية أكبر. يمكن للبرامج التلقائية للدردشة بعد ذلك بدء "عمليات دفق" مخصصة لجمع البيانات، استنادًا إلى سياق المحادثة.
في هذا العرض التوضيحي، ستقوم بإنشاء برنامج تلقائي للدردشة باستخدام Llama 2 وPython، كما ستقوم بربطه مع WhatsApp Flows لتحسين إمكانات جمع البيانات الخاصة به. خلال القيام بذلك، ستتعرَّف على الطريقة التي يؤدي من خلالها WhatsApp Flows إلى تعزيز سهولة استعمال المستخدمين لتجربة البرنامج التلقائي للدردشة وتحسين دقة وكفاءة جمع بيانات العملاء.
سيُجيب البرنامج التلقائي للدردشة الخاص بك على طلبات المستخدمين واستفساراتهم باستخدام WhatsApp Flows لجمع البيانات. وبشكل أكثر تحديدًا، فإنه سيتيح للمستخدمين التحدُّث إلى البرنامج التلقائي للدردشة والبحث عن معلومات حول الخدمات التي يقدمها فندق وهمي في إسبانيا والتواصل مع الشركة للحصول على الدعم.
سيستخدم البرنامج التلقائي للدردشة بيانات if
بسيطة بالاقتران مع نموذج Llama 2 القياسي لتوفير صلاحية وصول إلى قاعدة معلومات عامة كافية.
الجزء 1:
إنشاء "Flows" باستخدام أداة إنشاء Flow من مدير واتساب.
الجزء 2:
تحويل نموذج Llama 2 من GGML إلى GGUF.
في هذا الجزء، ستستخدم أداة إنشاء Flow لإنشاء بعض عمليات الدفق. بدلاً من ذلك، يمكنك استخدام واجهة API لمنصة Flows، والتي لن نتحدث عنها هنا.
للمتابعة، تأكَّد مما يلي:
تثبيت ngrok.
لديك حساب مطوّرتم التحقق منه على Meta للمطوّرين والتعرُّف على واجهة API السحابية المستضافة بواسطة Meta.
وأخيرًا، تأكَّد من إكمال الخطوات المطلوبة لاستخدام "Flows". يمكنك أيضًا معاينة كود المشروع بالكامل.
للبدء، انتقِل إلى صفحة Flows في حساب واتساب للأعمال الخاص بك. إذا كانت هذه هي المرة الأولى التي تستخدم فيها Flows، فمن المفترض أن تجد زرًا بعنوان بدء إنشاء Flows. وبخلاف ذلك، فسيكون هناك زر إنشاء دفق في الزاوية العلوية اليسرى من الصفحة.
انقر على الزر الظاهر لفتح مربع حوار حيث يمكنك إدخال بعض التفاصيل حول الدفق الخاص بك:
أولاً، ستقوم بإنشاء دفق يتيح للمستخدم الحصول على معلومات حول الخدمات التي تقدمها شركة الفندقة.
أدخِل اسمًا في حقل الاسم. بعد ذلك، ضمن القائمة المنسدلة الفئات، اختر تسجيل، واترك القائمة المنسدلة القالب على خيار لا شيء. انقر على إرسال.
ستعرض الصفحة التالية محررًا في الجانب الأيمن ومعاينة في الجانب الأيسر.
استبدِل محتويات المحرر باستخدام ترميز JSON للدفق الخاص بك. (يمكنك التعرُّف على المزيد حول Flow JSON في وثائق المطوّر.)
احفظ الدفق، ومن المفترض أن تشبه المعاينة الخاصة بك الصورة التالية:
يتضمن الدفق شاشة واحدة تتيح للمستخدم إدخال التفاصيل الخاصة به وتحديد الخدمات التي يهتم بها ورسالة إضافية اختيارية. عندما ينقر المستخدم على إرسال، يتم إغلاق الدفق وإرسال البيانات التي تم تسجيلها إلى نشاطك التجاري لمعالجتها. تتضمن إحدى طرق إرسال هذه البيانات استخدام نقاط النهاية. مع ذلك، لا يحتاج هذا المشروع إلى نقطة نهاية. سيتم إرسال هذه البيانات إلى نفس 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
.
يمكنك تعيين مفاتيح payload
مثل أي متغير. يمكن أن تمثل القيم المقابلة كائنات البيانات أو أسماء مكونات الدفق (مثل إسناد اسم نموذج HTML).
يمكنك الآن الاطلاع على الدفق قيد التشغيل وعرض محاكاة لتجربة مستخدم فعلية باستخدام زر التبديل المعاينة التفاعلية:
بعد الاختبار، يمكنك نشر الدفق؛ نظرًا لأنه حاليًا في حالة "مسودة". للقيام بذلك، افتح القائمة الموجودة على يسار خيار حفظ، وانقر على نشر. الدفق الآن جاهز ويمكن استخدامه.
ستقوم الآن بإنشاء دفق "اتصل بنا".
ابدأ بتكرار نفس عملية إنشاء الدفق الأولية. في الفئة، اختر اتصل بنا. استبدِل محتويات المحرر باستخدام ترميز JSON هذا لعرض ما يلي:
انشر الدفق وتابع إلى القسم التالي لإعداد برنامج تلقائي للدردشة. يعرض القسم ثلاث وظائف — send_message
وflow_details
وflow_reply_processor
— والتي تتضمن المنطق الأساسي لإرسال عمليات الدفق إلى المستخدمين. يتضمن القسم أيضًا منطق معالجة حمولات بيانات الدفق الواردة. لذا؛ فإننا نوصي بمراجعته حتى إذا كنت قد قمت بالفعل بإنشاء برنامج تلقائي للدردشة.
بعد ذلك، ستقوم بتكوين البرنامج التلقائي للدردشة ودمجه مع Flows.
قبل المتابعة، تأكَّد من وجود ما يلي:
المعرفة بأساسيات Python وإصدار حديث له
تنزيل إصدار HuggingFace من Llama 2. لا يتطلب نموذج HuggingFace من 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
والمحتوى التالي، بحيث يتم تعيين القيم بشكل صحيح. (يمكنك استخدام أي سلسلة من أجل 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 وY وN باستخدام الوظيفة الواردة أدناه. ستساعد الوظيفة الواردة أدناه على مطابقة ردود المستخدمين بالخيارات المقابلة.
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"
.
بعد ذلك، تتضمن الوظيفة التالية بيانات if
التي تستخدم حزمة Python RegEx، re
، للبحث عن مصطلحات محددة من رسالة العميل لتحديد نوع الرد الذي يجب إرساله للمستخدم:
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
يعرض ردًا تم تسجيله من الدفق.
تُرسل الخيارات الأخرى، CONTACT_US
وTALK_TO_AN_AGENT
، حمولات بيانات الدفق إلى المستخدم. تنشأ حمولات بيانات الدفق من وظيفة flow_details
، والتي يظهر تكوينها أدناه. تدمج حمولة البيانات تفاصيل الدفق الأساسية، بما في ذلك FLOW_ID
، والتي يمكنك استرجاعها من صفحة Flows في حساب واتساب للأعمال الخاص بك. من الممكن أيضًا تحديد هذه المعرفات في متغيرات البيئة الخاصة بك.
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
تُنشِئ هذه الطريقة action.parameters.flow_token
من خلال تجميع معرفات UUID عشوائية. يتم نقل action.parameters.flow_action_payload.screen
كمعلمة (screen_id
). في الوضع الأمثل، من المفترض أن تمثل معرف الشاشة الأولية التي تنوي عرضها على المستخدم عند تنفيذ action.parameters.flow_cta
.
وأخيرًا، إضافة مسارات webhook. يتم تشغيل طلب GET
من webhook عند إضافة webhook إلى تطبيقك على Meta للمطوّرين. ويقوم بإرجاع طلب 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
لاستخراج الرد من الدفق وإرساله مرة أخرى إلى المستخدم:
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
) أساسيًا للتمييز بين دفقين؛ وبالتالي استخراج الردود بالشكل المناسب خلال نقل معرفات الشاشة الأولى الصحيحة.
قبل تشغيل الرمز البرمجي، قارنه مع الإصدار الكامل وتأكَّد من مطابقة كل شيء.
قبل المتابعة، قم بتشغيل هذا الأمر من الوحدة الطرفية لديك:
flask --app main run --port 5000
إذا نجح الأمر، فمن المفترض أن ترى رسالة تنص على ما يلي:
* Running on http://127.0.0.1:5000
بعد ذلك، قم بتشغيل ngrok http 5000
للحصول على عنوان URL يرتبط بتطبيقك. انسخ الرابط.
بعد ذلك، في حساب المطوّر الخاص بك على Meta للمطوّرين، انقر على قائمة التكوين ضمن واتساب في لوحة التنقل على الجانب الأيمن:
في بطاقة Webhook، انقر على تعديل.
بعد ذلك، في حقل عنوان URL لإعادة الاستدعاء من مربع الحوار المفتوح، الصق عنوان URL الذي تم نسخه وقم بإرفاق /webhook
إليه.
أضِف الرمز من متغير TOKEN
لملف .env
الخاص بك إلى حقل تحقق من الرمز. انقر على تحقق وحفظ لغلق مربع الحوار.
الآن، من نفس البطاقة، انقر على إدارة وحدِّد حقل الرسائل. من المفترض أن تبدو البطاقة على النحو التالي:
أصبح webhook جاهزًا الآن.
يمكنك إرسال رسالة، مثل "مرحبًا"، إلى رقم حسابك. من المفترض أن تتلقى الرد المناسب. جرِّب الرد باستخدام مطالبة موضَّحة في القائمة لاختبار Flows:
فيما يلي لقطة شاشة أخرى توضِّح رد البرنامج التلقائي للدردشة. يطلب المستخدم ترجمة سريعة، والتي يمكن أن يقدمها البرنامج التلقائي.
يعمل WhatsApp Flows كأداة فعَّالة للأنشطة التجارية من أجل جمع معلومات منظمة وتحسين تفاعلات العملاء وتسهيل التواصل بين الأنشطة التجارية والمستهلكين. إحدى طرق إنشاء Flows هي من خلال أداة إنشاء Flow من مدير واتساب، والتي توفِّر واجهة سهلة الاستخدام لإنشاء عمليات الدفق.
يوفِّر هذا التطبيق التجريبي لمحة عن الطريقة التي يمكنك من خلالها استخدام WhatsApp Flows لتحسين تفاعل العملاء والتحليلات التي تستند إلى البيانات. للاستخدامات الأكثر تخصصًا، يمكنك أيضًا تكوين Llama 2 وWhatsApp Flows لربط البرنامج التلقائي للدردشة الخاصة بك مع نموذج مخصص أو تدريبه على مصدر بيانات خاص؛ مما يتيح له الإجابة عن الأسئلة باللغة الطبيعية حول منتجك أو الوظائف الأخرى.
استخدِم WhatsApp Flows للارتقاء بمستوى تفاعلات العملاء وتسهيل عملية جمع البيانات في تطبيقاتك اليوم. جرّبه الآن.