MENU
  • HOME
  • Struccle
  • 取引実績
  • お問い合わせ
  • 資料DL
  • 会社概要
  • FAQ
  • Struccle記事
  • BigQuery記事
データ流通、検索エンジン開発のプロフェッショナル
DataStructor
  • HOME
  • Struccle
  • 取引実績
  • お問い合わせ
  • 資料DL
  • 会社概要
  • FAQ
  • Struccle記事
  • BigQuery記事
DataStructor
  • HOME
  • Struccle
  • 取引実績
  • お問い合わせ
  • 資料DL
  • 会社概要
  • FAQ
  • Struccle記事
  • BigQuery記事
  1. ホーム
  2. AI_Agent
  3. Agent開発
  4. AI Agent開発日記 2024/10/01

AI Agent開発日記 2024/10/01

2025 2/10
AI_Agent Agent開発
2025年2月8日2025年2月10日
目次

この記事について

この記事では、Dialogflow CX を使用してデータストア参照型検索エージェントを作成するための調査内容や、その他の関連する調査結果をまとめています。

dialogflowCXの回答で使える変数について

  • Dialogflow CX の「Agent Says」などで使用できるシステム変数を活用することで、ユーザーとのやり取りをより動的にすることができます。これらの変数は、データストアからの検索結果やユーザーの入力、セッション情報、ナレッジベースの詳細情報、日時関連など、様々な情報を参照する際に役立ちます。

システム変数の一覧

  • ① データストアの検索結果
    • 検索結果のテキスト内容:$request.knowledge.answers[0]
      → データストアから取得した検索結果の内容が格納されている。
    • 関連ファイルのリンク情報:$request.knowledge.sources[0]
      → 検索結果に関連するファイルのリンク情報が入っている。
  • ② ユーザー入力関連
    • ユーザーの発話内容:$request.query
      → ユーザーが送信したメッセージの全文。
    • 特定のパラメータ値:$session.params.<パラメータ名>
      → フロー内で設定されたパラメータの値を取得できる。
  • ③ セッション情報
    • セッションID:$session.id
      → 現在の会話セッションの一意な識別子。
    • ユーザー情dia報:$session.params.userId
      → ユーザーIDなど、セッション内で保持されている情報。
  • ④ ナレッジベースの詳細情報
    • タイトル情報:$sys.func.GET_FIELD($sys.func.GET($request.knowledge.sources[0], 0), "title")
      → 検索結果のドキュメントのタイトルを取得。
    • ドキュメントのURL:$sys.func.GET_FIELD($sys.func.GET($request.knowledge.sources[0], 0), "uri")
      → ナレッジベースのドキュメントのリンクを取得。
  • ⑤ 日時関連
    • 現在の日付:$sys.date
      → YYYY-MM-DD 形式で現在の日付を取得。
    • 現在の時刻:$sys.time
      → HH:mm:ss 形式で現在の時刻を取得。

参照記事

Google Cloud
System functions reference  |  Dialogflow CX  |  Google Cloud

Dialogflow CX Webhook を使用して AI でテキスト生成をして回答を行うコード

  • このコードは、Google Cloud Functions を利用して HTTP リクエストを受け取り、Vertex AI の Generative Model(Gemini)を使用してテキストを生成し、その結果を返す Webhook のコードです。良ければ参考にしてください。

webhook設定

requirements.txt

functions-framework==3.*
requests
google-cloud-aiplatform
vertexai
furl
google-cloud-storage

main.py

import functions_framework
import requests
import vertexai
import json
from vertexai.generative_models import GenerationConfig, GenerativeModel, Part
from furl import furl
from google.cloud import storage
from urllib.parse import urlparse
from pathlib import Path

def interview(project_id: str,location: str,model: str,text: str) -> str:
    # Initialize Vertex AI
    vertexai.init(project=project_id, location=location)

    # Load the model
    model = GenerativeModel(model_name=model)

    # Generation Config
    config = GenerationConfig(
        max_output_tokens=2048, temperature=0.4, top_p=1, top_k=32
    )

    # Generate text
    response = model.generate_content(
        text, generation_config=config
    )

    return response.text

@functions_framework.http
def webhook(request):
    response = request.get_json()
    text = response["text"]
    model = "gemini-1.5-flash-001"
    output_text = interview("project_id","us-central1",model,text)

    response["fulfillmentResponse"] = {
            "messages": [
                {
                    "text": {
                        "text": [
                            output_text
                        ],
                        "allowPlaybackInterruption": False
                    }
                }
            ]
        }

    print(json.dumps({"severity": "INFO", "message": response}))
    return response

dialogflowCXのwebhookでリッチコンテンツを使ってみた。

リッチコンテンツとは

Dialogflow CX では、ボタン・画像・カードなどのインタラクティブな要素を含む応答フォーマットを使用でき、設定することで、利便性が向上します。

  • やりたいこと
    • URLをボタン式にして出力したい
  • 試したこと
    • webhookのresponse部分を下記のように設定して動作を確認する
  • 結果
    • 無事ボタン式で動作した

webhook設定

参照記事

Google Cloud
Dialogflow CX Messenger のフルフィルメント  |  Google Cloud

リッチコンテンツを適用したwebhookのresponse設定部分

response["fulfillmentResponse"] = {
    "messages": [  # Dialogflow CX のレスポンスメッセージ
        {
            "payload": {  # メッセージのペイロード(リッチコンテンツを含む)
                "richContent": [  # Dialogflow CX のリッチコンテンツ(複数の UI 要素をリストで管理)
                    [
                        {
                            "type": "info",  # 情報カード(タイトル+説明文)
                            "title": "参照テキスト",  # タイトル部分
                            "subtitle": "hello_test",  # サブタイトル(追加説明)
                        },
                        {
                            "type": "button",  # ボタン要素(クリック可能)
                            "icon": {  # ボタンに表示するアイコン設定
                                "type": "chevron_right",  # 矢印アイコン
                                "color": "#FF9800"  # オレンジ色のアイコン
                            },
                            "text": "参照リンク",  # ボタンに表示するテキスト
                            "link": "https://example.com"  # ボタンをクリックしたときのリンク先
                        },
                        {
                            "type": "divider"  # 区切り線(コンテンツの分割用)
                        }
                    ] 
                ]
            }
        }
    ]
}

データストアにアップロードしたGCSのファイルが文字化けする場合の対処法

  • データストアにアップロードしたGCSのファイルをリンクから表示する際、文字化けが発生することがあります。これは、ファイル自体のエンコード設定の問題か、ブラウザのエンコード設定の問題が原因である可能性があります。このような問題を防ぐために、ファイルをGCSにアップロードする際にエンコード設定を適切に定義するコードをご紹介します。
  • 使用ライブラリのインストール
    • pip install google-cloud-storage
  • Google Cloudの認証について
    • storage.Client()を使うには、Google Cloudの認証情報が必要です。認証にはサービスアカウントキーを使用します。手順としては以下の通りです。
    • Google Cloud Consoleでサービスアカウントを作成し、JSONキーをダウンロードします。
    • 環境変数GOOGLE_APPLICATION_CREDENTIALSにダウンロードしたサービスアカウントキーのパスを設定します。

GCSへのアップコード

bucket_name = "" #アップ先バケット名
file_name = "" #アップ先ファイルディレクトリ
text = ""

storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(file_name)
blob.upload_from_string(text, content_type='text/plain; charset=UTF-8', timeout=300)

GCSからファイル取得コード

bucket_name = "" #アップ先バケット名
file_name = "" #アップ先ファイルディレクトリ

storage_client = storage.Client()
bucket = storage_client.get_bucket(bucket_name)
blob = storage.Blob(file_name, bucket)
content = blob.download_as_string().decode('utf-8')

Dialogflow CXのデータストア参照対話型エージェントのプロンプトで、データの文の区切りを認識させることはできるのか?

  • やりたいこと
    • データストアに .txt ファイルをアップロードし、Dialogflow CX のデータストア参照型対話エージェントで一文のみを参照して回答させたいが、実際には周囲の文章も含めて取得され、回答されてしまう。これを一文だけ参照して回答させることが可能かを、
      Agent Settings > Gen AI > Datastore > カスタムプロンプトのプロンプトで設定してみて確認したい。
  • 結果
    • 下記のような指示文をプロンプトに追加してみたが、一文ごとに区切られることはなく、回答率が下がるだけだった。
      • ソースからユーザーのクエリに最も関連性の高い「一文」のみを抽出し、それ以外の文を含めずに回答してください。
        文が長い場合でも、一つの完全な文のみを返してください。
        回答に関係のない文を含めないでください。
      • ソースから最も関連性の高い「一文」のみを抜き出して回答してください。
        他の文や周囲の文脈を含めず、厳密に一文のみを抽出してください。
      • ソース内で最も関連性の高い一文のみを抜き出して回答してください。他の文や前後の文脈を加えず、厳密に一文だけを提示してください。また、[。]は文の区切りを意味します
    • ファイルの文章を「。」ではなく改行で区切るようにしたところ、一文だけを参照するようになった。しかし、参照部分が二つ以上の文に分かれている場合、参照されなくなってしまった。

Dialogflow CX のデータストアを参照する対話型エージェントが出力した、GCS のファイルの URL リンクで、テキストフラグメントが時々反映されない問題の原因

  • Dialogflow CX で対話型エージェントがデータストアの検索結果として参照ファイルのリンク情報を出力した際に、通常はされるべきテキストフラグメントが反映されない場合の原因と解決策について紹介します。

テキストフラグメントの仕組みについて

  • #:~:text=キーワード の形式で URL の末尾につけると、
    ページ内の指定したキーワードの部分へ直接スクロール し、該当テキストがハイライトされます。
    Chrome や Edge などの一部のブラウザで対応しています。

ほとんどのテキストフラグメントが反映されない原因と解決策

  • 原因
    • 空白や改行の違いにより、テイストフラグメントの文とGCS内のファイルの文が一致せず、ハイライトされない問題が発生する事がある
    • テキストフラグメントには文字数制限があり、その制限を超えるとハイライトされなくなる。
  • 解決策
    • ファイルに改行や空白を含めない
    • Webhookを使用して文字数を調整したり、テキストフラグメントの文とGCS内のテキストフラグメントの文の類似部分を取得し、それを基にテキストフラグメントの文を置き換えてDialogflow CXに結果を返すようにするなど

dialogflowCXの対話型エージェントに紐づけるデータストアにBigQueryのデータは入れられるのか?

  • やりたいこと
    • Dialogflow CX の対話型エージェントに紐づけるデータストアとして、BigQuery(BQ)のデータをアップロードできるか確認したい。
  • 試したこと
    • Dialogflow CX の対話型エージェントに接続可能な以下の 3 つのデータストア形式に、BQ のデータをアップロードできるか検証した。
      • 非構造化ドキュメント(PDF、HTML、TXT など) → アップロード不可
      • リンクされた非構造化ドキュメント(JSONL とメタデータ) → アップロード不可
      • チャットアプリケーション用のよくある質問の構造化データ(CSV) → アップロード不可
    • また、エージェントに紐づける前に、BQ の以下の 5 種類のデータストアを作成し、それぞれに JSON や CSV を格納して検証したが、対話型エージェントとの接続はできなかった。
      • Structured – BigQuery table with your own schema
        Structured with metadata – BigQuery table with metadata
        メディア – 構造化メディアデータが格納された BigQuery テーブル
        Unstructured – BigQuery table with metadata
        Healthcare – BigQuery table with structured healthcare data

エージェントに紐づいているデータストアは削除できるのか?

  • やりたいこと
    • エージェントに紐づいているデータストアを削除できるのかを検証する
  • 試したこと
    • 設定や記事を詳しく確認
    • データストアを削除するコードを使ってみる
  • 結果
    • 設定には該当する項目が見当たらなかった。
    • 発見した記事には、以下のように記載されていた。
      「アプリに接続されているデータストアは削除できません。データストアがアプリに接続されている場合は、そのアプリを削除する必要があります。」
    • データストアを削除するコードを実行したところ、データストアがアプリに紐付いているため削除できないというエラーが発生した。

データストアのファイルを削除する際に使用したサンプルコードが掲載されている記事。

Google Cloud
データストアを削除する  |  AI Applications  |  Google Cloud データストアを削除する

2.5MB以上のファイルを、Dialogflow CXで利用可能なすべてのデータストアに登録し、それぞれのデータストアで受け入れ可能かを検証した結果、どのファイル形式が2.5MB以上のサイズでも登録可能であるかを確認する。

  • やりたいこと
    • 2.5MB以上のTXT、JSON、HTML、PDF、CSV形式のファイルを、Dialogflow CXに紐づけられるすべての形式のデータストアに登録し検証した結果、どのファイル形式がどのデータストアで2.5MB以上のサイズでも通るのかを確認しました。
  • 検証方法
    1. dialogflowCXと紐づけられていない状態のデータストアにファイルを追加して検証。
      • データを登録した後、Dialogflow CXと紐づけられることを確認。
    2. 既にDialogflow CXと紐づけられたデータストアにファイルを追加して検証。

検証結果

dialogflow CXに紐づけられていない状態のデータストア

非構造化ドキュメント(PDF、HTML、TXT など)
結果: PDFのみ2.5MB以上が通った

リンクされた非構造化ドキュメント(JSONL とメタデータ)
結果: PDFのみ2.5MBが通った

チャット アプリケーション用のよくある質問の構造化データ(CSV)
結果: CSVのみ項目ごとに分割されファイル化されたが通った

ファイルをアップロードした後、すべてのデータストアが Dialogflow CX と紐づけられた。


既にDialogflow CXと紐づけられたデータストア

非構造化ドキュメント(PDF、HTML、TXT など)
結果: PDFのみ2.5MB以上のファイルが通った

リンクされた非構造化ドキュメント(JSONL とメタデータ)
結果: PDFもその他も通らなかった

チャット アプリケーション用のよくある質問の構造化データ(CSV)
結果: CSVのみ項目ごとに分割されファイル化されたが通った


全体的な結果まとめ

  • PDFとCSVはそれぞれの方法で2.5MB以上でも読み込めることが確認できた。
  • エージェントに紐づけられていない状態では、リンクされた非構造化ドキュメントでもPDFが通った。
    しかし、エージェントに紐づけられた状態で作成した場合、リンクされた非構造化ドキュメントではPDFも通らなくなる傾向があった。

PDFをテキスト化するおすすめのAPI「Document AI」

  • PDFをテキスト化できるAPIを探していたところ、「Document AI」を見つけました。試した結果、高精度でテキストを取得できたので、共有しておきます。

参考記事

LayerX エンジニアブログ
Document AI を使った請求書読み取り機能の検証 | yu-ya4 - LayerX エンジニアブログ LayerX で機械学習エンジニアとして働いている松村 @yu-ya4 です。現在はAI-OCRチームにて、バクラクシリーズのOCR機能の開発を主に行なっています。この記事は LayerX Tec...
Google Cloud
Document AI | Google Cloud Document AI ソリューション スイートには、ドキュメント処理用の事前トレーニング済みモデル、カスタムモデル用の Workbench、検索と保存のための Warehouse が含まれてい...

GCS へフォルダ構造を維持したままアップロードおよびダウンロードを行うコード。

  • os.walk()を使い、GCSにフォルダ構造を維持したまま アップロードするコードとダウンロードするPythonコードを共有しておきます。

GCSへのアップロードコード

from google.cloud import storage
import os

def upload_folder_with_structure(bucket_name, local_folder, destination_folder=""):
    """フォルダ自体を含めてGCSにアップロード"""
    client = storage.Client()
    bucket = client.bucket(bucket_name)

    # アップロードするフォルダの名前を取得
    folder_name = os.path.basename(os.path.normpath(local_folder))

    for root, _, files in os.walk(local_folder):
        for file_name in files:
            local_path = os.path.join(root, file_name)
            
            # `local_folder` を基準にした相対パスを取得し、その前にフォルダ名を追加
            relative_path = os.path.relpath(local_path, local_folder)
            gcs_path = os.path.join(destination_folder, folder_name, relative_path).replace("\\", "/")  # Windows対策

            blob = bucket.blob(gcs_path)
            blob.upload_from_filename(local_path)

            print(f"Uploaded {local_path} to gs://{bucket_name}/{gcs_path}")

# 使用例
bucket_name = "your-bucket-name"
local_folder = "path/to/local/folder"
gcs_folder = "your-gcs-folder"  # 空文字ならGCSのルートにアップロード

upload_folder_with_structure(bucket_name, local_folder, gcs_folder)

GCSからのダウンロードコード

from google.cloud import storage
import os

def download_folder_from_gcs(bucket_name, gcs_folder, local_folder):
    """GCSのフォルダをローカルにフォルダ構造を維持したままダウンロード"""
    client = storage.Client()
    bucket = client.bucket(bucket_name)

    # GCSのフォルダ内のオブジェクト一覧を取得
    blobs = bucket.list_blobs(prefix=gcs_folder)

    for blob in blobs:
        # GCS上のパスをローカルのパスに変換
        relative_path = os.path.relpath(blob.name, gcs_folder).lstrip("/")
        local_path = os.path.join(local_folder, relative_path)

        # フォルダ構造を作成
        os.makedirs(os.path.dirname(local_path), exist_ok=True)

        # ファイルをダウンロード
        blob.download_to_filename(local_path)
        print(f"Downloaded gs://{bucket_name}/{blob.name} to {local_path}")

# 使用例
bucket_name = "your-bucket-name"
gcs_folder = "your-gcs-folder/local-folder"  # ダウンロードしたいGCSフォルダ
local_folder = "path/to/local/destination"  # 保存先のローカルフォルダ

download_folder_from_gcs(bucket_name, gcs_folder, local_folder)

os.walk()参照記事

Python documentation
os — Miscellaneous operating system interfaces Source code: Lib/os.py This module provides a portable way of using operating system dependent functionality. If you just want to read or write a file see open(...

まとめ

Dialogflow CX で使えるシステム変数について

  • データストアの検索結果を取得する $request.knowledge.answers[0]や、
    ユーザー入力やセッション情報を取得する $request.query $session.params.<パラメータ名>などのシステム変数について紹介した

Dialogflow CX Webhook を使用して AI でテキスト生成をして回答を行うコード

  • Dialogflow CX の webhook機能を使ってGoogle Cloud Functions で HTTP リクエストを処理し、Gemini でテキスト生成を行うサンプルコードを紹介した

Dialogflow CX の Webhook でリッチコンテンツを使ってみた

  • Dialogflow CX のリッチコンテンツ(ボタン・カード・画像など)についてや、
  • リッチコンテンツを適用した Google Cloud Functions の response 部分のサンプルを紹介した。

Dialogflow CX のデータストアにアップロードした GCS のファイルが文字化けする場合の対処法

  • GCSにアップロードしたファイルが文字化けするほとんどの原因は、エンコード設定の不一致で。アップロード時とダウンロード時にフォーマットを明示的に指定することで回避可能。サンプルコードも記載しています。

Dialogflow CX のデータストア参照対話型エージェントのプロンプトで、データの文の区切りを認識させることはできるのか?

  • Dialogflow CX のデータストア参照型対話エージェントで、一文のみを参照して回答させる設定を試みたが、周囲の文も含まれてしまう問題が発生。
  • プロンプトで「一文のみを抽出する」指示を追加 → 効果なし、回答率低下
  • 「。」ではなく改行で区切る → 一文のみ参照されるが、参照部分が複数文に分かれると取得されない

Dialogflow CX のデータストアを参照する対話型エージェントが出力した GCS のファイルの URL リンクで、テキストフラグメントが時々反映されない問題の原因

  • 大半の原因は、空白や改行の違いによりテキストフラグメントがGCS内のテキストと一致しないことや、文字数制限を超えてハイライトが無効になることだった。
  • その対策として、ファイル内の改行や空白を最小限に抑えるほか、Webhookを使用して文字数を調整し、GCS内の類似テキストを基にフラグメントを最適化する方法がある。

Dialogflow CX の対話型エージェントに紐づけるデータストアに BigQuery のデータは入れられるのか?

  • 検証した範囲内でアップロードはできなかった

エージェントに紐づいているデータストアを削除する方法

  • 検証した範囲内では紐づいているエージェントがある場合、削除は不可、
    先にエージェントを削除する必要があった。

2.5MB 以上のファイルを Dialogflow CX で利用可能なすべてのデータストアに登録し、それぞれのデータストアで受け入れ可能かを検証した結果、どのファイル形式が 2.5MB
以上のサイズでも登録可能であるかを確認する

  • PDFとCSVは登録可能(CSVは分割される)リンクされた非構造化ドキュメント(JSONLなど)は2.5MB以上が通らない。エージェントと未紐づけのデータストアではPDFが通過するが、紐づけ後は通らなくなる傾向あり

PDF をテキスト化するおすすめの API「Document AI」

  • PDFをテキスト化するうえでおすすめのAPIを紹介しました。

GCS へフォルダ構造を維持したままアップロードおよびダウンロードを行うコード

  • GCS へフォルダ構造を維持したままアップロードおよびダウンロードを行うサンプルコードを紹介しました。

人気記事

  • BigQueryの無料枠を活用しよう!制限と注意点、活用方法を解説
  • BigQueryでエラー解決!よくあるエラーと対処法
  • BigQueryのレベル別学習リソースまとめ!初心者から上級者まで役立つ情報源
  • 【SUUMOスクレイピング】Struccleで物件データを全件収集
  • BigQuery入門!無料データでSQLの基本文字列関数をマスター
AI_Agent Agent開発
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次
カテゴリー
  • AI_Agent (153)
    • Agent開発 (153)
  • BigQuery (100)
    • BigQueryTips (11)
    • BigQueryでデータ分析 (49)
    • BigQueryのFAQ (1)
    • BigQuery入門 (8)
    • BigQuery学習教材 (22)
    • BigQuery導入ガイド (3)
    • BigQuery最新情報 (3)
    • BigQuery活用事例 (4)
  • Struccle (184)
    • Struccleでスクレイピング (10)
      • suumoの物件データを収集&分析 (1)
      • アニマルジョブの電話番号、メールアドレスを全件収集 (1)
      • データ集計 (6)
      • ホットペッパービューティーのヘアサロンデータを収集&分析 (1)
      • 食べログの飲食店データを収集&分析 (1)
    • Struccleデータ料金事例 (173)
      • 商品分析 (15)
      • 営業リスト (119)
      • 競合分析&市場調査 (58)
      • 自動車 (11)
      • 自社活用 (7)
    • Struccle活用企業様の紹介 (1)
  • 当ブログのコーディング実行環境設定 (4)
目次