Amazon Kendra HANDS-ON に参加してみた #jawsug #jawsugyokohama

2023.06.11

こんにちは!AWS事業本部コンサルティング部のたかくに(@takakuni_)です。

JAWS-UG 横浜 #58 で Amazon Kendra のハンズオンを行ったため、ハンズオンの参加レポートを書きたいと思います。

今回のイベントでは、アマゾン ウェブ サービス ジャパン合同会社 の 関谷さんをお招きして、 Kendra の概要や使い方をご説明いただいた後に、ハンズオンを行う流れでした。

Amazon Kendra について新機能/ソリューションを含めてご説明いただき、とても有意義な会でした。

やってみた

ハンズオンの流れをおさらいしてみようと思います。

手順を試してみたい方は 1 〜 1.5 時間程度、余裕を持って実施してください。

以下の URL をベースにハンズオンが行われましたが、手順にないものもあったので、もう一度やってみようと思います。(今回は東京リージョンでデプロイします。)

CloudFormation スタックのデプロイ

URL に記載されている CloudFormation テンプレートをダウンロードしてデプロイします。

リソースの作成(特に インデックスの作成)には、45分程度かかります。次の手順(Cloud9の作成)を先に進めておきましょう。

Cloud9 の作成

Streamlit を起動する Cloud9 環境を立ち上げます。インスタンスタイプは大きめの m5.large を利用します。

Python のインストール

現在の Python のバージョンを確認すると 3.7 であることがわかります。

cm-takakuni.shinnosuke:~/environment $ python -V
Python 3.7.16

Python3.7 では LangChain が動かないため、 Python 3.8 をインストールしていきます。 (今回は直にインストールしていますが、必要に応じて仮想環境をご利用ください。)

sudo amazon-linux-extras install -y python3.8
sudo ln -sf /usr/bin/python3.8 /usr/bin/python3
pip install urllib3==1.26.6

Streamlit のインストール

Streamlit を利用して Web アプリケーションを構成しているため、インストールしていきます。

pip install streamlit

セキュリティグループの許可

Streamlit で利用するポートの開放を行います。デフォルトでは、 8501 番ポートが利用されます。

Streamlit のテスト

Streamlit のテストをしてみましょう。streamlit hello コマンドを実行し、 External URL の URL を踏んでみます。

takakuni:~/environment $ streamlit hello

Collecting usage statistics. To deactivate, set browser.gatherUsageStats to False.


  Welcome to Streamlit. Check out our demo in your browser.

  Network URL: http://172.31.10.134:8501
  External URL: http://192.0.2.96:8501

  Ready to create your own Python apps super quickly?
  Head over to https://docs.streamlit.io

  May you create awesome apps!

正しく、セキュリティグループの許可および、アプリケーションが実行されていれば、以下のような画面になると思います。問題なければ ctrl + c で停止します。

OpenAI, Langchain のインストール

OpenAI, Langchain のインストールを行います。

pip install langchain
pip install openai

アプリケーションのデプロイ

最後にサンプルアプリケーションのデプロイを行います。

まずは、アプリケーションファイルのクローン、インストールを行います。

cd ~/environment
git clone https://github.com/aws-samples/amazon-kendra-langchain-extensions.git
cd ~/environment/amazon-kendra-langchain-extensions
pip install .

環境変数を設定します。

AWS_REGION, KENDRA_INDEX_ID は、 CloudFormation テンプレートの出力タブに表示されているものを利用して下さい。 OPENAI_API_KEY は、 OpenAI の API キーを指定します。

export AWS_REGION="<YOUR_AWS_REGION>"
export KENDRA_INDEX_ID="<YOUR_KENDRA_INDEX_ID>"
export OPENAI_API_KEY="<YOUR_OPENAI_API_KEY>"

サンプルアプリケーションを起動します。

cd ~/environment/amazon-kendra-langchain-extensions/samples
streamlit run app.py openai

streamlit hello コマンドでテストした場合と同じく、 External URL をクリックします。

入力キーが表示され「What is Kendra」と質問すると、Amazon Kendra についての回答が返ってきました。ソース付きで返ってくるのが、とてもいいですね。

日本語で回答してほしいな...

日本語で質問すると、回答が英語で返ってきました。

日本語で回答できるよう、アプリケーションを変更してみましょう。

kendra_chat_open_ai.py の prompt_template を以下のように変更してみましょう。

amazon-kendra-langchain-extensions/samples/kendra_chat_open_ai.py

from aws_langchain.kendra_index_retriever import KendraIndexRetriever
from langchain.chains import ConversationalRetrievalChain
from langchain.prompts import PromptTemplate
from langchain import OpenAI
import sys
import os

MAX_HISTORY_LENGTH = 5

def build_chain():
  region = os.environ["AWS_REGION"]
  kendra_index_id = os.environ["KENDRA_INDEX_ID"]

  llm = OpenAI(batch_size=5, temperature=0, max_tokens=300)
      
  retriever = KendraIndexRetriever(kendraindex=kendra_index_id, 
      awsregion=region, 
      return_source_documents=True)

  prompt_template = """
  以下は、人間と AI のフレンドリーな会話です。
  AI は饒舌で、その文脈から具体的な内容をたくさん提供してくれます。
  AI は質問に対して答えがわからない場合、正直に「わかりません」と答えます。
  {context}
  指示:上記の資料に基づき、 {question} に対する詳細な答えを述べよ。文書に存在しない場合は正直に「わかりません」と答えなさい。解答してください:
  """
  PROMPT = PromptTemplate(
      template=prompt_template, input_variables=["context", "question"]
  )

  return ConversationalRetrievalChain.from_llm(llm=llm, retriever=retriever, qa_prompt=PROMPT, return_source_documents=True)
  

def run_chain(chain, prompt: str, history=[]):
  return chain({"question": prompt, "chat_history": history})


if __name__ == "__main__":
  class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

  qa = build_chain()
  chat_history = []
  print(bcolors.OKBLUE + "Hello! How can I help you?" + bcolors.ENDC)
  print(bcolors.OKCYAN + "Ask a question, start a New search: or CTRL-D to exit." + bcolors.ENDC)
  print(">", end=" ", flush=True)
  for query in sys.stdin:
    if (query.strip().lower().startswith("new search:")):
      query = query.strip().lower().replace("new search:","")
      chat_history = []
    elif (len(chat_history) == MAX_HISTORY_LENGTH):
      chat_history.pop(0)
    result = run_chain(qa, query, chat_history)
    chat_history.append((query, result["answer"]))
    print(bcolors.OKGREEN + result['answer'] + bcolors.ENDC)
    if 'source_documents' in result:
      print(bcolors.OKGREEN + 'Sources:')
      for d in result['source_documents']:
        print(d.metadata['source'])
    print(bcolors.ENDC)
    print(bcolors.OKCYAN + "Ask a question, start a New search: or CTRL-D to exit." + bcolors.ENDC)
    print(">", end=" ", flush=True)
  print(bcolors.OKBLUE + "Bye" + bcolors.ENDC)

アプリケーションを再度、起動すると日本語で回答してくれるようになりました!

まとめ

Kendra をデプロイした CloudFormation スタック, Cloud9 環境, CloudWatch Logs, OpenAI の API キーを削除して後片付け終了です。

以上、「Amazon Kendra HANDS-ON に参加してみた」でした!従量課金で手っ取り早く検証できる部分とてもいいですね。また別のコネクターを利用して検索システムを作ってみたいと思いました。

この記事がどなたかの参考になれば幸いです。AWS事業本部コンサルティング部のたかくに(@takakuni_)でした!