📝

Vertex AI Search x LINE:LINEから受け取った質問の可視化 vol.2

2024/02/26に公開

はじめに

こんにちは、クラウドエースの岸本です。
今回は、前回の記事で作成した LINE と Vertex AI Search and Conversation の社内チャットボットの続編です。
LINE で受け取った質問をカテゴリ化し、Looker Studio で可視化してみたいと思います。
Looker Studio については以下の動画、記事で簡単に説明されています。

今回の構成図です。
0-1

対象読者

  • Google Cloud を触るのが初めての方
  • Google Cloud が好きな方

やること・やらないこと

やること

  • BigQuery でモデルを作成
  • 質問のカテゴリ分け
  • データの可視化

やらないこと

  • データの分析
  • コードの解説
  • Looker Studio の高度な使い方
  • 各サービスの詳細な設定や説明

構築手順

構築手順は以下の通りです。

    1. BigQuery にテーブルを作成
    1. Vertex AI のソースコードの編集
    1. BigQuery でモデルを作成
    1. 質問のカテゴリ分け
    1. データの可視化

1. BigQuery にテーブルを作成

はじめに、BigQuery にテーブルを作成します。
そうすることで、質問が来た際に、BigQuery にデータを送信することができます。
公式ドキュメントをもとに作成していきます。
また BigQuery について、簡単な説明が以下のリンクにありますので参考にしてください。

【構成図】
0-2

手順は以下の通りです。

  • 1-1. API の有効化
  • 1-2. データセットの作成
  • 1-3. テーブルの確認
  • 1-4. スキーマの設定

1-1. API の有効化

まずは、BigQuery API を有効化します。
Google Cloud のコンソール画面で BigQuery と検索し、API を有効化します。
1-1

1-2. データセットの作成

次に、データセットを作成します。
以下の画像のように、3 つの黒丸をクリックし、[データセットを作成]をクリックします。
1-2

項目に関しては、データセット ID を入力し、その他はデフォルトのままで作成します。
1-3

1-3. テーブルの作成

次に、テーブルを作成します。
作成されたデータセットをクリックすると、以下の画像が出てきます。
[テーブルを作成]をクリックし、テーブルを作成します。
1-4

項目
プロジェクト Your Project
データセット Chat_bot
テーブル chat_bot_table

上記の値を設定します。その他はデフォルトのままで作成します。

1-4. スキーマを設定

テーブルの列の型を定義するスキーマを設定します。
先ほど作成したテーブルをクリックし[スキーマの編集]をクリックします。
以下の画面になるので、新しいフィールド欄の[+フィールドを追加]をクリックします。
そして以下のように設定します。

名前 タイプ モード
query_text STRING NULLABLE

1-5

以上で、BigQuery にテーブルを作成することができました。
これからは、このテーブルにデータを送信するようにソースコードを編集していきます。

2. Vertex AI のソースコードの編集

次に、Vertex AI のソースコードを編集します。
ここでは、質問が来た際に、BigQuery にデータを送信するようにします。
もちろん、LINE 上では質問に対する回答も同時に行っています。

【構成図】
0-3

高度な使い方

また以下の記事を参考にすると、高度な使い方もできますので、参考にしてください。

前回の記事のソースコードをベースに編集していきます。
ここでは以下の 2 ステップを行います。

  • 2-1. BigQuery にデータを送信するようにソースコードを編集
  • 2-2. 実際に質問を投げて質問が BigQuery に送信されたか確認

【前回記事】

2-1. BigQuery にデータを送信するようにソースコードを編集

BigQuery にデータを送信するようにソースコードを編集します。
先ほど作成したテーブル ID を使用します。
以下のように、ソースコードを編集します。

app.py
import os
import config
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage
from google.api_core.client_options import ClientOptions
from google.cloud import discoveryengine
from google.cloud import bigquery
app = Flask(__name__)
# BigQueryクライアントの初期化
bigquery_client = bigquery.Client()
# LINE Bot APIとWebhook Handlerの初期化
line_bot_api = LineBotApi(config.token)
handler = WebhookHandler(config.secret)
# Google CloudのプロジェクトID、ロケーション、データストアIDの設定
PROJECT_ID = config.project_id
LOCATION = config.location
DATA_STORE_ID = config.datastore
TABLE_ID = config.table_id
def send_to_bigquery(user_message: str):
    table_id = TABLE_ID  # BigQueryのテーブルIDを設定
    rows_to_insert = [
        {"query_text": user_message}
    ]
    errors = bigquery_client.insert_rows_json(table_id, rows_to_insert)
    if errors:
        app.logger.error(f"BigQuery insert error: {errors}")
# Google Discovery Engineのクライアントを取得する関数
def get_client():
    client_options = (
        ClientOptions(api_endpoint=f"{LOCATION}-discoveryengine.googleapis.com")
        if LOCATION != "global"
        else None
    )
    return discoveryengine.SearchServiceClient(client_options=client_options)
# 検索要約を取得する関数
def search_summaries(client, search_query: str) -> str:
    serving_config = client.serving_config_path(
        project=PROJECT_ID,
        location=LOCATION,
        data_store=DATA_STORE_ID,
        serving_config="default_config",
    )
    request = discoveryengine.SearchRequest(
        serving_config=serving_config,
        query=search_query,
        page_size=3,
        content_search_spec={
            "summary_spec": {
                "summary_result_count": 3,
                "ignore_non_summary_seeking_query": True,
                "ignore_adversarial_query": True
            },
            "extractive_content_spec": {
                "max_extractive_answer_count": 1
            }
        }
    )
    response = client.search(request)
    app.logger.info(f"Full Vertex AI response: {response}")
    return response.summary.summary_text if response.summary else "該当する結果は見つかりませんでした。"
@app.route("/callback", methods=['POST'])
def callback():
    signature = request.headers['X-Line-Signature']
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'
# Line request -> Vertex AI -> Line responce
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    user_message = event.message.text
    client = get_client()
    bot_response = search_summaries(client, user_message)
    send_to_bigquery(user_message)
    try:
        line_bot_api.reply_message(event.reply_token, TextSendMessage(text=bot_response))
    except Exception as e:
        app.logger.error(f"Error in reply_message: {e}")
if __name__ == '__main__':
    port = int(os.environ.get('PORT', 8080))
    app.run(debug=False, host='0.0.0.0', port=port)
config.py

テーブル ID を追加しました。実際の値に置き換えてください。
テーブル ID は、先ほど作成したテーブルの[詳細]に記載されています。

token = "アクセストークン"
secret = "チャネルシークレット"
project_id = "プロジェクトID"
location = "global"
datastore = "データストアID"
table_id = "テーブルID"

これで、LINE から質問が来た際、BigQuery にデータを送信することができます。
実際に送信されているか確認したいと思います。

2-2. 実際に質問を投げて質問が BigQuery に送信されたか確認

ここでは、前回作成したチャットボットに LINE で質問を投げてみます。

以下の質問を LINE で投げてみました。

  • ”おはようございます。”
  • ”勤務時間を教えてください。”

すると、テーブルの PREVIEW 欄にデータが送信されていることが確認できました。
1-6

以上で、質問が来た際に、BigQuery にデータが送信されるようになりました。
次に、BigQuery に送信されたデータをカテゴリ分けしていきたと思います。

3. BigQuery でモデルを作成

はじめにカテゴリ分けを行うために、LLM に基づいたモデルを作成します。
モデルを作成には、以下のドキュメントをもとに作成しました。

【構成図】
0-4

作成手順は以下の通りです。

  • 3-1. 接続を作成
  • 3-2. 接続のサービスアカウントに権限を付与
  • 3-3. モデルを作成

3-1. 接続を作成

リモートモデルを作成する際は Vertex AI に接続する必要があります。
手順は公式ドキュメントと同じです。
BigQuery のコンソール画面で、[+追加]をクリックします。
1-7

その後、一般的なソース欄で[外部データソースへの接続]をクリックし、接続 ID を remote_modelと設定します。
その他はデフォルトのままで作成します。

1-8

3-2. 接続のサービスアカウントに権限を付与

次に、接続のサービスアカウントに権限を付与します。
そうすることで、接続サービスアカウントが Vertex AI にアクセスすることができます。
BigQuery のコンソール画面 → エクスプローラー → 外部接続 →us.remote_model をクリックします。
1-9

赤枠で囲われたサービスアカウントに以下の権限を付与します。

  • Vertex AI ユーザーロール

[IAM と管理]で先ほどのサービスアカウントに権限を付与します。
権限付与の詳細な手順は以下の公式ドキュメントを参照してください。

3-3. モデルを作成する

次に、モデルを作成します。
クエリエディタで、以下の SQL 文を実行します。

SQL 文 1
CREATE OR REPLACE MODEL `chat_bot.chat_bot_model`
  REMOTE WITH CONNECTION `接続ID`
  OPTIONS (remote_service_type = 'CLOUD_AI_LARGE_LANGUAGE_MODEL_V1');

これで、モデルが作成されました。
1-10
次に、作成したモデルを使って質問のカテゴリ分けを行います。

4. SQL 文で質問のカテゴリ分け

ここでは作成したモデルを使って質問のカテゴリ分けを行います。
SQL 文にプロンプトを埋め込み、カテゴリ分けを行います。

以下のドキュメントを参照しました。

【構成図】
0-5

SQL 文 2
WITH explanation_t AS (
  SELECT
    query_text,
    ml_generate_text_llm_result AS explanation
  FROM
    ml.generate_text(
      MODEL `chat_bot.chat_bot_model`,
      (
        SELECT
          CONCAT('問い合わせ内容のtextから顧客の問い合わせ内容が次の[]で囲まれたもののうちどれに当たるか答えなさい。次の値のみで回答してください。["給料に関してと問い合わせ", "休暇に対しての問い合わせ", "育児に関してのお問い合わせ", "就業規則に関してのお問い合わせ", "その他"] "', query_text, '"') AS prompt,
          query_text
        FROM
          `TABLE_ID`
      ),
      STRUCT(TRUE AS flatten_json_output)
    )
)
SELECT
  query_text,
  explanation
FROM
  explanation_t;

これで質問が来た際に、そのカテゴリを判定することができます。
実際に実行してみると以下のように、LINE で送信して質問がカテゴリ化され表示されています。

1-11

これは 2-2 で作成したテーブルに送信された質問を参照しています。
その参照しているデータを、上記の SQL 文中のプロンプトでカテゴリ分けを行っています。
カテゴリを分ける指示さえすれば、このプロンプトは自由に書き換えて頂いても構いません。

最後にカテゴリ化されたデータを簡単に Looker Studio で可視化したいと思います。

5. データの可視化

カテゴリ化されたデータを可視化します。
カテゴリ化されたものを大項目とし、
小項目に実際に LINE からのリクエストを表示できるようにしたいと思います。

【構成図】
0-6

BigQuery から Looker Studio の可視化自体は数クリックで完結します。

先ほどの出力結果の画面から、
[データを探索]→[Looker Studio で調べる]のボタンをクリックします。
これで Looker Studio が開きます。
1-12

しかし、LINE で質問したものが

  • ”おはようございます。”
  • ”勤務時間を教えてください。”

の 2 つしかないので、LINE で 10 個くらい質問し、再度SQL文2を実行したいと思います。
以下のように追加で 10 個質問しSQL文2を実行してみました。
(会社に関することを質問しました。)
1-13

そして、上記と同じ流れで Looker Studio を開きます。
デフォルトでは以下のように表示されるかと思います。
1-14

これを一度削除し、カスタマイズしてみます。
上部の[グラフを追加]から、円グラフ選択し、以下のように 2 つ並べます。

1-15
イメージとしては、左側の円グラフにカテゴリを表示、右側に具体的な質問内容を表示したいと思います。
そして、あるカテゴリをクリックすると、そのカテゴリに分類されている、具体的な質問内容が右側の円グラフに表示されるようにしたいと思います。

左側の円グラフをクリックし、右側のディメンションを query_text から explanation に変更します。
右側のディメンションを query_text のままにしておきます。
そうすると以下のようになリます。
1-16

最後の左側の円グラフのカテゴリをクリックすると、右側の円グラフに問い合わされた質問内容が表示されます。
1-17
これで、カテゴリ化されたデータを可視化することができました。

まとめ

以上で、LINE で受け取った質問をカテゴリ化し、Looker Studio で可視化することができました。
これを作成することで、質問の傾向を把握することができます。
またこの記事は、作成したチャットボットを自分好みにカスタマイズしてほしいという思いがあります。
そのためこの記事は手順書のようになっています。
頭で閃いた発想が実際にアプリケーションとして動くというのは、とても楽しいことです。
今回は私も簡単にではありますが、質問の可視化を行えたら経営判断などに使用できるのではないかと思い作成してみました。
いまではわからないことは生成 AI に聞けば大体は解決できます。
これからも閃いたことを形にしていきたいと思います。
意見やコメントいただけると嬉しいです。

Discussion