前回の投稿で、Amazon BedrockのEmbeddingsを試しました。
LLMと独自ナレッジを組み合わせたFAQに活用できそうです。
ベクトルデータベースのQdrantでは、単体のサーバーとして構築する方法だけでなく、メモリー上で動作させたりローカルファイルシステムで動作させることができます。
ローカルファイルとして動作するということは、 Lambda化できるのではないか!? と思い、挑戦しました。
手順
-
SAMプロジェクトを作成
sam init
コマンドを実行し、SAMプロジェクトを生成します。言語はPython 3.10、Zipでデプロイの方式を選択しました。 -
hello_world/requirements.txt
に必要なライブラリーを追加します。バージョンは2023/9/30時点のものです。GA直後のため、今後バージョンアップするものと思われます。boto3==1.28.57 langchain==0.0.303 qdrant-client
-
Qdrantのデータベースファイルを
hello_world
ディレクトリに格納します。
hello_worldディレクトリ内の配置はこのようになります。hello_world/ ├── app.py ├── __init__.py ├── local_qdrant │ ├── collection │ │ └── ec2 │ │ └── storage.sqlite │ └── meta.json └── requirements.txt
-
app.pyにロジックを記述します。
1点ひねった部分があります。
Lambda上での動作時、ファイルシステムが/tmpを除いてリードオンリーになります。Qdrantに接続した際に.lock
ファイルを作成しようとするのですが、作成できないのでエラーとなります。
エラーを回避するため、Qdrantのファイルを/tmpにコピーしています。shutil.copytree('./local_qdrant', '/tmp/local_qdrant')
app.py
import json import boto3 import shutil from langchain.chains import RetrievalQA from langchain.embeddings import BedrockEmbeddings from langchain.llms import Bedrock from langchain.prompts import PromptTemplate from langchain.vectorstores import Qdrant from qdrant_client import QdrantClient shutil.copytree('./local_qdrant', '/tmp/local_qdrant') # データベースファイルを/tmpにコピー embeddings = BedrockEmbeddings( client=boto3.client('bedrock-runtime'), model_id='amazon.titan-embed-text-v1' ) qdrant_client=QdrantClient(path='/tmp/local_qdrant') # /tmpのデータベースファイルを使用する db = Qdrant( client=qdrant_client, collection_name='ec2', embeddings=embeddings, ) prompt_template = '''Human: Text: {context} Question: {question} Answer the question based on the text provided. If the text doesn't contain the answer, reply that the answer is not available. Assistant: ''' PROMPT = PromptTemplate( template=prompt_template, input_variables=['context', 'question'] ) llm = Bedrock( client=boto3.client('bedrock-runtime'), model_id="anthropic.claude-instant-v1", verbose=True ) chain_type_kwargs = {"prompt": PROMPT} qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=db.as_retriever(), chain_type_kwargs=chain_type_kwargs, return_source_documents=True) def lambda_handler(event, context): answer = qa(event["input"]) print(answer) return { "statusCode": 200, "body": answer["result"], }
-
template.yamlを編集
- メモリーを512MB以上にする
- タイムアウト時間を1分程度にする
- Bedrockへのアクセス権限を付与する
-
sam build
とsam deploy
を実行
以上です。これでベクトルDBを内部に保持したLambdaができました。
呼び出し
- テストイベント
{
"input": "EC2とは?"
}
- レスポンス
{
"statusCode": 200,
"body": " EC2 (Amazon Elastic Compute Cloud) は、Amazon が提供するクラウドコンピューティングサービスです。EC2はクラウド内で「コンピューティング」を可能にするサービスで、ユーザーはEC2のウェブサービスインターフェイスを使用して必要な機能やリソースを簡単に取得および設定できるとのことです。つまりEC2はAmazonのクラウド上で仮想サーバー(インスタンス)を作成、管理、使用できるサービスです。"
}
やったね!!