•  


챗봇 經驗에 WhatsApp Flows 追加하기
開發者 消息으로 돌아가기

챗봇 經驗에 WhatsApp Flows 追加하기

2024年 3月 20日 製作: 개피 G(Gafi G), 이리나 바그너(Iryna Wagner)

現在 그 어느 때보다 많은 비즈니스가 WhatsApp을 通한 챗봇을 使用하여 顧客과 疏通하고, 顧客의 니즈를 把握하고, 必須 데이터를 蒐集하고 있습니다. 그러나 데이터를 蒐集하고 整理하는 方法은 複雜하고 效率性이 떨어질 수 있습니다. WhatsApp Flows 가 바로 이 問題를 解決합니다.

챗봇에 WhatsApp Flows를 統合하면 蒐集한 顧客 情報를 더 效果的으로 把握할 수 있습니다. 챗봇은 對話의 컨텍스트에 따라 데이터 蒐集을 위한 特定 플로를 始作합니다.

이 튜토리얼에서는 Llama 2와 Python을 使用하여 챗봇을 만들고 이를 WhatsApp Flows에 連結하여 데이터 蒐集 機能을 向上합니다. 이 過程에서 WhatsApp Flows가 어떤 式으로 챗봇 經驗의 使用者 親熟度를 높이고 顧客 데이터 蒐集의 正確性과 效率性을 改善하는지 알아볼 수 있습니다.

WhatsApp Flows로 챗봇 經驗 向上하기

只今부터 만들 챗봇은 데이터 蒐集用 WhatsApp Flows를 使用하여 使用者 要請과 프롬프트에 應答합니다. 具體的으로는, 使用者가 챗봇과 對話를 나누고, 假想의 스페인 호텔에서 提供하는 서비스에 對한 情報를 檢索하고, 호텔에 連絡하여 支援을 받을 수 있도록 支援합니다.

챗봇은 簡單한 if 文科 標準 Llama 2 모델을 使用하여 이 作業을 處理하는 데 必要한 情報가 담긴 知識 베이스에 對한 액세스를 提供합니다.

進行할 段階

파트 1:

파트 2:

  • Llama 2 모델을 GGML에서 GGUF로 變換합니다.

  • 플로와 챗봇을 統合하는 Python 코드를 作成합니다.
  • 메시지를 受信 待機하는 Webhook을 만듭니다.
  • 애플리케이션을 實行합니다.

파트 1: 플로를 만드는 方法

파트 1에서는 플로 빌드 道具를 使用하여 플로를 만듭니다. Flows API 를 使用하여 플로를 만드는 方法도 있으나, 여기서는 다루지 않습니다.

파트 1 必須 條件

튜토리얼을 따라서 進行하려면 다음이 必要합니다.

마지막으로, Flows를 使用하기 위한 必須 段階 를 完了해야 합니다. 完成된 프로젝트 코드를 미리 볼 수도 있습니다.

始作하기

始作하려면 WhatsApp Business 計定의 플로 페이지로 移動합니다. Flows를 使用하는 것이 처음이라면 플로 만들기 始作 버튼이 標示됩니다. 처음이 아니라면 페이지 오른쪽 上段에 플로 만들기 버튼이 標示됩니다.

標示된 버튼을 클릭하여 對話 箱子를 열면 플로의 몇 가지 詳細 情報를 入力할 수 있습니다.

WhatsApp Chatbox 시작하기

서비스 問議 플로

먼저 使用者가 호텔에서 提供하는 서비스에 對한 情報를 알아볼 수 있도록 支援하는 플로를 만들겠습니다.

이름 필드에 이름을 入力합니다. 그런 다음 카테고리 드롭다운에서 加入하기 를 選擇하고, 템플릿 드롭다운은 없음 으로 남겨둡니다. 提出 을 클릭합니다.

다음 페이지에는 왼쪽에 에디터가 標示되고 오른쪽에 미리 보기가 標示됩니다.

에디터에 入力된 內容을 플로의 JSON 마크업 으로 바꿉니다. (플로 JSON에 對한 仔細한 內容은 開發者 文書 를 參照하세요.)

플로를 貯藏합니다. 미리 보기가 아래 이미지와 같이 標示됩니다.

Chatbox 플로

이 플로에는 使用者가 情報를 入力하고, 願하는 서비스를 選擇하고, 選擇的으로 追加 메시지를 入力할 수 있는 하나의 畵面이 있습니다. 使用者가 提出 을 클릭하면 플로가 닫히고 蒐集된 데이터가 處理될 수 있도록 비즈니스에 電送됩니다. 이 데이터를 電送하는 한 가지 方法은 엔드포인트 를 使用하는 것입니다. 그러나 이 프로젝트에는 엔드포인트가 必要하지 않습니다. 데이터는 챗봇을 驅動하는 것과 同一한 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 樣式의 name 屬性 과 類似)을 나타낼 수 있습니다.

이제 인터랙티브 미리 보기 토글을 使用하여 플로가 實行되어 實際 使用者 經驗을 시뮬레이션하는 것을 볼 수 있습니다.

Chatbox 인터랙티브 미리 보기

테스트를 마쳤으면 플로가 現在 臨時 貯藏 狀態에 있으므로 플로를 揭示할 수 있습니다. 플로를 揭示하려면 貯藏 오른쪽에 있는 메뉴를 열고 揭示 를 클릭합니다. 이제 플로를 使用할 수 있습니다.

問議하기 플로

이番에는 '問議하기' 플로를 만들겠습니다.

먼저 플로 만들기 프로세스를 反復합니다. 카테고리로 問議하기 를 選擇합니다. 에디터에 入力된 內容을 이 JSON 마크업 으로 바꾸면 플로가 다음과 같이 렌더링됩니다.

Chatbox 문의하기 플로

플로를 揭示하고, 챗봇을 設定하는 다음 섹션으로 넘어가세요. 다음 섹션에서는 使用者에게 플로를 電送하는 老職을 包含하는 세 가지 函數( send_message , flow_details , flow_reply_processor )를 使用합니다. 受信된 플로 페이로드를 處理하는 로직度 包含되어 있습니다. 이미 챗봇을 만든 境遇에도 다음 섹션을 살펴보세요.

파트 2: 챗봇을 設定하는 方法

여기서는 챗봇을 構成하여 플로에 統合합니다.

파트 2 必須 條件

튜토리얼을 따라서 進行하려면 다음이 必要합니다.

  • 最新 버전의 Python과 Python에 對한 基本 知識

  • 다운로드한 HuggingFace 버전 의 Llama 2. HuggingFace Llama 2 모델에는 追加的인 道具나 專用 하드웨어가 必要하지 않습니다. 公式 버전 을 使用해도 되지만, 그러려면 追加 設定이 必要합니다.

  • 計定의 액세스 토큰과 電話番號 ID

  • 코드 에디터

Python을 使用하여 플로와 챗봇 統合하기

챗봇은 使用者의 入力을 바탕으로 使用者를 支援하도록 設計된 미리 定義된 스크립트에 따라 作動합니다. 最初 相互 作用에서는 맞춤化된 人事말 텍스트와 使用者의 메시지의 따른 텍스트 基盤 메뉴가 標示됩니다. 이러한 옵션은 호텔에서 提供하는 서비스에 對해 問議하기, 호텔 相談員에게 問議하기, 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" 機能이 트리거됩니다.

다음으로, 아래의 函數에는 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_GREETINGS_AND_PROMPT 가 指定된 狀態로 send_message 메서드가 呼出됩니다. 다음은 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 )가 包含됩니다.

Chatbox 샘플 인사말

마찬가지로, 使用者가 호텔에서 提供하는 서비스에 對해 質問하면 서비스를 包含하는 텍스트 메시지( service_intro_text )가 使用者에게 電送됩니다. 여기에 더해 使用者에게 相談員과 對話하기를 願하는지 묻는 프롬프트度 包含됩니다.

Chatbox 샘플 안내

챗봇 應答이 必要한 境遇( CHATBOT )에는 챗봇 모델을 初期化하고, 메시지 콘텐츠에 入力하고, 應答을 處理하여 使用者에게 電送합니다. FLOW_RESPONSE 는 該當 플로에서 蒐集된 應答을 標示합니다.

나머지 옵션인 CONTACT_US TALK_TO_AN_AGENT 는 使用者에게 플로 페이로드를 電送합니다. 이 플로 페이로드는 flow_details 函數에서 構成됩니다. 아래에는 函數의 本文이 나와 있습니다. 페이로드는 FLOW_ID 를 비롯한 基本的인 플로 詳細 情報 로 構成되는데, 이 情報는 WhatsApp Business 計定의 플로 페이지에서 確認할 수 있습니다. 環境 變數 內에서 이러한 ID를 定義하는 것도 可能합니다.

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 가 實行될 때 使用者에게 表示할 初期 畵面의 ID를 나타내야 합니다.

마지막으로, Webhook 經路를 追加합니다. Webhook GET 要請은 Meta for Developers에 Webhook을 追加하는 時點에 初期化되고, 成功한 境遇 要請의 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 메서드를 使用하여 메시지 페이로드를 抽出하고 處理합니다. 이 코드는 메시지 페이로드만 處理하기 때문에, 메시지가 아닌 페이로드가 캡처되면 誤謬가 發生합니다. 페이로드가 messages 本文이 存在하는지 確認하는 if 門을 使用할 수 있습니다.

@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 )를 使用하여 두 플로를 區分하여 適切한 應答을 抽出하고 올바른 첫 番째 畵面 ID를 傳達합니다.

코드를 實行하기 前에 完成된 버전 과 比較하여 모든 값이 一致하는지 確認하세요.

Webhook을 設定하는 方法

다음으로 넘어가기 前에 터미널에서 아래 命令을 實行합니다.

flask --app main run --port 5000 
        

命令이 成功하면 다음과 같은 메시지가 標示됩니다.

* Running on http://127.0.0.1:5000
        

다음으로, ngrok http 5000 命令을 實行하여 애플리케이션에 매핑되는 URL을 가져옵니다. 링크를 複寫합니다.

그런 다음 Meta for Developers 開發者 計定에서 왼쪽 探索 패널에 있는 WhatsApp 아래의 構成 을 클릭합니다.

Chatbox 구성

Webhook 카드에서 修正 을 클릭합니다.

그런 다음 열리는 對話 箱子의 콜백 URL 필드에 複寫한 URL을 붙여넣고 그 뒤에 /webhook 을 追加합니다.

.env 파일의 TOKEN 變數에 들어 있는 토큰을 引證 토큰 필드에 追加합니다. 確認 및 貯藏 을 클릭하여 對話 箱子를 닫습니다.

Webhook 카드에서 管理 를 클릭하고 메시지 필드를 選擇합니다. 그러면 카드가 다음과 같이 標示됩니다.

WhatsApp Chatbox Webhook

이제 Webhook이 準備되었습니다.

애플리케이션 實行하기

本人의 計定 番號 에 'Hello'와 같은 메시지를 보내보세요. 그러면 適切한 應答이 受信됩니다. 메뉴에 標示된 프롬프트로 答辯하여 플로를 테스트해보세요.

WhatsApp Chatbox 앱 실행

다음은 챗봇의 應答을 보여주는 또 다른 스크린샷입니다. 使用者가 簡單한 飜譯을 要請하자 챗봇이 適切하게 應答하는 것을 볼 수 있습니다.

WhatsApp Chatbox 앱 실행

結論

WhatsApp Flows는 비즈니스가 構造化된 情報를 蒐集하고 顧客 相互 作用을 向上하고 비즈니스와 消費者 사이의 커뮤니케이션을 簡素化하는 데 使用할 수 있는 强力한 道具입니다. 플로를 만드는 한 가지 方法은 使用者 親和的인 플로 디자인 인터페이스를 提供하는 WhatsApp 管理者 플로 빌드 道具를 使用하는 것입니다.

이 데모 애플리케이션을 통해 向上된 顧客 應對와 데이터 基盤 分析을 위해 WhatsApp Flows를 使用하는 方法을 알아볼 수 있었습니다. 보다 특수한 用途로 使用하려면 챗봇을 맞춤 모델에 連結하거나 獨自的인 데이터 소스를 바탕으로 學習하도록 Llama 2와 WhatsApp Flows를 構成하여 製品에 對한 自然語 質問에 答辯하고 그 밖의 機能을 提供하도록 할 수 있습니다.

只今 바로 WhatsApp Flows를 使用하여 顧客 應對를 向上하고 애플리케이션을 통한 데이터 蒐集을 簡素化해보세요. 只今 使用해보세요 .


- "漢字路" 한글한자자동변환 서비스는 교육부 고전문헌국역지원사업의 지원으로 구축되었습니다.
- "漢字路" 한글한자자동변환 서비스는 전통문화연구회 "울산대학교한국어처리연구실 옥철영(IT융합전공)교수팀"에서 개발한 한글한자자동변환기를 바탕하여 지속적으로 공동 연구 개발하고 있는 서비스입니다.
- 현재 고유명사(인명, 지명등)을 비롯한 여러 변환오류가 있으며 이를 해결하고자 많은 연구 개발을 진행하고자 하고 있습니다. 이를 인지하시고 다른 곳에서 인용시 한자 변환 결과를 한번 더 검토하시고 사용해 주시기 바랍니다.
- 변환오류 및 건의,문의사항은 juntong@juntong.or.kr로 메일로 보내주시면 감사하겠습니다. .
Copyright ⓒ 2020 By '전통문화연구회(傳統文化硏究會)' All Rights reserved.
 한국   대만   중국   일본