0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Knowledge base for Amazon Bedrockは冷たい回答をする?(LangChainで解決?)

Last updated at Posted at 2023-12-23

Knowledge base for Amazon Bedrockがマネージドで手軽そうなので試してみました。

S3バケットを作成

Knowledge baseで使用するS3バケットをus-east-1で作成します。

image.png

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を作成

  1. 「Amazon Bedrock」サービスから、Knowledge baseを選択

  2. 名前を入力します。
    image.png

  3. 必要に応じてタグを設定し、「Next」をクリックします。
    image.png

  4. データソース名と最初に作ったバケットを指定し、「Next」をクリックします。
    image.png

  5. ベクトルデータベースに利用する基盤モデルとデータベースを選択します。デフォルトで「Next」を選択しました。
    image.png

  6. 確認画面が表示されます。「Create Knowledge base」をクリックします。

すると、「Preparing vector database in Amazon Opensearch Serverless. This process may take several minutes to complete.」と表示され、しばらく待ちます。

完了すると以下のメッセージが表示されます。
image.png

データを投入

今回は、以下のサンプルを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を開始します。しばらく時間がかかります。

image.png

完了しましたが、以下のエラーが出ました。

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の対象になかったですが、認識しているようです。

image.png

Knowledge baseに登録されていることは教えてくれますが、

image.png

タスクの依頼は、「Sorry, I am unable to assist you with this request.」の一点張り。。。
機嫌を損ねたのかと思い、おだててみましたが同じでした。

image.png

image.png

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だから読めないのかと思ったら、内容はわかっているようです。

image.png

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をカスタマイズしていただければと思います。ご不明な点があれば遠慮なくご質問
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?