オペ用チケット全文検索システムを作ってみた

2018.02.08

はじめに

前回のブログで、zendeskのチケットデータをAmazon Elasticsearch Serviceへ自動でアップロードする方法をご紹介しました。

ZendeskのチケットデータをAmazon Elasticsearch Serviceへ自動的にアップロードする

今回はサポートメンバーがAmazon Elasticsearch Serviceから類似チケットを ChatWorkを使用して検索できるようにしましたのでご紹介いたします。

Overview

画像

  • ユーザーは検索したいキーワードをChatWorkに投稿
  • ChatWorkのWebhookでPOSTリクエスト
  • Amazon API Gatewayを使用してAWS Lambda(VPC)を実行
    • Amazon API Gateway はPOSTメソッド
    • インターネットアクセスが必要なのでNAT ゲートウェイを使用
    • VPCプライベートサブネットのAmazon Elasticsearch Serviceで検索
  • 検索結果をChatWorkに投稿

設定内容

ChatWork

ChatWorkのWebhookの設定をします。

画像

  • Webhook URLに Amazon API Gateway で作成したURLを入力
  • EventはRoom Eventを選択しMessage createdにチェック
  • Room IDを指定

AWS Lambda

コードはgithubへアップしましたが簡単に説明します。

ChatWork Webhookで検索キーワードを取得

lambda_function.py

keyword = event['webhook_event']['body']

Amazon Elasticsearch Serviceで検索

  • Bool Queryでmustを使いkeywordsが全て含まれるチケットを探すようにしています。
  • _sourceで検索に引っかかったチケットの件名とurlだけ取得しています。

client/es.py

def get_document_and(self, keyword):

    must_keywords = []

    keywords = keyword.split()

    for keyword in keywords:
        must_keyword = {
            "match": {"comment.body": keyword}
        }

        must_keywords.append(must_keyword)

    search_query = {
        "query":
            {
                "bool":
                    {
                        "must": [
                            must_keywords
                        ]
                    }
            },
        "_source":
            [
                "subject",
                "url"
            ]
    }

    response = self.es.search(index="zendesk", body=search_query)

    return response

検索結果を成形

  • レスポンスをlistにしてからChatWorkに送る内容を作成しています。

lambda_function.py

tickets = []

for ticket_record in response['hits']['hits']:
    ticket = Ticket(ticket_record)
    tickets.append(ticket)

util/message.py

def get_message_body(message_id, reply_account, tickets, room_id):

    body = ''

    if not tickets:

        message = f'[rp aid={reply_account} to={room_id}-{message_id}]' + \
                  f'[info][title]Search Results(Sort by highest score)[/title]' + \
                  f'There is no result.[/info]'

        return message

    for ticket in tickets:

        body += ticket.subject + '\n' + ticket.url + '\n'

    message = f'[rp aid={reply_account} to={room_id}-{message_id}]' + \
        f'[info][title]Search Results(Sort by highest score)[/title]' + \
        f'{body}[/info]'

    return message

ChatWorkへ検索結果をPOSTする

client/chatwork.py

def post_messages(message, room_id):

    url = f'{URL}/rooms/{room_id}/messages'
    params = {"body": message}
    response = requests.post(url, headers=headers, params=params)

    return response

検索してみる

検索キーワードを入力

画像

レスポンス

画像

スコアの高い順に、チケットの件名とURLが返って来ました。

まとめ

ChatWorkに検索キーワードを作成するだけで誰もが類似チケットを検索できるようになりました。 ではまた