Knowledge base for Amazon Bedrockがマネージドで手軽そうなので試してみました。
S3バケットを作成
Knowledge baseで使用するS3バケットをus-east-1で作成します。
knowledge baseと異なるリージョンで作成すると以下のようなエラーが発生します。
Encountered error: The authorization header is malformed; the region 'us-east-1' is wrong; expecting 'ap-northeast-1' (Service: S3, Status Code: 400, Request ID: FN180R0R8AMGPMG4, Extended Request ID: EAHFoSfHXsAoZQLBXsJyuYU5te9OGwWUxJNbHMyVRiQBR3z2q6AFt8Qkv72U0PjKtg+EWenD4EY=). Call to Amazon S3 Source did not succeed.
Knowledge baseを作成
-
「Amazon Bedrock」サービスから、Knowledge baseを選択
-
確認画面が表示されます。「Create Knowledge base」をクリックします。
すると、「Preparing vector database in Amazon Opensearch Serverless. This process may take several minutes to complete.」と表示され、しばらく待ちます。
データを投入
今回は、以下のサンプルをknowledge baseに突っ込んでみます。
Cloud9で以下のコマンドを実行します。
$ git clone https://github.com/aws-samples/amazon-bedrock-samples
$ aws s3 cp --recursive amazon-bedrock-samples s3://amazon-bedrock-samples-20231223
「Sync」ボタンでSyncを開始します。しばらく時間がかかります。
完了しましたが、以下のエラーが出ました。
Error warning
Ignored 1 files as they were larger than service limit of MaximumFileSizeSupported: 52428800 bytes
Encountered error: Ignored 2 files as their file format was not supported.. Call to Amazon S3 Source did not succeed.
Knowledge baseでサポートするファイルは以下の通りのため、
画像ファイルなどでエラーが発生していると思います。気にせず進めます。
- Plain text (.txt)
- Markdown (.md)
- HyperText Markup Language (.html)
- Microsoft Word document (.doc/.docx)
- Comma-separated values (.csv)
- Microsoft Excel spreadsheet (.xls/.xlsx)
- Portable Document Format (.pdf)
The maximum file size for a single file is 50 MB.
とりあえず試してみます。
ipynbはKnowledge baseの対象になかったですが、認識しているようです。
Knowledge baseに登録されていることは教えてくれますが、
タスクの依頼は、「Sorry, I am unable to assist you with this request.」の一点張り。。。
機嫌を損ねたのかと思い、おだててみましたが同じでした。
Pythonから実行
import boto3
import json
bedrock_agent = boto3.client(
service_name='bedrock-agent-runtime',
region_name='us-east-1'
)
prompt = """\n\nHuman:
あなたはAWSのエキスパートです。
agents/agentsforbedrock-retailagent/open-api-spec/customerservicebot.jsonを参考にAWS SAMのtemplate.yamlを作成してください。
\n\nAssistant:
"""
response = bedrock_agent.retrieve_and_generate(
input={
'text': prompt,
},
retrieveAndGenerateConfiguration={
'type': 'KNOWLEDGE_BASE',
'knowledgeBaseConfiguration': {
'knowledgeBaseId': '作成したIDを入力',
'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-v2:1',
}
}
)
print(response['output'])
{'text': '残念ながら、検索結果にtemplate.yamlファイルの作成方法が含まれていませんでした。OpenAPI仕様ファイルは参照できますが、SAMテンプレートファイルの作成手順は不明です。
Claudeは、SAMテンプレートの作り方を知っているはずなのに、かなり冷たい回答です。
JSONだから読めないのかと思ったら、内容はわかっているようです。
Text Playgroundで通常実行
普通のClaude2に質問してみました。
今度は、SAMテンプレートを作成してくれました。
Knowledge baseを使うと劣化するのかわかりませんが、かなり冷たい回答ばかりでした。
Human:
あなたはAWSのエキスパートです。以下のOpenAPI仕様ファイルをもとに、AWS SAMのtemplate.yamlを作成してください。
```json
{
"openapi": "3.0.0",
"info": {
"title": "Customer Service Bot API",
"version": "1.0.0",
"description": "Customer service APIs for a retail store selling shoes"
},
"paths": {
"/customer/{CustomerName}": {
"get": {
"summary": "Get customer information",
"description": "Based on provided customer name, return customer information like customer ID, preferred activity and others",
"operationId": "getCustomerInfo",
"parameters": [{
"name": "CustomerName",
"in": "path",
"description": "Customer Name",
"required": true,
"schema": {
"type": "string"
}
}],
"responses": {
"200": {
"description": "Get customer information",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"CustomerID": {
"type": "int",
"description": "This is the Customer ID used to place the order"
},
"Addr1": {
"type": "string",
"description": "Customer billing address line1"
},
"Addr2": {
"type": "string",
"description": "Customer billing address line2"
},
"City": {
"type": "string",
"description": "Customer billing city"
},
"State": {
"type": "string",
"description": "Customer billing state"
},
"Zipcode": {
"type": "string",
"description": "Customer billing zipcode"
},
"PreferredActivity": {
"type": "string",
"description": "Customer preferred activity"
},
"ShoeSize": {
"type": "int",
"description": "Customer shoe size"
},
"OtherInfo": {
"type": "string",
"description": "Additional information about customer like interests"
}
}
}
}
}
}
}
}
}
},
"/place_order": {
"get": {
"summary": "Sub task to place an order on behalf of the customer",
"description": "Place an order for a shoe by creating an Order record and updating inventory in the database",
"operationId": "placeshoeOrder",
"parameters": [{
"name": "ShoeID",
"in": "query",
"description": "Shoe ID to place an order",
"required": true,
"schema": {
"type": "int"
}
},
{
"name": "CustomerID",
"in": "query",
"description": "Customer ID to place an order",
"required": true,
"schema": {
"type": "int"
}
}],
"responses": {
"200": {
"description": "Order has been placed",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Your order has been placed"
}
}
}
}
}
}
}
}
},
"/check_inventory": {
"get": {
"summary": "Returns all details related to shoes, including inventory details",
"description": "Checks inventory for shoes and returns all availale information about available shoes, including shoe ID, shoe colors, inventory, best fit activity, style description and price ",
"operationId": "checkShoeInventory",
"responses": {
"200": {
"description": "Returns Shoe information",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"ShoeID": {
"type": "int",
"description": "This is the shoe ID for this shoe"
},
"BestFitActivity": {
"type": "string",
"description": "Best fit activity for this shoe"
},
"StyleDesc": {
"type": "string",
"description": "Detailed description of the shoe"
},
"ShoeColors": {
"type": "string",
"description": "The colors of this shoe"
},
"Price": {
"type": "string",
"description": "Price of this shoe"
},
"InvCount": {
"type": "int",
"description": "Inventory count"
}
}
}
}
}
}
}
}
}
}
}
```
Assistant:
Here is the AWS SAM template.yaml generated from the OpenAPI spec:
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
Customer service APIs for a retail store selling shoes
Globals:
Api:
OpenApiVersion: 3.0.0
EndpointConfiguration: REGIONAL
Resources:
GetCustomerInfoFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: get_customer_info/
Handler: app.lambda_handler
Runtime: python3.8
Events:
GetCustomerInfo:
Type: Api
Properties:
Path: /customer/{CustomerName}
Method: get
PlaceShoeOrderFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: place_shoe_order/
Handler: app.lambda_handler
Runtime: python3.8
Events:
PlaceShoeOrder:
Type: Api
Properties:
Path: /place_order
Method: get
CheckShoeInventoryFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: check_shoe_inventory/
Handler: app.lambda_handler
Runtime: python3.8
Events:
CheckShoeInventory:
Type: Api
Properties:
Path: /check_inventory
Method: get
Outputs:
GetCustomerInfoApi:
Description: "API Gateway endpoint URL for GetCustomerInfo function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Stage/customer/{CustomerName}"
PlaceShoeOrderApi:
Description: "API Gateway endpoint URL for PlaceShoeOrder function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Stage/place_order"
CheckShoeInventoryApi:
Description: "API Gateway endpoint URL for CheckShoeInventory function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Stage/check_inventory"
```
The key aspects are:
- Each path in the OpenAPI spec is defined as an AWS::Serverless::Function resource
- The function CodeUri points to the implementation code for that function
- API Gateway endpoints are configured for each path/method combination using Api event
- Output section defines the endpoint URLs for each function
Let me know if you have any other questions!
LangChainで実装
LangChainでもKnowledge baseが使えるようなので試してみました。
from langchain.llms import Bedrock
from langchain.chains import RetrievalQA
from langchain.retrievers.bedrock import AmazonKnowledgeBasesRetriever
llm = Bedrock(
region_name='us-east-1',
model_id='anthropic.claude-v2:1',
model_kwargs={
"max_tokens_to_sample":4096,
"temperature":0,
"top_k":250,
"top_p":1,
"stop_sequences": ["\n\nHuman"]
}
)
retriever = AmazonKnowledgeBasesRetriever(
knowledge_base_id="作成したIDを入力",
region_name="us-east-1",
retrieval_config={
"vectorSearchConfiguration": {
"numberOfResults": 4
}
}
)
prompt = """
\n\nHuman:
あなたはAWSのエキスパートです。
以下のOpenAPI仕様が書かれたファイルをもとに、AWS SAMのtemplate.yamlを作成してください。
agents/agentsforbedrock-retailagent/open-api-spec/customerservicebot.json
\n\nAssistant:
"""
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
verbose=True
)
result = qa_chain.run(prompt)
print(result)
以下が結果です。
かなり改善されたように思いますが、パスが{proxy+}になっているあたり手抜き感があります。。。
> Entering new RetrievalQA chain...
> Finished chain.
はい、AWS SAMのtemplate.yamlファイルを作成するのを助けましょう。
まず、提供されたOpenAPI仕様ファイル(customerservicebot.json)を確認します。このファイルには、エージェントが使用できるAPIの詳細が定義されています。
次に、その情報を使用してSAMのtemplate.yamlを以下のように作成します:
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: An AWS SAM template for creating a customer service bot agent
Globals:
Function:
Timeout: 10
MemorySize: 128
Tracing: Active
Resources:
CustomerServiceBotFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: customer_service_bot_code/
Handler: app.lambdaHandler
Runtime: python3.7
Policies:
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
Events:
CatchAll:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
Outputs:
CustomerServiceBotApi:
Description: "API Gateway endpoint URL"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
```
このtemplateでは、CustomerServiceBotFunctionというLambda関数を定義しています。これがOpenAPI仕様に定義されたAPIを実装する関数になります。
またAPI Gatewayも定義して、このLambda関数を公開するエンドポイントを作成しています。
必要に応じてこのtemplateをカスタマイズしていただければと思います。ご不明な点があれば遠慮なくご質問