AWS Kendra使ってドキュメント検索（API Gateway+Lambda）

# Kendra
##AWS Kendraとは
https://aws.amazon.com/jp/kendra/

>Amazon Kendra は、機械学習を原動力とする高精度で使いやすいエンタープライズ検索サービスです。Kendra は、ウェブサイトおよびアプリケーションに強力な自然言語検索機能を提供するため、エンドユーザーは企業全体に散在する膨大な量のコンテンツ内で必要な情報をより簡単に見つけることができます。

https://dev.classmethod.jp/articles/kendra-reinvent2019/

re:Invent 2019で発表された。
エンタープライズ検索って言って社内ドキュメントの中から、欲しい情報を簡単に探せるよっていうサービスっぽい。日本語はまだ未対応。

簡単にデータソースの設定ができて、深層学習モデルをアクティブに再訓練して、検索の正確性がどんどん上がっていく、と。


## S3にファイルアップロード
今回はデータソースはS3を使うので、適当にネットから拾ってきたデジカメの取扱説明書を置いておく。英語しか対応していないので英語版。

日本語対応するまでは実用するとしてもドキュメントを英語に変換する必要がある（AWS Translateと使ってアップロード時に翻訳変換かければいいかもしれないけど精度は不明）

https://kendra-translate-test.s3-us-west-2.amazonaws.com/nex-3n_manual.pdf


## INDEX作成
Kendraは日本リージョンないのでus-west-2を選択。
Roleの設定とかポチポチやるだけ。３０分くらいかかるみたい。ほっといたら出来てた。

<img width="1165" alt="スクリーンショット 2020-05-19 10.29.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68474/8b5437ec-758a-b6f5-9471-192a178305d1.png">


## データソース設定
今回はS3を使ってみる。
SharePoint Onlineもあるので、社内ドキュメントとは相性良いのかも。

<img width="1094" alt="スクリーンショット 2020-05-19 12.56.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68474/d8627d8a-b2db-87c1-7710-91dcf0aa03a2.png">

対象のバケットと、Roleと、データ同期のスケジュールを設定する。
今回はファイル更新しないのでRun on demandに設定。
<img width="878" alt="スクリーンショット 2020-05-19 13.00.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68474/3d7271d4-e3ba-37d5-0c4e-aae22d20e4ff.png">

出来た。Index IDは検索する際に使う。
Document Countが１で、１ファイルが対象ドキュメントになっているのがわかる。

<img width="1116" alt="スクリーンショット 2020-05-19 13.04.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68474/cb054f93-a142-073a-8a60-dd05b342af13.png">

## Search Consoleで検索できるか確認
もちろん英語で。

Q、充電時間はどのくらい？
A、約290分だよ

出来た。

<img width="723" alt="スクリーンショット 2020-05-19 13.10.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68474/9093c14b-31d6-a15f-167f-9e702033a1d0.png">

# Slackからスラッシュコマンドで使ってみる（APIGateWay＋Lambda）

##Lambda設定
- Python3.8で。
- 実行ロールにKendraへのアクセスを許可する
- あとはタイムアウト値を伸ばした（デフォルトって3秒なんですね。３秒だとタイムアウトになったので１０秒に。）

```
import boto3
from urllib import parse

def lambda_handler(event, context):
    kendra = boto3.client('kendra')
    
    # SlashCommandから送られた引数
    text = parse.parse_qs(event['body'])['text'][0]

    # kendraにIndexID指定して投げる
    response = kendra.query(IndexId='XXXXXXXXXXXXXXXXXXXXXXXXXXX', QueryText=text)

    # jsonレスポンスをごにょごにょしてTextを抽出Slackに返す
    item = response['ResultItems'][0]
    res = item['AdditionalAttributes'][0]['Value']['TextWithHighlightsValue']['Text']
    
    response = {
        "statusCode": 200,
        "body": res
    }
    return response
```
##APIGateway設定
特に変わった設定はなし。
作成されたURLをSlash Command側で使う。

<img width="1171" alt="スクリーンショット 2020-05-19 13.23.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68474/7548e3e3-2627-84fd-c6a6-edc09bc5e8ee.png">

##Slash Command設定
SlackAPIで自分で作ってもいいけど、Slackが提供しているアプリがあったのでこれを使う。

<img width="1052" alt="スクリーンショット 2020-05-19 13.27.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68474/6d607915-2624-79ea-472c-12ccea9f13cf.png">

コマンドと、POST先のAPIGatewayのURLを設定する
<img width="1035" alt="スクリーンショット 2020-05-19 13.29.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68474/78a8d781-d3d2-7073-efdd-8bdb03e9cb0c.png">

Slash Commandsで送られるPOSTデータの中身

```
token=mFrLp0CXBndhvtRvBQY6Y6ke
team_id=T0001
team_domain=example
channel_id=C2147483705
channel_name=test
user_id=U2147483697
user_name=Steve
command=/weather
text=94070
response_url=https://hooks.slack.com/commands/1234/5678
```

##完成
画面をみながらやってみます