
大規模言語モデル(LLM)
大規模言語モデル(LLM: Large Language Model)は人工知能の一種であり、大量のテキストデータを学習して言語に関する知識を獲得する機械学習モデルです。自然言語処理の分野でとても重要な役割を果たしています。
イベント
マガジン
技術ブログ
はじめに 弊社では LLM を活用した機能開発の観測基盤として Langfuse をセルフホストで運用しています。Langfuse は LLM アプリケーションのトレーシングやプロンプト管理等に活用できるオープンソースの LLM エンジニアリングプラットフォームです。 さてこの種のサービスには認証の課題がつきまといます。Langfuse は標準でメールアドレス / パスワードによるログインが可能ですが、弊社の方針として開発組織内で利用、管理しているアプリケーションやサービス群には IAM Identity Center を IdP とする SSO を採用しています。 Redash や SendGrid といったサービスで既にこの方式を採用しており、Langfuse でも同様に IAM Identity Center 経由の SSO ログインを実現したいと考えました。 ところが Langfuse は IAM Identity Center を IdP として直接サポートしていません。Langfuse の認証は NextAuth.js ベースであり、対応する認証方式は OAuth / OIDC が中心です *1 。では IAM Identity Center の OIDC 機能をそのまま使えるかというと、そう単純ではありません。IAM Identity Center が OIDC を提供するにはアプリケーション側が trusted token issuer に対応している必要があり、Langfuse はこれに該当しないため直接利用できません。 Cognito と Langfuse の SSO 連携については 既に優れた先例 がありますが、ここに IAM Identity Center を加えた構成についての情報はあまり無いようです。ニッチな話題かもしれませんが、同様の課題を抱えている方もいるのではと考え、本稿にて事例を紹介できればと思います。 構成 前述の事情を踏まえ、間に Amazon Cognito を挟む構成としました。Cognito は SAML によって IdP からの認証情報を受け取り、これを OIDC にてアプリケーション(今回の場合は Langfuse)に提供する役目を担います。IAM Identity Center は SAML による外部アプリケーション(今回の場合は Cognito)のフェデレーションをサポートしているので、これを組み合わせると以下のような構成が実現できます。 IAM Identity Center --- (SAML) ---> Cognito --- (OIDC) ---> Langfuse 認証フローを時系列で描くと以下のようになります。 sequenceDiagram autonumber participant User as ユーザー (Browser) participant LF as Langfuse participant Cog as Cognito participant IDC as IAM Identity Center User->>LF: SSO ログインボタンをクリック LF->>User: Cognito のログイン URL へリダイレクト User->>Cog: 認証リクエスト (OIDC) Cog->>User: IAM Identity Center へリダイレクト User->>IDC: SAML 認証リクエスト IDC->>User: ログイン画面の表示 / 認証の実施 IDC->>User: SAML Assertion を発行 User->>Cog: SAML Assertion をポスト (ACS URL) Cog->>Cog: SAML Assertion の検証 / ユーザー情報の処理 Cog->>User: Langfuse へリダイレクト (認可コード) User->>LF: 認可コードを送信 LF->>Cog: トークン交換リクエスト Cog->>LF: ID トークン / アクセストークン (OIDC) LF->>User: ログイン完了 要するに Cognito が SAML -- OIDC 間の橋渡し役を担う格好です。ユーザー視点では Langfuse のログイン画面で SSO ボタンを押すと IAM Identity Center のログイン画面に遷移し、認証後 Langfuse に戻ってきます。 これを実現する構成が以下のようになります。本稿の趣旨は Langfuse 利用にかかる SSO ログイン化が主軸につき、Langfuse 本体の構成はかなり端折った図である点ご容赦ください *2 構成図。admin / langfuse / logging / security は AWS アカウント名の意 なお上図における logging / security 各アカウントは以下拙稿における member / security に対応するものです。主に SSO ログイン時の監査に使われる周辺要素であり、本稿では詳細を割愛します。 設定の手順 設定は大きく4つのステップに分かれます。 IAM Identity Center に SAML アプリケーションを登録する(admin アカウント) Cognito で SAML IdP と OIDC クライアントを構成する(langfuse アカウント) Langfuse に OIDC 関連の環境変数を設定する(langfuse アカウント) SSO ログインへの一本化(langfuse アカウント) 以下、各ステップの内容を解説します。 Step 1: IAM Identity Center への SAML アプリケーション登録 admin アカウントの IAM Identity Center に、Langfuse 用のカスタム SAML アプリケーション( customer-managed application )を Terraform で登録します *3 。 aws_ssoadmin_application リソースで application_provider_arn に custom-saml を指定し、IAM Identity Center のポータル上での可視性を有効にします。 あわせて aws_ssoadmin_application_assignment で SSO ログインを許可する対象を紐付けます。グループ単位での割り当ても可能ですが、弊社では職責や担当職務に応じて柔軟にアクセス範囲を制御したかったため、ユーザー単位での割り当てとしました *4 。 続いてマネジメントコンソールから Application metadata を設定します。これは Cognito が SAML Assertion を正しく受け取るために必要な設定です。 Application ACS URL : https://<Cognito ドメイン>.auth.<リージョン>.amazoncognito.com/saml2/idpresponse Application SAML audience : urn:amazon:cognito:sp:<Cognito User Pool ID> ACS URL は Cognito User Pool のドメイン名から、SAML audience は Cognito User Pool の ID からそれぞれ導出されます。Step 2 で Cognito User Pool を作成した後に設定する、という順序になります *5 。 同じくマネジメントコンソールから Attribute mappings を設定します。SAML Assertion に含めるユーザー属性と Cognito 側の属性との対応を定義するものです。 User attribute in the application Maps to this string value or user attribute in IAM Identity Center Format Subject(変更不可) ${user:email} persistent email ${user:email} basic email_verified true unspecified name ${user.name} unspecified email_verified を固定値 true としているのは弊社の運用上 IAM Identity Center で管理されているユーザーのメールアドレスは検証済みであると見なして差し支えないためです。これは以下の拙稿に詳細を譲りますが、弊社の IAM Identity Center は IdP として Entra ID を参照しており、Entra ID 上のユーザ情報を信頼できるケースに該当する為です。 最後に、マネジメントコンソールから SAML メタデータファイルをダウンロードします。 IAM Identity Center コンソールへ移動 Application assignments → Applications を選択 Customer managed タブへ移動 対象の SAML アプリケーションを選択 IAM Identity Center metadata 内の IAM Identity Center SAML metadata file からダウンロード このメタデータ XML ファイルは次のステップで Cognito に渡す必要があります。 Step 2: Cognito の構成 langfuse アカウント側では Cognito User Pool を作成し、IAM Identity Center を SAML IdP として登録した上で、Langfuse 向けの OIDC クライアントを構成します。 まず Step 1 でダウンロードした SAML メタデータ XML を S3 バケットに手動でアップロードし、Terraform からは data "aws_s3_object" で参照します *6 。S3 バケット自体も Terraform で作成し、サーバーサイド暗号化とパブリックアクセスブロックを設定しています。 続いて、この SAML メタデータを使って aws_iam_saml_provider と aws_cognito_identity_provider の2つを設定します。前者は IAM レベルでの SAML プロバイダ登録、後者は Cognito User Pool に対する SAML IdP の登録です。 aws_cognito_identity_provider では attribute_mapping で Step 1 の Attribute mappings との対応を指定します。 なお provider_details には ignore_changes を設定しています。Cognito は MetadataFile を解釈して内部的にいくつかの属性を展開するため、内容に変更がなくても terraform plan で差分が出続けます。これを抑制するための措置です。 次に aws_cognito_user_pool_client を設定します。これは Langfuse から見た OIDC クライアントに相当するリソースです。OAuth フローには Authorization Code Grant( code )を、スコープには openid / email / profile を指定します。 callback_urls には Langfuse の OIDC コールバック URL( https://<Langfuse のドメイン>/api/auth/callback/custom )を設定します。トークンの有効期間やクライアントシークレットの生成など、必要な設定を適宜入れます。 最後に、Cognito が払い出した Client ID / Client Secret / Issuer URL を aws_ssm_parameter (SecureString)で SSM パラメータストアに格納し、Langfuse の ECS タスク定義から参照できるようにします。 Step 3: Langfuse への環境変数設定 Langfuse は Custom OAuth Provider としての設定を環境変数で受け取ります。ECS タスク定義に以下の環境変数を追加しました。 平文で渡すものとして AUTH_CUSTOM_NAME 、 AUTH_CUSTOM_CHECKS 、 AUTH_CUSTOM_ALLOW_ACCOUNT_LINKING の3つがあります。SSM パラメータストアから取得する秘密情報として AUTH_CUSTOM_CLIENT_ID 、 AUTH_CUSTOM_CLIENT_SECRET 、 AUTH_CUSTOM_ISSUER の3つがあり、これらは Step 2 で格納した値を参照します。 AUTH_CUSTOM_NAME は Langfuse のログイン画面に表示される SSO ボタンのラベルです。わかりやすい名称を選ぶと良いでしょう AUTH_CUSTOM_CHECKS には pkce を指定し PKCE (Proof Key for Code Exchange) を有効にしています AUTH_CUSTOM_ALLOW_ACCOUNT_LINKING を true にすると、同一メールアドレスの既存アカウントと SSO アカウントが紐付けられます SSO 導入前のアカウントとの互換性のために有効にしています これが無いと後述のトラブルシュート時に Cognito 側で対応する手法が取れず Langfuse 側 DB を直接触ってアカウント管理をする手間が発生します Step 4: SSO ログインへの一本化 SSO ログインが安定稼動していることを確認した後、環境変数 AUTH_DISABLE_USERNAME_PASSWORD を true に設定してメールアドレス / パスワードによるログインを無効化しました。これにより Langfuse のログイン画面は SSO ボタンのみが表示される状態になります。アカウント管理を IAM Identity Center に一元化でき、Langfuse 側での個別のアカウント発行 / 削除が不要となります。 サンプルコード Step 1〜2 で使用した Terraform コードの抜粋を以下に示します。それぞれ collapsed になっていますので、クリックして中身を参照ください。 admin アカウント: IAM Identity Center への SAML アプリケーション登録 # Identity Store からユーザー情報を参照 data "aws_identitystore_user" "main" { for_each = toset (local.langfuse_users) identity_store_id = tolist (data.aws_ssoadmin_instances.main.identity_store_ids) [ 0 ] alternate_identifier { unique_attribute { attribute_path = "UserName" attribute_value = each.key } } } # カスタム SAML アプリケーションの登録 resource "aws_ssoadmin_application" "langfuse" { name = "Langfuse" application_provider_arn = "arn:aws:sso::aws:applicationProvider/custom-saml" instance_arn = tolist (data.aws_ssoadmin_instances.main.arns) [ 0 ] portal_options { visibility = "ENABLED" sign_in_options { origin = "IDENTITY_CENTER" } } } # SSO ログインを許可するユーザーの割り当て resource "aws_ssoadmin_application_assignment" "langfuse" { for_each = toset (local.langfuse_users) # 職責に応じてフィルタしたユーザーリスト application_arn = aws_ssoadmin_application.langfuse.arn principal_id = data.aws_identitystore_user.main [ each.key ] .id principal_type = "USER" } langfuse アカウント: Cognito の構成 # ----- SAML メタデータの管理 ----- # メタデータ XML を格納する S3 バケット(暗号化・パブリックアクセスブロックは別途設定) resource "aws_s3_bucket" "saml_metadata" { bucket = "mntsq-$ { var.env } -saml-metadata" } # IAM Identity Center からダウンロードしたメタデータ XML を参照 data "aws_s3_object" "saml_metadata" { bucket = aws_s3_bucket.saml_metadata.id key = "langfuse.xml" } # ----- SAML プロバイダ・Cognito User Pool ----- resource "aws_iam_saml_provider" "langfuse" { name = "langfuse" saml_metadata_document = data.aws_s3_object.saml_metadata.body } resource "aws_cognito_user_pool" "langfuse" { name = "langfuse" auto_verified_attributes = [ "email" ] } resource "aws_cognito_user_pool_domain" "langfuse" { user_pool_id = aws_cognito_user_pool.langfuse.id domain = "mntsq-$ { var.env } -langfuse" } # IAM Identity Center を SAML IdP として登録 resource "aws_cognito_identity_provider" "langfuse" { user_pool_id = aws_cognito_user_pool.langfuse.id provider_name = "langfuse" provider_type = "SAML" provider_details = { "MetadataFile" = data.aws_s3_object.saml_metadata.body } attribute_mapping = { email = "email" email_verified = "email_verified" name = "name" } lifecycle { # Cognito が MetadataFile を解釈して provider_details を展開するため、 # 毎回差分が出るのを抑制する ignore_changes = [ provider_details ] } } # ----- OIDC クライアント (User Pool Client) ----- resource "aws_cognito_user_pool_client" "langfuse" { name = "langfuse" user_pool_id = aws_cognito_user_pool.langfuse.id allowed_oauth_flows_user_pool_client = true allowed_oauth_scopes = [ "openid" , "email" , "profile" ] allowed_oauth_flows = [ "code" ] supported_identity_providers = [ aws_cognito_identity_provider.langfuse.provider_name ] access_token_validity = 8 id_token_validity = 8 refresh_token_validity = 1 token_validity_units { access_token = "hours" id_token = "hours" refresh_token = "days" } callback_urls = [ "https://<Langfuse のドメイン>/api/auth/callback/custom" ] default_redirect_uri = "https://<Langfuse のドメイン>/api/auth/callback/custom" generate_secret = true } # ----- 認証情報の SSM パラメータストア格納 ----- resource "aws_ssm_parameter" "auth_id" { name = "/$ { var.env } /langfuse/AUTH_CUSTOM_CLIENT_ID" type = "SecureString" value = aws_cognito_user_pool_client.langfuse.id } resource "aws_ssm_parameter" "auth_secret" { name = "/$ { var.env } /langfuse/AUTH_CUSTOM_CLIENT_SECRET" type = "SecureString" value = aws_cognito_user_pool_client.langfuse.client_secret } resource "aws_ssm_parameter" "auth_issuer" { name = "/$ { var.env } /langfuse/AUTH_CUSTOM_ISSUER" type = "SecureString" value = "https://cognito-idp.$ { data.aws_region.current.name } .amazonaws.com/$ { aws_cognito_user_pool.langfuse.id } " } トラブルシューティング 運用を開始して以降、SSO ログインが失敗するケースに遭遇しました。とくに初回ログイン時に顕著で、Cognito と Langfuse との間でユーザー情報のフェデレーションがうまくいかない場合に発生します。 リトライで解消するケースもありますが、それでも解決しない場合は Cognito 側のユーザーを一旦削除し、再度 Langfuse へ SSO ログインしてもらう ことで通るようになります。Cognito User Pool 内のユーザーは IAM Identity Center から federate されたものなので、削除しても次回の SSO ログイン時に再作成されます。 手順としては以下の通りです。 Cognito User Pool のマネジメントコンソールへ移動 User management → Users でログインに失敗しているユーザーを特定 対象ユーザーを選択し、まず Disable user access を実施 その後 Delete user を実行 ユーザー削除後に改めて SSO ログインを試みてもらえば、Cognito 側にユーザーが再作成されてログインが成功するはずです。 おわりに IAM Identity Center を IdP として Langfuse に SSO ログインを実現する構成について解説しました。ポイントは Cognito を SAML と OIDC との翻訳役として活用する 点です。 設定にあたっては Terraform とマネジメントコンソールの手作業が混在する点がやや煩雑です。とくに IAM Identity Center 側の Application metadata や Attribute mappings、SAML メタデータの取得はコンソール操作が必要であり、手順として残しておかないと再現が難しくなります。 Cognito + Langfuse の SSO 構成 については先例がありますが、IAM Identity Center を加えた構成についてはあまり情報が見当たりませんでした。このパターンは Langfuse に限らず、OIDC のみをサポートするアプリケーションに IAM Identity Center 経由の SSO を提供したい場合に広く応用できるものと考えています。同様の課題を抱えている方の参考になれば幸いです。 文責:MNTSQ 株式会社 SRE 秋本 注記:この記事は文責者の過去記事と弊社内のドキュメントをもとに Claude Opus 4.6 が作成した内容を9割程度そのまま使用しています *1 : https://langfuse.com/self-hosting/security/authentication-and-sso を参照。Langfuse は Google / GitHub / Azure AD (Entra ID) / Okta / Auth0 / Custom OAuth Provider 等をサポートしています *2 : 興味のある方向け:ECS で ClickHouse 含めて Langfuse が必要とする諸要素を動作させ、DB は Aurora PostgreSQL、キャッシュ関連は ElastiCache にて Valkey クラスタを組んで動作させています *3 : 実際には全ての設定を Terraform でカバーできるわけではないので、適宜 AWS マネジメントコンソールからの設定作業も必要になります *4 : この種の柔軟さをグループ単位で表現できなかったという内部事情もあります *5 : 厳密には Cognito User Pool の作成 → IAM Identity Center の Application metadata 設定 → Cognito 側の残りの設定、という順序を踏む必要があります。Terraform で一括管理する場合は初回適用時にこの依存関係を意識する必要があります。要するに IAM Identity Center と Cognito とを行ったり来たりする必要が2026年2月時点で有ります *6 : SAML メタデータはコード管理の対象としていません。IAM Identity Center 側で生成されるものであり、かつ XML の内容が大きいため S3 経由での参照としました。メタデータの取得手順は Step 1 に記載の通りです
はじめに こんにちは!NTTデータグループの工藤です。 最近、友人との会話の中で、近年注目されているMCPツールポイズニングという攻撃手法について教えてもらいました。MCP(Model Context Protocol)を介して与えられるツール定義や情報が悪意をもって改変されることで、LLMの挙動を攻撃者の意図する方向へ誘導できるという内容でした。 印象的だったのは、ユーザ側の入力ではなく、LLMが利用するツールや仕組みそのものが悪用される点でした。 正規の連携であっても攻撃が成立し得る構造を整理するため、本記事ではMCPツールポイズニングの仕組みと対策について紹介します。 MC
本記事は 2026 年 2 月 26 日 に公開された「 Improving order history search using semantic search with Amazon OpenSearch Service 」を翻訳したものです。 Amazon で買い物をしたことがあれば、 注文履歴 を使ったことがあるでしょう。この機能は 1995 年まで遡る注文履歴を保持しており、すべての購入を追跡・管理できます。注文履歴の検索機能では、検索バーにキーワードを入力して過去の購入品を見つけられます。商品を見つけるだけでなく、同じ商品や類似商品を簡単に再購入でき、時間と手間を節約できます。 Rufus や Alexa など、Amazon のショッピング体験を支えるさまざまな機能が注文履歴検索を活用し、過去の購入品を見つける手助けをしています。そのため、注文履歴検索には過去の購入品をできるだけ正確かつ迅速に見つける能力が求められます。 本記事では、Your Orders チームが Amazon OpenSearch Service と Amazon SageMaker を使い、既存のレキシカル検索システムにセマンティック検索機能を導入して注文履歴検索を改善した方法を紹介します。 レキシカル検索の限界 注文履歴検索では、 レキシカルマッチング を使って、検索キーワードの少なくとも 1 つの単語に一致する商品を顧客の注文履歴全体から取得しています。たとえば「orange juice」と検索すると、オレンジジュースだけでなく、過去に注文した生のオレンジや他のフルーツジュースも取得されます。レキシカルマッチングは検索キーワードに正確に一致する商品の 再現率 は高いものの、この例の「health drinks」のような関連キーワードや汎用的なキーワードではうまく機能しません。 Amazon の AI ショッピングアシスタント Rufus の登場以来、効率的で充実したショッピング体験を求める顧客が増え、Rufus で過去の購入品を検索するケースも増えています。「Show me healthy drinks」のように、「kombucha」「green tea」「protein shakes」といった長く正確な用語を気にせず検索できるようになりました。検索体験が会話的で意図ベースになり、商品をより直感的に見つけられるようになっています。Rufus が「Show me the healthy drinks I bought last year」のような注文履歴検索に同じ直感的な体験で応えるには、基盤となる注文履歴データストア (Your Orders) に、従来のレキシカルマッチングを超えて検索キーワードの意味を理解する セマンティック検索 機能が必要です。 セマンティック検索の実装における課題 この規模でセマンティック検索を実装するにあたり、次の技術的課題がありました。 スケール – 世界中の顧客の注文履歴に対応する数十億件のレコードでセマンティック検索を有効にする必要がありました。 ゼロダウンタイム – バックエンドでセマンティック検索を導入する変更を行う間も、システムの可用性を 100% 維持する必要がありました。 検索品質の低下防止 – セマンティック検索は検索品質の向上が目的ですが、逆効果になるケースもあります。たとえば、顧客が商品名を正確に覚えていてその名前に一致する商品だけを見つけたい場合、類似商品も表示すると結果が混雑し、目的の商品を見つけにくくなります。同様に、注文 ID のように固有の意味を持たない識別子で検索する場合、セマンティック検索は機能しません。このようなシナリオではレキシカル検索のみを使用します。 ソリューション概要 セマンティック検索は 大規模言語モデル (LLM) を基盤としています。LLM は主に人間の言語で学習されており、学習済みの言語のテキストを受け取り、入力テキストの長さに関係なく固定長のエンベディングベクトルを出力するように適応できます。エンベディングベクトルは入力テキストの意味を捉えるよう設計されており、意味的に類似した 2 つのテキストは、それぞれのエンベディングベクトルの コサイン類似度 が高くなります。注文履歴のセマンティック検索では、エンベディング生成と類似度計算の対象となる入力テキストは、顧客の検索フレーズと購入済み商品の商品テキストです。 ソリューションは 2 つのパートに分かれます。 大規模リクエスト処理に向けたスケーラビリティとレジリエンシーの向上 – セマンティック検索を実装する前に、増加する計算負荷に対応できるインフラストラクチャを確保する必要があり、 セルベースアーキテクチャ を採用しました。すべてのユースケースで必要ではありませんが、リクエスト量やデータ量が非常に大きいシステムでは、セマンティック検索のようなリソース集約型機能の実装前に大きな効果を発揮します。 セマンティック検索の実装 – まず利用可能なエンベディングモデルを評価し、 Amazon Bedrock のオフライン評価機能でさまざまなモデルをテストしました。モデルを選定した後、エンベディングベクトル生成のインフラストラクチャを構築しました。 システムのスケーラビリティとレジリエンシーの向上 スケーラビリティとレジリエンシーの向上には、 セルベースアーキテクチャ の設計パターンを採用しました。セルベースの設計では、システムを同一の小さな自己完結型のチャンク (セル) に分割し、各セルがシステム全体のトラフィックの一部のみを処理します。次の図は、注文履歴検索のセルベース設計の概要を示しています。 各セルは定義された顧客のサブセットを担当します。セル間で顧客リクエストを処理するための通信は不要です。各顧客はセルに割り当てられ、その顧客からのリクエストはすべて該当セルにルーティングされます。各セルの OpenSearch Service ドメインは、担当する顧客のサブセットのデータのみを保持します。セル数 (N) とセル間のデータ分散はビジネスユースケースに依存しますが、データとトラフィックをできるだけ均等に分散させることが目標です。 ルーティングロジックはユースケースに応じてシンプルにも高度にもできます。セル割り当て値はリクエストごとにランタイムで計算するか、一度計算して Amazon DynamoDB などのキャッシュや永続データストアに書き込み、以降のリクエストで参照する方法があります。注文履歴検索では、ロジックがシンプルで高速だったため、リクエストごとにランタイムで実行しました。永続データストアからセル割り当てを参照する方法は、一部のセルが時間とともに「重く」なるリスクがある場合に特に有効です。その場合、パーティショニングロジックを変更する代わりに、データストア内の特定キーのセル割り当て値を上書きするだけで、重いセルのデータを再分散できます。パーティショニングロジックの変更はすべてのセルのデータ分散に影響する可能性があります。 システムの負荷が増加した場合、セル数を増やして追加トラフィックに対応できます。セル数を増やさなくても、負荷の高いセルから軽いセルにキーを再割り当てすることで、既存の N セル間でデータを再分散し、負荷をより均等に分散させてインフラストラクチャをより効率的に活用できます。 セルベースアーキテクチャはシステムのレジリエンシー向上にも役立ちます。たとえば、1 つのセルが失われた場合、キャパシティの低下は 100% ではなく 1/N にとどまります。さらに、パーティショニングキーを 2 つ以上のセルに割り当てて複数のセルに書き込むことで、キャパシティ低下をさらに抑えられます。この場合、単一セルの喪失がデータ損失につながることはありません。 セマンティック検索の実装 注文履歴検索にセマンティック検索を実装するには、いくつかの重要な判断と技術的ステップが必要でした。まず利用可能なエンベディングモデルを評価し、Amazon Bedrock のオフライン評価機能でさまざまなモデルをビジネスドメインの要件に照らしてテストしました。この評価でユースケースに最適なモデルを特定し、選定後にエンベディングベクトル生成のインフラストラクチャを構築しました。エンベディングモデルをコンテナ化して Amazon Elastic Container Registry (Amazon ECR) に登録し、SageMaker 推論エンドポイントにデプロイして大規模なベクトル計算を処理しました。 検索インフラストラクチャには、セマンティック検索機能の実装に OpenSearch Service を選択しました。OpenSearch Service は、必要なベクトルストレージと、ユーザーに関連性の高い結果を提供する検索アルゴリズムの両方を備えていました。 最大の課題の 1 つは、既存の注文でセマンティック検索をサポートするために過去のデータを更新することでした。 AWS Step Functions でワークフローをオーケストレーションし、 AWS Lambda 関数でレガシーデータのベクトル生成を処理するデータ処理パイプラインを構築し、対象のすべてのレコードでセマンティック検索を提供できるようにしました。 次の図は、アーキテクチャの概要を示しています。 モデルの評価と選定 注文履歴検索では、Amazon 固有のデータで学習されたエンベディングモデルを使用しています。ドメイン固有の学習は、生成されるエンベディングベクトルがビジネスコンテキストで適切に機能し、質の高い結果を返すために不可欠です。 候補モデルの評価には、Amazon Bedrock 上の Anthropic Claude を使った LLM-as-a-judge 手法を採用しました。Anthropic Claude に、顧客の注文履歴から匿名化された商品テキストと検索フレーズを含むプロンプトを与え、関連性に基づいて商品をフィルタリングおよびランク付けしました。この結果を比較用のグラウンドトゥルースとして使用しました。 モデルの評価には標準的なランキング指標を使用しました。 Normalized Discounted Cumulative Gain (NDCG) – 理想的な順序に対するランキング品質を測定 Mean Reciprocal Rank (MRR) – 最初の関連アイテムの位置を考慮 Precision – 取得結果の精度を評価 Recall – すべての関連アイテムを取得する能力を評価 このプロセスにより最適なモデルを決定しました。 検索戦略: 顧客スコープの包括的検索 注文履歴検索には 2 つの重要な要件があります。 リクエスト元の顧客の注文履歴のみを検索する – ある顧客の注文履歴の商品が別の顧客の検索結果に表示されてはなりません。 その顧客の履歴をすべて検索する – 検索アルゴリズムが何らかの理由で評価しなかったために、顧客の検索フレーズに関連する商品が表示されないことがあってはなりません。 このアプローチでは、OpenSearch Service を使って検索クエリを発行した顧客のすべての商品を取得し、検索フレーズに対する各商品の関連性スコアを計算し、スコア順にソートして上位 K 件の結果を返します。各顧客に対して包括的な結果カバレッジを提供します。 OpenSearch Service によるベクトルストレージ 効率的なベクトルストレージと検索のために、OpenSearch Service の 2 つの機能を使用しました。 knn_vector データ型 – エンベディングベクトルを格納するための組み込みサポート。既存のドメインでもインデックスの再作成なしにこのフィールド型を追加でき、すべてのレコードに対する正確な kNN 検索が可能です。ほとんどの顧客のレコード数は正確な kNN でスケールできる範囲だったため、近似 kNN は不要でした。 スクリプトスコアリング – Painless スクリプトがサーバーサイドでベクトル類似度を計算し、クライアントの複雑さを軽減しつつ低レイテンシーを維持します。 ハイブリッド検索 ハイブリッド検索とは、レキシカル検索とセマンティック検索の結果を組み合わせ、それぞれの強みを活かすことです。OpenSearch Service のハイブリッドクエリ機能により、クライアントは単一のリクエストで両方のクエリタイプを指定でき、ハイブリッド検索の実装が簡素化されます。OpenSearch Service は両方のクエリを並列実行し、結果をマージし、サブクエリの関連性スコアを正規化し、指定されたソート順 (デフォルトは関連性スコア) で結果をソートしてからクライアントに返します。 両方の検索タイプの利点を活用できます。たとえば、顧客が orderId で検索する場合のように、検索フレーズに意味的な意味があまりないシナリオがあります。セマンティック検索はこのようなケースには適しておらず、キーワードマッチングが最適です。 ハイブリッド検索機能により、注文履歴検索の実装工数と潜在的なレイテンシー増加を抑えられました。 過去のデータの更新 インフラストラクチャのセットアップ後、新しく取り込まれるレコードは関連するエンベディングベクトルとともに永続化され、セマンティック検索をサポートします。しかし、顧客が検索する際は通常、以前に購入した商品を検索します。そのため、古いレコードにエンベディングがなければ、顧客体験の改善にはつながりません。バックフィルの方法はデータ規模に依存します。 潜在的な顧客影響を最小化するリリース 最後のステップは、問題発生時の影響を最小限に抑えながらクライアントに変更をリリースすることでした。具体的には以下の方法を採用しました。 セマンティック検索フローで一時的な問題が発生した場合、リクエスト全体を失敗させるのではなく、レキシカルのみの検索にフォールバックするよう実装する。セマンティック検索が実行されなくても、空の結果ではなくレキシカル検索の結果をクライアントに返せるようにする。 デフォルトの動作をレキシカルのみの検索とし、セマンティック検索機能が必要なクライアントはリクエストに追加フラグを渡す必要があるようにゲーティングする。これにより、該当リクエストのみでセマンティックまたはハイブリッドフローが実行される。 初期期間中は新しいフローをフィーチャーフラグの背後に配置し、重大な問題が検出された場合に完全にオフにできるようにする。 顧客体験の改善例 Rufus が注文履歴を照会して顧客の質問に答えた例を紹介します。 次のスクリーンショットは、「sustainable utensils」のクエリで木製スプーンが検出される例と、タイトルの説明に「charger」というキーワードがないウォールコネクターを含むさまざまな種類の充電器が検出される例を示しています。 次のスクリーンショットは、タイトルの説明にクエリキーワードが含まれていなくても、セマンティック検索が関連する結果を検出する例を示しています。 セマンティック検索機能の導入により、Rufus が関連商品を取得して顧客に表示できるようになりました。導入前は、こうしたクエリに対して結果を返せませんでした。 ビジネスへの影響 主なビジネス成果は以下のとおりです。 顧客体験の改善 – クエリの再現率が 10% 向上し、関連する結果を返す検索の割合が増加しました。また、過去の注文の検索に関するカスタマーサービスへの問い合わせも減少しました。 パートナー連携の成功 – Alexa と Rufus の自然言語処理能力が強化され、注文履歴クエリの解釈精度が向上しました。パートナーチームによるリランキングや後処理の必要性も軽減されました。クエリ成功率は 20% 向上し、より多くの顧客検索が少なくとも 1 つの関連商品を返すようになりました。また、結果カバレッジが 48% 向上し、レキシカル検索では見逃されていた関連する一致をセマンティック検索が一貫して検出するようになりました。 まとめ 本記事では、Amazon の注文履歴検索をセマンティック検索機能に対応させた方法を紹介しました。既存インフラストラクチャの制約の中で最先端の AI 技術を活用し、機能アップグレード中もサービスの中断を回避して SLA を維持するソリューションを開発しました。実装にはバックフィルも含まれ、通常の取り込み速度の数倍のレートで数十億のドキュメントを処理し、過去に購入された商品のエンベディングベクトルを計算しました。慎重なエンジニアリングが求められましたが、極端な負荷下でも OpenSearch Service のレジリエンシーを活用して対応しました。 この基盤を活かして、検索技術を継続的に進化させられます。エンベディングベクトルのフレームワークに改良モデルを組み込めるほか、パーソナライゼーションやマルチモーダル検索など新機能への拡張にも対応できます。 Exact k-NN search の手順に従って、正確な k-NN 検索を今すぐ始められます。OpenSearch クラスターのマネージドソリューションをお探しの場合は、 Amazon OpenSearch Service をご確認ください。 著者について Shwetabh Shwetabh は、Amazon のシニアソフトウェアエンジニアで、分散システムと機械学習に関心があります。仕事以外では、技術的な深掘りや示唆に富むノンフィクションを好む読書家です。 Harshavardhan Miryala Harshavardhan は、Amazon のソフトウェアエンジニアで、機械学習、特に情報検索と分散コンピューティングに関心があります。仕事以外では、ラケットスポーツやサッカー観戦を楽しんでいます。 Ayush Kumar Ayush は、Amazon のテックリーダーで、14 年以上の経験を持つビルダーです。Your Orders Search プロダクトをリードしています。余暇にはクリケット観戦や幼い子どもとの遊びを楽しんでいます。 この記事は Kiro が翻訳を担当し、Solutions Architect の 榎本 貴之 がレビューしました。




























