🙄

【NLU祭り】AWSとLINEで作る簡易感情分析くんハンズオン

2021/09/01に公開

はじめに

2021年9月1日に開催の 【NLU祭り】AWSとLINEで作る簡易感情分析くんハンズオンで利用するハンズオン手順です。

事前準備

ハンズオンを進めるには、AWSアカウント と LINE Developers への登録が必要です。

AWSアカウントの作成は以下のページを参考にしてください。
AWS アカウント作成の流れ

LINE Developers は、LINEアカウントでログインします。アカウントがないかたは、お手持ちのスマートフォンでLINE にサインアップしてください。

対象者

ハンズオンの対象者は以下のようなかたを想定しています。レベルとしてはビギナー向けの内容となっています。

  • プログラミングを始めたばかりの人
  • AWSのAIサービスを触ってみたい人
  • LINEのサービス開発に興味のある人
  • Botを作ってみたい人

使用言語

ハンズオンの一部では、コーディングをしていただきます。言語は javascript です。node.js を利用します。バージョンは14.0です。

ハンズオン中に出てくる用語

  • LINE Developers コンソール(以下、LINE コンソール)
  • AWS マネジメントコンソール(以下、AWS(の)マネコン)

進めかた

ハンズオンは 4つのステップで構成されています。各ステップで動作確認の工程を設けていますので、一つ一つ動くことを確認しながら進めます。各ステップには実際に手を動かして手順をなぞっている動画を置いていますので、参考にしながら進めてください。

ハンズオン

1. LINE Messaging APIの設定 (5分)

https://youtu.be/owKgsfYtUuY

手順

  1. LINE Developers アカウントにログインして provider を選びます。
  2. Channels -> LINE message API の順にクリックします。
  3. 以下を入力します。
  4. LINE Messaging API タブをクリック
  5. 画面一番下の Channel access token を作成しておきます。(後で使います

動作確認

  1. LINE Messaging API タブに表示されるQRコードをLINEアプリで読み取り、友達追加します。Welcome メッセージが表示されたらOKです。

2. AWS API GatewayでAPIを作ろう (5分)

https://youtu.be/Iz409QAcBL0

手順

  1. AWSのマネコンにログインして、API Gateway を選びます。
  2. Create API -> REST API -> New API を選び、APIの名前を入力します。
  3. Resource -> Actions -> Create Method -> POST の順に選びます。
  4. APIのルート ("/(スラッシュ)")を選択 -> Actions -> Enable CORS を選択して、デフォルト設定のまま ”Enable CORES and Replace .." をクリックします。(エラー出ますが気にせず進めます)
  5. ResourceのPOSTを選択 -> Create Lambda Function をクリックします。
  6. Function Name を入力し、Create
  7. [動作確認] Lambda Functions の Test を作成して、"Hello World"が出ることを確認します。
  8. API Gateway に戻り、-> POST -> Lambda Function に 7. で作成したLambda Function Name を入れて確定します。
  9. [動作確認] Testを選択して、Lambda Function のレスポンスが表示されることを確認します。
  10. Actions -> Deploy API を選択し、Stagedev と入力し確定します。
  11. 画面上部 InvokeURL のところに LINEから呼び出すAPIのURLが生成されます。(後からつかいます。

CLIが使えるかたは、CURLで実際にAPIが呼び出せるか確認してみてください。

-> % curl -X POST https://m1axtw35c3.execute-api.eu-central-1.amazonaws.com/dev | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    50  100    50    0     0    561      0 --:--:-- --:--:-- --:--:--   561
{
  "statusCode": 200,
  "body": "\"Hello from Lambda!\""
}

3. AWS LambdaでAPIの中身を実装しよう (15分)

Step1, 2

https://youtu.be/wY21N-T0HNw

Step 3

https://youtu.be/D_ai-NevH5k

Step 4, 5

https://youtu.be/11lx6OuOr6E

手順

  1. LINE のチャンネルにWebhookを設定します。webhookのURLは、APIGateway -> Stage を選択したときに画面上部に出てくるURLです。URLのVerifyWebhookをEnableにするtoggleを忘れずにOnにします。

  2. [動作確認] Botにメッセージを送って、Lambdaで確認します。

  3. Lambdaでレスポンスを実装します。ここからはPC上でコードを編集します。

  • AWSのマネコンで Lambda Function の環境変数に Channel Access Tokenを設定します

    名前: CHANNEL_ACCESS_TOKEN
    値: LINE Developers コンソールで作成した Channel Access Token

  • 以下のサイトからソースコードをダウンロードします。
    https://resources.hugtech.io/LINExNLU/lambda.zip

  • index.js を以下のように編集します。

const Axios = require('axios');
exports.handler = async (event) => {
    // TODO implement
    console.log(JSON.stringify(event));
    
    // 返信用のHTTPクライアント
    const axios = Axios.create({
        baseURL: 'https://api.line.me/v2/bot/',
        headers: {
            authorization: `Bearer ${process.env.CHANNEL_ACCESS_TOKEN}`
        }
    });

    // {
    //     "destination": "U09816cbb66f47b52439034e267624bdd",
    //     "events": [
    //         {
    //             "type": "message",
    //             "message": {
    //                 "type": "text",
    //                 "id": "14635305814473",
    //                 "text": "こんにちは"
    //             },
    //             "timestamp": 1629927717459,
    //             "source": {
    //                 "type": "user",
    //                 "userId": "Uc6d1807d59a0d007bee5567a44d2ebea"
    //             },
    //             "replyToken": "283100e2afbc4cc8a968ffc3ccf0f479",
    //             "mode": "active"
    //         }
    //     ]
    // }
  
    // 返信するメッセージ
    const res = await axios.post('/message/reply', {
        replyToken: event.events[0].replyToken,
        messages: [
            {
                type: 'text',
                text: 'こんにちは'
            }
        ]
    });
    console.log(res);
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
  • ソースコードを Zip に固めてアップロードします。

MacのTerminalでやるかたはこちらの例を参考にしててください。(デスクトップに作成されるlambda.zip をアップロードしてください)

[11時34分44秒] [~/hugtech/LiNE] 
-> % ls
index.js     node_modules package.json yarn.lock
[11時34分45秒] [~/hugtech/LiNE] 
-> % zip -r ~/Desktop/lambda.zip .
  1. [動作確認] 実際のBotからメッセージを送って応答が返ってくるか確認します。

4. Amazon Comprehend を使ってネガポジ判定して応答を返そう(15分)

Step 1, 2, 3

https://youtu.be/uHvPIE9DlS0

Step 4, 5

https://youtu.be/j_A5sTqqvTI

手順

  1. Lambda Function に Amazon Comprehend を使用する許可を与えます
    Amazon Comprehend
  • AWS Lambda のコンソールで、Configuration -> Permissions -> IAM Role を選択します。
  • Add Policies -> ComprehendFullAccess を追加します。
  1. index.js を以下のように編集します。
const { Comprehend } = require('aws-sdk');
const Axios = require('axios');
exports.handler = async (event) => {
    // TODO implement
    console.log(JSON.stringify(event));
    const axios = Axios.create({
        baseURL: 'https://api.line.me/v2/bot/',
        headers: {
            authorization: `Bearer ${process.env.CHANNEL_ACCESS_TOKEN}`
        }
    });

    // {
    //     "destination": "U09816cbb66f47b52439034e267624bdd",
    //     "events": [
    //         {
    //             "type": "message",
    //             "message": {
    //                 "type": "text",
    //                 "id": "14635305814473",
    //                 "text": "こんにちは"
    //             },
    //             "timestamp": 1629927717459,
    //             "source": {
    //                 "type": "user",
    //                 "userId": "Uc6d1807d59a0d007bee5567a44d2ebea"
    //             },
    //             "replyToken": "283100e2afbc4cc8a968ffc3ccf0f479",
    //             "mode": "active"
    //         }
    //     ]
    // }

    const comprehend = new Comprehend();
    const sentiment = await comprehend.batchDetectSentiment({
        LanguageCode: 'ja',
        TextList: [
            event.events[0].message.text
        ]
    }).promise();

    console.log(JSON.stringify(sentiment));
    
    const res = await axios.post('/message/reply', {
        replyToken: event.events[0].replyToken,
        messages: [
            {
                type: 'text',
                text: 'こんにちは'
            }
        ]
    });
    console.log(res);
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
  1. [動作確認] LINEアプリから BOT にメッセージを送ります。AWSのマネコンに戻り、ネガポジ判定の結果を CloudWatchで 確認します。ネガポジ判定のレスポンスがログに出ていることを確認したら次のステップに進みましょう。

  2. ネガポジ判定によって以下のように5段階で返却するように、index.js を編集します。

condition message
positive > 0.90 今日もガンガンいきましょう!
positive < 0.60 きっと今日もバッチリ
negative < 0.60 なにか元気ないね。嫌なことあった?
negative > 0.90 いのちを大事に。。
上記以外 ふだんどおりが一番だね

編集後の index.js はこんな感じです。

const { Comprehend } = require('aws-sdk');
const Axios = require('axios');
exports.handler = async (event) => {
    // TODO implement
    console.log(JSON.stringify(event));
    const axios = Axios.create({
        baseURL: 'https://api.line.me/v2/bot/',
        headers: {
            authorization: `Bearer ${process.env.CHANNEL_ACCESS_TOKEN}`
        }
    });

    // {
    //     "destination": "U09816cbb66f47b52439034e267624bdd",
    //     "events": [
    //         {
    //             "type": "message",
    //             "message": {
    //                 "type": "text",
    //                 "id": "14635305814473",
    //                 "text": "こんにちは"
    //             },
    //             "timestamp": 1629927717459,
    //             "source": {
    //                 "type": "user",
    //                 "userId": "Uc6d1807d59a0d007bee5567a44d2ebea"
    //             },
    //             "replyToken": "283100e2afbc4cc8a968ffc3ccf0f479",
    //             "mode": "active"
    //         }
    //     ]
    // }

    const comprehend = new Comprehend();
    const sentiment = await comprehend.batchDetectSentiment({
        LanguageCode: 'ja',
        TextList: [
            event.events[0].message.text
        ]
    }).promise();

    console.log(JSON.stringify(sentiment));

    // {
    //     "ResultList": [
    //         {
    //             "Index": 0,
    //             "Sentiment": "POSITIVE",
    //             "SentimentScore": {
    //                 "Positive": 0.9982763528823853,
    //                 "Negative": 0.00011879993689944968,
    //                 "Neutral": 0.0015732598258182406,
    //                 "Mixed": 0.000031572893931297585
    //             }
    //         }
    //     ],
    //     "ErrorList": []
    // }

    let responseText = 'ふだんどおりが一番だね';
    const {
        Sentiment,
        SentimentScore
    } = sentiment.ResultList[0];

    switch (Sentiment) {
        case 'POSITIVE':
            if (SentimentScore.Positive > 0.90) {
                responseText = '今日もガンガンいきましょう!';
            } else if (SentimentScore.Positive > 0.60) {
                responseText = 'きっと今日もバッチリ';
            }
            break;
        case 'NEGATIVE':
            if (SentimentScore.Negative > 0.90) {
                responseText = 'いのちを大事に。。';
            } else if (SentimentScore.Negative > 0.60) {
                responseText = 'なにか元気ないね。嫌なことあった?';
            }
            break;
        case 'NEUTRAL': break;
        case 'MIXED': break;
        default: break;
    }
    console.log(responseText);


    const res = await axios.post('/message/reply', {
        replyToken: event.events[0].replyToken,
        messages: [
            {
                type: 'text',
                text: responseText 
            }
        ]
    });
    console.log(res);
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
  1. [動作確認] LINEアプリから BOT にメッセージを送って、判定できてるか確認します。


BOT完成後のソースは以下からダウンロードできます。

https://resources.hugtech.io/LINExNLU/lambda_complete.zip

おつかれさまでした。これで今日のノルマは終了です。完走おめでとうございます!
余裕のあるかたはアドバンスドのセクションにもトライしてみてください。

(Advanced) 音声メッセージに対応しよう

Demo

https://youtu.be/HjIjpMr0vwg

ユーザーからの音声メッセージにも応答を返せるようにBotを改造しましょう。
Amazon Transcribe を使って、ユーザーの音声を文字に変換して、先ほどと同様に Amazon Comprehend でネガポジ判定にかけてみましょう。

Amazon Transcribe

準備

https://youtu.be/UvmZcxIF9lo

  1. IAM設定
    • Lambda Function に S3FullAccessとTranscribeFullAccess を付与します。
  2. S3バケットの設定
    • Amazon Transcribe の 入出力用に S3バケットを準備します
  3. ffmpeg の Lambda Layerを準備

ソースコードの編集

  • ユーザーのメッセージがaudioの場合に、音声データを LINEのgetMessageContentで取得する
/**
 * audioデータを取得するファンクション
 * @param {*} messageId LINEから送られたaudioのID
 * @returns Audio バイナリデータ
 */
const getAudioData = (messageId) => {
    const client = new line.Client({
        channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN
    });

    return new Promise((resolve, reject) => {
        let audio = [];
        client.getMessageContent(messageId).then((stream) => {
           stream
            .on('data', (chunk) => audio.push(Buffer.from(chunk)))
            .on('end', () => resolve(Buffer.concat(audio)))
            .on('error', (err) => reject(err))
        })
    })
}
  • 音声データをffmpegで Amazon Transcribe が読み取れるデータに変換する
/**
 * audioデータを Amazon Transcribe で読み取れる形式のデータ(wav)に変換して保存するファンクション
 * @param {*} audio getAudioData ファンクションで取得した音声バイナリデータ
 * @param {*} filename ファイル名
 * @returns audio data 保存先のパス
 */
const m4a2wav = (audio, filename) => {
    const inputFile = '/tmp/audio.m4a';
    const outputFile = `/tmp/${filename}.wav`;
    const fd = fs.openSync(inputFile, 'w');
    fs.writeSync(fd, audio);
    spawnSync('/opt/bin/ffmpeg', ['-i', inputFile, '-ar', '16000', '-c:a', 'pcm_s16le', outputFile]);
    return outputFile;
}

上述した2つのファンクションを使って、音声データの取得からファイルを変換するまでのコード

        const jobName = uuidv4();
        const audio = await getAudioData(event.events[0].message.id);
        console.log(audio);

        const audioFile = m4a2wav(audio, jobName);
        console.log(audioFile);
  • 変換したファイルを入力用のS3バケットへ保存する
        // Amazon Transcribe の入力ファイルは S3 でホストする必要があるので、S3に保存
        const s3 = new S3();
        const s3Param = {
	   // バケットは準備のセクションで作成したもの 
            Bucket: 'in.lineaudio.hugtech.io',
            Key: `${jobName}.wav`,
            Body: fs.readFileSync(audioFile)
        };
        console.log(s3Param);
        s3.putObject(s3Param).promise()
  • Transcribe で文字起こしする
        // Transcribe 実行(文字起こし)
	// バケットは準備のセクションで作成したもの
        const OutputBucketName = 'out.lineaudio.hugtech.io';
        const transcribe = new TranscribeService();
        const transcribeParam = {
            TranscriptionJobName: jobName,
            LanguageCode: 'ja-JP',
            MediaFormat: 'wav',
            Media: {
		// 入力用バケットに保存した音声ファイルのURLを指定する
                MediaFileUri: `https://in.lineaudio.hugtech.io.s3.eu-central-1.amazonaws.com/${jobName}.wav`,

            },
            OutputBucketName 
        };
        console.log(transcribeParam);
        await transcribe.startTranscriptionJob(transcribeParam).promise();
  • Transcribe のジョブが終わるのを待つ
        // 文字起こしは非同期で行われるので完了を待つ
        const getJob = async (name) => {
            const job = await transcribe.getTranscriptionJob({
                TranscriptionJobName: name
            }).promise();
            return job;
        }

        let job = await getJob(jobName);
        let count = 0;
	// 文字起こしの完了は、ジョブを取得して、TranscriptionJobStatusを確認することで判定できる。
        while (job.TranscriptionJob.TranscriptionJobStatus !== 'COMPLETED' && count <= 100) {
            count++;
            await delay(500);
            job = await getJob(jobName);
        }
        console.log(job.TranscriptionJob.Transcript.TranscriptFileUri);
  • Transcribe された結果が出力用のS3バケットにJSONで保存されるので、抽出して、Comprehendを実行する
        // 文字起こし結果を取得
        const Key = path.basename(job.TranscriptionJob.Transcript.TranscriptFileUri);
        const transcribeResult = await s3.getObject({
            Bucket: OutputBucketName,
            Key
        }).promise();

        // {
        //     "jobName": "3abacaa6-9d25-4f22-b610-9c48280294a2",
        //     "accountId": "623357820778",
        //     "results": {
        //         "transcripts": [
        //             {
        //                 "transcript": "を突かれたまでです"
        //             }
        //         ],
        //         "items": [
        // :

        const transcribeResultJson = JSON.parse(transcribeResult.Body.toString());
        console.log(transcribeResult.Body.toString());
        comprehendText = transcribeResultJson.results.transcripts[0].transcript;
  • Comprehendの結果から応答メッセージを作成する(
  • Push Message で ユーザーに応答する
    // 応答はpushメッセージで返す(文字起こしに時間がかかるので、replyメッセージの有効期間が切れてしまう
    const res = await axios.post('/message/push', {
        to: event.events[0].source.userId,
        messages: [
            {
                type: 'text',
                text: responseText 
            }
        ]
    });
    console.log(res);
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

ソースコード(完全版)

const { Comprehend, TranscribeService, S3 } = require('aws-sdk');
const Axios = require('axios');
const line = require('@line/bot-sdk');
const { spawnSync } = require('child_process')
const fs = require('fs');
const { v4: uuidv4 } = require('uuid');
const delay = require('delay');
const path = require('path');

/**
 * audioデータを取得するファンクション
 * @param {*} messageId LINEから送られたaudioのID
 * @returns Audio バイナリデータ
 */
const getAudioData = (messageId) => {
    const client = new line.Client({
        channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN
    });

    return new Promise((resolve, reject) => {
        let audio = [];
        client.getMessageContent(messageId).then((stream) => {
           stream
            .on('data', (chunk) => audio.push(Buffer.from(chunk)))
            .on('end', () => resolve(Buffer.concat(audio)))
            .on('error', (err) => reject(err))
        })
    })
}

/**
 * audioデータを Amazon Transcribe で読み取れる形式のデータ(wav)に変換して保存するファンクション
 * @param {*} audio getAudioData ファンクションで取得した音声バイナリデータ
 * @param {*} filename ファイル名
 * @returns audio data 保存先のパス
 */
const m4a2wav = (audio, filename) => {
    const inputFile = '/tmp/audio.m4a';
    const outputFile = `/tmp/${filename}.wav`;
    const fd = fs.openSync(inputFile, 'w');
    fs.writeSync(fd, audio);
    spawnSync('/opt/bin/ffmpeg', ['-i', inputFile, '-ar', '16000', '-c:a', 'pcm_s16le', outputFile]);
    return outputFile;
}

exports.handler = async (event) => {
    // TODO implement
    console.log(JSON.stringify(event));
    const axios = Axios.create({
        baseURL: 'https://api.line.me/v2/bot/',
        headers: {
            authorization: `Bearer ${process.env.CHANNEL_ACCESS_TOKEN}`
        }
    });

    // {
    //     "destination": "U09816cbb66f47b52439034e267624bdd",
    //     "events": [
    //         {
    //             "type": "message",
    //             "message": {
    //                 "type": "audio",
    //                 "id": "14668691969739",
    //                 "duration": 1468,
    //                 "contentProvider": {
    //                     "type": "line"
    //                 }
    //             },
    //             "timestamp": 1630438177007,
    //             "source": {
    //                 "type": "user",
    //                 "userId": "Uc6d1807d59a0d007bee5567a44d2ebea"
    //             },
    //             "replyToken": "4f74af372c1e4b0c9eacdda76a9829df",
    //             "mode": "active"
    //         }
    //     ]
    // }
    let comprehendText = '';

    if (event.events[0].message.type === 'audio') {
        const jobName = uuidv4();
        const audio = await getAudioData(event.events[0].message.id);
        console.log(audio);

        const audioFile = m4a2wav(audio, jobName);
        console.log(audioFile);

        // Amazon Transcribe の入力ファイルは S3 でホストする必要があるので、S3に保存
        const s3 = new S3();
        const s3Param = {
            Bucket: 'in.lineaudio.hugtech.io',
            Key: `${jobName}.wav`,
            Body: fs.readFileSync(audioFile)
        };
        console.log(s3Param);
        s3.putObject(s3Param).promise()

        // Transcribe 実行(文字起こし)
        const OutputBucketName = 'out.lineaudio.hugtech.io';
        const transcribe = new TranscribeService();
        const transcribeParam = {
            TranscriptionJobName: jobName,
            LanguageCode: 'ja-JP',
            MediaFormat: 'wav',
            Media: {
                MediaFileUri: `https://in.lineaudio.hugtech.io.s3.eu-central-1.amazonaws.com/${jobName}.wav`,

            },
            OutputBucketName 
        };
        console.log(transcribeParam);
        await transcribe.startTranscriptionJob(transcribeParam).promise();


        // 文字起こしは非同期で行われるので完了を待つ
        const getJob = async (name) => {
            const job = await transcribe.getTranscriptionJob({
                TranscriptionJobName: name
            }).promise();
            return job;
        }

        let job = await getJob(jobName);
        let count = 0;
        while (job.TranscriptionJob.TranscriptionJobStatus !== 'COMPLETED' && count <= 100) {
            count++;
            await delay(500);
            job = await getJob(jobName);
        }
        console.log(job.TranscriptionJob.Transcript.TranscriptFileUri);

        // 文字起こし結果を取得
        const Key = path.basename(job.TranscriptionJob.Transcript.TranscriptFileUri);
        const transcribeResult = await s3.getObject({
            Bucket: OutputBucketName,
            Key
        }).promise();

        // {
        //     "jobName": "3abacaa6-9d25-4f22-b610-9c48280294a2",
        //     "accountId": "623357820778",
        //     "results": {
        //         "transcripts": [
        //             {
        //                 "transcript": "を突かれたまでです"
        //             }
        //         ],
        //         "items": [
        // :

        const transcribeResultJson = JSON.parse(transcribeResult.Body.toString());
        console.log(transcribeResult.Body.toString());
        comprehendText = transcribeResultJson.results.transcripts[0].transcript;

    } if (event.events[0].message.type === 'text') {
        comprehendText = event.events[0].message.text
    }
    
    // {
    //     "destination": "U09816cbb66f47b52439034e267624bdd",
    //     "events": [
    //         {
    //             "type": "message",
    //             "message": {
    //                 "type": "text",
    //                 "id": "14635305814473",
    //                 "text": "こんにちは"
    //             },
    //             "timestamp": 1629927717459,
    //             "source": {
    //                 "type": "user",
    //                 "userId": "Uc6d1807d59a0d007bee5567a44d2ebea"
    //             },
    //             "replyToken": "283100e2afbc4cc8a968ffc3ccf0f479",
    //             "mode": "active"
    //         }
    //     ]
    // }

    const comprehend = new Comprehend();
    const sentiment = await comprehend.batchDetectSentiment({
        LanguageCode: 'ja',
        TextList: [
            // event.events[0].message.text
            comprehendText
        ]
    }).promise();

    console.log(JSON.stringify(sentiment));

    // {
    //     "ResultList": [
    //         {
    //             "Index": 0,
    //             "Sentiment": "POSITIVE",
    //             "SentimentScore": {
    //                 "Positive": 0.9982763528823853,
    //                 "Negative": 0.00011879993689944968,
    //                 "Neutral": 0.0015732598258182406,
    //                 "Mixed": 0.000031572893931297585
    //             }
    //         }
    //     ],
    //     "ErrorList": []
    // }

    let responseText = 'ふだんどおりが一番だね';
    const {
        Sentiment,
        SentimentScore
    } = sentiment.ResultList[0];

    switch (Sentiment) {
        case 'POSITIVE':
            if (SentimentScore.Positive > 0.90) {
                responseText = '今日もガンガンいきましょう!';
            } else if (SentimentScore.Positive > 0.60) {
                responseText = 'きっと今日もバッチリ';
            }
            break;
        case 'NEGATIVE':
            if (SentimentScore.Negative > 0.90) {
                responseText = 'いのちを大事に。。';
            } else if (SentimentScore.Negative > 0.60) {
                responseText = 'なにか元気ないね。嫌なことあった?';
            }
            break;
        case 'NEUTRAL': break;
        case 'MIXED': break;
        default: break;
    }
    console.log(responseText);

    // 応答はpushメッセージで返す(文字起こしに時間がかかるので、replyメッセージの有効期間が切れてしまう
    const res = await axios.post('/message/push', {
        to: event.events[0].source.userId,
        messages: [
            {
                type: 'text',
                text: responseText 
            }
        ]
    });
    console.log(res);
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

BOT完成後のソースは以下からダウンロードできます。

https://resources.hugtech.io/LINExNLU/lambda_advanced.zip

おつかれさまでした!

Discussion