Azure Cognitive Searchの検索精度:OpenAIのEmbeddingモデルより10%劣る

NLP
Cloud
Published

June 2, 2023

TD;DR

Azure Cognitive Searchの検索精度は、OpenAIのEmbeddingモデルより10%劣ることが分かりました。サービスを使うときのセットアップ手順などを考えると、Retrieval-Augmented Generationの中にあるRetrieverとして使う価値がほぼないと思います。

はじめに

Microsoft Build 2023の中で

# https://github.com/Azure-Samples/azure-search-python-samples/blob/main/Quickstart/v11/azure-search-quickstart.ipynb
_=!pip install azure-search-documents
import os
from azure.core.credentials import AzureKeyCredential
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents import SearchClient
from azure.search.documents.indexes.models import (
    ComplexField,
    CorsOptions,
    SearchIndex,
    ScoringProfile,
    SearchFieldDataType,
    SimpleField,
    SearchableField,
)
import dotenv
dotenv.load_dotenv()

service_name = os.environ["AZURE_SEARCH_SERVICE_NAME"]
admin_key = os.environ["AZURE_SEARCH_ADMIN_KEY"]
index_name = "testmicrosoft" # test
True
endpoint = "https://{}.search.windows.net/".format(service_name)
admin_client = SearchIndexClient(
    endpoint=endpoint, index_name=index_name, credential=AzureKeyCredential(admin_key)
)

search_client = SearchClient(
    endpoint=endpoint, index_name=index_name, credential=AzureKeyCredential(admin_key)
)
# Delete the index if it exists
try:
    result = admin_client.delete_index(index_name)
    print ('Index', index_name, 'Deleted')
except Exception as ex:
    print (ex)
Index testmicrosoft Deleted
# Specify the index schema
name = index_name
fields = [
        SimpleField(name="AID", type=SearchFieldDataType.String, key=True),
        SearchableField(name="Answer", type=SearchFieldDataType.String, analyzer_name="ja.microsoft"),
        SearchableField(name="Keywords", type=SearchFieldDataType.String, analyzer_name="ja.microsoft"),
    ]
cors_options = CorsOptions(allowed_origins=["*"], max_age_in_seconds=60)
scoring_profiles = []
index = SearchIndex(
    name=name,
    fields=fields,
    scoring_profiles=scoring_profiles,
    cors_options=cors_options)

try:
    result = admin_client.create_index(index)
    print ('Index', result.name, 'created')
except Exception as ex:
    print (ex)
Index testmicrosoft created
import pandas as pd
# https://zenodo.org/record/2783642
q_df = pd.read_csv("https://zenodo.org/record/2783642/files/Questions.csv")
a_df = pd.read_csv("https://zenodo.org/record/2783642/files/Answers.csv")
print("q_df.shape:", q_df.shape)
print("a_df.shape:", a_df.shape)
q_df.columns = [c.strip() for c in q_df.columns]
a_df.columns = [c.strip() for c in a_df.columns]
df = q_df.merge(a_df, on="AID")
df.columns = ["query","AID","document"]

metadata = a_df[["AID"]].to_dict(orient="records")
documents = a_df["Text"].tolist()
query_list = list(zip(q_df["Text"], q_df["AID"]))
display(q_df.head(3))
display(a_df.head(3))
q_df.shape: (427, 2)
a_df.shape: (79, 2)
Text AID
0 履修している授業で先生が資料をアップロードしているはずだが、コース上に資料が見当たらない。 A001
1 資料をマイページに置いたが、学生からは見えなかった。 A001
2 前期の科目の「資料」を学生から見られないようにするにはどうしたら良いか? A001
AID Text
0 A001 資料が見つからない場合は、以下の点を確認してください。<br><br><br>【受講生編】<...
1 A002 資料のアップロードやお知らせ作成時の電子メールでの通知の有無は、各授業の担当教員が設定できま...
2 A003 kibacoにはファイルへパスワードを設定する機能はありません。資料は受講生全員に開示されま...
documents = [
    {
    "@search.action": "upload",
    "AID": aid,
    "Answer": answer,
    "Keywords": "",
    }
    for aid, answer in zip(a_df["AID"], a_df["Text"])
]
try:
    result = search_client.upload_documents(documents=documents)
    print("Upload of new document succeeded: {}".format(result[0].succeeded))
except Exception as ex:
    print (ex.message)
from dataclasses import dataclass
from tqdm.auto import tqdm

DOC_NUM = len(a_df)
@dataclass
class EvaluationResults:
    result_df: pd.DataFrame
    mrr: float
    recall_at_1: float
    recall_at_5: float


def mrr(rank_array):
    return (1 / rank_array).mean()

def recall_at_k(rank_array, k):
    return (rank_array <= k).mean()


def evaluate(query_list, get_rank_func):
    result_list = []
    for query, aid in tqdm(query_list):
        rank_result = get_rank_func(query)
        if aid not in rank_result:
            rank = DOC_NUM + 1
        else:
            rank = rank_result.index(aid) + 1
        
        result_list.append((query, rank, rank_result))

    result_df = pd.DataFrame(result_list, columns=["query", "rank", "rank_result"])
    return EvaluationResults(result_df, mrr(result_df["rank"]), recall_at_k(result_df["rank"], 1), recall_at_k(result_df["rank"], 5))

def get_rank(query):
    result = search_client.search(search_text=query, top=DOC_NUM)
    return [hit["AID"] for hit in result]
result_azure_cog = evaluate(query_list, get_rank)
result_azure_cog_microsoft = evaluate(query_list, get_rank) # change analyzer_name="ja.microsoft"
result_azure_cog.mrr, result_azure_cog.recall_at_1, result_azure_cog.recall_at_5
result_azure_cog_microsoft.mrr, result_azure_cog_microsoft.recall_at_1, result_azure_cog_microsoft.recall_at_5
(0.5845928050824319, 0.4496487119437939, 0.7517564402810304)
import pickle 
with open("../../data/result_dic.pkl", "rb") as f:
    result_dic = pickle.load(f)
EOFError: Ran out of input
new_result_dic = {}
new_result_dic["result_azure_cog"] = result_azure_cog
new_result_dic["result_azure_cog_microsoft"] = result_azure_cog_microsoft
result_list = []
for model in result_dic.keys():
    result = result_dic[model]
    if result:
        result_list.append([model,result.mrr, result.recall_at_1, result.recall_at_5] )
    else:
        result_list.append([model,0, 0,0] )
        
result_df = pd.DataFrame(
    result_list, 
    columns = ["model_id","mrr","recall_at_1","recall_at_5"]
    ).sort_values("mrr", ascending=False)

result_df.reset_index(drop=True, inplace=True)
result_df
model_id mrr recall_at_1 recall_at_5
0 OpenAIEmbeddings 0.684147 0.548009 0.868852
1 result_azure_cog 0.584593 0.449649 0.751756
2 result_azure_cog_microsoft 0.580532 0.454333 0.740047
3 TensorflowHubEmbeddings 0.560619 0.407494 0.761124
4 paraphrase-multilingual-mpnet-base-v2 0.525899 0.398126 0.676815
5 oshizo/sbert-jsnli-luke-japanese-base-lite 0.520106 0.405152 0.655738
6 paraphrase-multilingual-MiniLM-L12-v2 0.497027 0.370023 0.639344
7 intfloat/multilingual-e5-base 0.481144 0.337237 0.632319
8 sonoisa/sentence-bert-base-ja-mean-tokens-v2 0.465294 0.327869 0.622951
9 setu4993/smaller-LaBSE 0.450434 0.290398 0.632319
10 sonoisa/sentence-bert-base-ja-en-mean-tokens 0.438923 0.304450 0.599532
11 setu4993/LaBSE 0.434725 0.274005 0.625293
12 Blaxzter/LaBSE-sentence-embeddings 0.434725 0.274005 0.625293
13 distiluse-base-multilingual-cased-v2 0.428484 0.264637 0.620609
14 ZurichNLP/unsup-simcse-xlm-roberta-base 0.419397 0.299766 0.526932
15 sentence-transformers/stsb-xlm-r-multilingual 0.361811 0.231850 0.484778
16 sonoisa/clip-vit-b-32-japanese-v1 0.320160 0.203747 0.437939
17 sonoisa/sentence-bert-base-ja-mean-tokens 0.293779 0.177986 0.402810
18 google/canine-s 0.270446 0.159251 0.358314
19 google/canine-c 0.258978 0.159251 0.341920
20 colorfulscoop/sbert-base-ja 0.227531 0.133489 0.295082
21 sonoisa/t5-base-japanese 0.213053 0.135831 0.278689
22 M-CLIP/M-BERT-Distil-40 0.170714 0.084309 0.236534
23 microsoft/unihanlm-base 0.162957 0.098361 0.187354
24 nielsr/lilt-xlm-roberta-base 0.143722 0.074941 0.173302
25 severinsimmler/xlm-roberta-longformer-base-16384 0.129116 0.072600 0.145199
26 TylorShine/distilhubert-ft-japanese-50k 0.000000 0.000000 0.000000
27 rinna/japanese-hubert-base 0.000000 0.000000 0.000000
28 sonoisa/sentence-luke-japanese-base-lite 0.000000 0.000000 0.000000
29 facebook/nllb-moe-54b 0.000000 0.000000 0.000000
30 ArthurZ/nllb-moe-128 0.000000 0.000000 0.000000
31 paulhindemith/fasttext-jp-embedding 0.000000 0.000000 0.000000
32 rinna/japanese-cloob-vit-b-16 0.000000 0.000000 0.000000
33 rinna/japanese-clip-vit-b-16 0.000000 0.000000 0.000000
34 sonoisa/sentence-t5-base-ja-mean-tokens 0.000000 0.000000 0.000000
35 megagonlabs/transformers-ud-japanese-electra-b... 0.000000 0.000000 0.000000
36 pkshatech/simcse-ja-bert-base-clcmlp 0.000000 0.000000 0.000000
# dump all result to result_dic
with open("../result_dic.pkl", "wb") as f:
    pickle.dump(result_df, f)
%load_ext autoreload
%autoreload 2
new_result_dic
{'result_azure_cog': EvaluationResult(result_df=                                             query  rank  \
 0    履修している授業で先生が資料をアップロードしているはずだが、コース上に資料が見当たらない。     7   
 1                       資料をマイページに置いたが、学生からは見えなかった。     1   
 2             前期の科目の「資料」を学生から見られないようにするにはどうしたら良いか?     2   
 3                              アップロード済みの資料が見当たらない。    10   
 4                                     先生の資料が見られない。     3   
 ..                                             ...   ...   
 422                                  推奨環境のブラウザは何か?     3   
 423                                   どのOSを使えば良いの?     1   
 424                                  どのブラウザなら使えるの?     2   
 425                                      推奨環境を教えて。    80   
 426                                   どのパソコンなら良いの?    80   
 
                                            rank_result  
 0    [A002, A008, A044, A009, A003, A052, A001, A05...  
 1    [A001, A005, A052, A010, A008, A055, A006, A00...  
 2    [A005, A001, A055, A078, A033, A052, A012, A05...  
 3    [A003, A044, A043, A008, A009, A002, A007, A04...  
 4    [A078, A002, A001, A008, A006, A057, A010, A07...  
 ..                                                 ...  
 422                                 [A043, A007, A079]  
 423               [A079, A004, A027, A002, A043, A065]  
 424                                 [A007, A079, A043]  
 425                                             [A043]  
 426                                                 []  
 
 [427 rows x 3 columns], mrr=0.5845928050824319, recall_at_1=0.4496487119437939, recall_at_5=0.7517564402810304),
 'result_azure_cog_microsoft': EvaluationResult(result_df=                                             query  rank  \
 0    履修している授業で先生が資料をアップロードしているはずだが、コース上に資料が見当たらない。     1   
 1                       資料をマイページに置いたが、学生からは見えなかった。     1   
 2             前期の科目の「資料」を学生から見られないようにするにはどうしたら良いか?     1   
 3                              アップロード済みの資料が見当たらない。     9   
 4                                     先生の資料が見られない。     2   
 ..                                             ...   ...   
 422                                  推奨環境のブラウザは何か?     2   
 423                                   どのOSを使えば良いの?     1   
 424                                  どのブラウザなら使えるの?     1   
 425                                      推奨環境を教えて。    45   
 426                                   どのパソコンなら良いの?     1   
 
                                            rank_result  
 0    [A001, A002, A044, A008, A009, A051, A052, A04...  
 1    [A001, A075, A056, A052, A005, A008, A010, A00...  
 2    [A001, A005, A012, A033, A051, A003, A008, A05...  
 3    [A003, A043, A002, A044, A009, A008, A007, A04...  
 4    [A003, A001, A046, A002, A047, A051, A012, A05...  
 ..                                                 ...  
 422  [A043, A079, A007, A033, A063, A001, A026, A01...  
 423  [A079, A019, A055, A023, A077, A002, A005, A04...  
 424         [A079, A007, A043, A023, A020, A039, A062]  
 425  [A043, A001, A012, A015, A024, A046, A030, A02...  
 426                     [A079, A023, A020, A039, A062]  
 
 [427 rows x 3 columns], mrr=0.5805322051879468, recall_at_1=0.45433255269320844, recall_at_5=0.7400468384074942)}