Amazon BedrockのEmbeddingsを試しました。（良さげです）

Amazon BedrockのEmbeddingsを試しました。

## 環境

* Ubuntu 22.04 (.devcontainer)
* Python 3.10
* VSCode + Python拡張 + Jupyter拡張

1. ライブラリーのインストール
    
    ```python
    %pip install -q -U \
      boto3==1.28.57 \
      langchain==0.0.303 \
      unstructured \
      qdrant-client
    ```

## Embeddingsしてベクトルデータベースを作成

1. [EC2のFAQ](https://aws.amazon.com/jp/ec2/faqs/)を取得

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/ab964d42-2fb1-1f89-586b-5ed26f4f1eea.png)
    
    ```python
    %%bash
    wget https://aws.amazon.com/jp/ec2/faqs/ -O ec2_faq.html
    ```
    
1. HTMLを読み込む
    
    ```python
    from langchain.document_loaders import UnstructuredHTMLLoader
    
    loader = UnstructuredHTMLLoader(file_path='ec2_faq.html', mode='single')
    
    data = loader.load()
    ```

1. チャンクに分割する

    `Titan Embeddings`モデルで渡せるサイズに収まるようにチャンク分割します。
    
    ```python
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=(512*0.6), chunk_overlap=512*0.1)
    splited_data = text_splitter.split_documents(data)
    ```
    
    一つのdataはこんな感じ
    
    ```
    Document(page_content='ページの内容\n\n全般\n\nインスタンスタイプ\n\nストレージ\n\nネットワークとセキュリティ\n\nマネジメント\n\n請求と購入のオプション\n\nプラットフォーム\n\nワークロード\n\n前世代向けの Nitro System サポート\n\n全般\n\n概要 |\xa0EC2 オンデマンドインスタンス制限 |\xa0EC2 SMTP エンドポイントポリシーへの変更 |\xa0サービスレベルアグリーメント (SLA)\n\n概要\n\nQ: Amazon Elastic Compute Cloud (Amazon EC2) とは何ですか?', metadata={'source': 'ec2_faq.html'})
    ```

1. Bedrock Embeddingsを作成。使用するモデルはAmazon Titan Embeddings

    ```python
    import boto3
    from langchain.embeddings import BedrockEmbeddings
    
    embeddings = BedrockEmbeddings(
      client=boto3.client('bedrock-runtime'),
      model_id='amazon.titan-embed-text-v1'
    )
    ```

1. Embeddingsの実行。[Qdrant](https://qdrant.tech/)というベクトルデータベースを使用します。

    ```python
    from langchain.vectorstores import Qdrant
    
    db = Qdrant.from_documents(
      documents=splited_data, 
      embedding=embeddings, 
      path='./local_qdrant',
      collection_name='ec2', 
      distance_func='Dot')
    ```

    `./local_qdrant`にベクトルデータが格納されます。

    ```python
    %%bash
    tree ./local_qdrant
    ```
    ```
    ./local_qdrant
    ├── collection
    │   └── ec2
    │       └── storage.sqlite
    └── meta.json
    
    2 directories, 2 files
    ```

    実態はSQLiteのようです。

## ベクトルデータベースを使用してFAQ検索

1. プロンプトテンプレートを作成。Claudeの求める形式のテンプレートにします。（Human:とAssistant:のところ）

    ```python
    from langchain.prompts import PromptTemplate
    
    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']
    )
    ```

1. Claude InstantのLLMを作成。

    ```python
    from langchain.llms import Bedrock
    
    llm = Bedrock(
        client=boto3.client('bedrock-runtime'),
        model_id="anthropic.claude-instant-v1",
        verbose=True
    )
    ```

1. RetrievalQAを作成。

    ```python
    from langchain.chains import RetrievalQA
    
    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)
    ```

1. 質問する。

    ```python
    answer = qa('EC2とはなんですか？')
    ```
    ```
    {'query': 'EC2とはなんですか？',
     'result': ' Amazon Elastic Compute Cloud(Amazon EC2)とは、Amazonが提供するクラウドコンピューティングサービスの一つです。EC2を使うとオンデマンドで必要な数の仮想サーバ(インスタンスといいます)を利用できます。ストレージ、ネットワーク、セキュリティなどのインフラ資源を管理する必要はなく、安価にスケーラブルな計算能力をサービスとして利用できます。',
     'source_documents': [Document(page_content='ページの内容\n\n全般\n\nインスタンスタイプ\n\nストレージ\n\nネットワークとセキュリティ\n\nマネジメント\n\n請求と購入のオプション\n\nプラットフォーム\n\nワークロード\n\n前世代向けの Nitro System サポート\n\n全般\n\n概要 |\xa0EC2 オンデマンドインスタンス制限 |\xa0EC2 SMTP エンドポイントポリシーへの変更 |\xa0サービスレベルアグリーメント (SLA)\n\n概要\n\nQ: Amazon Elastic Compute Cloud (Amazon EC2) とは何ですか?', metadata={'source': 'ec2_faq.html'}),
      Document(page_content='ページの内容\n\n全般\n\nインスタンスタイプ\n\nストレージ\n\nネットワークとセキュリティ\n\nマネジメント\n\n請求と購入のオプション\n\nプラットフォーム\n\nワークロード\n\n前世代向けの Nitro System サポート\n\n全般\n\n概要 |\xa0EC2 オンデマンドインスタンス制限 |\xa0EC2 SMTP エンドポイントポリシーへの変更 |\xa0サービスレベルアグリーメント (SLA)\n\n概要\n\nQ: Amazon Elastic Compute Cloud (Amazon EC2) とは何ですか?', metadata={'source': 'ec2_faq.html'})]}
    ```

    > Amazon Elastic Compute Cloud(Amazon EC2)とは、Amazonが提供するクラウドコンピューティングサービスの一つです。EC2を使うとオンデマンドで必要な数の仮想サーバ(インスタンスといいます)を利用できます。ストレージ、ネットワーク、セキュリティなどのインフラ資源を管理する必要はなく、安価にスケーラブルな計算能力をサービスとして利用できます。

    回答返ってきました！良さげです！

    :::note
    claude-instant-v1でも違和感ないですね。コストも考慮すると使い所ありそうです
   :::