はじめに

皆様、ご自身のウェブサイトに強力なサイト内検索機能を導入したいと考えたことはありませんか? ユーザーが求める情報を素早く見つけられるサイトは、顧客満足度向上に直結します。今回は、Google Cloud の Discovery Engine を活用して、データストアの作成からウェブサイトのインポートまで、サイト内検索機能を構築する基本的なステップをご紹介します。

Google Cloud Discovery Engineとは?

Google Cloud Discovery Engine は、Google の検索技術を基盤とした強力な検索・レコメンデーションプラットフォームです。ウェブサイトのコンテンツをインデックス化し、ユーザーが求める情報を高精度で検索できる機能を提供します。これにより、開発者は複雑な検索エンジンの構築に時間を費やすことなく、質の高い検索体験をユーザーに提供できます。

ステップ1:データストアを作成する

まず、Discovery Engine でコンテンツを保存・管理するための「データストア」を作成します。データストアは、インデックス化したい情報源の種類や用途に合わせて設定します。

データストア作成のポイント

  • プロジェクトID(project_id): Google Cloud プロジェクトのIDを指定します。
  • ロケーション(location): データストアを配置するリージョンを指定します。「global」も選択可能です。
  • データストアID(data_store_id): データストアを一意に識別するためのIDです。任意の文字列を指定します。
  • ディスプレイ名(display_name): データストアの表示名です。管理画面などで識別しやすくするために設定します。
  • 業界の種別(industry_vertical): データストアが扱うコンテンツの業界を指定します。一般的なウェブサイトであれば「GENERIC」を選択します。
  • ソリューションタイプ(solution_types): データストアの主な用途を指定します。サイト内検索の場合は「SOLUTION_TYPE_SEARCH」を選択します。
  • コンテンツ設定(content_config): データソースの種類を指定します。ウェブサイトをインポートする場合は「PUBLIC_WEBSITE」を選択します。
!pip install google-cloud-discoveryengine
!pip install google-api-core
from google.api_core.client_options import ClientOptions
from google.cloud import discoveryengine

def create_data_store_sample(
    project_id: str,
    location: str,
    data_store_id: str,
) -> str:

    client_options = (
        ClientOptions(api_endpoint=f"{location}-discoveryengine.googleapis.com")
        if location != "global"
        else None
    )

    client = discoveryengine.DataStoreServiceClient(client_options=client_options)

    parent = client.collection_path(
        project="{プロジェクトID}",
        location="global",
        collection="default_collection",
    )

    data_store = discoveryengine.DataStore(
        display_name="My Data Store-4",
        # Options: GENERIC, MEDIA, HEALTHCARE_FHIR
        industry_vertical=discoveryengine.IndustryVertical.GENERIC,
        # Options: SOLUTION_TYPE_RECOMMENDATION, SOLUTION_TYPE_SEARCH, SOLUTION_TYPE_CHAT, SOLUTION_TYPE_GENERATIVE_CHAT
        solution_types=[discoveryengine.SolutionType.SOLUTION_TYPE_SEARCH],
        # Options: NO_CONTENT, CONTENT_REQUIRED, PUBLIC_WEBSITE
        content_config=discoveryengine.DataStore.ContentConfig.PUBLIC_WEBSITE,
    )

    request = discoveryengine.CreateDataStoreRequest(
        parent=parent,
        data_store_id=data_store_id,
        data_store=data_store,
    )

    operation = client.create_data_store(request=request)

    print(f"Waiting for operation to complete: {operation.operation.name}")
    response = operation.result()

    metadata = discoveryengine.CreateDataStoreMetadata(operation.metadata)

    print(response)
    print(metadata)

    return operation.operation.name

project_id = "プロジェクトID" # あなたのプロジェクトIDに置き換えてください
location = "global" # 必要に応じてロケーションを変更してください
data_store_id = "データストアID" # あなたのデータストアIDに置き換えてください

print(create_data_store_sample(project_id,location,data_store_id))

出力

Waiting for operation to complete: projects/{プロジェクト番号}/locations/global/collections/default_collection/operations/
name: "projects//{プロジェクトID}/locations/global/collections/default_collection/dataStores/{データストアID}"
display_name: "データストア名"
industry_vertical: GENERIC
solution_types: SOLUTION_TYPE_SEARCH
default_schema_id: "default_schema"
content_config: PUBLIC_WEBSITE
serving_config_data_store {
}

ステップ2:ウェブサイトをインポートする

データストアの作成が完了したら、次にインデックス化したいウェブサイトのコンテンツをデータストアにインポートします。これにより、Discovery Engine がウェブサイトの情報を収集し、検索可能な状態にします。

ウェブサイトインポートのポイント

データストアID(data_store_id): ステップ1で作成したデータストアのIDを指定します。
URIパターン(uri_pattern): インデックス化したいウェブサイトのURLパターンを指定します。ワイルドカード(*)を使用して、特定のパス配下のページをまとめて指定することも可能です。http や https プロトコルは含めません。
ターゲットサイトタイプ(type_): 指定したURIパターンをインデックスに含めるか(INCLUDE)、除外するか(EXCLUDE)を指定します。
完全一致(exact_match): URIパターンを厳密に一致させるかどうかを指定します。

以下のPythonコードでウェブサイトのコンテンツをインポートできます。

from google.api_core.client_options import ClientOptions
from google.cloud import discoveryengine_v1 as discoveryengine

project_id = "プロジェクトID" # プロジェクトIDに置き換えてください
location = "global" # 必要に応じてロケーションを変更してください
data_store_id = "データストアID" # ステップ1で作成したデータストアIDに置き換えてください
uri_pattern = "{ドメイン}/{PATH}*" # インデックス化したいウェブサイトのURIパターンに置き換えてください。httpsは不要です。

client_options = (
    ClientOptions(api_endpoint=f"{location}-discoveryengine.googleapis.com")
    if location != "global"
    else None
)

client = discoveryengine.SiteSearchEngineServiceClient(
    client_options=client_options
)

site_search_engine = client.site_search_engine_path(
    project=project_id, location=location, data_store=data_store_id
)

target_site = discoveryengine.TargetSite(
    provided_uri_pattern=uri_pattern,
    # 対象とする場合はINCLUDE、除外する場合は EXCLUDE
    type_=discoveryengine.TargetSite.Type.INCLUDE,
    exact_match=False,
)

operation = client.create_target_site(
    parent=site_search_engine,
    target_site=target_site,
)

response = operation.result()

metadata = discoveryengine.CreateTargetSiteMetadata(operation.metadata)

print(response)
print(metadata)

出力

provided_uri_pattern: "{ドメイン}/*"
type_: INCLUDE
generated_uri_pattern: "{ドメイン}/{除外したいPATH}/*"
root_domain_uri: "{ドメイン}"
update_time {
seconds: 1749116769
nanos: 908000000
}

ステップ3:検索機能を試す

データストアの作成とウェブサイトのインポートが完了したら、実際に検索機能を試してみましょう。ここでは、Pythonコードを使って特定のクエリで検索を実行する方法を紹介します。

データソースをアイレットのホームページとして「生成AIの事例は」というクエリで検索を実行してみます。

from typing import List

from google.api_core.client_options import ClientOptions
from google.cloud import discoveryengine_v1 as discoveryengine

project_id = "プロジェクトID" # あなたのプロジェクトIDに置き換えてください
location = "global"          # Values: "global", "us", "eu"
engine_id = "エンジンID" # あなたのエンジンIDに置き換えてください
search_query = "検索内容を記載"

def search_sample(
    project_id: str,
    location: str,
    engine_id: str,
    search_query: str,
) -> List[discoveryengine.SearchResponse]:
    client_options = (
        ClientOptions(api_endpoint=f"{location}-discoveryengine.googleapis.com")
        if location != "global"
        else None
    )

    client = discoveryengine.SearchServiceClient(client_options=client_options)

    serving_config = f"projects/{project_id}/locations/{location}/collections/default_collection/engines/{engine_id}/servingConfigs/default_config"

    content_search_spec = discoveryengine.SearchRequest.ContentSearchSpec(
        snippet_spec=discoveryengine.SearchRequest.ContentSearchSpec.SnippetSpec(
            return_snippet=True
        ),
        summary_spec=discoveryengine.SearchRequest.ContentSearchSpec.SummarySpec(
            summary_result_count=5,
            include_citations=True,
            ignore_adversarial_query=True,
            ignore_non_summary_seeking_query=True,
            model_prompt_spec=discoveryengine.SearchRequest.ContentSearchSpec.SummarySpec.ModelPromptSpec(
                preamble="YOUR_CUSTOM_PROMPT" # 必要に応じてカスタムプロンプトを設定
            ),
            model_spec=discoveryengine.SearchRequest.ContentSearchSpec.SummarySpec.ModelSpec(
                version="stable",
            ),
        ),
    )

    request = discoveryengine.SearchRequest(
        serving_config=serving_config,
        query=search_query,
        page_size=10,
        content_search_spec=content_search_spec,
        query_expansion_spec=discoveryengine.SearchRequest.QueryExpansionSpec(
            condition=discoveryengine.SearchRequest.QueryExpansionSpec.Condition.AUTO,
        ),
        spell_correction_spec=discoveryengine.SearchRequest.SpellCorrectionSpec(
            mode=discoveryengine.SearchRequest.SpellCorrectionSpec.Mode.AUTO
        ),
    )

    response = client.search(request)
    print(response)

    return response

search_sample(project_id,location,engine_id,search_query)

下記のようにアイレットの生成AI事例が検索されて返ってきました

SearchPager<results {
  ---------------------省略---------------------
results {
  id: "1"
  document {
    name: "projects/{プロジェクト番号}/locations/global/collections/default_collection/dataStores/{データストアID}/branches/0/documents/1"
    id: "1"
    derived_struct_data {
      fields {
        key: "title"
        value {
          string_value: "アイレット株式会社における生成 AI 活用事例を公開しました ..."
        }
      }
      fields {
        key: "snippets"
        value {
          list_value {
            values {
              struct_value {
                fields {
                  key: "snippet"
                  value {
                    string_value: "Mar 7, 2024 ... アイレットは、Google Cloud の生成 AI サービス「Vertex AI Search and Conversation」を活用した高度な検索機能を cloudpack 公式サイトに実装しました ..."
                  }
                }
---------------------省略---------------------
                      fields {
                        key: "og:url"
                        value {
                          string_value: "https://www.iret.co.jp/news/20240912.html"
                        }
                      }
---------------------省略---------------------                      fields {
                        key: "og:description"
                        value {
                          string_value: "アイレット株式会社における生成 AI 活用事例を公開しました。アイレットでは、デザインからシステム設計・開発、クラウドを活用したインフラ設計・構築・運用監視にいたるまで、あらゆる側面からサービスをご提供し、お客様の課題解決をお手伝いします。"
---------------------省略---------------------
}
total_size: 139
attribution_token: "×××"
summary {
  summary_skipped_reasons: LLM_ADDON_NOT_ENABLED
}

まとめ

本記事では、Google Cloud Discovery Engine を利用して、ウェブサイトのサイト内検索機能を構築するための第一歩として、データストアの作成とウェブサイトコンテンツのインポート、そして簡単な検索の実行方法をご紹介しました。これらのステップを踏むことで、ウェブサイトの情報を効率的にインデックス化し、ユーザーが求める情報へ迅速にアクセスできる環境を整えることができます。

Discovery Engine は、さらに詳細な設定や高度な検索機能を提供しており、ウェブサイトの特性に合わせた柔軟な検索体験を実現することが可能です。ぜひ、この強力なツールを活用して、ユーザーにとってより魅力的なウェブサイトを目指してください。

最後までお読みいただきありがとうございました。この記事が、皆様のサイト内検索構築の一助となれば幸いです。