Closed4

ベクトルデータベース「Weaviate」を試す 4:自分でベクトル化したデータを使う

kun432kun432

パッケージインストール。自分でベクトル化するので、OpenAIのクライアントパッケージも。

!pip install -U weaviate-client openai

クライアント初期化。モジュールは使わないのでAPIキーはここで渡さない。

import weaviate
import weaviate.classes as wvc
import os
import requests
import json
from google.colab import userdata

client = weaviate.connect_to_wcs(
    cluster_url=userdata.get('WEAVIATE_CLUSTER_URL'),
    auth_credentials=weaviate.auth.AuthApiKey(userdata.get('WEAVIATE_API_KEY')),
)

コレクション作成。なるほど、明示的にベクトル化モジュールを無効化しているのと、ベクトルインデックスの設定を行っている。

faq = client.collections.create(
    "FAQ",
    vectorizer_config=wvc.config.Configure.Vectorizer.none(),
    vector_index_config=wvc.config.Configure.VectorIndex.hnsw(
        distance_metric=wvc.config.VectorDistances.COSINE
    ),
)

登録データ作成。データセットは引き続きこれ。

https://linecorp.com/ja/csr/newslist/ja/2020/260

!wget https://d.line-scdn.net/stf/linecorp/ja/csr/dataset_.zip
!unzip dataset_.zip
import pandas as pd

df = pd.read_excel("dataset_.xlsx")
df.drop(columns=["ID","サンプルID", "カテゴリ2","出典","<参考>UMカテゴリタグ","<参考>UMサービスメニュー\n(標準的な行政サービス名称)"], inplace=True)
df.rename(columns={
    'サンプル 問い合わせ文': 'question',
    'サンプル 応答文': 'answer',
    'カテゴリ1': 'category',
}, inplace=True)

手元でベクトル化する。"text-embedding-3-small"で一番小さい次元数にしてみた。

import os
from google.colab import userdata
from openai import OpenAI
from tqdm import tqdm

tqdm.pandas()

os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY')

embedding_model = "text-embedding-3-small"
dimensions = 512

openai_client = OpenAI()

def get_embedding(text, model, dimensions):
    text = text.replace("\n", " ")
    response = openai_client.embeddings.create(
        input=[text],
        model=model,
        dimensions=dimensions,
    )
    return response.data[0].embedding

df["answer_embeddings"] = df["answer"].progress_apply(lambda x: get_embedding(x, embedding_model, dimensions))
df

faq_objs = df.to_dict(orient='records')
print(len(faq_objs))
print(faq_objs[0])
662
{'question': '母子手帳を受け取りたいのですが、手続きを教えてください。', 'answer': '窓口で妊娠届をご記入いただき、母子手帳をお渡しします。\n住民票の世帯が別の方が代理で窓口に来られる場合は、委任状が必要になります。\n\n▼詳しくはこちら\n(自治体HP内関連ページのURL)', 'category': '妊娠・出産', 'answer_embeddings': [0.07447286695241928, 0.050039201974868774, ...snip....]}

Weaviateのデータオブジェクトに変換して、コレクションにデータ追加。

wvc_faq_objs = []

for i, d in enumerate(faq_objs):
    wvc_faq_objs.append(wvc.data.DataObject(
            properties={
                "answer": d["answer"],
                "question": d["question"],
                "category": d["category"],
            },
            vector=d["answer_embeddings"]
        ))

faq.data.insert_many(wvc_faq_objs)

ではretrieval

query = faq_objs[0]["question"]  # question: "母子手帳を受け取りたいのですが、手続きを教えてください。"
query_vector = get_embedding(query, embedding_model, dimensions)

response = faq.query.near_vector(
    near_vector=query_vector,
    limit=5,
    return_metadata=wvc.query.MetadataQuery(distance=True, certainty=True)
)

for r in response.objects:
    print(r.metadata.distance)
    print(r.metadata.certainty)
    print(r.properties)
    print()
0.28132718801498413
0.8593363761901855
{'answer': '母子手帳をなくしたときは、再交付を受けてください。\nお子さんが出生前の母子手帳については、(再交付を受けられる場所)で再交付を受けられます。\nお子さんが出生後の母子手帳については、(再交付を受けられる場所)で受けられます。\n申請の際はご本人確認できるものをお持ちください。\n\n◆お問い合わせ\n(自治体の担当課等の名称)\n(電話番号)/(開庁時間)', 'question': '母子手帳をなくした場合は再発行できますか?', 'category': '妊娠・出産'}

0.32557380199432373
0.8372130990028381
{'answer': '母子手帳は、○○市役所本庁舎△△階××課窓口、◎◎出張所、………(その他の受け取り場所を適宜記載)………で受け取れます。\n\n▼詳しくはこちら\n(自治体HP内関連ページのURL)', 'question': '母子手帳の受け取り場所はどこですか?', 'category': '妊娠・出産'}

0.33146047592163086
0.8342697620391846
{'answer': '母子手帳は、妊娠届の内容を確認させていただき、その場でお渡しします。\n\n▼詳しくはこちら\n(自治体HP内関連ページのURL)', 'question': '母子手帳はすぐに発行してもらえますか?', 'category': '妊娠・出産'}

0.34868359565734863
0.8256582021713257
{'answer': '産前は母子手帳以外の手続きは特にありません。\n産後に、出生の届出や出生通知書の提出、(自治体が行う出産助成等)の申請をお願いします。', 'question': '母子手帳の他に産前に市役所でやるべき手続きはありますか?', 'category': '妊娠・出産'}

0.37558841705322266
0.8122057914733887
{'answer': '母子手帳は住所が変わってもそのままお使いいただけます。再発行等の手続は必要ありません。\n\n◆お問い合わせ\n(自治体の担当課や子育てセンター等の名称)\n(電話番号)/(開庁時間)', 'question': '母子手帳は転出してもそのまま持っていてよいですか?', 'category': '妊娠・出産'}

類似度のメトリクスは、前回まではdistanceを使っていたけども、コサイン類似度の場合はcertaintyが使えるらしい、いわゆるスコアと考えて良さそう。

https://weaviate.io/developers/weaviate/config-refs/distances#distance-vs-certainty

今回は回答からベクトルデータを作ったので、当然回答でretrievalすれば高いスコアになる。

query = faq_objs[0]["answer"]  # answer: "窓口で妊娠届をご記入いただき、母子手帳をお渡しします。 住民票の世帯が別の方が代理で窓口に来られる場合は..."
query_vector = get_embedding(query, embedding_model, dimensions)

response = faq.query.near_vector(
    near_vector=query_vector,
    limit=5,
    return_metadata=wvc.query.MetadataQuery(distance=True, certainty=True)
)

for r in response.objects:
    print(r.metadata.distance)
    print(r.metadata.certainty)
    print(r.properties)
    print()
-2.384185791015625e-07
1.0000001192092896
{'answer': '窓口で妊娠届をご記入いただき、母子手帳をお渡しします。\n住民票の世帯が別の方が代理で窓口に来られる場合は、委任状が必要になります。\n\n▼詳しくはこちら\n(自治体HP内関連ページのURL)', 'question': '母子手帳を受け取りたいのですが、手続きを教えてください。', 'category': '妊娠・出産'}

0.14668071269989014
0.9266596436500549
{'answer': '妊娠したら妊娠届を○○課窓口(または支所・出張所窓口)に提出し、母子手帳を受け取ってください。\n\n▼詳しくはこちら\n(自治体HP内関連ページのURL)', 'question': '妊娠したので、必要な手続きを教えてください。', 'category': '妊娠・出産'}

0.21182173490524292
0.8940891027450562
{'answer': '母子手帳は、妊娠届の内容を確認させていただき、その場でお渡しします。\n\n▼詳しくはこちら\n(自治体HP内関連ページのURL)', 'question': '母子手帳はすぐに発行してもらえますか?', 'category': '妊娠・出産'}

0.24781405925750732
0.8760929703712463
{'answer': '妊娠届(母子手帳交付申請含む)は代理でも届出することができます。ただし、妊婦ご本人と同一世帯の方以外が代理申請する場合は、委任状が必要になります。\nまた、妊娠届には妊娠週数、分娩予定日、性病に関する健康診断(血液検査)の有無、結核に関する健康診断(レントゲン検査)の有無及び診断を受けた医療機関の名前・所在地・診断者氏名を記入していただく必要がありますので、予め妊婦(委任者)ご本人にご確認の上お越しください。\n\n▼詳しくはこちら\n(自治体HP内関連ページのURL)', 'question': '妊娠届を代理でも届出できますか?', 'category': '妊娠・出産'}

0.2511765956878662
0.8744117021560669
{'answer': '妊娠した人は、(市役所○○課、保健所、保健相談所等の妊娠届を出せる場所を記載してください。)で妊娠届を出してください。(母子手帳や妊婦健診の受診票など、妊娠した人にお渡しするもの)をさしあげます。なるべく早めの届出をお願いします。\n\n▼詳しくはこちら\n(自治体HP内関連ページのURL)', 'question': '妊娠届について教えてください。', 'category': '妊娠・出産'}
kun432kun432

Weaviateで対応していないモジュールを使う場合、特にWCSだとモジュールの追加もできないようなので、必要になるユースケースはあるかもしれないけど、せっかくWeaviate使うならモジュールは積極的に使いたい気がする。

このスクラップは2ヶ月前にクローズされました