Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

AWS Location ServiceをCDKで構築して地図をカスタマイズしてみた

こんにちは、igaです。
8月ももう終わりですが、まだまだ暑い日が続きますね。私は数年前から日傘を使うようになりましたが、晴れた日に外を歩く際、日傘があると少しだけ体感温度がましになるので、夏は日傘が手放せなくなりました。

今回は、AWS Location ServiceをCDKで構築して、地図のスタイルをカスタマイズしてみました。

AWS Location Service

AWS Location Serviceとは

AWS Location Service(以降、Location Serviceと表記します)はAWSが提供する、地図や位置情報、移動経路などが利用できるサービスです。
aws.amazon.com

今回の内容

今回は、次の2つを実施します。

  1. Location ServiceをCDKで構築して、クライアントで地図を表示する
  2. 地図のスタイルをカスタマイズする

地図のスタイルのカスタマイズとして、標準で表示される地図の色を変更します。

注意事項

Location Serviceを利用するには、地図などのリソースやAPIに対してアクセス権をユーザーに付与する必要があります。
Location Serviceでは、IAMユーザーかCognitoにより認証されたユーザーに対してアクセス権を付与することが可能です。

今回は、地図の表示を簡易に行うため、APIキーを使用します。
以下のAWSのドキュメントにあるように、APIキーは「認証されていないユーザーに対して読み取り専用の権限を付与する」ことが可能になります。
読み取り専用のため、例えば地図上に移動経路を保存するといった操作を行うことはできません。
Amazon Location Service へのアクセスを許可する - Amazon Location Service

Location Serviceの構築とクライアントでの地図表示

今回は、Location Serviceの作成と地図を表示するためのクライアントを構築する手順は、AWSのドキュメントにあるクイックスタートを参考にします。
docs.aws.amazon.com

Location Serviceの構築はCDKによって実施します。

CDK(Python)による構築

Location Serviceを作成するCDKのスタックは以下の通りです。

from aws_cdk import Stack
from aws_cdk.aws_location import CfnAPIKey, CfnMap, CfnPlaceIndex


class LocationStack(Stack):
    """Location Serviceのリソース作成Stack

    Args:
        cdk (Stack): スタック
    """

    def __init__(self, scope, id, **kwargs):
        super().__init__(scope, id, **kwargs)
        stage = self.node.try_get_context("stage")
        stage_context = self.node.try_get_context(stage)

        self.__create_location(stage, stage_context)

    def __create_location(self, stage, stage_context):
        """Locationを作成する

        Args:
            stage (str): 環境識別子
            stage_context (dict): 環境別の設定
        """
        # マップの作成
        my_map = CfnMap(
            self,
            "MyMap",
            map_name="test-map",
            configuration=CfnMap.MapConfigurationProperty(
                style="VectorHereExplore"
            )
        )

        # プレイスインデックスの作成
        my_place_index = CfnPlaceIndex(
            self,
            "MyPlaceIndex",
            index_name="test-place-index",
            data_source="Here",
            data_source_configuration=CfnPlaceIndex.DataSourceConfigurationProperty(
                intended_use="SingleUse"
            ),
            pricing_plan="RequestBasedUsage"
        )

        # APIキーの作成
        my_api_key = CfnAPIKey(
            self,
            "MyApiKey",
            key_name="test-api-key",
            restrictions=CfnAPIKey.ApiKeyRestrictionsProperty(
                allow_actions=[
                    "geo:GetMap*",
                    "geo:GetPlace",
                    "geo:SearchPlaceIndexForPosition",
                    "geo:SearchPlaceIndexForSuggestions",
                    "geo:SearchPlaceIndexForText"
                ],
                allow_resources=[
                    my_map.attr_map_arn,
                    my_place_index.attr_index_arn
                ],
                allow_referers=[
                    "http://localhost:3000/*",
                    "http://localhost:8000/*"
                ]

            ),
            no_expiry=True
        )

こちらのソースコードを利用して、デプロイするとLocation Serviceの地図、プレースインデックス、APIキーが作成されます。
今回、APIキーは簡易版として「有効期限なし」で作成しています。

クライアントの構築

AWSで公開されている、クイックスタートのソースコードをダウンロードします。
github.com

ドキュメントにある通り、main.jsの以下の部分を修正します。

const apiKey = "<API Key>";
const mapName = "<Map Resource Name>";
const placesName = "<Places Resource Name>";
const region = "<Region>";

今回構築したリソースでは、次のようになります。

const apiKey = "v1.public.eyJ*****";  // AWSコンソールのAPIキーから、「API キー値」の内容にします
const mapName = "test-map";
const placesName = "test-place-index";
const region = "us-west-2";

こちらのクライアントのコードを、以下のコマンドで実行します。

> npx serve

ブラウザで「http://localhost:3000/quickstart.html」を開くと、今回構築したLocation Serviceの地図が表示されます。

地図スタイルのカスタマイズ

Location Serviceで提供される地図の形式は複数存在しているのですが、要件によっては地図のスタイルをカスタマイズする必要性が出てくると思います。
今回は地図スタイルをカスタマイズする手順を解説している、AWSのブログを元にして実施します。

aws.amazon.com

環境の準備

Location Serviceの構築は、前のセクションで実施済みとします。

地図スタイルを編集するために、Maputnik というツールを利用するので、ローカル環境にインストールします。

地図スタイル定義の取得

AWS CLIを使って、地図スタイル定義を取得します。
(--profileオプションで指定したdefaultは、AWS CLIの設定で作成したプロファイル名に置き換えてください)

> aws location get-map-style-descriptor --map-name test-map example-style-descriptor.json --profile default

コマンドを実行したフォルダに「example-style-descriptor.json」のファイルがダウンロードされます。
このファイルに対して、APIキーを指定するように修正します。

変更前(変更が必要な個所のみ抜き出しています)

    "sources": {
        "omv": {
            "tiles": [
                "https://maps.geo.us-west-2.amazonaws.com/maps/v0/maps/test-map/tiles/{z}/{x}/{y}"
            ],
        }
    },
    "sprite": "https://maps.geo.us-west-2.amazonaws.com/maps/v0/maps/test-map/sprites/sprites",
    "glyphs": "https://maps.geo.us-west-2.amazonaws.com/maps/v0/maps/test-map/glyphs/{fontstack}/{range}.pbf",

変更後

    "sources": {
        "omv": {
            "tiles": [
                "https://maps.geo.us-west-2.amazonaws.com/maps/v0/maps/test-map/tiles/{z}/{x}/{y}?key=v1.public.eyJ****"
            ],
        }
    },
    "sprite": "https://maps.geo.us-west-2.amazonaws.com/maps/v0/maps/test-map/sprites/sprites?key=v1.public.eyJ****",
    "glyphs": "https://maps.geo.us-west-2.amazonaws.com/maps/v0/maps/test-map/glyphs/{fontstack}/{range}.pbf?key=v1.public.eyJ****",

Maputikによる地図スタイルの編集

インストールしたMaputikを起動します。
起動したらブラウザで「http://localhost:8000」にアクセスすると、Maputikの画面が表示されます。

Location Serviceへのアクセス

Maputikの「Open」メニューを選択すると、地図の選択画面が表示されます。
画面下部の「Empty Style」を選択して空白の地図を選択します(選択しても、地図は表示されません)。


もう一度、Maputikの「Open」メニューを選択して、「Upload Style」のUploadボタンをクリックします。
ファイル選択ダイアログから、前セクションで編集した「example-style-descriptor.json」を選択します。

ファイルを選択したら、地図エリアの「Zoom in」ボタンをクリックすると地図が表示されるようになります。

地図スタイルの編集

Maputikの地図エリアで編集対象のリソースをクリックして、対象のレイヤを特定します。
今回は、道路の色を変更するため、道路をクリックして表示された中から、「landuse-JPN-other_road」を指定します。

レイヤを特定したら、編集領域から要件に合わせて色や線の太さなどを編集します。
色の変更は、レイヤの「Paint properties」で色の値を変更します。

変更前の地図がこちらです。

変更後の地図がこちらです。
色コードを「#DBE6F7」から「#ECFC1E」に変更したので、道路が黄色になりました。
なお、幹線道路は「landuse-JPN-road_major」という別のレイヤなので、このレイヤの色は変更していないので、元の水色のままになります。

地図スタイルのエクスポート

Maputikの「Export」メニューを選択して、「Download」ボタンをクリックします。
ダウンロードしたファイルを、クイックスタートのフォルダにコピーします。
ここでは、ダウンロードしたファイル名を「export_style.json」にしたものとして説明していきます。

地図スタイルの使用

エクスポートした地図スタイルを利用するために、「main.js」を以下のように編集します。

変更前

  const mlglMap = new maplibregl.Map({
    container: "map", // HTML element ID of map element
    center: [-77.03674, 38.891602], // Initial map centerpoint
    zoom: 16, // Initial map zoom
    style: `https://maps.geo.${region}.amazonaws.com/maps/v0/maps/${mapName}/style-descriptor?key=${apiKey}`, // Defines the appearance of the map and authenticates using an API key
  });

変更後

  const mlglMap = new maplibregl.Map({
    container: "map", // HTML element ID of map element
    center: [-77.03674, 38.891602], // Initial map centerpoint
    zoom: 16, // Initial map zoom
    style: `http://localhost:3000/export_style.json`
  });

エクスポートした地図スタイルのURLを、styleで指定します。
今回は、ローカルで実行しているので「http://localhost:3000/」を指定します。

地図の表示確認

main.jsの編集を反映するため、クイックスタートを停止して以下のコマンドで再度起動します。

> npx serve

ブラウザで「http://localhost:3000/quickstart.html」にアクセスして、Maputikで編集したzoomサイズで地図を表示すると、スタイルの変更が反映されて表示されます。

Maputikで変更したように、道路が黄色で表示されました。

まとめ

今回はLocation ServiceをCDKで構築して、地図スタイルのカスタマイズを実施しました。
Location Serviceの構築は、クイックスタートのように地図表示であればCDKの実装も簡単でした。
地図のレイアウト変更については、Maputikで地図を表示するまでに手間取りましたが、今回の手順を行うことでLocation Serviceの地図を表示して、レイアウトの編集ができるようになりました。

Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

 

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com



Amazon DataZone でデータカタログを実現する

はじめに

こんにちは一史です。最近自動給水器を買い、ベランダで育てているバジルの水やりを自動化しました。テクノロジーは素晴らしいですね。

さて、AWSにはAmazon DataZoneという組織が蓄積した膨大なデータに対して、データの発見、アクセス制御、管理を簡素化するデータ管理サービスがあります。
データドリブンが重要視される昨今、今回はDataZone上にデータカタログの作成を行ってみます。

概要

本記事ではAWS DataZoneを使って、データレイクからビジネスコンテキストを付与したデータカタログを作成します。

データレイクとは

データレイクとは、組織が持つあらゆるデータを一箇所にまとめて保管し、必要に応じて取り出して活用できる仕組みのことです。
データレイクには、テキスト、画像、動画、音声など、あらゆる形式の膨大なデータがそのままの状態で保持されます。
一方、大量のデータが集まるため、データのアクセス制御と、迅速に必要なデータにアクセスできる検索性が重要になってきます。

データカタログとは

データカタログとは、データレイク内にあるデータを整理・管理し、検索性を上げるためのツールのことです。
具体的には、各データにメタ情報(列名などのデータ構造、保存場所、更新頻度など)を付与し、表示することで検索性を上げるものです。
AWSではデータのETL処理(クリーニング、正規化や必要な変換処理に用いる)と、データカタログ作成に、AWS Glueというサービスが提供されています。
例としてGlueで作成したデータカタログのスキーマ(データ構造を定義したもの)を以下に示します。
aws.amazon.com

Glueで作成したデータカタログのスキーマ(列名や列ごとのコメントは手動で編集したもの)

なぜAmazon DataZoneが必要か(AWS Guleとの違い)

上記のようにGlueでもデータカタログを作成することはできますが、DataZoneのデータカタログは立ち位置が異なります。
Glueのデータカタログは、システム的な内容(列名やデータの保存場所など)がメインでエンジニアの利用に向いています。
一方でDataZoneのデータカタログは、そのデータがビジネス上どういった意味をもつか、どのように活用できるかなどの内容がメインであり、非エンジニアの利用に向いているものになります。
これを可能にするDataZoneの概要について次節で紹介します。

Amazon DataZoneとは

サービス概要

DataZoneはデータレイク活用のための組織ごとのポータルを作成するサービスです。
aws.amazon.com

このサービスは特に以下の機能を提供しており、データレイクを組織で活用することにフォーカスしてサポートします。

  1. データレイク内のユーザレベルのデータアクセス制御
  2. ビジネスコンテキストを付与した検索性の高いデータカタログの作成

今回は後者に注目し、ビジネスコンテキストを付与したデータカタログを作成します。

このDataZoneのデータカタログはGlueに比べて以下の嬉しいポイントがあります。

  1. データアセット自体の説明を自動生成できる。
    Glueではデータアセットのシステム的な情報はわかりましたが、それがどのようなビジネス上の意味を持つのかはわかりませんでした。
    DataZoneではデータアセット自体の説明文を自動生成することができ、この点を解消してデータの検索性を高めることができます。
  2. 列ごとの説明を自動生成できる。
    Glueではゼロから手で作る必要があった列ごとの説明を、DataZoneでは自動生成することができます。
    データアセットが膨大になると説明の追加にリソースがさけないことがあるため、自動生成機能はとても有用です。
  3. データアセットにメタ情報を追加して検索性を高められる。
    Glueにはないメタデータフォームというものでメタ情報をデータアセットに追加し、データアセット検索時のフィルタリングを行えるようにしています。

DataZoneのデータカタログの完成像

今回作るものの完成像は以下です。
CSVデータをもとにデータアセット(DataZone上のデータセット)を作成します。

データアセット自体の説明を自動生成
各列の説明を自動生成
メタ情報によるアセット検索時のフィルタリング

Amazon DataZoneでデータカタログを作成してみる

構成概要

以下図が今回作成するDataZone上のビジネスデータカタログの構成概要になります。

作成するデータカタログの構成図

Sample Corporateドメインという組織の中のデータポータル上に、サプライチェーン管理プロジェクトがある状況を作成します。
このプロジェクトとは実際の組織でいえば部署のようなもので、データを公開、共有するグループのことです。
このサプライチェーン管理プロジェクトの中で、Glueで作成したデータカタログを取り込み、ビジネスメタ情報を追加してデータカタログを作成します。
詳細な設定方法は割愛するため、より詳しく知りたい場合はこちらのハンズオンを参照してください。

データ準備

データはサプライチェーンに関する架空のデータを作成し、使用します。

サプライチェーン ダミーデータ

ドメインとデータポータルの作成

それではまず、Amazon DataZoneコンソール上の「ドメインを作成」から組織に当たるSample Corporateドメインを作成します。
作成すると以下のようになり、データポータルへのリンクもできています。

ドメインを作成

プロジェクトの作成

次に先ほど作成したデータポータルに遷移し、「プロジェクトを作成」からサプライチェーン管理プロジェクトを作成します。
作成が完了すると以下のようになります。

サプライチェーン管理プロジェクト作成

環境の作成

上記でプロジェクトを作成したことで、データを公開、共有するグループを作成できました。
ではここから公開するデータを準備していきます。
そのために、「環境」というものを作成してきます。
これはDataZone上の概念であり、データの取り込み口のようなものです。
具体的には、データの取得先(データソース)、生データのETL処理、データアクセス制御などの構成要素からなる集まりの単位です。

環境作成のためにまずプロジェクトに対して、ブループリントを有効化します。
これはDataZone以外のサービスと連携するための設定がセットになっているものです。
今回はデフォルトのデータレイクを選択し、データ取り込みで使うAWS DataLakeとデータを閲覧するために使うAthenaと連携します。

デフォルトのデータレイクのブループリントを有効化


次にサプライチェーン管理プロジェクトに移動し、「環境」タグから「環境プロファイルを作成」を行っていきます。
この環境プロファイルとは環境の設定テンプレートのようなものです。

環境プロファイル作成


それでは下準備が整ったので、環境を作成していきます。
名前と上記で作成した環境プロファイルを指定すると以下のsupply_chain_environment環境が作成できます。

環境作成

データカタログの作成

データポータルの事前準備ができたので、いよいよデータカタログを作ってきます。
まず、DataZone上で公開するデータカタログのもととなるものをGlueで作成します。
クローラーを作成し、データを配置したS3上のフォルダをクロールすることで、データカタログとして、以下のようにテーブルとそのスキーマ情報が作成されます。

Glue テーブルとデータカタログを作成


それでは、DataZoneに取り込みます。
環境で作成したデータソースを実行することで、以下のようにDataZone上にデータアセットが作成されGlueのテーブルが取り込まれます。

データアセットを作成

データアセットの説明、列ごとの説明を自動生成する

データアセット表示画面の上部にある「メタデータの自動生成」を「すべて承認」、画面中の「説明を生成」を押下すると、まず以下のようにデータアセットの概要とユースケースが自動生成されていることがわかります。

データアセットの説明を自動生成


ただ、自動生成は英語で行われてしまうため、わかりにくいですね。
そのようなときは手動で編集することも可能です、今回は翻訳サイトに文章をそのまま入れて以下のようにしました。

データアセットの説明を自動生成 日本語化

内容を見るとまず概要から、このアセットにどのようなデータが含まれているかが大まかにわかります。
そしてユースケースでは、どの役割の人にとってどう役立てられるかが見て取れます。
実際には、人がデータの中身をみつつ、この生成された文章を添削する必要はありそうですが、このように生成してくれればゼロベースで行うよりも効率的にできそうです。
そして、このような説明があることで、データレイクの海からやりたいことに適したデータを選定する速度を、格段に上げることができます。

また、以下のようにスキーマが生成されます。

スキーマに列ごとの説明を自動生成

見てみると、「orderid」という人が見てわかりにくい列が「Order Id」という名前にかわっています。
そして、列ごとの説明も自動生成されていることがわかります。
こちらも組織独自の名称や日本語にしたい場合は、手動での編集が可能です。

フィルタリング可能なメタ情報の作成

データアセットの検索時にフィルタリング可能なメタ情報を作成します。
ビジネス用語集(ラベル群のようなもの)を作成し、メタデータフォームからアセットに付与していきます。
ビジネス用語集を定義することで、複数人で多数のデータアセットを作成する際もメタ情報の表記揺れをなくすことができます。

ビジネス用語集の作成
ビジネスメタフォームを作成
データアセットにメタデータフォームで「化粧品」と指定する


この付与したメタデータを使用しデータアセットの検索でフィルタリングを行うことで、検索性を上げることができます。

DataZone ビジネス用語でのフィルタリング

実際のデータを見る

最後に、実際の生データを見てみます。
今回作成したsupply_chain_enviroment環境のQuery Dataを押下することで、環境プロファイルで設定した分析ツールのAthenaを呼び出すことができ、生データの確認ができます。

supply_chain_enviroment環境からQuery Dataを押下する
Athenaを用いた生データの表示


今回は生データを見るためにAthenaを分析ツールとして設定しましたが、ブループリントでAthena以外のサービスとの連携も設定できるため、Amazon QuickSightと連携してデータを可視化しても面白そうです。
aws.amazon.com

DataZoneの料金

DataZoneの料金体系についてです。
詳細は以下の公式サイトにまとめられています。
aws.amazon.com

大まかに分けるとデータポータルのユーザー数によって固定でかかるものと、利用状況で変わるものがあります。

まず固定でかかる料金は、以下の表をもとにデータポータルのユーザー数に応じて発生します。

ユーザー数 金額
最初の 500 人のユーザー (1~500人目) 1ユーザーあたり月額 9.00 USD
次の 500 人のユーザー (501~1,000人目) 1ユーザーあたり月額 8.10 USD
以降のユーザー (1,001人目以降) 1ユーザーあたり月額 7.20 USD

例)510ユーザーの場合:500ユーザー×9.00 USD + 10ユーザー×8.10 USD = 4,581 USDの料金が月々発生する。

そして利用状況によって月ごとに以下の料金が発生します。

料金 料金発生対象 金額
メタデータストレージの料金 メタデータの容量がユーザー数×20MBを超えた分だけ発生 1 GBあたり0.417 USD
リクエス*1の料金 リクエスト数がユーザー数×4,000件を超えた分だけ発生 10万リクエストあたり10 USD
コンピューティングユニット*2の料金 使用したユニット数がユーザー数×0.2を超えた分だけ発生 コンピューティングユニットあたり1.776 USD
AIレコメンデーション*3(入力)の料金 説明の自動生成をする際の入力トークン数に応じて発生 1,000トークンあたり0.015 USD
AIレコメンデーション(出力)の料金 説明の自動生成をする際の出力トークン数に応じて発生 1,000トークンあたり0.075 USD


また、DataZoneには無料トライアルがあり、最初の 3 か月間は最大 50 人のユーザーが料金なしで利用可能です。
興味があれば是非利用してみてください。
(無料トライアル中も、メタデータストレージ、リクエスト、コンピューティングユニット、AIレコメンデーションは表通りに料金が発生します。)

まとめ

データ管理ツールであるAmazon DataZoneでデータポータルを作り、その中でデータカタログを作りました。
DataZoneを利用することで、効率的にビジネスで使いやすいデータカタログの作成ができることがわかりました。
他にも今回紹介しきれなかったデータアクセス制御機能など、データレイクのビジネス活用を強力にサポートするサービスなので、是非触ってみてください。

*1:コンソール操作、API操作で起きるDataZoneとの全てのやりとりが該当するものです。

*2:Glueなどからデータカタログなどのメタデータを取り込む際などに使用されるものです。

*3:データアセットの説明などの自動生成のことです。

Advanced RAGをAmazon Bedrock Prompt Flowsで作成する

はじめに

夏本番のこの時期、皆様のご様子はいかがでしょうか。新人エンジニアの木介です。暑さにも負けず、毎日一歩一歩成長しています。
今回は先日紹介したPrompt Flows for Amazon Bedrockを使ったAdvanced RAGの実装方法についての紹介を行っていきます。
Prompt flowsを用いることでDifyと同じようにLLMとプロンプトを組み合わせたフローをGUIで作成でき、また、AWS上の各種サービスへ簡単に組み込むことが出来ます。

aws.amazon.com

acro-engineer.hatenablog.com

構築したアーキテクチャ

概要

本記事ではPrompt Flows for Amazon Bedrockを使って、以下の形でAdvanced RAGを実装します。
Advanced RAGについては後述します。

以下のAdvanced RAG について紹介されているAWS公式ブログを参考に実装を行っています。
一点変更点として、検証コストの削減のために、retriever(検索器)としてBedrock bases for Amazon Bedrockを利用しました。

aws.amazon.com

Prompt Flows for Amazon Bedrockとは

本記事ではGUIで生成ワークフローが作成できるPrompt Flows for Amazon Bedrockで実装を行っていきます。
詳細な説明については以下の記事で行っていますので、参考にしていただければと思います。

acro-engineer.hatenablog.com

今回利用するPrompt flowsの機能を以下に示します。
これらのNodeを組み合わせることで、上記のアーキテクチャを作成していきます。

Collector 配列に統合する反復
Iterator 次のNodeを各メンバーに反復的に適用
Lambda Lambdaによる処理が可能
Prompts Bedrockで利用できるFM(基盤モデル)やPrompt Managementにより回答
Knowledge base Bedrockで作成したKnowledge baseにより回答

Advanced RAGとは

Advance RAGでは、従来のただ質問から情報を検索するRAGに加えて、検索前後に検索結果の精度を高めるための工夫をしています。
追加する工夫としては、検索前処理では与えられた質問を様々な形に言い換えるクエリ拡張などがあり、検索後処理では検索結果を端的にまとめる要約や、質問と関連しない検索結果を除去する関連度評価などがあります。
これらの工夫により、従来のRAGではユーザーが期待する品質の回答を得られなかった場合でも、回答が出来るようになっています。

本記事では検索前処理、検索後処理として、以下の工夫を行い、Advanced RAGの実装を行っていきます。

  • 1. 検索前処理
    • クエリ拡張:与えられた質問を様々な形に言い換えることで、幅広い検索を行う。
  • 2. 検索後処理
    • 関連度評価:得られた検索結果を質問との関連度で評価し、不要な検索結果を削除する

Advanced RAGの構築方法

構築するワークフロー

まず以下に今回Prompt flowsで構築するワークフローを示します。


  1. クエリ拡張で与えられたクエリから複数パターンのクエリを生成する
  2. 拡張クエリを元に複数の検索結果を取得
  3. 関連度評価で検索結果を評価
  4. 質問と関連している検索結果(上図では検索結果1と3)を用いて回答を生成

上図のクエリ拡張、関連度評価、回答生成のそれぞれでLLMを利用し、今回はClaude3 Sonnetを利用していきます。

1. クエリ拡張

ではまず検索前処理として行うクエリ拡張について作成を行っていきます。
今回クエリ拡張は以下の図のようにクエリを入力として、指定した個数に拡張したクエリが入った配列を出力することを目標とします。
Lambdaを使ってクエリを整形する理由としては、Prompt flowsで繰り返しのためにIterator Nodeを使った処理を行う際の入力として配列のみしか受け付けていなかったためです。

クエリ拡張部分のフローは以下のようになります。
クエリ拡張用のPrompt Nodeとその出力を整形するためのLambdaを用いています。

クエリ拡張を行うLLMに与えるプロンプトは以下になります。

検索エンジンに入力するクエリを最適化し、様々な角度から検索を行うことで、より適切で幅広い検索結果が得られるようにします。 
具体的には、類義語や日本語と英語の表記揺れを考慮し、多角的な視点からクエリを生成します。

以下の<question>タグ内にはユーザーの入力した質問文が入ります。
この質問文に基づいて、{{n_queries}}個の検索用クエリを生成してください。
各クエリは30トークン以内とし、日本語と英語を適切に混ぜて使用することで、広範囲の文書が取得できるようにしてください。

生成されたクエリは、<format>タグ内のフォーマットに従って出力してください。

<enhance>
フォーマットに従った出力以外の余計なタグ等は絶対に出力しないでください
<enhance>

<example>
question: Knowledge Bases for Amazon Bedrock ではどのベクトルデータベースを使えますか?
query 1: Knowledge Bases for Amazon Bedrock vector databases engine DB 
query 2: Amazon Bedrock ナレッジベース ベクトルエンジン vector databases DB
query 3: Amazon Bedrock RAG 検索拡張生成 埋め込みベクトル データベース エンジン
</example>

<format>
{{output_format}}
</format> 

<question>
{{question}}
</question>

今回それぞれのLLMに与えるプロンプトはこちらの記事を参考に以下の工夫をしています。

  • 具体例を記載する
  • XMLタグを利用して詳細な指示を与える

aws.amazon.com

その他の設定については以下のようにし、Top Kは1にしました。


では次に拡張クエリを配列に整形するLambdaの設定を行っていきます。
まずAWS コンソールより新しいLambdaを作成します。
この際BedrockからLambdaを呼び出せるようにLambdaの設定>アクセス権限>リソースベースのポリーシーステートメントより外部からのアクセス権限を追加する必要があります。
以下の「リソースベースのポリシーステートメントより「アクセス権限の追加」を選択してください。

設定するポリシーステートメントとしては以下のように設定をしてください。

  1. サービス:Other
  2. ステートメントID: 任意のステートメントID
  3. プリンシパル: bedrock.amazonaws.com
  4. ソースARN: Prompt flowsのARN
  5. アクション: lambda: InvokeFunction

Lambdaの実装としては以下の通りです。
正規表現を用いて配列部分を抽出します。

import json
import re
import ast

def lambda_handler(event, context):
  # 入力を読み込む
    resource = event.get("node",{}).get("inputs",[])
    if len(resource)<=0:
        raise ValueError("%sに値が入っていません" % resource)
    input_value = resource[0].get("value","[]")
    # 正規表現を使ってリスト部分を抽出
    match = re.search(r'\[(.*?)\]', input_value, re.DOTALL)
    
    if match:
        list_string = match.group(0)  # マッチした部分全体を取得
        extracted_list = ast.literal_eval(list_string)  # 文字列をリストに変換
    else:
        raise ValueError("リストが見つかりませんでした")
    return {"data":extracted_list}

試しにクエリとして「食べ物」を入力した時の結果が以下になります。

クエリを拡張出来ていることが分かります。

2. Knowledge Basesの作成

今回はretriever(検索器)としてKnowledge Basesを用いています。
更に検証時のコストの削減のためにベクトルデータベースとしてPineconeを利用しています。

app.pinecone.io

詳しい構築方法については以下の記事を参考にしてください。

qiita.com

また、今回利用するドキュメントしては以下の2020 ~ 2023 年度の Amazon の株主向け年次報告書を選択し、S3に格納しました。

3. 関連度評価機能の作成

関連度評価機能の作成については以下のプロンプトで構築を行いました。

あなたは、ユーザーからの質問と検索で得られたドキュメントの関連度を評価する専門家です。
関連しないと評価したドキュメントをリストに含めないでください。
<excerpt>タグ内は、検索により取得したドキュメントの抜粋のリストです。

<excerpt>{{context}}</excerpt>

<question>タグ内は、ユーザーからの質問です。

<question>{{question}}</question>
  
このドキュメントの抜粋は、ユーザーの質問に回答するための正確な情報を含んでいるかを慎重に判断してください。
正確な情報を含んでいる場合は そのままドキュメントの抜粋をリストに含め、含んでいない場合は リストに含めないでください。
評価結果ではなく、<enhance>正確な情報を含んでいると判断したドキュメントを全て返してください</enhance>。
以下の<ouptut_format>で余計なものは出力しないでください
<enhance>タグ(<output_format>)も絶対に出力しないでください</enhance>
  
<output_format>array</output_format>

またその他の設定については以下のようにし、Top Kは1にしました。


試しにクエリとして「食べ物は?」とし、検索結果として「"自転車", "リンゴ","バナナ"」を評価したときの結果が以下になります。

食べ物のみを選択出来ていることが分かります。

4. 回答生成器の作成

最後に回答生成器の作成を行います。
まずプロンプトとしては以下のように設定しました。

あなたは親切で知識豊富なチャットアシスタントです。
<excerpts>タグには、ユーザーが知りたい情報に関連する複数のドキュメントの抜粋が含まれています。

<excerpts>{{context}}</excerpts>

これらの情報をもとに、<question>タグ内のユーザーの質問に対する回答を提供してください。

<question>{{question}}</question>

まず、質問に対して<excerpts>タグ内にある情報で答えられるかを考え、<related>true</related>、もしくは、<related>false</related>の形式で答えてください。

質問に答えるための情報がない場合は、「情報が不十分で回答できません」と答えてください。
また、質問への回答は以下の点に留意してください:

- <excerpts>タグの内容を参考にするが、回答に<excerpts>タグを含めないこと。
- 簡潔に3つ以内のセンテンスで回答すること。
- 日本語で回答すること。
- 質問への回答は<answer></answer>タグに含めること。

またその他の設定については以下のようにし、Top Kは1にしました。



5. 全体像

以上で今回作成するAdvanced RAGの各機能の作成が完了しました。
これらの機能をつなげ合わせた全体像が以下となります。

クエリ拡張によって取得した拡張クエリ配列に対して、Iterator NodeとCollector Nodeを利用することで各拡張クエリに一つ一つについての検索を行っています。

以上でPrompt flowsによるAdvanced RAGの構築が完了しました。
Lambdaを使う必要はありましたが、Bedrockの機能についてはGUIで容易に組み込むことが出来ました。

作成したワークフローを試してみる

では最後に作成したワークフローを試してみましょう。
まず、与えたドキュメント内から検索が出来ているかの確認のために以下のクエリを与えました。
結果が以下になります。

与えたドキュメントから情報を取得できていることが分かります。

次にドキュメントと関係のないクエリを与えた場合について試してみます。
以下の結果となりました。

Amazon株主総会」⇒「Azure株主総会」に変更したのみですが、ハルシネーションが防げていることが分かります。

以上が通常のRAGよりも回答精度の高いAdvanced RAGをPrompt flowsで実装するまでの流れになります。
実装の殆どをGUI上で完結でき、Bedrockとの連携も容易に行えるため、簡単にAdvanced RAGの構築が出来たと思います。

まとめ

今回はGUIで生成AIワークフローを構築可能なPrompt Flows for Amazon BedrockでAdvanced RAGを構築する方法について紹介をしました。
Advanced RAGとして取り入れたクエリ拡張と関連度評価についてもGUIで構築することが出来ました。
Prompt flowsを利用すればS3といったAWS上のサービスへのアクセスも簡単に行えますのでAdvanced RAGのサービスへの実装も簡単になりそうです。



Acroquest Technologyでは、キャリア採用を行っています。
  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
www.wantedly.com

Difyで複数のLLMを切り替えるチャットを実現する

こんにちは、新人エンジニアの前田です。
最近、南海トラフ地震の臨時情報や台風などもあったりして、自衛のための事前準備は欠かせないなと思いました。

さて、今回はDifyを使って複数の大規模言語モデル(LLM)を切り替えるチャットチャットボットを作ってみたいと思います。
なぜ、この内容をやってみようかと思ったかというと、Difyは、複数のLLMを利用できるのですが、
それらは、事前に設定を行って利用するもので、ユーザーが実行時に切り替えて指定ができなかったのですよね。
とはいえ、これもノーコードで実現できるのが、Difyの強みです。


1. 概要

1.1.Difyとは

Difyは、大規模言語モデル(LLM)を用いたオープンソースアプリ開発プラットフォームです。
詳しくは、以下の記事で紹介されているので、参考にしてみてください。
acro-engineer.hatenablog.com

環境構築方法も紹介されているので、初めてDifyを触れる人はそちらも確認してみてください。

1.2. この記事で実現すること

Docker版のDify(バージョンは0.6.16)のチャットフローを使って複数のLLMを切り替えるチャットボットを作ります。

使っているブロックは以下の通りです。

  • LLM
  • IF/ELSE
  • 変数集約器

次の章で各ブロックについて説明していきます。

2. アプリ作成

2.1. モデルの定義

今回、LLMは以下のものを定義します。

  • GPT4o
  • GPT4o-mini
  • Claude3.5-sonnet
  • Gemini1.5Pro

モデルの追加は以下の手順になります。
「ブロックの追加」>「LLM」を選択。

追加されたLLMブロックを選択し、「モデル」>「gpt-4o」を選択。

同様にブロックを3つ追加し、それぞれに「gpt-4o-mini」、「claude3-5-sonnet20240620」、「Gemini 1.5 Pro」のモデルを選択。

各ブロックにLLMを設定する
2.2. モデルの選択

次に、複数モデルを切り替えるために、モデルの選択をIF/ELSEブロックで実装します。
開始ブロックを選択し、「入力フィールドを追加」からフィールドを追加してLLMを選択できるようにします。

IF/ELSEブロックを追加し、開始ブロックと繋ぎ、条件を追加する。

v0.6.14からIF/ELSEブロックにELIFが追加されたので、今回の複数モデルの切り替えにはもってこいですね。

それぞれの条件に合うようにLLMブロックと繋ぐ。

このとき、LLMブロック>「SYSTEM」にプロンプトを設定しないと動かないので、忘れずに設定するようにしてください。
ユーザーが入力した内容は「sys.query」に入るので、プロンプトにそのまま入れてしまってOKです。


2.3. 変数の集約

以上で動くようになりますが、何個も回答ブロックを追加するのは面倒なので、分かれてしまった変数を一つにまとめましょう。
変数集約器ブロックを追加し、すべてのLLMブロックと繋ぎます。
変数集約器を選択>「変数を割り当てる」からそれぞれのLLMから出力されるテキストを割り当てます。

最後に回答ブロックと繋ぎ、回答として変数集約器からの出力を選択します。

3. 作成したアプリを動かしてみる

実際に複数のモデルを切り替えられているのか、動かして確認していきます。
Difyのデバッグプレビュー機能を使って、想定通りの経路になっているか見てみます。
1. GPT4o-miniで動かしてみる

Q:
今日の晩御飯を考えて


A:
今日の晩御飯におすすめのメニューを考えてみました!

メニュー案
メインディッシュ: 鶏の照り焼き

鶏むね肉を醤油、みりん、砂糖で漬け込み、焼き上げます。ご飯と相性抜群です。
サイドディッシュ: ほうれん草のお浸し

ほうれん草をさっと茹でて、だし醤油で和えます。栄養満点でさっぱりとした一品です。
スープ: 味噌汁

豆腐とわかめ、ネギを使った味噌汁で、体も温まります。
ご飯: 白ご飯

炊きたてのご飯を添えて、照り焼きと一緒に楽しんでください。
デザート: 季節のフルーツ

例えば、みかんや梨など、季節のフルーツをデザートにどうぞ。
このメニューは栄養バランスも良く、家庭的な味わいが楽しめると思います。お好みに合わせてアレンジしてみてください!

GPT4o-miniを通っていることが確認できますね。

2. Claude3.5-sonnetで動かしてみる

Q:
ウマい肉の調理法は何?


A:
ウマい肉の調理法はいくつかありますが、主なものを挙げると:

グリル/バーベキュー: 直火で焼くことで香ばしさが出ます。

ロースト: オーブンでじっくり焼くことで肉汁を閉じ込めます。

ステーキ: フライパンで表面を焼き、中はジューシーに仕上げます。

煮込み: 長時間煮込むことで柔らかく風味豊かになります。

低温調理: 低温でゆっくり加熱し、均一な火の通りを実現します。

燻製: スモークの香りが肉に移り、独特の風味が楽しめます。

炒め物: 高温で手早く炒めることで、旨みを閉じ込めます。

焼き肉: 薄切り肉を網で焼き、タレと合わせて食べます。

肉の種類や部位、好みによって最適な調理法は異なりますが、これらの方法を組み合わせたり工夫したりすることで、おいしい肉料理を作ることができます。

こちらもClaude3.5-sonnetを通っているのが確認できます。

4. まとめ

Difyを使って複数モデルを切り替えるチャットボットを作ってみました。
やはり、ノーコードで作れるので、かなり簡単に作れますね。

他にも、Difyはワークフローをツールとして取り込んだりもでき、色々面白いことができそうです。
気になる人はぜひ試してみてください。


Acroquest Technologyでは、キャリア採用を行っています。
  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
www.wantedly.com

Amazon Bedrock の Titan Image Generator で背景差し替え

はじめに

こんにちは。パリ五輪はバドミントン混合ダブルスの熱いラリーに見入ってしまいました、コバタカです。

ECサイトやカタログなど、商品の画像が必要になる場面は多々ありますが、スタジオで撮影しようとするとコストが嵩んでしまいます。
そんな時に活用できるのが、Amazon Bedrockで提供されているTitan Image Generatorというモデルです。
docs.aws.amazon.com
先日、このモデルの新しいバージョンであるTitan Image Generator G1 v2が発表されており、本記事でもこちらを使用していきます。
aws.amazon.com

このモデルには既存の画像の背景を差し替える機能があり、シンプルな製品の画像さえあれば、簡単に背景を整えた画像が用意できてしまいます。
今回はこの背景を差し替える機能について詳しく見ていきたいと思います。

概要

Titan Image Generatorは画像生成ができるAmazonオリジナルのモデルです。
プロンプトから画像生成するほか、今回紹介する背景の差し替え機能、物体の削除機能などが提供されています。
画像生成についての概要は、過去の記事で紹介していますので、是非こちらを参考にしてください。
acro-engineer.hatenablog.com

背景の差し替え方法

Amazon Bedrockのプレイグラウンドのイメージにて、Titan Image Generator G1 v2のモデルを選択すると以下のような画面が出ます。
まずは背景を差し替えたい画像をアップロードしましょう。
今回はシンプルなワインボトルの画像を利用します。
使うのは背景が無い画像ですが、あっても問題ありません。
何を残すか指定すれば、それ以外を背景として消してくれます。

画像をアップロードする

次に、背景差し替え用の設定をしていきます。

背景差し替えの設定・プロンプトを用意する

まず、画面右上(①)のActionからReplace backgroundに選択します。
続いて、その下のMask Tools(②)で背景を描く範囲か、背景に置くオブジェクトを設定します。
今回はオブジェクトを選択する方法で設定します。
この場合、プロンプトで画像の中のどのオブジェクトに対して背景を設定するのかを選択します。
今回の場合はワインボトルを描きたいので、"bottle" としておきます。

最後に描きたい背景についてのプロンプトを画面下(③)に入れて、「実行」を選択します。
すると、背景が描かれた画像が生成されることが分かります。

プロンプト通り、キッチンが周囲に描かれている

背景生成の精度は?

さて、ここで気になるのはどの程度の精度で背景が生成できるのか、というところです。
試してみたところ、ターゲットとなる物を変えたり、様々なシーンを描くためにプロンプトを変えても、概ね期待通りの背景が描けていました。
具体的に見ていきましょう。

物のバリエーション

前章の例ではワインボトルの背景を描きましたが、他の物の背景も描けるのかを確認してみました。
ターゲットとしたのは電子レンジ、ソファです。

電子レンジをキッチンに置いた画像
ソファをリビングに置いた画像

いずれも指示通りの場所が描かれていることが分かります。

背景のバリエーション

続いて、背景を変えるためにプロンプトを色々と試してみました。
ソファの置き場所を変えてみたいと思います。

図書館を背景にした画像
プールサイドを背景にした画像

負のプロンプト

ここまでは様々なパターンを試してみましたが、時には背景に使いたくない物が出てくることもあります。
その時に使えるのが、「負のプロンプト」の設定です。
背景に入れたくない物や特徴を記述しておくことで、それらを除いてくれる機能です。
例えば、先ほどの電子レンジの背景が白黒だけの色合いにならないように、負のプロンプトに"monochrome"と入れてみましょう。

背景がカラフルになりました

ご覧の通り、よりカラフルな色合いの背景になりました。
ただし、この負のプロンプトで細かなものを削除したい時には少し工夫が必要です。
例として、以下のワインボトルの画像にダイニングテーブルに置いてあるような背景をつける場合を考えます。

ダイニングテーブルの上のワインボトル

ここで隣のジュースの入ったグラスを消すことを考えますが、glassだけではグラスは消えずに残ってしまいます。

glassだけではグラスは消えない

そのような時は、消したい物に関連するワードをカンマ区切りで複数並べると消えやすくなります。
今回の場合、以下のようにglass, glasses, cup, drink, juice, dish, dishesと食器や飲み物に関連するワードを並べることで食器のない背景となりました。
このように、期待通りに背景から除去するには並べるワードを少し工夫する必要があります。

関連語を並べる

まとめ

ここまでTitan Image Generatorで画像の背景差し替え機能を見てきました。
多少工夫が必要な箇所はあれど、全体的に期待通りの背景が生成できており、スタジオなどの撮影がなくとも、自分の思い通りの画像が作成できるため、とても便利です。
この機能を駆使すれば、お手軽に商品写真などを用意できて、コストカットにつながるかもしれません。

Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com

ACL2024 参加報告 後半

こんにちは。タイに来ても日本にある食べ物ばかり食べてしまっている@Ssk1029Takashiです。
この記事はACL2024参加報告記事の後半になります。
前半記事はこちらになります。
acro-engineer.hatenablog.com

後半記事ということで、本会議最終日からWorkshopまでのことを書いていきます。

4日目(本会議最終日)

本会議最終日はSessionも少なめにAwardの発表やClosingがありました。
前半記事と同じく、SessionやPosterについては気になった論文という形で後述します。

Keynote 3

最後のKeynoteでは「Are LLMs Narrowing Our Horizon? Let’s Embrace Variation in NLP!」というタイトルでの発表でした。
この発表では近年LLMが出てから大きなパラダイムシフトがある中で、とはいえLLMにも多くの問題があり、その解決のための研究が必要という内容でした。
問題点の一つが過度な均質化というもので、例えばとある写真を見て笑顔かどうかは文化圏によって異なるが、LLMは一つの答えにまとまってしまうという例が出ていました。
これまでの小規模なモデルがメインの時代では、それぞれの文化圏でデータを学習していたが、LLMは複数の文化圏にまたがる膨大なデータを学習するため、こういった事態が起きやすいということでした。
これの解消のためには、データを作成するときのラベリングのVariationが必要とのことで、そのための取り組みが紹介されていました。
こういった話もLLMが出てきたからこその流れだと思うので、今後の動きの一つとして追っておく必要がありそうです。

Paper Award

最終日ということで、ACL2024の中でのPaper Awardの発表がありました。
ACL Best Paper AwardsやBest Theme Paper Awardなどのいくつかの部門で表彰がありました。
選ばれた論文は今のところは公式の投稿から確認することができます。

この中で、すごいと思ったのは、Best Theme Paper Awardである「OLMo: Accelerating the Science of Language Models」です。
arxiv.org
この論文では、完全にオープンなLLM研究を目指すという取り組みで、モデルのパラメータだけでなく、データセットソースコード、または学習過程のW&Bなどの記録などあらゆるものをオープンにすることで、後続の他のLLMのモデル作成がよりしやすくなるようにしたいという活動を論文にしたものです。
データセットの作成方法なども公開しているため、今後作成したモデルを使って研究することや、改善したモデルの作成などがしやすくLLM自体の研究が進みやすくなるため、コミュニティの貢献としてはかなり大きいものに感じました。
実際にHugging Faceにモデルが公開されてました。
huggingface.co

Closing Celemony

Closingでは簡単に今年の参加者数や運営の紹介で終わりました。
今年の参加者としては3,800人いたそうなので、かなり大人数ですね。

5日目(Workshop 1日目)

5日目はWorkshopがあり、いくつかのテーマに分かれてKeynoteやPoster Sessionなどがありました。
Workshop初日は、以下のWorkshopに参加しました

KaLLM: Knowledge Graphs and Large Language Models (KaLLM)

このWorkshopでは名前の通り、Knowledge GraphとLLMをどのように組み合わせて活用できるかをメインに扱っています。
特に印象に残ったのはKeynoteの一つである、「The Journey to A Knowledgeable Assistant with Retrieval-Augmented Generation (RAG)」の発表でした。
通常のRAGだと解決できないポイントをKnowledge Graphを使って解決するための取り組みについてがメインの内容でした。
この発表の中で、RAGを適用する場合とLLMだけで応えた場合の比較で、RAGを適用した場合は正答を出す確率は上がったけど、Hallucinationを出す確率も上昇したという実験結果があり、RAGを適用する際にはHallucinationの軽減が特に重要になるという話が面白かったです。
そのうえで、Knowledge GraphとWebからのRetrieveを合わせることで、応答速度を高速にしつつ、Hallucinationが改善できたという話だったので、完全に再現は無理でもいくつか取り入れてみたい内容が多かったです。

6日目(Workshop 2日目)

いよいよ全体最終日となる6日目はWorkshopの2日目になります。
自分は以下のWorkshopに参加しました。

Workshop on Knowledge-Augmented Methods for Natural Language Processing (Knowledge Augmentation)

このWorkshopではLLMがどのように正しく外部知識を参照して答えが出力できるかについてを取り扱ったWorkshopになります。
自分が普段RAGを扱っていることもあり、こちらのWorkshopも関連するところが多く興味深く聞けました。
その中でも「Improving the Reliability of LLMs in Socially-Oriented Knowledge-Intensive Tasks」というKeynoteでの取り組みが面白かったです。
このKeynoteではLLMの出力でHallucinationがあるかを判定するタスクについてメインで解説がありました。
Hallucinationを検知するための手法でいくつか手法があり、例えば一番簡単なのはプロンプトに検知するための文言を追加することでLLMの出力を抑制する方法や、Hallucinationを抑制するための学習データでFine-tuningする手法、LLMが出力するトークンのProbabilityを見て、Tokenの確からしさからHallucinationを検知する手法などあります。
Keynoteの中では、複数のLLMモデルを正誤判定器として導入する方法を提案しており、知識範囲や得意分野が異なるモデルでLLMの出力が事実かを判定することで精度を上げられるというものでした。
異なるモデルの判定用モデルを置くという発想は汎用的に今後必要になりそうなので、それが複数ではなくても単体でも一定の性能を発揮できればより実世界での適用も広がりそうだと思いました。

面白かった論文

後半ではAwardsやWorkshopをメインに扱ったので、論文紹介は一件だけ前半で紹介しきれてなかった以下を紹介します。

Spiral of Silence: How is Large Language Model Killing Information Retrieval?—A Case Study on Open Domain Question Answering

arxiv.org

この論文では、LLMが生成した文章が元データの中に増えていくにつれてQuestion Answeringの精度にどのような影響が出るかをシミュレーションしたものになります。
現実世界でも、ネットにLLMが生成した記事などが増え続けており、学習データなども汚染されているということは聞きますが、そういった現実世界の状況とこれから起こりうることをシミュレーションするという実験が面白かったです。
細かい実験の条件などは省略しますが、簡単に言うとQueryをもとにRAGで生成した回答で参照元のドキュメントを書き替える、ということを何回も繰り返していって回答の精度の変化を見ていくというものでした。
結果として、短期的には精度は向上するが、長期的には精度が悪化するという結果が得られたとのことです。
長期的に精度が悪化するのはLLMが生成するテキストにバイアスがあり、特定の傾向で間違えるケースが増えてくるということと、LLMが参照元としてLLMが生成した文章を選ぶことが増えるため、間違えた参照をさらに間違えたもので更新して、それをもう一度参照して、、と言ったことが発生したようです。
LLM自身が持つバイアスという問題を実際にシミュレーションで解き明かしつつ、どのように悪影響が出るのかを複数の軸で評価する実験手法が面白かったです。

総括

というわけで1週間に及ぶ学会が一通り終了しました。
学会の内容としてはほとんどがLLMを扱ったものでしたが、LLMの既存の課題を解決するための手法だったり、LLMをツールのように使う手法だったり、それぞれ多種多様な向き合い方があり面白かったです。
また、データセットを構築する論文が多めに感じました。
おそらくCoTなどのLLMが出てきたことで新しく評価したいタスクが生まれてきているためだと思いました。この中から研究としてどれが続いていくのかはACL以外の学会含めてみていく必要がありそうです。
海外の学会に参加するのは初めてでしたが、やはり現地だからこそ感じ取れるものがあるので、現地参加は良いなと思いました。
来年もぜひ参加してみたいですね。
それではまた。

Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com

ACL2024 参加報告 前半(~3日目)

こんにちは。タイの気温がほぼ日本と同じでちょっとげんなりしている@Ssk1029Takashiです。
私は自然言語処理の国際学会であるACL2024に参加するため、タイのバンコクに来ています。
2024.aclweb.org

今アクロクエストではRAGを用いたプロダクトを開発しており、LLMを含むNLPの最新の動向を追うためにACLに参加することにしました。
本記事ではTutorialから本会議2日目までの内容を記載していきます。

ACLとは

ACLとは正式名称「Association for Computational Linguistics」という学会で、自然言語処理を扱うトップカンファレンスとして知られています。
毎年、世界各地でカンファレンスが開催されており、今年はタイのバンコクでの開催となりました。

会場周辺の様子

初日(Tutorial)

初日は本会議ではなく、Tutorialから開始でした。
講習会のような形で、言語処理系の特定の技術について担当する人が説明してくれます。

Tutorialの様子

私は以下2つのTutorialに参加しました。

  • Automatic and Human-AI Interactive Text Generation
  • Watermarking for Large Language Model

特に「Watermark for Large Language Model」の内容が印象に残ったので、少しだけ紹介します。

Watermarking for Large Language Model

このTutorialでは「Text Watermark」と「Model Watermark」という2つのWatermarkをメインで紹介されていました。
この章では「Text Watermark」についてメインで紹介します。
Watermarkというのは日本語で言うと「透かし」になりますが、LLMが生成したテキストに対して透かしのような概念を取り入れられないかという取り組みになります。
Text WatermarkはLLMで生成された文章かを判別できるように、LLMによる誤報やデマを防ぐための技術として注目されている技術です。
ベーシックは手法として「Green-Red Watermark」というものが紹介されていました。
この手法では、ランダムに生成されたTokenをLLMが選びやすくなるように、モデルの後段で処理を入れることで、生成されたテキストがWatermarkを入れて生成されたものかを判別するというものです。

https://arxiv.org/pdf/2301.10226

上記画像はText Watermarkを入れた場合に、LLMの出力からWatermarkありなしを判定できている様子です。
この手法を使うことで、LLMから生成した文章を判定して追跡することが可能になるとのことです。
LLMが出てきたからこその技術という感じがあり、面白いですね。
上記のようなベースの手法を紹介した後、後続のWatermarkの手法や評価方法について解説があり、これまでの研究を抑えられる面白いTutorialでした。

2日目(本会議初日)

2日目から本会議が始まり、Opening CelemonyとKeynoteから始まりました。

Opening Celemony

今年のカンファレンスの概要や採択の傾向などが説明されました。
論文の投稿数は年々増えている傾向にありますが、やはりLLMが出た影響からか去年が一番跳ねていますね。

採択率は21.3%とのことで、全体が多い分下がってはいるそうです。
分野として、Resources and EvaluationやEfficient/Low-Resource Methods for NLPのトラックでの投稿が増えているとのことなので、LLMを使う・評価する方向での研究が増えた結果のようです。

Keynote1

最初のKeynoteは「Does In-Context-Learning Offer the Best Tradeoff in Accuracy, Robustness, and Efficiency for Model Adaptation?」というIn-Context-Learningについて扱った発表でした。
元々、In-Context-Learningは複数のモデルを組み合わせるなど複雑な学習、推論が必要なタスクだったが、今のGPT相当のLLMが事前学習+Few Shotで様々なタスクに簡単に適用するようになったのはなぜか、ということを様々な面で検証しようという内容でした。
自分自身、LLMを使っているとなぜそれができる?と感じる場面が多いので、それの一部を解き明かすための取り組みは興味深いものでした。

Session

2日目からは本会議に入るので、Keynoteの後は各分野に分かれてSession がありました。
Question AnsweringとInformation Retrieval and Text Miningを中心に聞きましたが、面白い論文ばかりで楽しかったです。
当記事では後述で3日目と合わせてまとめて、いくつか特に興味を引かれた論文を紹介しようと思います。

3日目(本会議2日目)

本会議2日目も最初はKeynoteから始まりました。
また、今日はSession自体は少なめになり、代わりに夜にSocial Galaというイベントが開かれました。

Keynote 2

2つ目のKeynoteは「Can LLMs Reason and Plan?」になります。
題名の通り、LLMでPlanningタスクをどのように扱えるかということについてになります。
今でもGPT−4などで、CoTをベースにした、Planninはいくつかサンプルなど紹介されていますが、Keynoteの中ではLLM単体では精度の高いPlanningはまだできない、と言われていました。
ただし、LLMをToolのように活用してフレームワークを組めば改善できるということも行っており、いくつかの改善手法の例を出してくれていました。
完全な自動化は難しく、人手を補助する役割などで、使うことが必要とのことでした。
Planningがそこまで精度良くないのは自分で試している中でも3,4ステップになると期待通りの動きをしてくれることが難しいのはまだまだある実感にもあっており、実際の実験結果を見れたのはよかったです。

Social Gala

本会議2日目の最後にはSocial Galaというパーティーのようなイベントがありました。
ホテルに集まって実施するのですが、なぜかムエタイが始まってしかもACLの参加者の人がリングに上がっていたりと面白かったです。
学会のこのようなイベントに出るのは初めてなのですが、新鮮でした。


気になった論文

まず前半までで気になった論文をいくつか挙げていきます。
自分が普段RAGを使ったプロダクトを開発していることもあり、Question AnsweringやGenerationなどのカテゴリをメインで見ていました。

arxiv.org
この論文では、Chain-of-Thoughtタスクの性能を測るためのベンチマークを提案する内容でした。
この論文ではCoTでのエラー要因はFactual Error(事実の間違い)とLogical Error(論理の間違い)があるから、その2点を計れるベンチマークを作ったとのことです。
実際に質問を入力にして、CoTのステップを出力し、各ステップごとに事実、論理的に正しいかを測ることでCoT性能を計るというベンチマークです。
アノテーションツールなどを作ってラベリング作業をして、約900個の質問に対して、CoTのステップとそれに対するラベル付を実施したそうです。
結果として、CoTでは間違いがちな事実的な正しさも含めて確認できるベンチマークが作れたようです。
CoTはLLMが出てきてから認識されたタスクであり、まだ手法や妥当性自体も研究されている所ですが、このようにベンチマークが出てくるとさらに普遍的な評価が進むので、今後の広がり方に期待ですね。

arxiv.org
この論文ではSemantic Searchに注目して、既存の手法の問題点を解決するためのLLMを使った手法を提案していました。
Semantic Searchについては既存では、SentenceBERTのようなbi-encoderを使った方式と主にGPTを使うcross-encoderの方式がありますが、bi-encoderは高速な代わりに精度に問題があり、cross-encoderは逆に高精度な代わりに速度に問題があるなど、一長一短あるという状態でした。
この論文ではLLMの出力を「蒸留」のような形でより軽量なモデルに教え込むことで、bi-encoderよりも高精度かつ、cross-encoderよりも高速なSemantic Searchが可能になったとのことです。
LLMの出力からSemantic Searchに必要な要素をLossとして計算することで、学習させる手法が面白く、実際より既存手法よりも効果的な結果が出ているのもすごかったです。
今はベクトル検索と合わせてリランクでSemantic Searchもよく活用されるので、これからさらに研究が進んで活用幅が広がりそうな内容でした。

DRAGIN: Dynamic Retrieval Augmented Generation based on the Real-time Information Needs of Large Language Models

aclanthology.org

この論文では、既存のRAGとは異なるDynamic RAGという手法を提案し、実現性などを検証したものになります。
既存のRAGは会話を始める時に、ユーザーの入力を元に関連するKnowledgeを検索し、その後の回答に使用することが一般的です。
ただし、この論文の著者は長文かつ複雑な文章を出力するようなタスクでは、出力中に外部データを参照する必要があるのではないかという主張のようです。
例えば、「アルゼンチンのワールドカップ優勝について長いコメントを書いて」と指示した時に、LLMが何か名言のようなものを出力したとすると、それを誰が言ったのかということを追加の知識を取得して出力する必要があります。
このように、出力過程で知識の検索が必要なタイミングを検知したい というのが、この論文の目的で、そのために DRAGAINというフレームワークを提案していました。
ざっくりいうと、検索が必要そうなTokenを検知できるようにという仕組みでしたが、 実際の実験では いくつか必要なタイミングで検索し、LLMのハルシネーションを抑えらるなどに活用できたとのことでした。
自分もRAGを使ったプロダクトを開発している中で、出力から検索するタイミングを検知するというのは、自分にはなかった発想で面白いなと思いました。

まとめ

ACL2024の前半までの参加記事でした。
明日からは本会議最終日とWorkshopがあるので、まだまだ楽しんでいきます。
それではまた。

Acroquest Technologyでは、キャリア採用を行っています。

  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

www.wantedly.com