すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB RDS:ApsaraDB RDS for PostgreSQLの上にLLM駆動の専用チャットボットを構築する

最終更新日:Jan 16, 2024

ChatGPTの発展に伴い、LLM (large language Model) とAI (generative artificial intelligence) は、書き込み、画像生成、コード最適化、情報検索など、さまざまな分野で重要な役割を果たし始めています。 LLMは、個々のユーザーや企業に役立ちます。 LLMは、エコシステムの革新を加速し、スーパーアプリケーションの構築をリードします。 このトピックでは、ApsaraDB RDS for PostgreSQLの上に専用チャットボットを構築する方法について説明します。

背景情報

LLMとジェネレーティブAIを使用して、特定のビジネスシナリオ専用のAI搭載アプリケーションを構築する企業や個人ユーザーが増えています。 LLMは、一般的な問題の解決において優れたパフォーマンスを発揮します。 ただし、LLMは、コーパストレーニングと大規模なモデル生成の制限により、適時性と専門知識の要件を満たすことができません。 情報化時代では、企業は知識ベースを頻繁に更新します。 ドキュメント、画像、オーディオファイル、およびビデオを含む業界の知識ベースは、機密であるか、または公衆に開示することができない。 企業がLLMを使用して業界向けのAIを利用したアプリケーションを構築したい場合、企業はトレーニングのためにナレッジベースを常にLLMにインポートする必要があります。

以下のリストは、一般的なトレーニングアプローチについて説明します。

  • 微調整: 既存のモデルの重みを微調整するために新しいデータセットが提供され、データセットは必要な効果を得るために常に更新されます。 このアプローチは、小さなデータセットまたはタスク固有のモデルに基づいてモデルをトレーニングするのに適しています。 しかし、このアプローチはコストがかかり、集中的なトレーニングを必要とする。

  • プロンプトチューニング: 必要な効果を得るために、モデルの重みの代わりにプロンプトが調整されます。 迅速なチューニングは、計算コストが少なく、リソースとトレーニング時間が少なく、微調整よりも柔軟性があります。

次のリストでは、ApsaraDB RDS for PostgreSQLの上にチャットボットを構築する利点について説明します。

  • ApsaraDB RDS for PostgreSQLは、業界のリアルタイムデータや専門知識をベクター埋め込みに変換するために使用できるpgvector拡張機能を提供します。 ApsaraDB RDS for PostgreSQLは埋め込みを保存し、ベクターベースの検索を高速化し、特定のプライベートドメインに関するQ&Aの精度を向上させます。

  • ApsaraDB RDS for PostgreSQLは、オンラインデータベーストランザクションとデータストレージタスクを同時に実行するために使用できる高度なオープンソースオンライントランザクション処理 (OLTP) データベースシステムです。 たとえば、ApsaraDB RDS For PostgreSQLを使用して、インタラクション、履歴レコード、およびトランザクションのチャットに費やされた時間を処理できます。 ApsaraDB RDS for PostgreSQLは、さまざまな機能を提供する一般的なデータベースシステムです。 これにより、プライベートドメインサービスの構築が容易になり、そのアーキテクチャが使いやすくなります。

  • pgvector拡張機能は、開発者コミュニティやオープンソースのPostgreSQLデータベースで広く使用されています。 さらに、ChatGPT Retrieval Pluginなどのツールは、最も早い機会にPostgreSQLデータベースでサポートされます。 ApsaraDB RDS for PostgreSQLは広く適用されており、ベクターベースの検索を実行するために完全にサポートされています。 また、豊富なツールとリソースを提供します。

このトピックでは、pgvector拡張機能とOpenAI埋め込みを使用して専用のチャットボットを構築する方法の例を示します。 pgvector拡張機能は、ApsaraDB RDS for PostgreSQLによって提供され、ベクトル類似性検索を実行します。 拡張の詳細については、「pgvector拡張を使用して高次元ベクトル類似性検索を実行する」をご参照ください。

前提条件

  • 次の要件を満たすApsaraDB RDS for PostgreSQLインスタンスが作成されます。

    • RDSインスタンスはPostgreSQL 14以降を実行します。

    • RDSインスタンスのマイナーエンジンバージョンが20230430以降です。

    説明

    RDSインスタンスのメジャーエンジンバージョンのアップグレードまたはマイナーエンジンバージョンの更新方法の詳細については、「メジャーエンジンバージョンのアップグレード」または「マイナーエンジンバージョンの更新」をご参照ください。

  • あなたはpgvector拡張の使用法と基本的な用語に精通しています。 詳細については、「pgvector拡張を使用して高次元ベクトル類似性検索を実行する」をご参照ください。

  • Secret APIキーが取得され、ネットワーク環境でOpenAIを使用できます。 このトピックで使用されるサンプルコードは、シンガポールリージョンのElastic Compute Service (ECS) インスタンスにデプロイされています。

  • Python開発環境がデプロイされます。 このトピックでは、Python 3.11.4PyCharm 2023.1.2を使用します。

条件

埋め込み

埋め込みは、高次元データを低次元空間に変換する方法である。 機械学習および自然言語処理 (NLP) では、埋め込みは、スパース記号またはオブジェクトを連続ベクトルとして表すために使用される一般的な方法です。

NLPでは、単語埋め込みは、実数値ベクトルの形式で単語を表すために使用される方法です。 これにより、コンピューターはテキストをよりよく理解できます。 単語埋め込みは、単語のセマンティクスと文法的関係をベクトル空間に変換するために使用されます。

OpenAIは埋め込みをサポートします。

実装の原則

このセクションでは、専用のチャットボットを構築するフェーズについて説明します。

フェーズ1: データ準備

  1. ドメイン固有のナレッジベースからテキストを抽出し、そのテキストをチャンクに分割します。 たとえば、大量のテキストを段落または文に分割し、キーワードまたはエンティティを抽出できます。 これにより、知識ベース内のデータの配置および管理が容易になる。

  2. OpenAIが提供する操作などのLLM操作を呼び出して、テキストチャンクをモデルにインポートし、テキスト埋め込みを生成します。 埋め込みは、後続の検索および照合のためにテキストの意味情報および文脈情報を取り込む。

  3. 生成されたテキスト埋め込み、テキストチャンク、およびテキストメタデータをRDSインスタンスに保存します。

フェーズ2: Q&A

  1. 質問をします。

  2. 質問の埋め込みを作成するためにOpenAIによって提供される埋め込み操作を呼び出します。

  3. pgvector拡張機能を使用して、RDSインスタンス内の類似度が指定されたしきい値を超えるテキストチャンクを検索し、結果を取得します。

次の図にプロセスを示します。

image..png

手順

フェーズ1: データ準備

この例では、[ApsaraDB RDS for PostgreSQLインスタンスの作成] のテキストデータが分割され、RDSインスタンスに保存されます。 ドメイン固有のナレッジベースを準備する必要があります。

このフェーズでは、最も重要なことは、ドメイン固有の知識ベースをテキスト埋め込みに変換し、効率的な方法で埋め込みを格納して一致させることです。 このようにして、LLMの強力なセマンティック理解機能を活用することで、ドメイン固有の高品質の回答と提案を取得できます。一部の既存のオープンソースフレームワークでは、URL、Markdown、PDF、Wordなどの形式のナレッジベースファイルを便利な方法でアップロードおよび解析できます。 たとえば、OpenAIのLangChainおよびオープンソースのChatGPT Retrieval Pluginフレームワークがサポートされています。 LangChainおよびChatGPT Retrieval Pluginは、バックエンドのベクターデータベースとしてpgvector拡張機能をサポートするPostgreSQLデータベースを使用できます。 これにより、LangChainとChatGPT RetrievalプラグインとRDSインスタンスの統合が容易になります。 統合後、ドメイン固有のナレッジベースを効率的に準備し、pgvector拡張機能によって提供されるベクトルインデックスと類似性検索を最大限に活用して、効率的なテキストマッチングとクエリを実装できます。

  1. RDSインスタンスに接続します。

  2. テストデータベースを作成します。 例: rds_pgvector_test

    データベースの作成rds_pgvector_test;
  3. テストデータベースに移動し、pgvector拡張子を作成します。

    存在しない場合は拡張ベクトルを作成します。
  4. ナレッジベースのデータを格納するテストテーブルを作成します。 例: rds_pg_help_docs

    CREATE TABLE rds_pg_help_docs (
      id bigserial一次キー、 
      title text, -- Title
      説明テキスト-説明
      doc_chunk text, -- テキストチャンク
      token_size int, -- テキストチャンク内の単語数
      埋め込みベクトル (1536); -- テキスト埋め込み 
  5. クエリを最適化および高速化するために、埋め込み列のインデックスを作成します。

    CREATE INDEX ON rds_pg_help_docs使用ivfflat (埋め込みvector_cosine_ops) WITH (lists = 100);
    説明

    ベクトルのインデックスを作成する方法の詳細については、「pgvector拡張を使用して高次元ベクトル類似性検索を実行する」をご参照ください。

  6. PyCharmでプロジェクトを作成し、ターミナルを開き、次のステートメントを入力して次の依存関係をインストールします。

    pip install openai psycopg2 tiktoken requests beautifulsoup4 numpy
  7. を作成します。ファイルを使用してナレッジベースのデータを分割し、分割したデータをRDSインスタンスに保存します。 この例では、knowledge_chunk_storage.pyファイルが作成されます。 サンプルコード:

    説明

    次のサンプルコードでは、カスタム分割メソッドは、ナレッジベース内のデータを固定文字数のチャンクに分割するだけです。 LangChainおよびOpenAIのオープンソースのChatGPT検索プラグインが提供する分割方法を使用できます。 知識ベースのデータの品質とチャンキング結果は、最終結果に大きな影響を与えます。

    openaiインポート
    インポートpsycopg2
    tiktokenのインポート
    インポートリクエスト
    からbs4インポートBeautifulSoup
    
    EMBEDDING_MODEL = "text-embedding-ada-002"
    tokenizer = tiktoken.get_encoding("cl100k_base")
    
    # RDSインスタンスに接続します。
    conn=psycopg2.connect (database="<データベース名>" 、
                            host="<RDSインスタンスのエンドポイント>" 、
                            user="<Username>" 、
                            password="<パスワード>" 、
                            port="<データベースポート番号>")
    conn.autocommit = True
    
    # OpenAIのAPIキー
    openai.api_key = '<シークレットAPIキー>'
    
    # カスタム分割方法 (次の方法は例です。)
      def get_text_chunks(text, max_chunk_size):
        chunks_ = []
        soup_ = BeautifulSoup (テキスト、'html.parser')
    
        content = ''.join(soup_.strings).strip()
    
        length = len (コンテンツ)
        start = 0
        while start < length:
            end = start + max_chunk_size
            if end >= length:
                end = length
    
            chunk_ = content[start:end]
            chunks_.append(chunk_)
    
            start = end
    
        チャンク_を返します
    
    
    # 分割するwebページを指定します。
    url = 'https:// help.aliyun.com/document_detail/148038.html'
    
    response = requests.get(url)
    if response.status_code == 200:
        # webページでデータを取得します。
        web_html_data = response.text
        soup = BeautifulSoup(web_html_data, 'html.parser')
        # H1タグでタイトルを取得します。
        title = soup.find('h1').text.strip()
    
        # 説明を取得します (説明はpタグで囲まれ、shortdescクラスに属します。)
        description = soup.find('p', class_='shortdesc').text.strip()
    
        # データを分割して保存します。
        chunks = get_text_chunks(web_html_data, 500)
        チャンク単位のチャンクの場合:
            doc_item = {
                'title': タイトル、
                '説明': 説明、
                'doc_chunk': チャンク、
                'token_size': len(tokenizer.encode (チャンク))
            }
    
            query_embedding_response = openai.Embedding.create ()
                model=EMBEDDING_MODEL、
                input=チャンク,
            )
    
            doc_item['embedding'] = query_embedding_response['data'][0]['embedding']
    
            cur = conn.cursor()
            insert_query = ''
            rds_pg_help_docsに挿入する 
                (title, description, doc_chunk, token_size, embeding) VALUES (% s, % s, % s, % s);
            '''
    
            cur.exeかわいい (insert_query, ()
                doc_item['title'] 、doc_item['description'] 、doc_item['doc_chunk'] 、doc_item['token_size'] 、
                doc_item['embedding'])
    
            conn.com mit()
    
    else:
        print (「webページの取得に失敗しました」) 
  8. Pythonプログラムを実行します。

  9. データベースにログインし、次のステートメントを実行して、ナレッジベースのデータが分割され、ベクトルとして格納されているかどうかを確認します。

    SELECT * からrds_pg_help_docs;

    image..png

フェーズ2: Q&A

  1. Pythonプロジェクトで、を作成します。pyファイルに質問を定義し、質問とRDSインスタンスのナレッジベースのデータの類似度を比較します。 この例では、chatbot.pyファイルが作成されます。 サンプルコード:

    openaiインポート
    インポートpsycopg2
    psycopg2.extrasからDictCursorをインポート
    
    GPT_MODEL = "gpt-3.5-turbo"
    EMBEDDING_MODEL = "text-embedding-ada-002"
    GPT_COMPLETIONS_MODEL = "text-davinci-003"
    MAX_TOKENS = 1024
    
    # OpenAIのAPIキー
    openai.api_key = '<シークレットAPIキー>'
    
    prompt ='RDSインスタンスを作成します。'
    
    prompt_response = openai.Embedding.create ()
        model=EMBEDDING_MODEL、
        input=プロンプト、)
    prompt_embedding = prompt_response['data'][0]['embedding']
    
    # RDSインスタンスに接続します。
    conn=psycopg2.connect (database="<データベース名>" 、
                            host="<RDSインスタンスのエンドポイント>" 、
                            user="<Username>" 、
                            password="<パスワード>" 、
                            port="<データベースポート番号>")
    conn.autocommit = True
    
    
    defの答え (prompt_doc, prompt):
        imprompt=f """
        次のファイルと手順に基づいて、次の質問に答えます。
        a. ファイル内のコンテンツが質問に関連しているかどうかを確認します。
        b. ファイル内のコンテンツを参照して質問に回答し、詳細な回答をMarkdownファイルとして提供します。
        c. ApsaraDB RDS for PostgreSQLとは無関係な質問に答えるには、「質問が私の範囲を超えているためわからない」を使用します。
    
        ファイル:
        \"\"\"
        {prompt_doc}
        \"\"\"
    
        質問: {prompt}
        """
    
        response = openai.Completion.create ()
            model=GPT_COMPLETIONS_MODEL、
            prompt=imprompt,
            温度=0.2、
            max_tokens=MAX_TOKENS
        )
    
        print(f "{response['choices'][0]['text']}\n")
    
    
    similarity_threshold = 0.78
    max_matched_doc_counts = 8
    
    # pgvector拡張子を使用して、類似度が指定されたしきい値を超えるファイルチャンクを検索します。
    similarity_search_sql = f'''
    SELECT doc_chunk, token_size, 1 - (embedding <=> '{prompt_embeding}') 類似性として
    FROM rds_pg_help_docs WHERE 1 - (embeding <=> '{prompt_embeding}') > {similarity_threshold} id LIMIT {max_matched_doc_counts};
    ''
    
    cur = conn.cursor(cursor_factory=DictCursor)
    cur.exeかわいい (similarity_search_sql)
    matched_docs = cur.fetchall()
    
    total_tokens = 0
    prompt_doc = ''
    プリント ('Answer: \n')
    matched_docsのmatched_docの場合:
        if total_tokens + matched_doc['token_size'] <= 1000:
            prompt_doc += f "\n ---\n{matched_doc['doc_chunk']}"
            total_tokens += matched_doc['token_size']
            continue
    
        答え (prompt_doc,prompt)
    
        total_tokens = 0
        prompt_doc = ''
    
    答え (prompt_doc,prompt) 
  2. Pythonプログラムを実行した後、答えを表示します。 次の図は、回答の例を示しています。

    説明

    より正確で完全な回答を得るために、分割方法と質問プロンプトを最適化できます。

    image..png

概要

専用のナレッジベースが接続されていない場合、「ApsaraDB RDS for PostgreSQLインスタンスを作成するにはどうすればよいですか? 」という質問に対するOpenAIの回答はAlibaba Cloudとは無関係です。 例:

image..png

RDSインスタンスに保存されている専用のナレッジベースが接続された後、「ApsaraDB RDS for PostgreSQLインスタンスを作成するにはどうすればよいですか? 」という質問に対する回答は、ApsaraDB RDS for PostgreSQLインスタンスに密接に関連しています。

要約すると、ApsaraDB RDS for PostgreSQLは、業界垂直向けのLLMドリブンのナレッジベースを完全に構築できます。