Closed4
ベクトルデータベース「Weaviate」を試す 4:自分でベクトル化したデータを使う
前回の続き
Weaviateの特徴の1つであるモジュールを使えば、ベクトル化プロセスをWeaviate側におまかせできるのだけど、これを使わずに自分でベクトル化したデータを登録することもできる。
パッケージインストール。自分でベクトル化するので、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
),
)
登録データ作成。データセットは引き続きこれ。
!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が使えるらしい、いわゆるスコアと考えて良さそう。
今回は回答からベクトルデータを作ったので、当然回答で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': '妊娠・出産'}
Weaviateで対応していないモジュールを使う場合、特にWCSだとモジュールの追加もできないようなので、必要になるユースケースはあるかもしれないけど、せっかくWeaviate使うならモジュールは積極的に使いたい気がする。
次はQuickstartでもすこしやったけど、WeaviateのGenerative SearchでまるっとRAGを構成するのをやる。
このスクラップは2024/03/10にクローズされました