Amazon Kendra + SageMaker JumpStartで生成AI / RAGをとりあえず動かす

## 概要
- 企業データをベースに、自然文でQAしてくれる検索拡張生成（RAG）のソリューション
- ChatGPTなど一般的な生成AIの場合、それっぽいけど正しいかわからない、または誤った情報が返されるハルシネーションリスクへの対策例としても注目されている
- 特に、企業データをベースとした回答生成をより効率的かつコスパ良く実現するために、すべてLLM頼りにせず、セマンティック検索の専用サービス（Amazon Kendra）を組み合わせている


## 元ネタ
高精度な生成系 AI アプリケーションを Amazon Kendra、LangChain、大規模言語モデルを使って作る

https://aws.amazon.com/jp/blogs/news/quickly-build-high-accuracy-generative-ai-applications-on-enterprise-data-using-amazon-kendra-langchain-and-large-language-models/

## ソリューション概要

Chat形式で質問を投げると、回答と参照文献のリンクを提示してくれるWebアプリ


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/108de9c4-6904-94f0-c82b-3d35a03bf241.png)

### 構成概要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/bd2c7839-2ecb-60cf-89d0-7a87c0f249f3.png)

- 主な構成要素
    - **Webアプリ** : Chat形式のQAインターフェース機能を提供する。Python Webアプリケーション作成用のOSSフレームワーク`Streamlit`で実装。
    - **Amazon Kendra** : ユーザーからの質問内容をもとにセマンティック検索で、事前に指定した対象ドキュメントをベースにドキュメント抜粋を含む検索結果を返す
    - **LLM** : Kendraが抽出した回答ドラフトをもとに、生成AIで要約して自然な回答文を作る。LLMの部分は`OpenAI API`など3rd Partyでも良いし、`Amazon SageMaker`で任意の要約系LLMをデプロイしても良いし、`Amazon Bedrock`(未GA)でも良い。


## とりあえず試す

### 各構成要素の素材
- チャットWebアプリ要素はGitHubで公開されている。
    - https://github.com/aws-samples/amazon-kendra-langchain-extensions/blob/main/kendra_retriever_samples/README.md
- `Amazon Kendra`要素は環境構築用 `Cloud Formation`テンプレートが公開されている
    - https://github.com/aws-samples/amazon-kendra-langchain-extensions/blob/main/kendra_retriever_samples/kendra-docs-index.yaml
- LLM要素は`OpenAI API`を利用する場合はAPI Keyを事前準備するだけ。`SageMaker`を利用する場合は`JumpStart`で要約系生成AIモデル（例:`Flan T5 XL`）の推論エンドポイントをデプロイする。（`Bedrock`は未GAなので割愛）


### [1] 環境準備

Cloud9を利用しても良いし、ローカル環境でも良い。
下記はLocal MACの場合。

※注意 : Python 3.9 以降がインストールされていること

必要なものをインストール

```python
# AWS SDK for Python
pip install boto3

# Python Webアプリケーション作成用のOSSフレームワーク
pip install streamlit

# LLMを使用したアプリケーション開発用のOSSフレームワーク
pip install langchain

# OpenAI APIを使うなら（SageMaker JumpStartなら不要）
pip install openai
```

### [2] CFnでKendra環境設定

基本は以下CFnテンプレートを利用して実行するだけ
https://github.com/aws-samples/amazon-kendra-langchain-extensions/blob/main/kendra_retriever_samples/kendra-docs-index.yaml

- スタックの起動には約 30 分かかり、その後同期してインデックスにデータを取り込むのに約 15 分かかる
- 検索用のデータソースとしては、lex、kendra、sagemakerの公式ドキュメント(html)をクローリングする

**CFnテンプレート抜粋**

```yaml
  #Docs Data Source
  KendraDocsDS:
    Type: 'AWS::Kendra::DataSource'
    Properties: 
      DataSourceConfiguration: 
        WebCrawlerConfiguration:
          UrlInclusionPatterns:
            - '.*https://docs.aws.amazon.com/lex/.*'
            - '.*https://docs.aws.amazon.com/kendra/.*'
            - '.*https://docs.aws.amazon.com/sagemaker/.*'
          Urls:
             SiteMapsConfiguration:
               SiteMaps:
                 - 'https://docs.aws.amazon.com/lex/latest/dg/sitemap.xml'
                 - 'https://docs.aws.amazon.com/kendra/latest/dg/sitemap.xml'
                 - 'https://docs.aws.amazon.com/sagemaker/latest/dg/sitemap.xml'
      IndexId: !GetAtt DocsKendraIndex.Id
      Name: 'KendraDocsDS'
      RoleArn: !GetAtt KendraDSRole.Arn
      Type: 'WEBCRAWLER'
```

CFnが実行完了したら、出力の AWS Regionと　KendraIndexIDをメモしておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/70c9a3ca-7a6e-b518-40a4-fa8d38d11d4a.png)


### [3] SageMaker JumpStartでLLM推論エンドポイントをデプロイ

要約のためのLLMモデルはSageMaker JumpStartで簡単にデプロイできる。

① SageMakerコンソールの `JumpStart` → `Foundation models` で、今回は`Flan T5 XL`を検索して選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/034a97c9-7741-40f1-ca68-10fd2678f25d.png)

② 次に、モデルの詳細画面で右上の「`Studioでノートブックを開く`」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/1e2afa04-576e-acbe-dc70-c9e5872d6cc3.png)

③ 次に、SageMakerStudioでノートブックが立ち上がるので、`3. Retrieve Artifacts & Deploy an Endpoint`の最後まですべて実行（4以降はとりあえず不要）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/d679740b-165f-6aa9-ccd8-63145cc1e0a7.png)

④ 実行が完了すると、`Flan T5 XL`を利用した推論エンドポイントが下記の通りデプロイされる。
エンドポイント名は後で利用するのでメモする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/e957a769-b2bc-ece3-b451-f2ce75900465.png)

### [4] Chat Webアプリを立ち上げと最後の仕上げ

基本は下記READMEの通り
https://github.com/aws-samples/amazon-kendra-langchain-extensions/blob/main/kendra_retriever_samples/README.md


**環境設定**
```python
# Langchain と Amazon Kendra で動作するサンプルのセットをクローン
git clone https://github.com/aws-samples/amazon-kendra-langchain-extensions.git

# ディレクトリ移動
cd amazon-kendra-langchain-extensions/kendra_retriever_samples

# 必要なライブラリインストール（一部は事前準備と重複あり）
pip install -r requirements.txt

# 環境変数設定
export AWS_REGION="対象リージョン 例: us-east-1"
export KENDRA_INDEX_ID="Kendra設定時にCFnで出力されたID"
export FLAN_XL_ENDPOINT="SageMakerでデプロイしたLLMエンドポイントの名前"
```

StreamlitのWEBアプリ起動
```python
streamlit run app.py flanxl --server.port 8080
```

こんな感じでブラウザでアプリが立ち上がる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/d8c6286e-0152-aaea-b2db-1de5d86aa9bc.png)

# 注意事項

作成したAWSリソースは課金が発生するので、必要に応じて削除すること