🐈

Google CloudのVector StoreでRAG Agentsを構築する【Cloud SQL for PostgreSQL編】

に公開

はじめに

今回の記事は、これまでの記事の続編です。
https://zenn.dev/asap/scraps/2702046ad34245

前回の記事では、Google CloudのBigQueryというサービスをVector Storeとして利用し、Google Cloud Strage(GCS)上のドキュメントを参照するRAGのシステムを構築しました。

今回は、Vector Storeとして、Cloud SQLのPostgreSQLを利用して、RAGのシステムを構築します。

例によって、自分の備忘録の側面が強いですが、参考になれば幸いです。

(再掲)RAGのVector Storeとして利用できるデータストア

ちなみに、今後の記事の流れにも関連しますが、現在Google CloudにてVector StoreをLangChainから利用するには、下記のデータストアが選択肢になります。
それらに対して、どのように利用するのかを今後解説したいと思います。

  • BigQuery(前回の記事)
    • langchain_google_community
  • Vertex AI Vector Search
    • langchain_google_vertexai
  • Cloud SQL for PostgreSQL
    • langchain-google-cloud-sql-pg-python
  • Cloud SQL for MySQL
    • langchain-google-cloud-sql-mysql-python
  • AlloyDB for PostgreSQL
    • langchain-google-alloydb-pg-python
  • Firestore
    • langchain-google-firestore-python
  • Spanner
    • langchain-google-spanner-python
  • Memorystore for Redis
    • langchain-google-memorystore-redis-python

上がデータストア名で、下が利用するライブラリになります。(めちゃくちゃ多い・・・)
(調べきれていないだけで、他にもあるかもです)

今回は、Cloud SQL for PostgreSQLをVector Storeとして利用する場合の解説記事です。

網羅的に、さまざまなデータストアを利用したときの実装方法などを解説する記事は少ないと感じましたので、参考になれば幸いです!

参考書籍

(書籍のリンクはamazonアフィリエイトリンクになります)

記事

LangChain と Google Cloud データベースを使用して強化された生成 AI アプリケーションを構築する
https://cloud.google.com/blog/ja/products/databases/build-rag-applications-with-langchain-and-google-cloud

LangChainのチュートリアル記事「Google Cloud SQL for PostgreSQL」
https://python.langchain.com/docs/integrations/vectorstores/google_cloud_sql_pg/

利用するライブラリ「langchain-google-cloud-sql-pg-python」
https://github.com/googleapis/langchain-google-cloud-sql-pg-python

書籍

Generative AI on Google Cloud with LangChain: Design scalable generative AI solutions with Python, LangChain, and Vertex AI on Google Cloud
英語ではありますが、非常に分かりやすい書籍です。
というか、現在においてLangChain+Google Cloudを取り巻くライブラリの複雑さは異常だと思っています。
各DBごとに必要なライブラリが乱立しており、どのライブラリを利用するのが良いのかが分かりにくいです。(なぜなら技術記事では、一つのライブラリ、一つのDBにフォーカスしており、他にどんな選択肢があるのかが分かりにくい)
本書籍は、それらをすべて統括して分かりやすく記載されているため、全体像が掴みやすくおすすめの書籍になっています。
英語の本ではありますが、購入時にPDFも一緒に取得することができる(2025年2月現在)ため、「Google 翻訳」のPDF変換機能で翻訳することで、英語がわからなくても読むことができますので、ぜひお試しください。
(PDFが取得可能かどうかは、Amazonの商品概要欄に記載してありますので、購入前にお確かめください)

LangChainとLangGraphによるRAG・AIエージェント[実践]入門
ChatGPT/LangChainによるチャットシステム構築[実践]入門
LangChainを利用することで、あらゆるモデルを統一的なコードで実行できるようになります。
langchainに関しては、こちらの書籍を読めば大体のことはできるようになりますので、おすすめです。
また、現在推奨されているLangGraphでのRAG Agentを構築するcreate_react_agentに関しても説明されておりますし、さらに複雑なAgentsの構築方法やデザイン方法も網羅されており、とても勉強になります!

大規模言語モデル入門
大規模言語モデル入門Ⅱ〜生成型LLMの実装と評価
よく紹介させていただいておりますが、こちらの書籍は、LLMのファインチューニングから、RLHF、RAG、分散学習にかけて、本当に幅広く解説されており、いつも参考にさせていただいております。
今回の記事で紹介したRAGの内容だけでなく、さらにその先であるRAGを前提としてInstruction Tuningについても触れており、とても面白いです。
LLMを取り扱っている方は、とりあえず買っておいても損はないと思います。
さまざまな章、ページで読めば読むほど新しい発見が得られる、スルメのような本だなといつも思っております。

LLMのファインチューニングとRAG ―チャットボット開発による実践
上記2冊の本よりもRAGやファインチューニングに絞って記載されている書籍です。だいぶ平易に書いてあるのでとてもわかりやすいと思いました。
また、本記事の内容ではないですが、RAGを実装する上でキーワード検索を加えたハイブリッド検索を検討することは一般的だと思います。本書はそこにも踏み込んで解説をしています。
また、キーワード検索でよく利用するBM25Retrieverが日本語のドキュメントに利用する際に一工夫がいるところなども紹介されており、使いやすい本だなと思いました。

成果物

下記のGithubをご覧ください。
https://github.com/personabb/GC_RAG_Sample/tree/main/Cloud_SQL_for_PostgreSQL

実行環境

著者の環境は下記です。
OS:MacOS 15.2
Python:3.11.9

Google Cloudの準備

これまでの記事で詳細に解説しているため、そちらをご参照ください

実行までの準備

ローカルでの準備

gcloud CLIをインストールする

これまでの記事で詳細に解説しているため、そちらをご参照ください

リポジトリをクローンする

下記のコードでリポジトリをクローンします。

git clone https://github.com/personabb/GC_RAG_Sample.git

今回の記事は、上記リポジトリのGC_RAG_Sample/Cloud_SQL_for_PostgreSQLフォルダ内に格納されているコードを利用します。

必要なパッケージをインストールする

下記のコマンドで必要なパッケージをインストールします。

cd ./GC_RAG_Sample/Cloud_SQL_for_PostgreSQL
pip install -r requirements.txt

上記で動かない場合は、下記も試してみてください。
(現時点での著者のバージョン付きパッケージです)

pip install -r requirements.lock

Google Cloudのプロジェクトにログインする

下記のコマンドでログインします。

gcloud auth application-default login

詳細な説明は、前回の記事をご参照ください。

Google Cloudでの準備

Google Cloud Storageにドキュメントの格納

こちらもこれまでの記事をご参照ください。
前回の記事と同じドキュメントを利用します。

具体的には、リポジトリ内の「Inputs/sample.txt」を、「gc_rag_sample_storage」バケットの「Inputs」フォルダの中にアップロードします。

Cloud SQLの設定

ベクトルデータを格納するDBをあらかじめ構築します。

Cloud SQLはコマンドから構築することもできますが、初めての場合は、おそらくコンソールから構築する方が分かりやすいと思いますので、そちらを実施します。

まずは、コンソール上部の検索窓から「Cloud SQL」と検索し、「Cloud SQL」サービスを選択します。

「CLOUD SQLに移動」をクリックします

「無料クレジットを利用してインスタンスを作成」をクリックします。

「Postgre SQL」を選択します。

「APIを有効にする」をクリックします。(時間がかかりますので、お待ちください)

下記のような画面が表示されたら、成功です。
テストなので、小さめな環境で試します。
「Cloud SQL のエディションの選択」では、「Enterprise」を選択します。
「エディションのプリセット」は「サンドボックス」を選択します。

続いて、「インスタンス情報」と「リージョンとゾーンの可用性の選択」を実施します。
「インスタンスID」には「my-pg-instance」を入力します。
「パスワード」には「!password!」を入力します。(ここは変更を推奨します)
(記載されている通りデフォルトのユーザ名は「postgres」になります。)
「リージョン」は馴染み深いので、「asia-northeast1 (東京)」に設定しておきます。

続いて、「インスタンスのカスタマイズ」の中の「構成オプションを表示」をクリックして、「データの保護」を変更します。
終了後インスタンスを削除することがわかっているので、「自動日時バックアップ」と「削除からの保護の有効化」を外しておきます。

最後に一番下の「インスタンスを作成」をクリックして、インスタンスを作成します。
時間がかかるのでお待ちください。

下記のような画面になれば成功です。
(作成中の文字が消えて、チェックマークが出れば成功です)

ここまで行くと、データベースにアクセスできるユーザや、データベース自体も追加で作成できるようになります。
左のタブの「ユーザ」や「データベース」から作成できます。

今回は、デフォルトで用意されている「postgres」ユーザと「postgres」データベースをそのまま利用します。

コードの修正

ここまでで、準備はほぼ完了です。
あとは、コード内のパラメータを変更します。
具体的には、どのGCSバケットを読み込むか、などの設定です。

ドキュメントをEmbeddingsモデルでベクトル化し、DBに格納するコード

upload_vactorstore_cloudsql-pg.pyを修正します。

必要に応じて、下記部分を変更してください。

./GC_RAG_Sample/Cloud_SQL_for_PostgreSQL/upload_vactorstore_cloudsql-pg.py
・・・
def main():
    # --- 定数定義 ---
    REGION = "asia-northeast1"
    BUCKET_NAME = "gc_rag_sample_storage"
    GCS_FOLDER = "Inputs"
    EM_MODEL_NAME = "text-multilingual-embedding-002"
    SQL_INSTANCE = "my-pg-instance"  
    SQL_DATABASE = "postgres"  
    SQL_TABLE_NAME = "vector_store"  
    SQL_DB_USER = "postgres"
    SQL_DB_PASSWORD = "!password!"
    RESET_TABLE_FLAG = True
・・・
  • REGION
    • GCSやCloud_SQL_for_PostgreSQLのリージョン
  • BUCKET_NAME
    • GCSのバケットの名称
  • GCS_FOLDER
    • GCSにおいて、読み込むドキュメントが格納されているフォルダ名
  • EM_MODEL_NAME
    • Vertex AIが提供しているEmbeddingsモデル
    • ドキュメントの内容をベクトル化するモデルを指定する
    • ここではtext-multilingual-embedding-002を利用しているが、Vertex AIから提供されていればなんでも利用可能
      • 他社モデルを利用したい場合は、コードの該当部分を変更する必要がある
  • SQL_INSTANCE
    • Cloud SQLで構築したインスタンスの名前
  • SQL_DATABASE
    • Cloud SQLで構築したデータベースの名前
  • SQL_TABLE_NAME
    • Cloud SQLで構築する予定のテーブル名
  • SQL_DB_USER
    • Cloud SQLで構築したインスタンスに接続するユーザ名
  • SQL_DB_PASSWORD
    • Cloud SQLで構築したインスタンスに接続するユーザのパスワード
  • RESET_TABLE_FLAG
    • Cloud SQLにベクトルデータを追加する前に、既存のテーブルを削除するかどうかのフラグ
    • Falseにすると実行のたびに、行がどんどん追加される

DBに保存された内容から、LLMがRAGで質問に回答するコード

search_rag_documents_cloudsql-pg.pysearch_rag_documents_cloudsql-pg_tools.pyを修正します。

必要に応じて、下記部分を変更してください。
(両コード共に修正箇所と内容は同一です)

./GC_RAG_Sample/Cloud_SQL_for_PostgreSQL/search_rag_documents_cloudsql-pg.py
・・・
def main():
    # --- 定数定義 ---
    REGION = "asia-northeast1"
    EM_MODEL_NAME = "text-multilingual-embedding-002"
    LLM_MODEL_NAME = "gemini-2.0-flash-001" 
    SQL_INSTANCE = "my-pg-instance"  
    SQL_DATABASE = "postgres"  
    SQL_TABLE_NAME = "vector_store"  
    SQL_DB_USER = "postgres"
    SQL_DB_PASSWORD = "!password!"


    # 質問文
    query = "16歳未満のユーザーが海外から当社サービスを利用した場合、親権者が同意していないときはどう扱われますか? そのときデータは国外にも保存される可能性がありますか?"
・・・
  • REGION
    • GCSやCloud_SQL_for_PostgreSQLのリージョン
  • EM_MODEL_NAME
    • Vertex AIが提供しているEmbeddingsモデル
    • ドキュメントの内容をベクトル化するモデルを指定する
    • ここではtext-multilingual-embedding-002を利用しているが、Vertex AIから提供されていればなんでも利用可能
      • 他社モデルを利用したい場合は、コードの該当部分を変更する必要がある
  • LLM_MODEL_NAME
    • Vertex AIが提供しているLLMモデル
    • ユーザの質問に回答するLLMを指定する
    • 他社のLLMを利用することも可能(LangChainで動かせれば)
      • その場合は、コード中のモデル定義部分のコードだけを変更すればOK
  • SQL_INSTANCE
    • Cloud SQLで構築したインスタンスの名前
  • SQL_DATABASE
    • Cloud SQLで構築したデータベースの名前
  • SQL_TABLE_NAME
    • Cloud SQLで構築する予定のテーブル名
  • SQL_DB_USER
    • Cloud SQLで構築したインスタンスに接続するユーザ名
  • SQL_DB_PASSWORD
    • Cloud SQLで構築したインスタンスに接続するユーザのパスワード
  • query
    -ユーザの質問文

実行方法

下記の手順でコードは実行できます。

DBへの登録

python upload_vactorstore_cloudsql-pg.py  

LLMにRAGで回答させる

python search_rag_documents_cloudsql-pg.py

もしくは

python search_rag_documents_cloudsql-pg_tools.py

実施内容

これまでの記事と同様に、下記コードを実装しています。
ただし、今回はドキュメントローダにGCSを、ベクトルストアにCloud SQL for PostgreSQLを利用します。

  • ドキュメントをEmbeddingモデルでベクトル化し、DBに格納するコード
  • DBに保存された内容から、LLMがRAGで質問に回答するコード(通常LLM)
  • DBに保存された内容から、LLMがRAGで質問に回答するコード(Tool CallingによるAgent)

ドキュメントをEmbeddingsモデルでベクトル化し、DBに格納する

今回も前回と同様のプライバシーポリシー(ダミー)をドキュメントとして利用しています。
内容はこちらです。

https://github.com/personabb/GC_RAG_Sample/blob/main/Cloud_SQL_for_PostgreSQL/inputs/sample.txt

コード解説

実際のコードは下記です。

https://github.com/personabb/GC_RAG_Sample/blob/main/Cloud_SQL_for_PostgreSQL/upload_vactorstore_cloudsql-pg.py

これまでの記事との差分に絞って解説いたします。

定数定義

./GC_RAG_Sample/Cloud_SQL_for_PostgreSQL/upload_vactorstore_cloudsql-pg.py
・・・
def main():
    # --- 定数定義 ---
    REGION = "asia-northeast1"
    BUCKET_NAME = "gc_rag_sample_storage"
    GCS_FOLDER = "Inputs"
    EM_MODEL_NAME = "text-multilingual-embedding-002"
    SQL_INSTANCE = "my-pg-instance"  
    SQL_DATABASE = "postgres"  
    SQL_TABLE_NAME = "vector_store"  
    SQL_DB_USER = "postgres"
    SQL_DB_PASSWORD = "!password!"
    RESET_TABLE_FLAG = True
・・・

これらの内容は下記のとおりです。

  • REGION
    • GCSやCloud_SQL_for_PostgreSQLのリージョン
  • BUCKET_NAME
    • GCSのバケットの名称
  • GCS_FOLDER
    • GCSにおいて、読み込むドキュメントが格納されているフォルダ名
  • EM_MODEL_NAME
    • Vertex AIが提供しているEmbeddingsモデル
    • ドキュメントの内容をベクトル化するモデルを指定する
    • ここではtext-multilingual-embedding-002を利用しているが、Vertex AIから提供されていればなんでも利用可能
      • 他社モデルを利用したい場合は、コードの該当部分を変更する必要がある
  • SQL_INSTANCE
    • Cloud SQLで構築したインスタンスの名前
  • SQL_DATABASE
    • Cloud SQLで構築したデータベースの名前
  • SQL_TABLE_NAME
    • Cloud SQLで構築する予定のテーブル名
  • SQL_DB_USER
    • Cloud SQLで構築したインスタンスに接続するユーザ名
  • SQL_DB_PASSWORD
    • Cloud SQLで構築したインスタンスに接続するユーザのパスワード
  • RESET_TABLE_FLAG
    • Cloud SQLにベクトルデータを追加する前に、既存のテーブルを削除するかどうかのフラグ
    • Falseにすると実行のたびに、行がどんどん追加される

Cloud SQL for PostgreSQLを定義する

./GC_RAG_Sample/Cloud_SQL_for_PostgreSQL/upload_vactorstore_cloudsql-pg.py
    #==============---CloudSQL---================
    # https://github.com/googleapis/langchain-google-cloud-sql-pg-python/blob/3aae0c69eaeb9f2781436363a788a3765d294923/src/langchain_google_cloud_sql_pg/engine.py#L98
    engine = PostgresEngine.from_instance(
        project_id=PROJECT_ID, region=REGION, instance=SQL_INSTANCE, database=SQL_DATABASE, user=SQL_DB_USER, password=SQL_DB_PASSWORD
    )

    if RESET_TABLE_FLAG:
        #Postgre SQLのテーブルを初期化
        engine.init_vectorstore_table(
            table_name=SQL_TABLE_NAME,
            vector_size=768,
            overwrite_existing=True,
        )
    else:
        print("既存のテーブルに追加します。")

    vector_store = PostgresVectorStore.create_sync(
        engine=engine,
        table_name=SQL_TABLE_NAME,
        embedding_service=embedding_model,
        distance_strategy=DistanceStrategy.COSINE_DISTANCE,
    )

    #===========================================

上記にて、Cloud SQLのDBに接続して、新しいテーブルを作成、接続、初期化しています。

最初にDBに接続し、RESET_TABLE_FLAGのフラグに応じて、テーブルの中身を初期化し、最後に、Vector Storeとして定義しています。

Cloud SQL for PostgreSQLにデータを追加する

./GC_RAG_Sample/Cloud_SQL_for_PostgreSQL/upload_vactorstore_cloudsql-pg.py
    # ---- Cloud SQL for PostgresSQL Vector Store にデータを追加する ----
    # https://github.com/googleapis/langchain-google-cloud-sql-pg-python/blob/3aae0c69eaeb9f2781436363a788a3765d294923/src/langchain_google_cloud_sql_pg/vectorstore.py#L202
    vector_store.add_texts(
        texts=texts,
        metadatas=metadatas,
        ids=ids,
    )

    print("\nデータの登録が完了しました。\n")

BigQueryの記事とほぼ同様ですが、上記によりCloud SQLのDBに、ドキュメントとベクトルデータ、メタデータを格納しています。
Cloud SQLの場合、現時点(2025年2月時点)ではadd_texts_with_embeddingsメソッドが実装されていないため、add_textsメソッドを利用しています。

このメソッドは、Vector Storeを定義した際に、設定したEmbeddingsモデルを利用して、内部でドキュメントを埋め込みに変換してくれるメソッドになります。
逆にいうと、事前に用意した埋め込みベクトルを用いて、Vector Storeに格納したい場合は、Cloud SQL for PostgreSQLは選択肢から外れます。

コードのその他部分は、これまでの記事と同様の内容のため、そちらを合わせてご覧ください。

実行後、Cloud SQL for PostgreSQLを確認する

コードを実行した後、Cloud SQL for PostgreSQLにデータが格納されているかを確認します。

まずは、コンソール上部の検索窓から「Cloud SQL」と検索し、「Cloud SQL」サービスを選択します。

「CLOUD SQLに移動」をクリックします

「my-pg-instance」をクリックします。

左タブの「Cloud SQL Studio」をクリックし、必要情報を入力して、「認証」をクリックしてください。
データベース名とユーザ名は変更していなければ「postgres」です。
パスワードは自分で設定したものを入力してください。記事通りであれば「!password!」です。

「エディタ」タブに移動し、下記コマンドを入力してから、「実行」をクリックしてください。

SELECT * FROM vector_store;

下記のようにデータが表示されたら、成功です。

  • langchain_id
    • 自動でつけられるユニークなID
  • content
    • ドキュメントのチャンクデータ
  • embedding
    • 埋め込みベクトルデータ
    • Defaultで設定している埋め込みモデルを利用している場合は、768次元の埋め込みベクトルが格納されています
  • langchain_metadata
    • 自分で設定できるメタデータ

DBに保存された内容から、LLMがRAGで質問に回答するコード(通常LLM)

続いて、これまでの記事と同様に、DBに格納された情報源を利用して、LLMが回答するコードの部分を実装します。
ドキュメントがダミーのプライバシーポリシーのため、今回のLLM君は、企業のQ&A botとして利用することを想定します。

ここでは、ユーザの質問文を、Embeddingsモデルによって、ベクトルに変換して、そのベクトルとDBに格納されているベクトルとで類似度を計算します。
そして、類似性が高いチャンクをLLMのプロンプトに提示し、その情報をもとにLLMに回答させることがゴールです。

LangChainを利用して実装するため、推奨されているLCEL記法を使って、Chainとして全部繋げて実行できることを目的にします。
その後、別の章にて、Tool CallingによるAgentの形で実装します。

コード解説

実際のコードは下記になります。

https://github.com/personabb/GC_RAG_Sample/blob/main/Cloud_SQL_for_PostgreSQL/search_rag_documents_cloudsql-pg.py

これまでの記事との差分に絞って解説します。
また、upload_vactorstore_cloudsql-pg.pyにて解説した部分に関しても省略します。

定数定義

./GC_RAG_Sample/Cloud_SQL_for_PostgreSQL/search_rag_documents_cloudsql-pg.py
・・・
def main():
    # --- 定数定義 ---
    REGION = "asia-northeast1"
    EM_MODEL_NAME = "text-multilingual-embedding-002"
    LLM_MODEL_NAME = "gemini-2.0-flash-001" 
    SQL_INSTANCE = "my-pg-instance"  
    SQL_DATABASE = "postgres"  
    SQL_TABLE_NAME = "vector_store"  
    SQL_DB_USER = "postgres"
    SQL_DB_PASSWORD = "!password!"


    # 質問文
    query = "16歳未満のユーザーが海外から当社サービスを利用した場合、親権者が同意していないときはどう扱われますか? そのときデータは国外にも保存される可能性がありますか?"
    #query = "おはよう"
    #query = "今日は12歳の誕生日なんだ。これから初めて海外に行くんだよね"
・・・
  • REGION
    • GCSやCloud_SQL_for_PostgreSQLのリージョン
  • EM_MODEL_NAME
    • Vertex AIが提供しているEmbeddingsモデル
    • ドキュメントの内容をベクトル化するモデルを指定する
    • ここではtext-multilingual-embedding-002を利用しているが、Vertex AIから提供されていればなんでも利用可能
      • 他社モデルを利用したい場合は、コードの該当部分を変更する必要がある
  • LLM_MODEL_NAME
    • Vertex AIが提供しているLLMモデル
    • ユーザの質問に回答するLLMを指定する
    • 他社のLLMを利用することも可能(LangChainで動かせれば)
      • その場合は、コード中のモデル定義部分のコードだけを変更すればOK
  • SQL_INSTANCE
    • Cloud SQLで構築したインスタンスの名前
  • SQL_DATABASE
    • Cloud SQLで構築したデータベースの名前
  • SQL_TABLE_NAME
    • Cloud SQLで構築する予定のテーブル名
  • SQL_DB_USER
    • Cloud SQLで構築したインスタンスに接続するユーザ名
  • SQL_DB_PASSWORD
    • Cloud SQLで構築したインスタンスに接続するユーザのパスワード
  • query
    -ユーザの質問文

カスタムRetriever

./GC_RAG_Sample/Cloud_SQL_for_PostgreSQL/search_rag_documents_cloudsql-pg.py
class VectorSearchRetriever(BaseRetriever):
    """
    ベクトル検索を行うためのRetrieverクラス。
    """
    vector_store: SkipValidation[Any]
    embedding_model: SkipValidation[Any]
    k: int = 5 # 返すDocumentのチャンク数

    class Config:
        arbitrary_types_allowed = True

    def _get_relevant_documents(self, query: str) -> List[Document]:
        # Dense embedding
        embedding = self.embedding_model.embed_query(query)
        search_results = self.vector_store.similarity_search_with_score_by_vector(
            embedding=embedding,
            k=self.k,
        )

        # Document のリストだけ取り出す
        return [doc for doc, _ in search_results]

    async def _aget_relevant_documents(self, query: str) -> List[Document]:
        return self._get_relevant_documents(query)

Cloud SQL for PostgreSQLにて使えそうなベクトル検索メソッドとして、similarity_search_with_score_by_vectorがあったため、こちらを利用しました。

なお、無理にカスタムRetrieverクラスを利用しなくても、本記事の内容でしたら下記でも十分です。
ただ、カスタムRetrieverクラスを利用することで、より細かい部分の制御が可能になります。

dence_retriever = vector_store.as_retriever() 

解説が必要な箇所はこれだけです。
LangChainを利用しているので、コアな部分のコードは同様に使いまわすことができるので便利ですね。

出力結果

本コードの出力結果は下記になります。
(ユーザクエリは「16歳未満のユーザーが海外から当社サービスを利用した場合、親権者が同意していないときはどう扱われますか? そのときデータは国外にも保存される可能性がありますか?」)

出力結果

===== DenseRetriever の実行結果 =====

DenseRetrieved Documents: [Document(metadata={'my_metadata': 22}, page_content='2. \n\n未成年者の個人情報保護\n\n:\n\n16歳未満の利用者の個人情報に関しては、一般のユーザーと同等のセキュリティ対策を講じていますが、必要に応じてより厳格なアクセス制限を設定する場合があります。たとえば、投稿やコミュニケーション機能を制限したり、年齢に応じたコンテンツ表示のフィルタリングを行うことが検討されます。\n\n3. \n\n照会・削除請求\n\n:\n\n親権者が、当社が保有する未成年者の個人情報について照会・訂正・削除を希望する場合は、前条の「開示等」の手続きに従ってご連絡ください。当社は必要に応じて年齢確認や委任状の提出を求め、正当な請求であることを確認した上で対応します。\n\n4. \n\n利用規約との整合性\n\n:\n\n未成年者が当社サービスを利用する場合は、プライバシーポリシーに加えて、サービスの利用規約に定められた年齢制限や制約事項なども遵守する必要があります。もし利用規約に違反していると判明した場合は、アカウント停止などの措置が取られることがあります。\n\n第11条(プライバシーポリシーの変更)'), Document(metadata={'my_metadata': 21}, page_content='4. \n\n手数料\n\n:\n\n開示等の手数料については、当社が別途定める方法により請求させていただく場合がありますので、あらかじめご了承ください。\n\n上記のように、当社はユーザーの権利を尊重し、迅速かつ誠実な対応に努めます。ただし、請求内容によっては相当の期間や追加資料を要する場合があります。その際には手続きの進捗状況や必要な対応を速やかにユーザーへ連絡します。\n\n第10条(未成年者の個人情報)\n\n当社は、16歳未満のユーザーが当社サービスを利用する場合、法定代理人(親権者等)の同意を得ることが必要である場合があると認識しています。ユーザーが未成年者であるにもかかわらず同意を得ていない場合、もしくは未成年者である旨を偽って利用登録を行った場合には、当社は一切の責任を負いかねます。\n\n1. \n\n親権者の同意取得\n\n:\n\n未成年者がサービスを利用するにあたっては、親権者が本ポリシーの内容を確認したうえで利用に同意することが望ましいと考えています。特に決済手段の登録や外部サービスとの連携など、リスクの高い行為については慎重な対応を求めています。\n\n2. \n\n未成年者の個人情報保護'), Document(metadata={'my_metadata': 17}, page_content='これらの技術を活用することで、当社はサービスの品質向上や適切なマーケティング活動を実現していますが、ユーザーのプライバシー保護にも十分配慮し、必要に応じて同意取得やオプトアウトの仕組みを提供するよう努めます。\n\n第8条(国際データ移転)\n\n当社は、日本国内だけではなく、ユーザーが所在する国または地域とは異なる管轄のサーバーやデータセンターを利用する場合があり、ユーザーの個人情報が国外へ移転されることがあります。たとえば、クラウドサービスプロバイダを通じて海外にあるデータセンターで個人情報を保管する場合などが挙げられます。\n\n1. \n\n保護水準の確認\n\n:\n\nこのような国際的なデータ移転に際しては、移転先の国や地域における個人情報保護法制が日本またはEUなどの基準と同等以上の水準にあるかどうかを確認し、必要に応じて適切な契約(EU標準契約条項など)を締結するなど、個人情報が適切に保護される体制を整備します。\n\n2. \n\nユーザーの明示的同意\n\n:'), Document(metadata={'my_metadata': 18}, page_content='2. \n\nユーザーの明示的同意\n\n:\n\nユーザーの明示的同意を得ることなく国際データ移転を行う場合、当社は日本国法令や国際ルールで認められた要件を満たす範囲でのみ実施します。たとえば、データの暗号化や仮名化を徹底することで、リスクを最低限に抑えた状態でデータを取り扱う措置を講じます。\n\n3. \n\n越境データのセキュリティ確保\n\n:\n\n国際回線を経由してデータを送信する場合、盗聴や改ざんのリスクが考えられるため、VPNの利用やSSL/TLS通信などを組み合わせ、情報が不正に傍受される可能性を極力排除します。さらに、国外のデータセンターへのアクセス権限を厳格に制限し、監査ログを取得・分析することで、不正アクセスを検知・阻止できる仕組みを維持しています。\n\n4. \n\nユーザーへの周知\n\n:'), Document(metadata={'my_metadata': 19}, page_content='4. \n\nユーザーへの周知\n\n:\n\n国際データ移転がサービス提供上不可避である場合、当社は利用規約や本ポリシーにてその旨を周知し、ユーザーがそのリスクや対策内容を理解できるよう配慮します。ユーザーが海外でサービスを利用する際には、各国の法規制やインターネットインフラ状況を踏まえて、データがどのように移転・保護されるのかを検討する必要があります。\n\n第9条(保有個人情報の開示・訂正・削除)\n\nユーザーは、当社が保有しているユーザー自身の個人情報について、開示、訂正、追加、削除、利用停止、または第三者提供の停止(以下「開示等」と総称)を請求する権利を有します。当社は、ユーザーからの開示等に関する請求があった場合、法令に基づき合理的な範囲で対応します。請求を希望される場合は、当社所定の手続き(本人確認等)を経たうえで、当社カスタマーサポートまでご連絡ください。\n\n1. \n\n開示の請求\n\n:')]

================= LLMの実行結果 =================
16歳未満のユーザーが当社のサービスを利用する場合、法定代理人(親権者等)の同意を得ることが必要となる場合があります。ユーザーが未成年者であるにもかかわらず同意を得ていない場合、もしくは未成年者である旨を偽って利用登録を行った場合には、当社は一切の責任を負いかねます。

また、当社は、日本国内だけではなく、ユーザーが所在する国または地域とは異なる管轄のサーバーやデータセンターを利用する場合があります。そのため、ユーザーの個人情報が国外へ移転されることがあります。国際データ移転がサービス提供上不可避である場合、当社は利用規約やプライバシーポリシーにてその旨を周知し、ユーザーがそのリスクや対策内容を理解できるよう配慮します。

関連する情報源の文章は以下の通りです。

  • 第10条(未成年者の個人情報)

    当社は、16歳未満のユーザーが当社サービスを利用する場合、法定代理人(親権者等)の同意を得ることが必要である場合があると認識しています。ユーザーが未成年者であるにもかかわらず同意を得ていない場合、もしくは未成年者である旨を偽って利用登録を行った場合には、当社は一切の責任を負いかねます。

  • 第8条(国際データ移転)

    当社は、日本国内だけではなく、ユーザーが所在する国または地域とは異なる管轄のサーバーやデータセンターを利用する場合があり、ユーザーの個人情報が国外へ移転されることがあります。

  • 4. ユーザーへの周知

    国際データ移転がサービス提供上不可避である場合、当社は利用規約や本ポリシーにてその旨を周知し、ユーザーがそのリスクや対策内容を理解できるよう配慮します。

前回の記事と同じような結果になりました!

これまでの記事にも書きましたが、想定回答は下記になります。

想定回答

想定回答
16歳未満のユーザーがサービスを利用する場合には、第10条の規定により親権者の同意が必要となります。もし同意が得られていない場合は、当社は責任を負いかねるとしています。また、海外からの利用であるため、ユーザーのデータが国際データ移転の対象となる場合があります。これに関しては第8条で規定されており、必要に応じてEU標準契約条項などの締結や暗号化を行う形でデータの保護が図られます。つまり、親権者の同意がない場合はアカウント停止や責任の免除が行われる可能性がある一方で、データそのものが国外サーバーに保存される際にはプライバシー保護のための措置が適用される仕組みになっています。

根拠の箇所
第10条(未成年者の個人情報)
「16歳未満のユーザーが当社サービスを利用する場合、法定代理人(親権者等)の同意を得ることが必要... 同意を得ずに登録された場合...当社は一切の責任を負いかねます。」

第8条(国際データ移転)
「...移転先の国や地域における個人情報保護法制が日本またはEUなどの基準と同等以上の水準にあるかどうかを確認し、必要に応じて適切な契約を締結するなどの対応を取る...」

DBに保存された内容から、LLMがRAGで質問に回答するコード(Tool CallingによるAgent)

これまでの記事と同様に、Tool CallingによるAgentを実装します。
実装の意図はこれまでの記事をご覧ください。

コード解説

実際のコードは下記になります。

https://github.com/personabb/GC_RAG_Sample/blob/main/Cloud_SQL_for_PostgreSQL/search_rag_documents_cloudsql-pg_tools.py

コードの構成要素に関しては、今回の記事と前回の記事で全て解説済みですので、上記のコードは読めるようになっているはずです。
繰り返しになるため、ここでは解説を省略します。

実行結果

本コードの出力結果は下記になります。
(ユーザクエリは「16歳未満のユーザーが海外から当社サービスを利用した場合、親権者が同意していないときはどう扱われますか? そのときデータは国外にも保存される可能性がありますか?」)

出力結果

================= エージェントの実行結果 =================

=== Message 0 ===
Type: HumanMessage
Content:
16歳未満のユーザーが海外から当社サービスを利用した場合、親権者が同意していないときはどう扱われますか? そのときデータは国外にも保存される可能性がありますか?

=== Message 1 ===
Type: AIMessage
Content:

Tool calls:
[{'name': 'Document_Search_Tool', 'args': {'__arg1': '16歳未満のユーザーが海外から当社サービスを利用した場合、親権者が同意していないとき'}, 'id': '8e54b468-e847-41ca-a165-26cc00ca5d8e', 'type': 'tool_call'}]
Response Metadata:
{'is_blocked': False, 'safety_ratings': [], 'usage_metadata': {'prompt_token_count': 197, 'candidates_token_count': 28, 'total_token_count': 225, 'prompt_tokens_details': [{'modality': 1, 'token_count': 197}], 'candidates_tokens_details': [{'modality': 1, 'token_count': 28}], 'cached_content_token_count': 0, 'cache_tokens_details': []}, 'finish_reason': 'STOP', 'avg_logprobs': -0.04525370682988848}

=== Message 2 ===
Type: ToolMessage
Content:
[Document(metadata={'my_metadata': 21}, page_content='4. \n\n手数料\n\n:\n\n開示等の手数料については、当社が別途定める方法により請求させていただく場合がありますので、あらかじめご了承ください。\n\n上記のように、当社はユーザーの権利を尊重し、迅速かつ誠実な対応に努めます。ただし、請求内容によっては相当の期間や追加資料を要する場合があります。その際には手続きの進捗状況や必要な対応を速やかにユーザーへ連絡します。\n\n第10条(未成年者の個人情報)\n\n当社は、16歳未満のユーザーが当社サービスを利用する場合、法定代理人(親権者等)の同意を得ることが必要である場合があると認識しています。ユーザーが未成年者であるにもかかわらず同意を得ていない場合、もしくは未成年者である旨を偽って利用登録を行った場合には、当社は一切の責任を負いかねます。\n\n1. \n\n親権者の同意取得\n\n:\n\n未成年者がサービスを利用するにあたっては、親権者が本ポリシーの内容を確認したうえで利用に同意することが望ましいと考えています。特に決済手段の登録や外部サービスとの連携など、リスクの高い行為については慎重な対応を求めています。\n\n2. \n\n未成年者の個人情報保護'), Document(metadata={'my_metadata': 22}, page_content='2. \n\n未成年者の個人情報保護\n\n:\n\n16歳未満の利用者の個人情報に関しては、一般のユーザーと同等のセキュリティ対策を講じていますが、必要に応じてより厳格なアクセス制限を設定する場合があります。たとえば、投稿やコミュニケーション機能を制限したり、年齢に応じたコンテンツ表示のフィルタリングを行うことが検討されます。\n\n3. \n\n照会・削除請求\n\n:\n\n親権者が、当社が保有する未成年者の個人情報について照会・訂正・削除を希望する場合は、前条の「開示等」の手続きに従ってご連絡ください。当社は必要に応じて年齢確認や委任状の提出を求め、正当な請求であることを確認した上で対応します。\n\n4. \n\n利用規約との整合性\n\n:\n\n未成年者が当社サービスを利用する場合は、プライバシーポリシーに加えて、サービスの利用規約に定められた年齢制限や制約事項なども遵守する必要があります。もし利用規約に違反していると判明した場合は、アカウント停止などの措置が取られることがあります。\n\n第11条(プライバシーポリシーの変更)'), Document(metadata={'my_metadata': 17}, page_content='これらの技術を活用することで、当社はサービスの品質向上や適切なマーケティング活動を実現していますが、ユーザーのプライバシー保護にも十分配慮し、必要に応じて同意取得やオプトアウトの仕組みを提供するよう努めます。\n\n第8条(国際データ移転)\n\n当社は、日本国内だけではなく、ユーザーが所在する国または地域とは異なる管轄のサーバーやデータセンターを利用する場合があり、ユーザーの個人情報が国外へ移転されることがあります。たとえば、クラウドサービスプロバイダを通じて海外にあるデータセンターで個人情報を保管する場合などが挙げられます。\n\n1. \n\n保護水準の確認\n\n:\n\nこのような国際的なデータ移転に際しては、移転先の国や地域における個人情報保護法制が日本またはEUなどの基準と同等以上の水準にあるかどうかを確認し、必要に応じて適切な契約(EU標準契約条項など)を締結するなど、個人情報が適切に保護される体制を整備します。\n\n2. \n\nユーザーの明示的同意\n\n:'), Document(metadata={'my_metadata': 18}, page_content='2. \n\nユーザーの明示的同意\n\n:\n\nユーザーの明示的同意を得ることなく国際データ移転を行う場合、当社は日本国法令や国際ルールで認められた要件を満たす範囲でのみ実施します。たとえば、データの暗号化や仮名化を徹底することで、リスクを最低限に抑えた状態でデータを取り扱う措置を講じます。\n\n3. \n\n越境データのセキュリティ確保\n\n:\n\n国際回線を経由してデータを送信する場合、盗聴や改ざんのリスクが考えられるため、VPNの利用やSSL/TLS通信などを組み合わせ、情報が不正に傍受される可能性を極力排除します。さらに、国外のデータセンターへのアクセス権限を厳格に制限し、監査ログを取得・分析することで、不正アクセスを検知・阻止できる仕組みを維持しています。\n\n4. \n\nユーザーへの周知\n\n:'), Document(metadata={'my_metadata': 19}, page_content='4. \n\nユーザーへの周知\n\n:\n\n国際データ移転がサービス提供上不可避である場合、当社は利用規約や本ポリシーにてその旨を周知し、ユーザーがそのリスクや対策内容を理解できるよう配慮します。ユーザーが海外でサービスを利用する際には、各国の法規制やインターネットインフラ状況を踏まえて、データがどのように移転・保護されるのかを検討する必要があります。\n\n第9条(保有個人情報の開示・訂正・削除)\n\nユーザーは、当社が保有しているユーザー自身の個人情報について、開示、訂正、追加、削除、利用停止、または第三者提供の停止(以下「開示等」と総称)を請求する権利を有します。当社は、ユーザーからの開示等に関する請求があった場合、法令に基づき合理的な範囲で対応します。請求を希望される場合は、当社所定の手続き(本人確認等)を経たうえで、当社カスタマーサポートまでご連絡ください。\n\n1. \n\n開示の請求\n\n:')]
Tool name: Document_Search_Tool

=== Message 3 ===
Type: AIMessage
Content:
16歳未満のユーザーが海外から当社サービスを利用した場合、親権者の同意を得ることが必要である場合があると認識しており、ユーザーが未成年者であるにもかかわらず同意を得ていない場合、もしくは未成年者である旨を偽って利用登録を行った場合には、当社は一切の責任を負いかねます。

また、国際データ移転がサービス提供上不可避である場合、当社は利用規約や本ポリシーにてその旨を周知し、ユーザーがそのリスクや対策内容を理解できるよう配慮します。

以下にtoolから取得した情報を記載します。

[Document(metadata={'my_metadata': 21}, page_content='4. \n\n手数料\n\n:\n\n開示等の手数料については、当社が別途定める方法により請求させていただく場合がありますので、あらかじめご了承ください。\n\n上記のように、当社はユーザーの権利を尊重し、迅速かつ誠実な対応に努めます。ただし、請求内容によっては相当の期間や追加資料を要する場合があります。その際には手続きの進捗状況や必要な対応を速やかにユーザーへ連絡します。\n\n第10条(未成年者の個人情報)\n\n当社は、16歳未満のユーザーが当社サービスを利用する場合、法定代理人(親権者等)の同意を得ることが必要である場合があると認識しています。ユーザーが未成年者であるにもかかわらず同意を得ていない場合、もしくは未成年者である旨を偽って利用登録を行った場合には、当社は一切の責任を負いかねます。\n\n1. \n\n親権者の同意取得\n\n:\n\n未成年者がサービスを利用するにあたっては、親権者が本ポリシーの内容を確認したうえで利用に同意することが望ましいと考えています。特に決済手段の登録や外部サービスとの連携など、リスクの高い行為については慎重な対応を求めています。\n\n2. \n\n未成年者の個人情報保護'), Document(metadata={'my_metadata': 22}, page_content='2. \n\n未成年者の個人情報保護\n\n:\n\n16歳未満の利用者の個人情報に関しては、一般のユーザーと同等のセキュリティ対策を講じていますが、必要に応じてより厳格なアクセス制限を設定する場合があります。たとえば、投稿やコミュニケーション
Tool calls:
[]
Response Metadata:
{'is_blocked': False, 'safety_ratings': [], 'usage_metadata': {'prompt_token_count': 2253, 'candidates_token_count': 520, 'total_token_count': 2773, 'prompt_tokens_details': [{'modality': 1, 'token_count': 2253}], 'candidates_tokens_details': [{'modality': 1, 'token_count': 520}], 'cached_content_token_count': 0, 'cache_tokens_details': []}, 'finish_reason': 'MAX_TOKENS', 'avg_logprobs': -0.01480783407504742}

================= 最終的な出力結果 =================
16歳未満のユーザーが海外から当社サービスを利用した場合、親権者の同意を得ることが必要である場合があると認識しており、ユーザーが未成年者であるにもかかわらず同意を得ていない場合、もしくは未成年者である旨を偽って利用登録を行った場合には、当社は一切の責任を負いかねます。

また、国際データ移転がサービス提供上不可避である場合、当社は利用規約や本ポリシーにてその旨を周知し、ユーザーがそのリスクや対策内容を理解できるよう配慮します。

以下にtoolから取得した情報を記載します。

[Document(metadata={'my_metadata': 21}, page_content='4. \n\n手数料\n\n:\n\n開示等の手数料については、当社が別途定める方法により請求させていただく場合がありますので、あらかじめご了承ください。\n\n上記のように、当社はユーザーの権利を尊重し、迅速かつ誠実な対応に努めます。ただし、請求内容によっては相当の期間や追加資料を要する場合があります。その際には手続きの進捗状況や必要な対応を速やかにユーザーへ連絡します。\n\n第10条(未成年者の個人情報)\n\n当社は、16歳未満のユーザーが当社サービスを利用する場合、法定代理人(親権者等)の同意を得ることが必要である場合があると認識しています。ユーザーが未成年者であるにもかかわらず同意を得ていない場合、もしくは未成年者である旨を偽って利用登録を行った場合には、当社は一切の責任を負いかねます。\n\n1. \n\n親権者の同意取得\n\n:\n\n未成年者がサービスを利用するにあたっては、親権者が本ポリシーの内容を確認したうえで利用に同意することが望ましいと考えています。特に決済手段の登録や外部サービスとの連携など、リスクの高い行為については慎重な対応を求めています。\n\n2. \n\n未成年者の個人情報保護'), Document(metadata={'my_metadata': 22}, page_content='2. \n\n未成年者の個人情報保護\n\n:\n\n16歳未満の利用者の個人情報に関しては、一般のユーザーと同等のセキュリティ対策を講じていますが、必要に応じてより厳格なアクセス制限を設定する場合があります。たとえば、投稿やコミュニケーション

続いてのユーザクエリは「おはよう」

出力結果

================= エージェントの実行結果 =================

=== Message 0 ===
Type: HumanMessage
Content:
おはよう

=== Message 1 ===
Type: AIMessage
Content:
おはようございます!何かお手伝いできることはありますか?

Tool calls:
[]
Response Metadata:
{'is_blocked': False, 'safety_ratings': [], 'usage_metadata': {'prompt_token_count': 162, 'candidates_token_count': 11, 'total_token_count': 173, 'prompt_tokens_details': [{'modality': 1, 'token_count': 162}], 'candidates_tokens_details': [{'modality': 1, 'token_count': 11}], 'cached_content_token_count': 0, 'cache_tokens_details': []}, 'finish_reason': 'STOP', 'avg_logprobs': -0.03182329643856396}

================= 最終的な出力結果 =================
おはようございます!何かお手伝いできることはありますか?

続いてのユーザクエリは「今日は12歳の誕生日なんだ。これから初めて海外に行くんだよね」

出力結果

================= エージェントの実行結果 =================

=== Message 0 ===
Type: HumanMessage
Content:
今日は12歳の誕生日なんだ。これから初めて海外に行くんだよね

=== Message 1 ===
Type: AIMessage
Content:
12歳のお誕生日おめでとうございます!🎉 初めての海外旅行、わくわくしますね!どちらに行かれるんですか? 楽しい思い出をたくさん作ってきてください!😊

Tool calls:
[]
Response Metadata:
{'is_blocked': False, 'safety_ratings': [], 'usage_metadata': {'prompt_token_count': 175, 'candidates_token_count': 35, 'total_token_count': 210, 'prompt_tokens_details': [{'modality': 1, 'token_count': 175}], 'candidates_tokens_details': [{'modality': 1, 'token_count': 35}], 'cached_content_token_count': 0, 'cache_tokens_details': []}, 'finish_reason': 'STOP', 'avg_logprobs': -0.1403693880353655}

================= 最終的な出力結果 =================
12歳のお誕生日おめでとうございます!🎉 初めての海外旅行、わくわくしますね!どちらに行かれるんですか? 楽しい思い出をたくさん作ってきてください!😊

こちらも前回と同様に、ユーザからの質問であればRAGをToolとして呼び出し、雑談には、Toolを実行せずに雑談として返すことができています。

まとめ

今回は、Google CloudのGCSをドキュメントローダとして、Cloud SQL for PostgreSQLをVector Storeとして利用したRAGのエージェントをLangGraphで実装しました。

次は、また別のVector Storeでの実装方法を記事にしたいと思います。

ここまで読んでくださり、ありがとうございました!

学習書籍

(書籍のリンクはamazonアフィリエイトリンクになります)

記事

LangChain と Google Cloud データベースを使用して強化された生成 AI アプリケーションを構築する
https://cloud.google.com/blog/ja/products/databases/build-rag-applications-with-langchain-and-google-cloud

LangChainのチュートリアル記事「Google Cloud SQL for PostgreSQL」
https://python.langchain.com/docs/integrations/vectorstores/google_cloud_sql_pg/

利用するライブラリ「langchain-google-cloud-sql-pg-python」
https://github.com/googleapis/langchain-google-cloud-sql-pg-python

書籍

Generative AI on Google Cloud with LangChain: Design scalable generative AI solutions with Python, LangChain, and Vertex AI on Google Cloud
英語ではありますが、非常に分かりやすい書籍です。
というか、現在においてLangChain+Google Cloudを取り巻くライブラリの複雑さは異常だと思っています。
各DBごとに必要なライブラリが乱立しており、どのライブラリを利用するのが良いのかが分かりにくいです。(なぜなら技術記事では、一つのライブラリ、一つのDBにフォーカスしており、他にどんな選択肢があるのかが分かりにくい)
本書籍は、それらをすべて統括して分かりやすく記載されているため、全体像が掴みやすくおすすめの書籍になっています。
英語の本ではありますが、購入時にPDFも一緒に取得することができる(2025年2月現在)ため、「Google 翻訳」のPDF変換機能で翻訳することで、英語がわからなくても読むことができますので、ぜひお試しください。
(PDFが取得可能かどうかは、Amazonの商品概要欄に記載してありますので、購入前にお確かめください)

LangChainとLangGraphによるRAG・AIエージェント[実践]入門
ChatGPT/LangChainによるチャットシステム構築[実践]入門
LangChainを利用することで、あらゆるモデルを統一的なコードで実行できるようになります。
langchainに関しては、こちらの書籍を読めば大体のことはできるようになりますので、おすすめです。
また、現在推奨されているLangGraphでのRAG Agentを構築するcreate_react_agentに関しても説明されておりますし、さらに複雑なAgentsの構築方法やデザイン方法も網羅されており、とても勉強になります!

大規模言語モデル入門
大規模言語モデル入門Ⅱ〜生成型LLMの実装と評価
よく紹介させていただいておりますが、こちらの書籍は、LLMのファインチューニングから、RLHF、RAG、分散学習にかけて、本当に幅広く解説されており、いつも参考にさせていただいております。
今回の記事で紹介したRAGの内容だけでなく、さらにその先であるRAGを前提としてInstruction Tuningについても触れており、とても面白いです。
LLMを取り扱っている方は、とりあえず買っておいても損はないと思います。
さまざまな章、ページで読めば読むほど新しい発見が得られる、スルメのような本だなといつも思っております。

LLMのファインチューニングとRAG ―チャットボット開発による実践
上記2冊の本よりもRAGやファインチューニングに絞って記載されている書籍です。だいぶ平易に書いてあるのでとてもわかりやすいと思いました。
また、本記事の内容ではないですが、RAGを実装する上でキーワード検索を加えたハイブリッド検索を検討することは一般的だと思います。本書はそこにも踏み込んで解説をしています。
また、キーワード検索でよく利用するBM25Retrieverが日本語のドキュメントに利用する際に一工夫がいるところなども紹介されており、使いやすい本だなと思いました。

Discussion