はじめに
昨今、生成AIを活用する際によく聞く RAG(Retrieval-Augmented Generation; 検索拡張生成)。
本記事ではその根幹技術の一つである Azure AI Search について、python の SDK を使用した、インデックス作成・データ投入・検索の基本を解説していきます。
想定読者
- Azure AI Search をこれから触る人
- Python で Azure AI Search の機能を利用したい人
この記事で得られること
Azure AI Search の概要理解
python の SDK を使った Azure AI Search の基本的な操作方法
- インデックスの作成
- データ投入
- 検索の実行
Azure AI Searchとは
Azure AI Searchは、RAG(Retrieval-Augmented Generation; 検索拡張生成)における「検索」を担う技術の一つです。
データを検索可能な形でインデックス化し、キーワード検索・ベクトル検索・ハイブリッド検索などの高度な検索機能とランキングを提供するクラウドベースの検索サービスです。
RAG(Retrieval-Augmented Generation; 検索拡張生成)について詳しく知りたい方は、以下の記事が分かりやすいです。
https://qiita.com/yakumo_09/items/361cede87b026957a7aa
Azure AI Search には、主に次の3種類の検索方法があります。
- キーワード検索
- 検索語とドキュメント内の語句の一致に基づいて結果を返す、一般的な全文検索です。
- ベクトル検索
- 検索語とドキュメントをそれぞれベクトル化し、類似度(コサイン類似度など)を基に検索する手法です。意味検索が可能になります。
- ハイブリッド検索
- キーワード検索とベクトル検索の両方を実行し、それぞれのスコアを統合して総合的にランキングする方式です。
Azure AI Search の検索機能の詳細については、こちらの記事が分かりやすいです。
https://zenn.dev/microsoft/articles/bc23b5e34d8a97
次のセクションでは Python SDK を用いて実際に Azure AI Search を操作し、インデックス作成から検索までの一連の流れを解説します。
Python で Azure AI Search を動かす
では、Python の SDK を使用して、Azure AI Search を動かしてみます。
今回は、Azure AI Search の操作を理解しやすくするために、カフェのレビューを 10 件ほどデモデータとして用意しました(生成AIに作ってもらいました)。
| id | content |
|---|---|
| 1 | ここのカフェラテは美味しい!特にミルクフォームが美味しい。 |
| 2 | エスプレッソは苦味が強く、深いコクが感じられる。 |
| 3 | 店内は落ち着いた雰囲気で、コーヒーが美味しかった。 |
| 4 | ここの紅茶は香りが強く、とてもフルーティ。 |
| 5 | カウンター席が多く、一人でも入りやすい。 |
| 6 | 季節限定の紅茶とケーキのセットが相性抜群で美味しい。 |
| 7 | クロワッサンがサクサクで最高。コーヒーとの相性も抜群。 |
| 8 | 美味しいが、値段が少し高めだと感じた。 |
| 9 | 季節限定の桃の紅茶が絶品だった。 |
| 10 | Wi-Fi が速くてオンライン会議も問題なくできた。 |
このデータを使って、インデックス作成 → データ投入 → 検索までの流れを実演していきます。
準備
Python で SDK を使用して Azure のリソースを操作するには、実行環境(ローカルPC / Notebook など)が Azure にアクセスするための認証情報(Credential)を取得できる状態になっている必要があります。
今回は、その準備としてAzure CLI を使って事前にログインしておきます。
az login
※ Azure CLI のインストールについては以下の記事を参照ください。
https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli?view=azure-cli-latest
インデックスの作成
まず、検索対象となるデータを格納するインデックスを作成します。
インデックスとは:
データを検索しやすいように整形し、検索用に最適化された構造で保持したものです。
(データ本体とは別で作られる “検索専用のデータベース” のようなもの)
Azure AI Search では、このインデックスのスキーマを定義することで
「どんなデータを検索したいのか」
「その項目を検索対象にするのか」
などを指定します。
以下は Python SDK を使ったインデックス作成の例です。
# 必要なライブラリのインポート
from azure.identity import DefaultAzureCredential
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
SimpleField,
SearchFieldDataType,
SearchableField,
SearchField,
VectorSearch,
HnswAlgorithmConfiguration,
VectorSearchProfile,
SearchIndex,
)
credential = DefaultAzureCredential() # 認証情報の取得
search_endpoint = 'Azure AI Search の エンドポイント'
#(「Azure portal/Azure AI Search/概要/URL」で値を確認できます)
search_index_client = SearchIndexClient(search_endpoint, credential)
# フィールドを定義
fields = [
SimpleField(name="id", type=SearchFieldDataType.String, key=True, sortable=True, filterable=True, facetable=True),
SearchableField(name="content", type=SearchFieldDataType.String, analyzer_name='ja.microsoft'),
SearchField(name="vector_content", type=SearchFieldDataType.Collection(SearchFieldDataType.Single),
searchable=True, vector_search_dimensions=3072, vector_search_profile_name="myHnswProfile")
]
# ベクトル検索に使用するアルゴリズムの設定
vector_search = VectorSearch(
algorithms=[
HnswAlgorithmConfiguration(
name="myHnsw"
)
],
profiles=[
VectorSearchProfile(
name="myHnswProfile",
algorithm_configuration_name="myHnsw",
)
]
)
# インデックスを作成
index_name = "cafe_review_index"
index = SearchIndex(
name=index_name,
fields=fields,
vector_search=vector_search,
)
search_index_client.create_or_update_index(index=index)
※ インデックスのフィールド定義の詳細については以下の公式ドキュメントを参照ください。
https://learn.microsoft.com/ja-jp/azure/search/search-how-to-create-search-index?utm_source=chatgpt.com&tabs=portal
※ ベクトル検索に使用するアルゴリズム(Hnsw)については、先ほど紹介した「Azure AI Searchの検索手法を比べてみた」の記事で分かりやすく解説されています。(再掲します。)
https://zenn.dev/microsoft/articles/bc23b5e34d8a97
データ投入(インデックスにデータをアップロード)
Azure AI Search の検索(特にベクトル検索・ハイブリッド検索)では、
テキストを Embedding(ベクトル化)してからインデックスに格納しておく必要があります。
ここでは、以下の手順でデータを投入していきます。
- カフェのレビュー文をEmbedding APIでベクトル化
- 元のテキストとベクトル化した文章を JSON形式にまとめる
- Azure AI Search にアップロード
# 必要なライブラリのインポート
import csv
from openai import OpenAI
from azure.search.documents import SearchClient
from azure.identity import DefaultAzureCredential
# データの読み込み
with open('data/cafe_review.csv', 'r') as file:
csv_reader = csv.reader(file)
# ヘッダーを読み込む
headers = next(csv_reader)
# データを読み込む
reviews = [row for row in csv_reader]
# ベクトル化の準備
openai_client = OpenAI(
api_key = 'APIキー',
base_url = 'OpenAI の APIエンドポイント'
)
def generate_embeddings(text):
response = openai_client.embeddings.create(
input=text,
model='text-embedding-3-large' # 埋め込みモデル
)
embeddings = response.data[0].embedding
return embeddings
# 1. データのベクトル化
for review in reviews:
content = review[1]
content_embeddings = generate_embeddings(content)
review.append(content_embeddings)
# 2. データをJSON形式にまとめる
review_json = []
for review in reviews:
review_dict = {
"id":review[0],
"content": review[1],
"vector_content": review[2],
}
review_json.append(review_dict)
# 3. データを Azure AI Search にアップロード
search_endpoint = 'Azure AI Search の エンドポイント'
index_name = "cafe_review_index"
credential = DefaultAzureCredential() # 認証情報の取得
search_client = SearchClient(
endpoint=search_endpoint,
index_name=index_name,
credential=credential
)
search_client.upload_documents(review_json)
検索
では、アップロードしたデータに対して、3種類の検索(キーワード検索・ベクトル検索・ハイブリッド検索)を実施していきます。
今回は、検索方法による違いが分かりやすいように、すべて 「美味しい紅茶」 というワードで検索します。
まず、検索に入る前に、どの検索方式でも共通で使用する準備コード(クライアント接続・Embedding生成など)を定義しておきます。
共通設定の準備
# 必要なライブラリのインポート
from azure.search.documents.models import QueryType, QueryCaptionType, QueryAnswerType, VectorizedQuery
from azure.identity import DefaultAzureCredential
from azure.search.documents import SearchClient
from openai import OpenAI
search_endpoint = 'Azure AI Search の エンドポイント'
index_name = "cafe_review_index"
credential = DefaultAzureCredential() # 認証情報の取得
search_client = SearchClient(
endpoint=search_endpoint,
index_name=index_name,
credential=credential
)
# ベクトル化の準備
openai_client = OpenAI(
api_key = 'APIキー',
base_url = 'OpenAI の APIエンドポイント'
)
def generate_embeddings(text):
response = openai_client.embeddings.create(
input=text,
model='text-embedding-3-large' # 埋め込みモデル
)
embeddings = response.data[0].embedding
return embeddings
# キーワード検索用クエリ
query = '美味しい紅茶'
# ベクトル検索用クエリ
embedding = generate_embeddings(query)
vector_query = VectorizedQuery(
vector=embedding,
fields="vector_content" # ベクトル検索するフィールド名
)
キーワード検索
results = search_client.search(
search_text=query, # キーワード検索用のクエリ
search_fields=["content"], # キーワード検索するフィールド名
select=["id", "content"], # 検索結果として取得するフィールド名
top=3
)
i = 1
for result in results:
print(f"{i}位 Score: {result['@search.score']}")
print(f"id: {result['id']}, content: {result['content']}")
print("-"*10)
i += 1
検索結果
1位 Score: 1.0256125
id: 1, content: ここのカフェラテは美味しい!特にミルクフォームが美味しい。
----------
2位 Score: 1.0107933
id: 4, content: ここの紅茶は香りが強く、とてもフルーティ。
----------
3位 Score: 0.7081689
id: 9, content: 季節限定の桃の紅茶が絶品だった。
----------
- キーワードの完全一致に近い検索
- 「単語そのもの」が含まれていないとヒットしない
ベクトル検索
results = search_client.search(
vector_queries=[vector_query], # ベクトル検索用のクエリ
select=["id", "content"], # 検索結果として取得するフィールド名
top=3
)
i = 1
for result in results:
print(f"{i}位 Score: {result['@search.score']}")
print(f"id: {result['id']}, content: {result['content']}")
print("-"*10)
i += 1
検索結果
1位 Score: 0.7167121
id: 6, content: 季節限定の紅茶とケーキのセットが相性抜群で美味しい。
----------
2位 Score: 0.7149178
id: 4, content: ここの紅茶は香りが強く、とてもフルーティ。
----------
3位 Score: 0.7107973
id: 9, content: 季節限定の桃の紅茶が絶品だった。
----------
- 文章の意味が近いものがヒットする。(「絶品」など)
- 単語が一致していなくても検索できる。
ハイブリッド検索
results = search_client.search(
search_text=query, # キーワード検索用のクエリ
vector_queries= [vector_query], # ベクトル検索用のクエリ
search_fields=["content"], # キーワード検索するフィールド名
select=["id", "content"], # 検索結果として取得するフィールド名
top=3
)
i = 1
for result in results:
print(f"{i}位 Score: {result['@search.score']}")
print(f"id: {result['id']}, content: {result['content']}")
print("-"*10)
i += 1
検索結果
1位 Score: 0.032786883413791656
id: 4, content: ここの紅茶は香りが強く、とてもフルーティ。
----------
2位 Score: 0.03253968432545662
id: 1, content: ここのカフェラテは美味しい!特にミルクフォームが美味しい。
----------
3位 Score: 0.03253968432545662
id: 6, content: 季節限定の紅茶とケーキのセットが相性抜群で美味しい。
----------
- キーワード検索 × ベクトル検索の両方でスコアが高い文章 が上位にくる
3. まとめ
Azure AI Search は、RAG 構成における「検索」を担う非常に重要なコンポーネントです。
本記事では、
- インデックスの作成
- データの投入
- キーワード検索 / ベクトル検索 / ハイブリッド検索
といった 基礎的な操作の流れ を Python SDK で実践しました。
実際のシステムでは、Azure OpenAI、AI Foundry、Copilot Studio などと組み合わせて
より高度な検索・生成アプリに発展させることができます。
この記事が Azure AI Search を触る第一歩となれば幸いです!