はじめに
お疲れ様です。@yuki_inkです。
Bedrock・Kendra・DynamoDBを利用してRAGアプリを作りたい!
ということで、LangChainを使って実装してみました。
Kendraを利用したRAGに加え、会話履歴のセッション管理を行えるアプリを目指しています。
今回の開発は、以下の記事で紹介されているアプリを参考に行いました。
今回は、LangChainが提供する機能を使って以下のようなことを実現したいと思います。
・チャットの会話履歴を記憶して、生成AIに文脈を踏まえた回答をさせる。
・会話履歴をDynamoDBに保存して、Lambda関数を呼び出す度に記憶がリセットされないようにする。
・会話履歴のセッション管理を行うことで、複数ユーザーの会話履歴を生成AIが区別できるようにする。
勉強がてら、今回は以下のクラスを利用しました。
- ChatBedrock
- AmazonKendraRetriever
- DynamoDBChatMessageHistory
- ConversationalRetrievalChain
やったこと
今回使用した環境は以下の通りです。
基本的に、記事執筆時点で最新のバージョンを利用しています。
項目 | 環境 |
---|---|
Lambda ランタイム | Python 3.12 (x86_64) |
langchain バージョン | 0.2.11 |
langchain-aws バージョン | 0.1.15 |
LLM モデル | Claude 3.5 Sonnet |
LLM バージョン | anthropic.claude-3-5-sonnet-20240620-v1:0 |
リージョン | バージニア北部 (us-east-1) |
1. BedrockからClaudeを利用可能にする
マネジメントコンソールの「モデルアクセス」画面から、利用したいモデルを使えるようにしておきます。
今回はバージニア北部リージョン(us-east-1)のClaudeを利用します。
2. Kendraの設定
非常に便利なCloudFormationテンプレートが公開されていたので、これを利用してリソースを作成しました。
公開されているCloudFormationで作成できるリソースは以下の通りです。
KendraのデータソースとしてS3が利用されています。
- インデックス用Kendra用IAMロール
- データソース用Kendra用IAMロール
- Kendraインデックス
- Kendra用のCloudWatch Logsロググループ
- Kendraデータソース
- S3バケット
- S3バケットポリシー
CloudFormationスタックのデプロイ
上記記事で公開されているCloudFormationテンプレートをそのまま流して、リソースを作成します。
CloudFormationテンプレート全量(参考記事から転載)
AWSTemplateFormatVersion: '2010-09-09'
Description: Kendra and S3
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Parameters:
- SysName
- Env
- KendraEdition
- KendraLogRetentionDays
- KendraDSBucketPrefix
Parameters:
SysName:
Type: String
Default: 'cm'
Description: 'System name for this stack.'
Env:
Type: String
Default: 'prd'
Description: 'Environment for this stack.'
AllowedValues:
- 'prd'
- 'stg'
- 'dev'
KendraEdition:
Type: String
Default: 'ENTERPRISE_EDITION'
Description: 'ENTERPRISE_EDITION is suitable for production environments. DEVELOPER_EDITION is suitable for development environments.'
AllowedValues:
- 'ENTERPRISE_EDITION'
- 'DEVELOPER_EDITION'
KendraLogRetentionDays:
Type: Number
Default: 365
Description: 'Retention days for Kendra logs.'
AllowedValues:
- 1
- 3
- 5
- 7
- 14
- 30
- 60
- 90
- 120
- 150
- 180
- 365
- 400
- 545
- 731
- 1096
- 1827
- 2192
- 2557
- 2922
- 3288
- 3653
KendraDSBucketPrefix:
Type: String
Default: 'awsdoc'
Description: 'Bucket prefix for search range.'
Resources:
##Role for Kendra Index
KendraIndexRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Sub '${SysName}-${Env}-kendra-index-role'
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Sid: ''
Effect: Allow
Principal:
Service: kendra.amazonaws.com
Action: 'sts:AssumeRole'
##Policy for Kendra Index
KendraIndexPolicy:
Type: 'AWS::IAM::ManagedPolicy'
Properties:
ManagedPolicyName: !Sub '${SysName}-${Env}-kendra-index-policy'
Roles:
- !Ref KendraIndexRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Resource: '*'
Condition:
StringEquals:
'cloudwatch:namespace': 'AWS/Kendra'
Action:
- 'cloudwatch:PutMetricData'
- Effect: Allow
Resource: '*'
Action: 'logs:DescribeLogGroups'
- Effect: Allow
Resource: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/kendra/*'
Action: 'logs:CreateLogGroup'
- Effect: Allow
Resource: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/kendra/*:log-stream:*'
Action:
- 'logs:DescribeLogStreams'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
##Kendra Index
KendraIndex:
Type: 'AWS::Kendra::Index'
Properties:
Name: !Sub '${SysName}-${Env}-kendra-index'
Edition: !Ref KendraEdition
RoleArn: !GetAtt KendraIndexRole.Arn
##CloudWatch LogGroup for Kendra Index
KendraIndexLogs:
Type: 'AWS::Logs::LogGroup'
Properties:
LogGroupName: !Sub
- '/aws/kendra/${IndexId}'
- IndexId: !GetAtt KendraIndex.Id
RetentionInDays: !Ref KendraLogRetentionDays
##Role for Kendra Data Source
KendraDSRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Sub '${SysName}-${Env}-kendra-ds-role'
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Sid: ''
Effect: Allow
Principal:
Service: kendra.amazonaws.com
Action: 'sts:AssumeRole'
##Policy for Kendra Data Source
KendraDSPolicy:
Type: 'AWS::IAM::ManagedPolicy'
Properties:
ManagedPolicyName: !Sub '${SysName}-${Env}-kendra-ds-policy'
Roles:
- !Ref KendraDSRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Resource:
- !Join
- ''
- - 'arn:aws:s3:::'
- !Ref KendraDSBucket
- '/*'
Action:
- 's3:GetObject'
- Effect: Allow
Resource: !GetAtt KendraDSBucket.Arn
Action:
- 's3:ListBucket'
- Effect: Allow
Resource: !Sub
- 'arn:aws:kendra:${AWS::Region}:${AWS::AccountId}:index/${IndexId}'
- IndexId: !GetAtt KendraIndex.Id
Action:
- 'kendra:BatchPutDocument'
- 'kendra:BatchDeleteDocument'
##Kendra Data Source
KendraDS:
Type: 'AWS::Kendra::DataSource'
Properties:
DataSourceConfiguration:
S3Configuration:
BucketName: !Ref KendraDSBucket
InclusionPrefixes:
- !Ref KendraDSBucketPrefix
IndexId: !GetAtt KendraIndex.Id
LanguageCode: 'ja'
Name: !Sub '${SysName}-${Env}-kendra-ds'
RoleArn: !GetAtt KendraDSRole.Arn
Type: 'S3'
##Data Source Bucket
KendraDSBucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: !Sub '${SysName}-${Env}-kendra-ds-bucket-${AWS::AccountId}'
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketKeyEnabled: true
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
##Data Source Bucket Policy
KendraDSBucketPolicy:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket: !Ref KendraDSBucket
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Deny
Action:
- 's3:GetObject'
Resource:
- !Join
- ''
- - 'arn:aws:s3:::'
- !Ref KendraDSBucket
- '/*'
Principal: '*'
Condition:
StringNotEquals:
aws:PrincipalArn:
- !GetAtt KendraDSRole.Arn
Outputs:
KendraIndexID:
Value: !GetAtt KendraIndex.Id
KendraDSID:
Value: !GetAtt KendraDS.Id
KendraDSBucketName:
Value: !Ref KendraDSBucket
S3バケットへのデータ投入
参考記事に記載されている通り進めていきます。
RAGで利用するドキュメントも参考記事に倣います。
CloudFormationスタックのデプロイが完了したら、CloudShell上で以下のコマンドを実施し、AWSの公式ドキュメント(PDFファイル)を作成したS3バケットにアップロードします。
後ほど詳述しますが、記事執筆時点で DynamoDB.pdf
についてはKendraへの同期が失敗します。
S3バケットへのデータ投入の対象から外して構いません。
# S3 バケット名を設定
BUCKET_NAME=<バケット名>
# S3 プレフィックスを設定
BUCKET_PREFIX=awsdoc
# AWS の公式ドキュメントの PDF ファイルをダウンロード
mkdir ${BUCKET_PREFIX}
cd ${BUCKET_PREFIX}
wget https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/dynamodb-dg.pdf -O DynamoDB.pdf
wget https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-dg.pdf -O Lambda.pdf
wget https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-ug.pdf -O VPC.pdf
wget https://docs.aws.amazon.com/ja_jp/kendra/latest/dg/kendra-dg.pdf -O Kendra.pdf
wget https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/route53-dg.pdf -O Route53.pdf
cd ..
### S3 バケットに PDF ファイルをアップロード
aws s3 cp ${BUCKET_PREFIX} s3://${BUCKET_NAME}/${BUCKET_PREFIX}/ --recursive
マネジメントコンソールから、S3バケットにPDFファイルがアップロードされていることを確認します。
Kendraデータソースの同期
参考記事に記載されている通り進めていきます。
データソースの画面から、Sync now
ボタンを押し、しばらく待ちます。
・・・おや(^^;)
5件のドキュメントをスキャンして、そのうち1件の処理に失敗したようです。
CloudWatch Logsでログを確認すると、DynamoDB.pdf
について以下のエラーが出ていました。
"IndexingStatus":"DocumentFailedToIndex","ErrorMessage":"Extracted document content size 5.902100 MB is larger than Kendra supported size 5.000000 MB"
AWSの公式ページでは、以下のように案内されています。
オリジナルのドキュメントは最大 50 MB のサイズで、ドキュメントごとに最大 5 MB のテキストを含めることができます。
(出典)Amazon Kendra の料金 - Amazon Web Services
DynamoDB.pdf
に含まれるテキスト情報が5.9MBで、Kendra側の上限をオーバーしてしまったというオチのようです。
ドキュメントのサイズについては注意が必要ですね。
DynamoDB.pdf
の同期は失敗しましたが、その他のドキュメントについては問題なく同期できているようなので、このまま前に進みます。
Kendraでの検索実行
参考記事に記載されている通り進めていきます。
Search indexed content の画面に移り、Default language of source documentsの設定を Japanese(ja)
に変えて、検索。
大丈夫そう!
3. DynamoDBテーブルの作成
チャット履歴をDynamoDBに保存させるため、DynamoDBのテーブルを作っておきます。
以下のCloudFormationテンプレートを使ってください。
AWSTemplateFormatVersion: '2010-09-09'
Description: DynamoDB for LangChain
Resources:
DynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: SessionId
AttributeType: S
KeySchema:
- AttributeName: SessionId
KeyType: HASH
BillingMode: PAY_PER_REQUEST
TableName: ChatMessageHistory
マネジメントコンソールから ChatMessageHistory
が作成されていることを確認します。
4. Lambda用IAMロールの作成
Lambdaから各種サービスを利用するためのIAMロールを作成します。
以下のCloudFormationテンプレートを使ってください。
AWSTemplateFormatVersion: '2010-09-09'
Description: IAM Role for Lambda
Resources:
LangChainFunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName : LangChainFunctionRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/AmazonKendraFullAccess
Policies:
- PolicyName: LangChainFunctionRolePolicy0
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: 'bedrock:*'
Resource: '*'
- Effect: Allow
Action: 'dynamodb:*'
Resource: "arn:aws:dynamodb:*:*:table/ChatMessageHistory"
マネジメントコンソールから LangChainFunctionRole
が作成されていることを確認します。
5. Lambdaレイヤーの作成
Lambda関数の標準状態では langchain / langchain-aws が利用できないため、Lambdaレイヤーを使ってパッケージを追加します。
今回はPython 3.12のLambdaを利用するので、Lambdaレイヤーに登録するzipファイルもPython 3.12の環境で作成する必要があります。
Lambdaレイヤーの作成は、以下の記事を参考にしながら実施しました。
CloudShell上のDockerを使う方法になっています。
この方法を試す前は、CloudShellの環境に直接Python 3.12を入れて langchain / langchain-aws をzip化しようとしていましたが、色々エラーが出て諦めました(Python 3.12のインストールで躓いた…)
Lambdaレイヤーの概要については以下の記事が分かりやすかったです。
【2024年春Ver.】AWS Lambda Layerの作成方法をわかりやすく解説【Python3.12】
Dockerfile作成
CloudShellを開いて、Dockerfileを作ります。
私はCloudShell上で vi Dockerfile-langchain-0.2.11
と叩いてファイルを作成しました。
FROM public.ecr.aws/lambda/python:3.12
WORKDIR /work
# システム更新と必要なパッケージのインストール
RUN dnf update && dnf install -y zip
RUN pip install --upgrade pip && \
pip install langchain==0.2.11 -t /python/lib/python3.12/site-packages/ && \
pip install langchain-community==0.2.11 -t /python/lib/python3.12/site-packages/ && \
pip install langchain-core==0.2.11 -t /python/lib/python3.12/site-packages/ && \
pip install langchain-aws==0.1.15 -t /python/lib/python3.12/site-packages/
# boto3など、不要なパッケージを削除
RUN rm -rf /python/lib/python3.12/site-packages/boto3* \
/python/lib/python3.12/site-packages/botocore* \
/python/lib/python3.12/site-packages/s3transfer* \
/python/lib/python3.12/site-packages/docutils* \
/python/lib/python3.12/site-packages/jmespath* \
/python/lib/python3.12/site-packages/chardet* \
/python/lib/python3.12/site-packages/six* \
/python/lib/python3.12/site-packages/python_dateutil*
ENTRYPOINT [""]
CMD zip -r langchain-0.2.11.zip /python/lib/python3.12/site-packages/
一部のパッケージを rm -rf
で削除していますが、これは、zipファイルが大きすぎると、Lambdaレイヤー登録時に Layers consume more than the available size of 262144000 bytes
と怒られるためです。
とりあえず消しても大丈夫そうなものを削除していますが、他にも消せるパッケージはあると思います。
イメージをビルドして、zip ファイルを生成
CloudShell上で以下コマンドを実行します。
$ docker build -t langchain-0.2.11 . -f Dockerfile-langchain-0.2.11
$ docker run -v "${PWD}":/work langchain-0.2.11
カレントディレクトリに langchain-0.2.11.zip
が作成されていますね。
Lambda レイヤーを登録
langchain-0.2.11.zip
をLambdaレイヤーに登録します。
CloudShellからzipファイルをダウンロードしてLambdaレイヤーの登録画面でアップロードする、という方法も可能ですが、CloudShellからAWS CLIコマンドで直接Lambdaレイヤーを登録する方が楽ですね。
$ aws lambda publish-layer-version \
--layer-name langchain-0-2-11 \
--zip-file fileb://langchain-0.2.11.zip \
--compatible-runtimes python3.12 \
--region us-east-1
マネジメントコンソールから、Lambdaレイヤーが登録されていることを確認します。
6. Lambda関数の作成
マネジメントコンソールからLambda関数を作っていきます。
ランタイムで Python 3.12
を、アーキテクチャで x86_64
を選択し、先ほど作成したIAMロールを関連づけます。
関数が作成できたら、レイヤーの追加
ボタンを押して、先ほど登録したLambdaレイヤーを追加します。
タイムアウト値を伸ばしておきましょう。
今回は長めに設定して、5分にしました。
次に、環境変数を設定します。
キー | 値 |
---|---|
INDEX_ID | ※先ほど作成したKendraインデックスのID |
MAX_TOKENS | 4096 |
MODEL_NAME | anthropic.claude-3-5-sonnet-20240620-v1:0 |
最後に、コードソース欄に以下のコードを入れて、Deploy
ボタンを押せば完了です。
import os
import json
import uuid
from langchain_aws import ChatBedrock
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain_community.chat_message_histories import DynamoDBChatMessageHistory
from langchain_community.retrievers import AmazonKendraRetriever
from langchain_community.retrievers.kendra import clean_excerpt
# 環境変数の値を取得
INDEX_ID = os.getenv('INDEX_ID')
MAX_TOKENS = os.getenv('MAX_TOKENS')
MODEL_NAME = os.getenv('MODEL_NAME')
# 使用するLLMモデルを宣言
llm = ChatBedrock(
model_id=MODEL_NAME,
model_kwargs={
"temperature": 0,
"max_tokens": int(MAX_TOKENS)
}
)
# Lambdaハンドラー
def lambda_handler(event, context):
# for debug
print(f"Received event: {json.dumps(event, ensure_ascii=False)}")
# イベントJSONから入力パラメーターを取得
session_id = event.get("session_id")
input_text = event.get("input_text")
# セッションIDが未設定の場合、新規にセッションIDをセットする (UUIDを使ったランダムな文字列)
if session_id is None:
session_id = str(uuid.uuid4())
# メインの処理を呼び出す
output_text = chat_conversation(session_id, input_text)
# Lambda関数のレスポンスを返す
return {
"session_id": session_id,
"output_text": output_text.encode('utf-8')
}
# メイン処理
def chat_conversation(session_id: str, input_text: str) -> str:
# Historyモジュール (Memoryの内容を外部記憶を使って永続化する)
history = DynamoDBChatMessageHistory(
table_name="ChatMessageHistory",
session_id=session_id,
)
# Retrieverモジュール (Kendraの情報を参照する)
retriever = AmazonKendraRetriever(
index_id=INDEX_ID,
attribute_filter={
"EqualsTo": {
"Key": "_language_code",
"Value": {"StringValue": "ja"},
},
},
page_content_formatter=original_content_formatter,
)
# Memoryモジュール (会話履歴を記憶する)
memory = ConversationBufferMemory(
chat_memory=history,
memory_key="chat_history",
input_key="question",
output_key="answer",
return_messages=True
)
# Chainモジュール (複数のモジュールを組み合わせて処理を行わせる)
chain = ConversationalRetrievalChain.from_llm(
llm,
chain_type="stuff",
retriever=retriever,
memory=memory,
return_source_documents=True,
verbose=True
)
chat_history = []
# LLMにプロンプトを与えて、応答を含む結果を得る
result = chain.invoke({"question": input_text})
# for debug
# print(f"Result: {result}")
# 得られた結果を型変換 (dictからstrへの変換)
output_text = json.dumps(result, default=str, ensure_ascii=False)
return output_text
# source などのメタデータもLLMに渡せるようにする
# (参考) https://qiita.com/s3kzk/items/be046a2ed62cd0663dbb#
def original_content_formatter(item):
text = ""
title = item.get_title()
if title:
text += f"Document Title: {title}\n"
excerpt = clean_excerpt(item.get_excerpt())
if excerpt:
text += f"Document Excerpt: \n{excerpt}\n"
## 以下2行を追加
if item.DocumentURI:
text += f"Document URI: {item.DocumentURI}\n"
return text
動かしてみる
最初は session_id
を指定せずに、メッセージ内容だけを指定して実行します。
{
"input_text": "Amazon Kendraの利点はなんですか"
}
以下の応答が返ってきました。
セッションIDとして f8f1ca03-6f49-4214-9edd-ff6109717ad8
が発行されています。
output_text
の中身をJSONチックに表示すると以下の通りです。
session_id
を指定していない最初のやり取りなので、chat_history
の中身が空になっています。
answer
の中身が最終的な回答になりますが、情報が多いに越したことはないので、今回は source_documents
の内容も返すようにしています。
{
"question": "Amazon Kendraの利点はなんですか",
"chat_history": [],
"answer": "Amazon Kendraの主な利点は以下の通りです:\n\n1. シンプルさ:\n - ドキュメントを管理するためのコンソールとAPIを提供しています。\n - シンプルな検索APIを使用して、ウェブサイトやモバイルアプリケーションなどのクライアントアプリケーションに簡単に統合できます。\n\n2. 接続性:\n - Microsoft SharePointなどのサードパーティのデータリポジトリやデータソースに接続できます。\n - データソースを使用して、ドキュメントのインデックス作成と検索を簡単に行うことができます。\n\n3. 高度な検索機能:\n - キーワードだけでなく、自然言語による複雑な質問にも対応できます。\n - 意味が曖昧な単語(例:「address」)の文脈を正しく推測し、関連情報を返すことができます。\n\n4. スケーラビリティとパフォーマンス:\n - 非常にスケーラブルで、高いパフォーマンス要求を満たすことができます。\n\n5. AWS統合:\n - Amazon S3やAmazon Lexなどの他のAWSサービスと緊密に統合されています。\n\n6. セキュリティ:\n - エンタープライズレベルのセキュリティを提供します。\n\nこれらの特徴により、Amazon Kendraは効率的で高度な企業向け検索ソリューションとなっています。",
"source_documents": [
{
"page_content": "Document Title: Kendra\nDocument Excerpt: \n. 1 Amazon Kendra のクエリ .. 1 Amazon Kendra の利点 . . 1 Amazon Kendra の利点 \nDocument URI: https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf\n",
"metadata": {
"result_id": "272801e4-d46f-414a-84e2-b61b6f151f64-9a12050f-9f4d-487a-aa0a-396abfa5a1c2",
"document_id": "s3://yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"source": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"title": "Kendra",
"excerpt": "................... 1 Amazon Kendra のクエリ ................................................................. ................................................................................. 1 Amazon Kendra の利点 ............................... .............................................. 1 Amazon Kendra の利点 ..................................................................",
"document_attributes": {
"_source_uri": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"_excerpt_page_number": 3
},
"score": "NOT_AVAILABLE"
}
},
{
"page_content": "Document Title: Kendra\nDocument Excerpt: \n 1 Amazon Kendra の利点 . . 1 Amazon Kendra の利点 2 Amazon Kendra Editions ..\nDocument URI: https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf\n",
"metadata": {
"result_id": "272801e4-d46f-414a-84e2-b61b6f151f64-86099966-2015-4f81-95c9-696724cd15d7",
"document_id": "s3://yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"source": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"title": "Kendra",
"excerpt": "................................................................................. 1 Amazon Kendra の利点 ............................... .............................................. 1 Amazon Kendra の利点 .................................................................. .................................................................................... 2 Amazon Kendra Editions ................................",
"document_attributes": {
"_source_uri": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"_excerpt_page_number": 3
},
"score": "NOT_AVAILABLE"
}
},
{
"page_content": "Document Title: Kendra\nDocument Excerpt: \nAmazon Kendra 開発者ガイド キーワードおよび自然言語に関する質問 - 意味がはっきりしない、複雑な会話内容を含む質問。 例え ば、キーノートのアドレス。 Amazon Kendra では、複数の文脈上の意味を持つ「address」のよう な単語が見つかると、検索クエリの意味を正しく推測し、関連情報を返します。 Amazon Kendra の利点 Amazon Kendra は非常にスケーラブルで、パフォーマンス要求を満たすことができ、Amazon S3 や Amazon Lex などの他の AWS のサービスと緊密に統合され、エンタープライズレベルのセキュリ ティを提供します。 Amazon Kendra を使用する利点のいくつかを以下に示します。 シンプルさ - Amazon Kendra は、検索するドキュメントを管理するためのコンソールと API を提供 します。 シンプルな検索 API を使用して、Amazon Kendra をウェブサイトやモバイルアプリケー ションなどのクライアントアプリケーションに統合できます。 接続性 - Amazon Kendra は、Microsoft SharePoint などのサードパーティのデータリポジトリまたは データソースに接続できます。 データソースを使用して、ドキュメントのインデックス作成と検索を 簡単に行うことができます。\nDocument URI: https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf\n",
"metadata": {
"result_id": "272801e4-d46f-414a-84e2-b61b6f151f64-ad75a0ad-6ebd-4336-8b21-f9288b15a519",
"document_id": "s3://yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"source": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"title": "Kendra",
"excerpt": "Amazon Kendra 開発者ガイド キーワードおよび自然言語に関する質問 - 意味がはっきりしない、複雑な会話内容を含む質問。 例え ば、キーノートのアドレス。 Amazon Kendra では、複数の文脈上の意味を持つ「address」のよう な単語が見つかると、検索クエリの意味を正しく推測し、関連情報を返します。 Amazon Kendra の利点 Amazon Kendra は非常にスケーラブルで、パフォーマンス要求を満たすことができ、Amazon S3 や Amazon Lex などの他の AWS のサービスと緊密に統合され、エンタープライズレベルのセキュリ ティを提供します。 Amazon Kendra を使用する利点のいくつかを以下に示します。 シンプルさ - Amazon Kendra は、検索するドキュメントを管理するためのコンソールと API を提供 します。 シンプルな検索 API を使用して、Amazon Kendra をウェブサイトやモバイルアプリケー ションなどのクライアントアプリケーションに統合できます。 接続性 - Amazon Kendra は、Microsoft SharePoint などのサードパーティのデータリポジトリまたは データソースに接続できます。 データソースを使用して、ドキュメントのインデックス作成と検索を 簡単に行うことができます。",
"document_attributes": {
"_source_uri": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"_excerpt_page_number": 15
},
"score": "NOT_AVAILABLE"
}
}
]
}
続いて、先ほど発行された session_id
を指定して、文脈の理解が問われそうな質問をしてみます。
※先ほどKendraの話をしていたので、言外にKendraのコストについて質問している。
{
"session_id": "f8f1ca03-6f49-4214-9edd-ff6109717ad8",
"input_text": "コストはどれくらいかかりますか。"
}
output_text
の中身をJSONチックに表示すると以下の通りです。
chat_history
に前回のやり取りが記録されているのが分かります。
また、answer
の内容から、ちゃんとKendraに関する話題と認識して回答してくれたようです。
{
"question": "コストはどれくらいかかりますか。",
"chat_history": [
{
"content": "Amazon Kendraの利点はなんですか"
},
{
"content": "Amazon Kendraの主な利点は以下の通りです:\n\n1. シンプルさ:\n - ドキュメントを管理するためのコンソールとAPIを提供しています。\n - シンプルな検索APIを使用して、ウェブサイトやモバイルアプリケーションなどのクライアントアプリケーションに簡単に統合できます。\n\n2. 接続性:\n - Microsoft SharePointなどのサードパーティのデータリポジトリやデータソースに接続できます。\n - データソースを使用して、ドキュメントのインデックス作成と検索を簡単に行うことができます。\n\n3. 高度な検索機能:\n - キーワードだけでなく、自然言語による複雑な質問にも対応できます。\n - 意味が曖昧な単語(例:「address」)の文脈を正しく推測し、関連情報を返すことができます。\n\n4. スケーラビリティとパフォーマンス:\n - 非常にスケーラブルで、高いパフォーマンス要求を満たすことができます。\n\n5. AWS統合:\n - Amazon S3やAmazon Lexなどの他のAWSサービスと緊密に統合されています。\n\n6. セキュリティ:\n - エンタープライズレベルのセキュリティを提供します。\n\nこれらの特徴により、Amazon Kendraは効率的で高度な企業向け検索ソリューションとなっています。"
}
],
"answer": "申し訳ありませんが、提供された文脈の中にAmazon Kendraの具体的な価格情報は含まれていません。Amazon Kendraの正確な価格設定については、AWSの公式ウェブサイトやAmazon Kendraの価格ページを確認するのが最良の方法です。価格は使用量、選択したエディション、データ量などの要因によって変わる可能性があります。",
"source_documents": [
{
"page_content": "Document Title: Kendra\nDocument Excerpt:\n例 えば、各都市のカテゴリでファセット検索を行うには、すべての都市カテゴリを含む _category カ スタムドキュメント属性を使用します。 提案する回答 機械学習で生成された回答をユーザーのクエリに追加します。 例: 「このコースはどれほど難しいで すか?」 Amazon Kendra はコースの難しさを指しているすべてのドキュメントで最も関連性の高い テキストを取得し、最も関連性の高い回答を提案できます。 よくある質問 よくある質問への回答を得るには、よくある質問ドキュメントを追加します。 例: 「このコースを完 了するのに何時間かかりますか?」 Amazon Kendra はこの質問に対する回答を含むよくある質問ド キュメントを使用して、正しい答えを出すことができます。 Sort 検索結果のソートを追加して、ユーザーが関連性、作成時刻、最終更新時刻、その他のソート基準で 結果を整理できるようにします。\nDocument URI: https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf\n",
"metadata": {
"result_id": "d7699b54-62d5-4e50-9f1c-9a764b136b03-77b435eb-abff-4036-84f9-2cf548814913",
"document_id": "s3://yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"source": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"title": "Kendra",
"excerpt": "例 えば、各都市のカテゴリでファセット検索を行うには、すべての都市カテゴリを含む _category カ スタムドキュメント属性を使用します。 提案する回答 機械学習で生成された回答をユーザーのクエリに追加します。 例: 「このコースはどれほど難しいで すか?」 Amazon Kendra はコースの難しさを指しているすべてのドキュメントで最も関連性の高い テキストを取得し、最も関連性の高い回答を提案できます。 よくある質問 よくある質問への回答を得るには、よくある質問ドキュメントを追加します。 例: 「このコースを完 了するのに何時間かかりますか?」 Amazon Kendra はこの質問に対する回答を含むよくある質問ド キュメントを使用して、正しい答えを出すことができます。 Sort 検索結果のソートを追加して、ユーザーが関連性、作成時刻、最終更新時刻、その他のソート基準で 結果を整理できるようにします。",
"document_attributes": {
"_source_uri": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"_excerpt_page_number": 152
},
"score": "NOT_AVAILABLE"
}
},
{
"page_content": "Document Title: Kendra\nDocument Excerpt:\n例: \"Amazon Kendra\" \"pricing\" を含むド キュメント。 上のいずれかの演算子を組み合わせて使用できます。 演算子や非常に複雑なクエリを過度に使用すると、クエリのレイテンシーに影響を与える可能性があ るので注意してください。 ワイルドカードは、レイテンシーの点で非常にコストのかかる演算子の 1 高度なクエリ構文による検索 1069 Amazon Kendra 開発者ガイド つです。 一般的に、使用する語句や演算子が多いほど、レイテンシーへの影響が大きくなります。 レ イテンシーに影響するその他の要因には、インデックス作成されたドキュメントの平均サイズ、イン デックスのサイズ、検索結果のフィルタリング、 Amazon Kendra インデックスの全体的な負荷など があります。 ブール値 ブール値演算子の AND、OR、NOT を使用して、単語を組み合わせたり、除外したりすることができ ます。 ブール演算子を使用した例を次に示します。 amazon AND sports Amazon Prime Video のスポーツまたはその他の類似コンテンツなど、テキストに「amazon」と\nDocument URI: https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf\n",
"metadata": {
"result_id": "d7699b54-62d5-4e50-9f1c-9a764b136b03-a1bd1300-0a18-412e-a1ab-08d0e2e4442f",
"document_id": "s3://yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"source": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"title": "Kendra",
"excerpt": "例: \"Amazon Kendra\" \"pricing\" を含むド キュメント。 上のいずれかの演算子を組み合わせて使用できます。 演算子や非常に複雑なクエリを過度に使用すると、クエリのレイテンシーに影響を与える可能性があ るので注意してください。 ワイルドカードは、レイテンシーの点で非常にコストのかかる演算子の 1 高度なクエリ構文による検索 1069 Amazon Kendra 開発者ガイド つです。 一般的に、使用する語句や演算子が多いほど、レイテンシーへの影響が大きくなります。 レ イテンシーに影響するその他の要因には、インデックス作成されたドキュメントの平均サイズ、イン デックスのサイズ、検索結果のフィルタリング、 Amazon Kendra インデックスの全体的な負荷など があります。 ブール値 ブール値演算子の AND、OR、NOT を使用して、単語を組み合わせたり、除外したりすることができ ます。 ブール演算子を使用した例を次に示します。 amazon AND sports Amazon Prime Video のスポーツまたはその他の類似コンテンツなど、テキストに「amazon」と",
"document_attributes": {
"_source_uri": "https://s3.us-east-1.amazonaws.com/yuki-ink-dev-kendra-ds-bucket-xxxxxxxxxxxx/awsdoc/Kendra.pdf",
"_excerpt_page_number": 14
},
"score": "NOT_AVAILABLE"
}
}
]
}
終わりに
以上、LangChainでRAGアプリを作ってみました。
LangChainのバージョンによってエラーが出たり出なかったりしたので、その点が一番苦労しました…
この機会に最新のLangChainを触れてよかったなぁと思います。
何かの助けになれば幸いです。
参考にした記事