ブログ

Elasticsearch と LlamaIndex を使用して RAG の機密情報と PII 情報を保護する

Elasticsearch と LlamaIndex を使用して RAG アプリケーション内の機密データと PII データを保護する方法。

この記事では、RAG (Retrieval Augmented Generation) フローでパブリック LLM を使用する際に、個人識別情報 (PII) と機密データを保護する方法について説明します。オープンソース ライブラリと正規表現を使用して PII と機密データをマスキングする方法と、パブリック LLM を呼び出す前にローカル LLM を使用してデータをマスキングする方法を検討します。

始める前に、この投稿で使用するいくつかの用語を確認しましょう。

用語について

LlamaIndex は、LLM (大規模言語モデル) アプリケーションを構築するための主要なデータ フレームワークです。LlamaIndex は、RAG (Retrieval Augmented Generation) アプリケーションの構築のさまざまな段階に抽象化を提供します。LlamaIndex や LangChain などのフレームワークは、アプリケーションが特定の LLM の API に密結合されないように抽象化を提供します。

ElasticsearchElasticによって提供されています。Elastic は、精度の高い全文検索、意味理解のためのベクトル検索、両方の長所を生かしたハイブリッド検索をサポートするスケーラブルなデータ ストアおよびベクトル データベースである Elasticsearch を提供する業界リーダーです。Elasticsearch は、分散型の RESTful 検索および分析エンジン、スケーラブルなデータ ストア、およびベクター データベースです。このブログで使用している Elasticsearch 機能は、Elasticsearch の無料およびオープン バージョンで利用できます。

検索拡張生成 (RAG)は、LLM に外部知識を提供してユーザーのクエリに対する応答を生成する AI テクニック/パターンです。これにより、LLM 応答を特定のコンテキストに合わせてカスタマイズし、汎用性を抑えることができます。

埋め込みは、テキスト/メディアの意味を数値的に表現したものです。それらは高次元情報の低次元表現です。

RAGとデータ保護

一般的に、大規模言語モデル (LLM) は、インターネット データでトレーニングできるモデル内で利用可能な情報に基づいて応答を生成するのに適しています。ただし、モデル内で情報が得られないクエリの場合、LLM にはモデル内に含まれていない外部知識または特定の詳細が提供される必要がありま す。このような情報は、データベースまたは社内のナレッジ システム内にある可能性があります。検索拡張生成 (RAG) は、特定のユーザー クエリに対して、まず外部 (LLM に対して) システム (データベースなど) から関連するコンテキスト/情報を取得し、そのコンテキストをユーザー クエリとともに LLM に送信して、より具体的で関連性の高い応答を生成する手法です。

これにより、RAG テクニックは、質問への回答、コンテンツの作成、コンテキストと詳細の深い理解が役立つあらゆるアプリケーションに非常に効果的になります。

その結果、RAG パイプラインでは、PII (個人識別情報) などの内部情報や機密情報 (名前、生年月日、口座番号など) がパブリック LLM に公開されるリスクがあります。

Elasticsearch のようなベクター データベースを使用する場合、データは安全です (ロール ベースのアクセス制御ドキュメント レベルのセキュリティなどのさまざまな手段を通じて)。ただし、データを外部のパブリック LLM に送信する場合は注意が必要です。

大規模言語モデル (LLM) を使用する場合、個人を特定できる情報 (PII) と機密データを保護することは、いくつかの理由から重要です。

  • プライバシーコンプライアンス: 多くの地域では、ヨーロッパの一般データ保護規則 (GDPR) や米国のカリフォルニア州消費者プライバシー法 (CCPA) など、個人データの保護を義務付ける厳格な規制があります。法的責任や罰金を回避するには、これらの法律を遵守する必要があります。

  • ユーザーの信頼: 機密情報の機密性と整合性を確保することで、ユーザーの信頼が構築されます。ユーザーは、自分のプライバシーが保護されると信じるシステムを使用したり、やり取りしたりする可能性が高くなります。

  • データ セキュリティ: データ侵害に対する保護が不可欠です。適切な保護措置を講じずに LLM に公開された機密データは盗難や悪用される可能性があり、個人情報の盗難や金融詐欺などの潜在的な危害につながる可能性があります。

  • 倫理的な考慮事項: 倫理的には、ユーザーのプライバシーを尊重し、ユーザーのデータを責任を持って扱うことが重要です。個人情報を不適切に取り扱うと、差別、汚名、その他の社会的悪影響が生じる可能性があります。

  • 企業の評判: 機密データを保護できない企業は評判が損なわれる可能性があり、顧客や収益の喪失など、ビジネスに長期的な悪影響を及ぼす可能性があります。

  • 悪用リスクの軽減: 機密データを安全に扱うことで、偏ったデータでモデルをトレーニングしたり、データを使用して個人を操作したり害を与えたりするなど、データやモデルの悪意のある使用を防ぐことができます。

全体として、PII と機密データの堅牢な保護は、法令遵守の確保、ユーザーの信頼の維持、データ セキュリティの確保、倫理基準の遵守、ビジネスの評判の保護、不正使用のリスクの軽減に必要です。

簡単な要約

前回の投稿では、LlamaIndex とローカルで実行される Mistral LLM を使用しながら、Elasticsearch をベクター データベースとして RAG テクニックを使用して Q&A エクスペリエンスを実装する方法について説明しました。ここではそれを基に構築します。

前回の投稿を読むことはオプションです。今回は前回の投稿で行った内容を簡単に説明/要約します。

架空の住宅保険会社のエージェントと顧客間のコールセンターの会話のサンプル データセットがありました。私たちは、「顧客はどのような水関連の問題について請求をしているのか?」といった質問に答えるシンプルな RAG アプリケーションを構築しました。

大まかに言うと、フローは次のようになります。

RAGフロー

インデックス作成フェーズでは、LlamaIndex パイプラインを使用してドキュメントを読み込み、インデックスを作成しました。ドキュメントはチャンク化され、埋め込みとともに Elasticsearch ベクター データベースに保存されました。

ユーザーが質問したクエリフェーズで、LlamaIndex はクエリに関連する上位 K 件の類似ドキュメントを取得しました。これらの上位 K 件の関連ドキュメントはクエリとともに、ローカルで実行されている Mistral LLM に送信され、ユーザーに返される応答が生成されました。ぜひ前回の投稿をご覧になったり、コードを調べたりしてください

前回の投稿では、LLM をローカルで実行しました。ただし、本番環境では、 OpenAIMistralAnthropicなどのさまざまな企業が提供する外部 LLM を使用する必要がある場合があります。ユースケースでより大きな基礎モデルが必要であるか、スケーラビリティ、可用性、パフォーマンスなどのエンタープライズ生産のニーズによりローカルでの実行がオプションではないことが原因である可能性があります。

RAG パイプラインに外部 LLM を導入すると、機密情報や PII が LLM に誤って漏洩するリスクが生じます。この投稿では、ドキュメントを外部 LLM に送信する前に、RAG パイプラインの一部として PII 情報をマスクする方法について説明します。

公立LLM取得のRAG

RAG パイプラインで PII と機密情報を保護する方法について説明する前に、まず LlamaIndex、Elasticsearch Vector データベース、OpenAI LLM を使用してシンプルな RAG アプリケーションを構築します。

要件

以下のものが必要となります。

  • 埋め込みを保存するためのベクター データベースとしてElasticsearch を起動して実行します。Elasticsearch のインストールに関する前回の投稿の手順に従ってください。

  • AI API キーを開きます。

シンプルなRAGアプリケーション

参考までに、コード全体はこのGithubリポジトリ(branch:protecting-pii)にあります。以下のコードを見ていくので、リポジトリのクローンは任意です。

お気に入りの IDE で、以下の 3 つのファイルを使用して新しい Python アプリケーションを作成します。

  • index.py データのインデックス作成に関連するコードが配置される場所。

  • query.py クエリと LLM の相互作用に関連するコードが配置される場所。

  • .env API キーなどの構成プロパティが配置される場所。

いくつかのパッケージをインストールする必要があります。まず、アプリケーションのルート フォルダーに新しい Python仮想環境を作成します。

python3 -m venv .venv

仮想環境をアクティブ化し、以下の必要なパッケージをインストールします。

source .venv/bin/activate
pip install llama-index 
pip install llama-index-embeddings-openai
pip install llama-index-vector-stores-elasticsearch
pip install sentence-transformers
pip install python-dotenv
pip install openai

.envでOpenAIとElasticsearchの接続プロパティを設定するファイル。

OPENAI_API_KEY="REPLACEME"
ELASTIC_CLOUD_ID="REPLACEME"
ELASTIC_API_KEY="REPLACEME"

データのインデックス作成

架空の住宅保険会社の顧客とコールセンターエージェント間の 会話 が含まれる conversations.json ファイルをダウンロードします。アプリケーションのルートディレクトリに、2つのPythonファイルと.envファイルと一緒にファイルを配置します。先ほど作成したファイル。以下はファイルの内容の例です。

{
"conversation_id": 103,
"customer_name": "Sophia Jones",
"agent_name": "Emily Wilson",
"policy_number": "JKL0123",
"conversation": "Customer: Hi, I'm Sophia Jones. My Date of Birth is November 15th, 1985, Address is 303 Cedar St, Miami, FL 33101, and my Policy Number is JKL0123.\nAgent: Hello, Sophia. How may I assist you today?\nCustomer: Hello, Emily. I have a question about my policy.\nCustomer: There's been a break-in at my home, and some valuable items are missing. Are they covered?\nAgent: Let me check your policy for coverage related to theft.\nAgent: Yes, theft of personal belongings is covered under your policy.\nCustomer: That's a relief. I'll need to file a claim for the stolen items.\nAgent: We'll assist you with the claim process, Sophia. Is there anything else I can help you with?\nCustomer: No, that's all for now. Thank you for your assistance, Emily.\nAgent: You're welcome, Sophia. Please feel free to reach out if you have any further questions or concerns.\nCustomer: I will. Have a great day!\nAgent: You too, Sophia. Take care.",
"summary": "A customer inquires about coverage for stolen items after a break-in at home, and the agent confirms that theft of personal belongings is covered under the policy. The agent offers assistance with the claim process, resulting in the customer expressing relief and gratitude."
}

データのインデックス作成を処理する以下のコードをindex.pyに貼り付けます。

# index.py
# pip install sentence-transformers
# pip install llama-index-embeddings-openai
# pip install llama-index-embeddings-huggingface

import json
import os
from dotenv import load_dotenv
from llama_index.core import Document
from llama_index.core import Settings
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore


def get_documents_from_file(file):
   """Reads a json file and returns list of Documents"""

   with open(file=file, mode='rt') as f:
       conversations_dict = json.loads(f.read())

   # Build Document objects using fields of interest.
   documents = [Document(text=item['conversation'],
                         metadata={"conversation_id": item['conversation_id']})
                for
                item in conversations_dict]
   return documents

# Load .env file contents into env
load_dotenv('.env')
Settings.embed_model = HuggingFaceEmbedding(
   model_name="BAAI/bge-small-en-v1.5"
)

def main():
   # ElasticsearchStore is a VectorStore that
   # takes care of Elasticsearch Index and Data management.
   es_vector_store = ElasticsearchStore(index_name="convo_index",
                                        vector_field='conversation_vector',
                                        text_field='conversation',
                                        es_cloud_id=os.getenv("ELASTIC_CLOUD_ID"),
                                        es_api_key=os.getenv("ELASTIC_API_KEY"))

   # LlamaIndex Pipeline configured to take care of chunking, embedding
   # and storing the embeddings in the vector store.
   llamaindex_pipeline = IngestionPipeline(
       transformations=[
           SentenceSplitter(chunk_size=350, chunk_overlap=50),
           Settings.embed_model
       ],
       vector_store=es_vector_store
   )

   # Load data from a json file into a list of LlamaIndex Documents
   documents = get_documents_from_file(file="conversations.json")
   llamaindex_pipeline.run(documents=documents)
   print(".....Indexing Data Completed.....\n")

if __name__ == "__main__":
   main()

上記のコードを実行すると、Elasticsearch にインデックスが作成され、 convo_indexという名前の Elasticsearch インデックスに埋め込みが保存されます。

LlamaIndex IngestionPipeline に関する説明が必要な場合は、 IngestionPipeline の作成セクションの前の投稿を参照してください。

クエリ

前回の投稿では、クエリにローカル LLM を使用しました。

この投稿では、以下に示すように、公開 LLM である OpenAI を使用します。

# query.py
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.llms.openai import OpenAI
from index import es_vector_store

# Public LLM where we send user query and Related Documents
llm = OpenAI()

index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents are sent as-is. So any PII/Sensitive data is sent to the LLM.
query_engine = index.as_query_engine(llm, similarity_top_k=10)

query="Give me summary of water related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)

上記のコードは、OpenAI からの応答を以下のように出力します。

顧客は、地下室の水害、水道管の破裂、屋根への雹害、適時通知の欠如、メンテナンスの問題、徐々に進行する消耗、既存の損傷などの理由による請求の拒否など、さまざまな水関連の請求を提起しています。いずれの場合も、顧客は請求の却下に対する不満を表明し、請求に関する公正な評価と決定を求めました。

RAG での PII のマスキング

これまで説明してきたのは、ユーザークエリとともにドキュメントをそのまま OpenAI に送信することです。

RAG パイプラインでは、関連するコンテキストが Vector ストアから取得された後、クエリとコンテキストを LLM に送信する前に、PII と機密情報をマスクする機会があります。

外部 LLM に送信する前に PII 情報をマスクする方法はいくつかあり、それぞれにメリットがあります。以下のオプションをいくつか見てみましょう

  1. spacy.io やPresidio (Microsoft が管理するオープン ソース ライブラリ) などの NLP ライブラリを使用します。

  2. LlamaIndexをそのまま使用する NERPIINodePostprocessor.

  3. ローカルLLMの使用 PIINodePostprocessor

上記のいずれかの方法を使用してマスキング ロジックを実装したら、PostProcessor (独自のカスタム PostProcessor または LlamaIndex が提供するすぐに使用できる PostProcessor) を使用して LlamaIndex IngestionPipeline を構成できます。

NLPライブラリの使用

RAG パイプラインの一部として、NLP ライブラリを使用して機密データをマスクできます。このデモでは、spacy.io パッケージを使用します。

新しいファイルquery_masking_nlp.pyを作成し、以下のコードを追加します。

# query_masking_nlp.py

# pip install spacy
# python3 - m spacy download en_core_web_sm
import re
from typing import List, Optional

import spacy
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor.types import BaseNodePostprocessor
from llama_index.core.schema import NodeWithScore
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
from index import es_vector_store

# Load the spaCy model
nlp = spacy.load("en_core_web_sm")

# Compile regex patterns for performance
phone_pattern = re.compile(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b')
email_pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
date_pattern = re.compile(r'\b(\d{1,2}[-/]\d{1,2}[-/]\d{2,4}|\d{2,4}[-/]\d{1,2}[-/]\d{1,2})\b')
dob_pattern = re.compile(
r"(January|February|March|April|May|June|July|August|September|October|November|December)\s(\d{1,2})(st|nd|rd|th),\s(\d{4})")
address_pattern = re.compile(r'\d+\s+[\w\s]+\,\s+[A-Za-z]+\,\s+[A-Z]{2}\s+\d{5}(-\d{4})?')
zip_code_pattern =  re.compile(r'\b\d{5}(?:-\d{4})?\b')
policy_number_pattern = re.compile(r"[A-Z]{3}\d{4}\.$")  # 3 characters followed by 4 digits, in our case e.g XYZ9876

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# match = re.match(policy_number_pattern, "XYZ9876")
# print(match)


def mask_pii(text):
   """
   Masks Personally Identifiable Information (PII) in the given
   text using pre-defined regex patterns and spaCy's named entity recognition.
   Args:
       text (str): The input text containing potential PII.
   Returns:
       str: The text with PII masked.
   """

   # Process the text with spaCy for NER
   doc = nlp(text)

   # Mask entities identified by spaCy NER (e.g First/Last Names etc)
   for ent in doc.ents:
       if ent.label_ in ["PERSON", "ORG", "GPE"]:
           text = text.replace(ent.text, '[MASKED]')

   # Apply regex patterns after NER to avoid overlapping issues
   text = phone_pattern.sub('[PHONE MASKED]', text)
   text = email_pattern.sub('[EMAIL MASKED]', text)
   text = date_pattern.sub('[DATE MASKED]', text)
   text = address_pattern.sub('[ADDRESS MASKED]', text)
   text = dob_pattern.sub('[DOB MASKED]', text)
   text = zip_code_pattern.sub('[ZIP MASKED]', text)
   text = policy_number_pattern.sub('[POLICY MASKED]', text)

   return text


class CustomPostProcessor(BaseNodePostprocessor):
   """
   Custom Postprocessor which masks Personally Identifiable Information (PII).
   PostProcessor is called on the Documents before they are sent to the LLM.
   """
   def _postprocess_nodes(
           self, nodes: List[NodeWithScore], query_bundle: Optional[QueryBundle]
   ) -> List[NodeWithScore]:
       # Masks PII
       for n in nodes:
          n.node.set_content(mask_pii(n.text))
       return nodes

   
# Use Public LLM to send user query and Related Documents
llm = OpenAI()
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents are masked based on custom logic defined in CustomPostProcessor._postprocess_nodes.
query_engine = index.as_query_engine(llm, similarity_top_k=10, node_postprocessors=[CustomPostProcessor()])



query = "Give me summary of water related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
response = query_engine.query(bundle)
print(response)

LLM による応答を以下に示します。

顧客からは、地下室の水害、水道管の破裂、屋根への雹害、大雨による浸水など、さまざまな水関連のクレームが出ています。これらの請求は、適時の通知の欠如、メンテナンスの問題、徐々に進行する消耗、既存の損傷などの理由に基づいて請求が拒否されたために、フラストレーションを招いています。顧客は、こうした請求拒否の結果、失望、ストレス、経済的負担を感じており、請求の公正な評価と徹底的な見直しを求めています。一部の顧客は保険金請求処理の遅延にも直面しており、保険会社が提供するサービスに対するさらなる不満が生じています。

上記のコードでは、Llama Index QueryEngine を作成するときに CustomPostProcessor を指定します。

QueryEngine によって呼び出されるロジックは、 CustomPostProcessor_postprocess_nodesメソッドで定義されています。私たちは SpaCy.io ライブラリを使用して名前付きエンティティを検出し、ドキュメントを LLM に送信する前に、いくつかの正規表現を使用してそれらの名前と機密情報を置き換えます。

以下に、元の会話の一部と、CustomPostProcessor によって作成されたマスクされた会話の例を示します。

原文:

顧客: こんにちは。私はマシュー ロペスです。生年月日は 1984 年 10 月 12 日、住所は 456 Cedar St, Smalltown, NY 34567 です。私の保険証券番号はTUV8901です。エージェント: こんにちは、マシュー。本日はどのようなご用件でしょうか?顧客: こんにちは。私の請求を却下するという貴社の決定に、大変失望しております。

CustomPostProcessor によってマスクされたテキスト。

顧客: こんにちは。私は [MASKED] です。[MASKED] は [DOB MASKED] で、456 Cedar St, [MASKED], [MASKED] 34567 に住んでいます。私の保険証券番号は[MASKED]です。エージェント: こんにちは、[MASKED]。本日はどのようなご用件でしょうか?顧客: こんにちは。私の請求を却下するという貴社の決定に、大変失望しております。

注記:

個人情報や機密情報を識別してマスキングすることは簡単な作業ではありません。機密情報のさまざまな形式とセマンティクスをカバーするには、ドメインとデータに関する十分な理解が必要です。上記のコードは一部のユースケースでは機能する可能性がありますが、ニーズとテストに基づいて変更する必要がある場合もあります。

LlamaIndexをそのまま使用する NERPIINodePostprocessor

LlamaIndexは、RAGパイプラインでPII情報を保護しやすくするために、 NERPIINodePostprocessor.

from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor import NERPIINodePostprocessor
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
from index import es_vector_store

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# Use Public LLM to send user query and Related Documents
llm = OpenAI()

ner_processor = NERPIINodePostprocessor()
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents masked using the NERPIINodePostprocessor so that PII/Sensitive data is not sent to the LLM.
query_engine = index.as_query_engine(llm, similarity_top_k=10, node_postprocessors=[ner_processor])

query = "Give me summary of fire related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
response = query_engine.query(bundle)
print(response)

応答は以下のとおりです

顧客は、火災により所有物件に損害が生じたとして損害賠償請求を起こした。あるケースでは、放火が補償範囲外であったため、ガレージの火災による損害に対する請求が却下されました。別の顧客は、保険でカバーされていた自宅の火災による損害について請求をしました。さらに、顧客がキッチンの火災を報告し、火災による損害が補償されることが保証されました。

ローカルLLMの使用 PIINodePostprocessor

また、データをパブリック LLM に送信する前に、ローカルまたはプライベート ネットワークで実行されている LLM を活用してマスキング作業を行うこともできます。

マスキングを行うには、ローカル マシン上の Ollama で実行されている Mistral を使用します。

Mistralをローカルで実行する

Ollamaをダウンロードしてインストールします。Ollamaをインストールした後、このコマンドを実行してmistralをダウンロードして実行します。

ollama run mistral

モデルを初めてローカルにダウンロードして実行するには数分かかる場合があります。以下のような「雲についての詩を書いてください」という質問をして、ミストラルが実行されているかどうかを確認し、その詩が気に入ったものかどうかを確認します。後でコードを通じてミストラル モデルとやり取りする必要があるため、ollama を実行したままにしておきます。

query_masking_local_LLM.pyという新しいファイルを作成し、以下のコードを追加します。

# pip install llama-index-llms-ollama
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor import PIINodePostprocessor
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.ollama import Ollama
from llama_index.llms.openai import OpenAI
from index import es_vector_store

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# Use Public LLM to send user query and Related Documents and Local LLM to mask
public_llm = OpenAI()
local_llm = Ollama(model="mistral")

pii_processor = PIINodePostprocessor(llm=local_llm)
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the public LLM.
# Note that documents are masked using the local llm via PIINodePostprocessor
# so that PII/Sensitive data is not sent to the public LLM.
query_engine = index.as_query_engine(public_llm, similarity_top_k=10, node_postprocessors=[pii_processor])


query = "Give me summary of fire related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)

応答は以下のようなものです

顧客は、火災により所有物件に損害が生じたとして損害賠償請求を起こした。あるケースでは、放火が補償範囲外であったため、ガレージの火災による損害に対する請求が却下されました。別の顧客は、保険でカバーされていた自宅の火災による損害について請求をしました。さらに、顧客がキッチンの火災を報告し、火災による損害が補償されることが保証されました。

まとめ

この投稿では、RAG フロー内でパブリック LLM を使用する際に PII と機密データを保護する方法を説明しました。私たちはそれを実現する複数の方法を実証しました。採用する前に、ユースケースとニーズに基づいてこれらのアプローチをテストすることを強くお勧めします。

関連記事

高度なRAGテクニックパート2:クエリとテスト

Han Xiang Choong

Elasticsearchによるエンティティ解決、パート4:究極のチャレンジ

Jessica Moszkowicz

Elastic Agent Builder と GPT-OSS を使用した HR 向け AI エージェントの構築

Tomás Murúa

高度なRAGテクニックパート1:データ処理

Han Xiang Choong

LangGraph.jsとElasticsearchを使用して金融AI検索ワークフローを構築

Jeffrey Rengifo

最先端の検索体験を構築する準備はできましたか?

十分に高度な検索は 1 人の努力だけでは実現できません。Elasticsearch は、データ サイエンティスト、ML オペレーター、エンジニアなど、あなたと同じように検索に情熱を傾ける多くの人々によって支えられています。ぜひつながり、協力して、希望する結果が得られる魔法の検索エクスペリエンスを構築しましょう。

はじめましょう