AIによる校閲・文章校正をSnowflakeでやってみる

こんにちは!ちゅらデータでCTOしてる菱沼です!

Snowflakeには外部関数という AWS API Gateway を呼び出せる機能があります!
今回はこの機能を使って、AI文章校正(なんちゃって)をしてみたいと思います!

参考:AWS での外部関数の作成
https://docs.snowflake.com/ja/sql-reference/external-functions-creating-aws.html 


はじめに

●AI文章校正のLambdaを作って、AWS API Gateway でアクセスできるようにする
●Snowflake では外部関数を使って AWS API Gateway を呼び出すことができる

 

Lambdaの準備(レイヤーにライブラリを登録)

今回はAI文章校正ということですが、あまりしっかりしたAIを用意すると、記事がそれだけで終わってしまうので、簡単にルールベースで実装のtextlintを使うことにします。

ではLambdaでtextlintを使えるようにするために、下記のコマンドでライブラリをzipにまとめましょう。

$ mkdir -p snowflake-blog ; cd $_
$ npm install textlint textlint-rule-preset-ja-technical-writing
$ mkdir nodejs
$ mv node_modules nodejs
$ zip -r nodejs.zip nodejs
$ ls -lh
total 75376
drwxr-xr-x  3 yuta.hishinuma  staff    96B 10 14 10:52 nodejs
-rw-r--r--  1 yuta.hishinuma  staff    37M 10 14 10:52 nodejs.zip
-rw-r--r--  1 yuta.hishinuma  staff   107K 10 14 10:52 package-lock.json

こうしてできたnodejs.zipをLambdaが利用するライブラリであるレイヤーに登録します。

ではAWSのコンソールにログインしてレイヤーの作成画面を開きます。
1. [レイヤーの作成]を押す

2. 各項目を入力して[作成]を押す

これでレイヤーに登録ができたので、次はLambdaに文章構成するプログラムを登録します。

 

Lambdaプログラムを登録

1. Lambdaのトップページから、[関数の作成]を押します。

2. 必要項目を入力して関数を作成します。


3. 出来上がった関数に事前につくったtextlinレイヤーを追加していきます。

4. textlintレイヤーを選択して追加を押します。

5. 最初は関数コードのindex.jsが下記のようになっています。

exports.handler = async (event) => {
    // TODO implement
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

これを、下記のように書き換えます。(貼り付けてOKです)

const textlint = require("textlint");
const { TextFixEngine } = textlint;

const options = {
    presets: [
        "preset-ja-technical-writing"
    ],
    textlintrc: false
};
const engine = new TextFixEngine(options);

exports.handler = async (event) => {
    var output = [];
    for (let i = 0; i <  event.data.length; i++) {
        await engine.executeOnText(event.data[i][1]).then((results) => {
            output.push([event.data[i][0], results[0].output]);
        });
    }
    return {
        data: output
    };
};

貼り付けができたら、[Deploy]ボタンを押します。

 

Lambda関数にAPI Gateway(トリガー)を作成

Lambda関数にプログラムを作り終わったらSnowflakeから呼び出せるようにトリガーを準備します。SnowflakeはAWSの「API Gateway」に対応しています。

1. API Gatewayを作るには、Lambda関数のデザイナーから[トリガーを追加]を押します。

2. 各項目を選択して、[追加]を押してください。

追加に成功するとLambda関数の[デザイナー]や[API Gateway]に追加されます。
Lambda関係の設定は一度ここで中断して、IAM関係の設定へ進みます。

 

AWSとSnowflakeを結ぶためのIAMロールを用意する

Snowflakeの外部関数はSnowflake側のAWSアカウントにあるユーザを使って、自分のAWSアカウントにAssumeRoleを使って権限を割り当てて、APIGatewayを実行することで実現します。

なので、Lambdaを用意したあとはIAMロールを作って、SnowflakeのアカウントにAssumeRoleする設定をしましょう。

1. まず、AWSコンソールでIAMの画面を開きロールを作成する画面を開きます。そして下記のスクリーンショットのように[別のAWSアカウント]を選択し、アカウントIDを入力します。この際アカウントIDはあとでSnowflakeのものに修正しますので、仮として自分のアカウントIDを入力しておきましょう。(SnowflakeとAWSを統合する際のよくある流れですね)

2. ポリシーを割り当てます。このとき先程作ったAPIGatewayをInvoke可能なポリシーを選びます。(今回はAmazonAPIGatewayInvokeFullAccessを設定しました)

3. タグの追加は必要ありませんので[次のステップ:確認]をクリックしてください。
4. ロール名を入力して[ロールの作成]をクリックしてください。(今回はロール名をAPIGatewayInvokeTextlintとしました)

5. 作成したロールの詳細を確認し、ロールARNをメモします。このロールARNはあとでSnowflakeの設定に使います。

これでIAMロールの設定は一旦完了です。あとでSnowflake側で生成されるIAMユーザやアカウントをこのIAMロールの[信頼関係]へ設定しに戻ってきます。

 

APIGatewayにリソースポリシーを設定する

一つ前にて作成したIAMロールが、2つ前に作ったAPIGatewayのリソースを実行できるようにする許可設定をAPIGatewayのリソースポリシーで行います。

1. APIGatewayに作成されているリソースを開き、リソースARNをメモします。

2. APIGatewayのリソースポリシーを開き、編集し保存します。


テンプレ:

{
    "Version": "2012-10-17",
    "Statement":
    [
        {
        "Effect": "Allow",
        "Principal":
            {
            "AWS": "arn:aws:sts::<自分のAWSアカウントID(12桁数値)>:assumed-role/<さっき作ったIAMロール名>/snowflake"
            },
        "Action": "execute-api:Invoke",
        "Resource": "<APIGatewayのリソースARN>"
    ]
}

例:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:sts::6**********6:assumed-role/APIGatewayInvokeTextlint/snowflake"
            },
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:ap-northeast-1:6**********6:y********2/*/*/textlint-function"
        }
    ]
}


3. 保存したらAPIをデプロイします。デプロイは[リソース]=>[アクション]から[APIのデプロイ]にて実行できます。

 

SnowflakeでAPI統合オブジェクトを作成

AWSコンソールからはなれ、いったんSnowflakeのWebUIへ戻ってください。これからSnowflakeにてAPI統合オブジェクトを作ります。
API統合オブジェクトを作るためにはACCOUNTADMINロールか、CREATE INTEGRATION権限をもったロールが必要ですので、スイッチロールしておいてください。

1. 下記のSQLを実行してAPI統合オブジェクトをつくります。名前は「my_api_integration_01」としてありますが自由に決めて問題ないです。

SQL:

create or replace api integration my_api_integration_01
  api_provider = aws_api_gateway
  api_aws_role_arn = '<AWSで作ったIAMロールのARN>'
  enabled = true
  api_allowed_prefixes = ('https://')
;

「'<AWSで作ったIAMロールのARN>’」は、途中でメモったIAMロールのARNです。たとえば「arn:aws:iam::6**********6:role/APIGatewayInvokeTextlint」のような値です。

2. 下記のSQLを実行し、「API_AWS_IAM_USER_ARN」と「API_AWS_EXTERNAL_ID」を確認しメモします。これをこのあとAWS側で使用します。

describe integration my_api_integration_01;

値の例:

API_AWS_IAM_USER_ARN … arn:aws:iam::123456789012:user/abcd-e-fghij1234
API_AWS_EXTERNAL_ID … ABC_ABC_SFCRole=1_hogehogehogehogehogehogeo=

 

AWSのIAMロールの信頼関係を設定

先程メモした「API_AWS_IAM_USER_ARN」と「API_AWS_EXTERNAL_ID」を使ってIAMロールの信頼関係を設定します。

1. 信頼関係を編集をクリックしてすると表示される[ポリシードキュメント]へ下記のテンプレにメモった値を埋め込みましょう。
できたら[信頼ポリシーを更新]をクリックします。

テンプレ:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "<API_AWS_IAM_USER_ARN>"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<API_AWS_EXTERNAL_ID>"
        }
      }
    }
  ]
}

これで、Snowflake側のユーザが、このIAMロールの権限を引き受けられるようになりました。

 

外部関数を作成

ようやく、Snowflakeから、AWSのAPIGatewayを呼び出す外部関数を作成します。
外部関数はデータベースに保存されるオブジェクトなので、use databaseをしてから、実行します。

use HOGEHOGE_DB;

create external function my_external_function(v varchar)
    returns variant
    api_integration =  my_api_integration_01
    as '<APIGatewayのAPIのURL>'
;

※<APIGatewayのAPIのURL>は、たとえば「https://<乱数値>.execute-api.ap-northeast-1.amazonaws.com/<ステージ名(defaultなど)>/textlint-function」のようになっているはずです。わからなければ、APIGatewayのステージのあたりから探しましょう。

上記のSQLが実行できたらこれで完成です。

 

Snowflakeで文章校正実行!

下記のように外部関数を使うことで文章校正が実行できるようになりました!

select PUBLIC.MY_EXTERNAL_FUNCTION('一つにすることができます');
=>結果:"1つにできます"

通常の関数と同じように実行できるので、テーブルに登録されている文章データを校正したり、いろいろ活用できます。

おめでとうございます!

 

よくあるエラー

・Error parsing JSON response for external function MY_EXTERNAL_FUNCTION: top-level JSON object must contain “data” JSON array element
これはjsonのレスポンスが誤っている例です。Snowflakeでは下記のようにdataというキーの配列値がトップレベルにあるJSONフォーマットしか外部関数のレスポンスとして許容してません。

{
  "data": [
    [0,"hoge"],
    [1,"fuga"],
    [2,"piyo"]
  ]
}

ですので、このエラーが出たときはJSONのレスポンスを見直してみましょう。

・Request failed for external function MY_EXTERNAL_FUNCTION. Error: 403 ‘{“Message”:”User: arn:aws:sts::6**********6:assumed-role/APIGatewayInvokeTextlint/snowflake is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:********8136:y******2/default/POST/textlint-function”}’
リソースポリシーが間違ってます。設定を見直しましょう。

Snowflakeに関するお問い合わせはサービス/研修のお問い合わせからご連絡ください。



DATUM STUDIOは、クライアントの事業成長と経営課題解決を最適な形でサポートする、データ・ビジネスパートナーです。
データ分析の分野でお客様に最適なソリューションをご提供します。まずはご相談ください。

このページをシェアする: