Closed7

ベクトルデータベース「Weaviate」を試す 13: Multiple target vectors

kun432kun432

久々のWeaviate.これが気になった。

https://twitter.com/weaviate_io/status/1836049352155926653

🚀 1.26でマルチターゲットベクトル検索を導入しました。

Weaviate 1.24では複数のベクトルを持つオブジェクトが導入されましたが、1.26ではさらに一歩進んでいます!複数のターゲットベクトルからの結果を組み合わせた単一のクエリを作成できるようになりました。

複数のベクトルを検索する際には、単一の名前付きベクトルではなく、ターゲットベクトルのリストをクエリに追加します。Weaviateは自動的にすべてのターゲット検索ベクトルからの結果を組み合わせます。内部のスコアリングメカニズムは、ハイブリッド検索のハイブリッド融合アルゴリズムと概念的に類似しています!

以前やったのは、Multiple vectors/Named vectorsという似たような機能だった。

https://zenn.dev/kun432/scraps/1c457c09774cd9

いずれの場合、ベクトルデータの中身が何であれ、1オブジェクトに対して1ベクトルデータになる。ただ、いろいろやっていくと、各プロパティごとにベクトル化して、プロパティごとに検索したくなることもある。これを実現するのが、Named vectors/Multiple vectorsになる。

例えば、QAのデータ、質問と回答の両方をそれぞれベクトル化してWeaviateに登録しておくと、質問で検索することも、回答で検索することも、できるというもの。一般的にクエリは質問に近いので、ピンポイントな質問に対しては最適な回答が期待できるだろうし、回答を検索すれば、クエリとの類似性は多少低くなるかもしれないが、文脈的に近しいものを拾う可能性が上がる。

今回新しく追加されたMultiple target vectorsはこういう感じらしい。

Multiple target vectors

マルチターゲットベクトル検索は、単一のクエリを使用して複数のターゲットベクトルを検索します。Weaviateはターゲットベクトルを同時に検索し、結果を自動的に結合します。

検索結果の結合

各マルチターゲットベクトル検索は、複数のシングルターゲットベクトル検索で構成されています。 検索結果は結合戦略に基づいて結合されます。 結合戦略は、クエリベクトルとターゲットベクトルの間の距離をどのように結合して単一の距離スコアを生成するかを決定します。

なるほど、Multiple vectors/Named vectorsの場合は、複数のプロパティに対して検索はできるが、

  • それぞれ検索する必要がある
  • それぞれの検索結果をどう使うかは自分で実装しなければいけない

というものだったのが、1つのクエリから複数のプロパティに対してベクトル検索を行い、それらの結果を統合して結果を返せるというものの様子。つまり、複数ベクトル検索のハイブリッドみたいなイメージなんだと思う。

kun432kun432
メモ

改めておさらい。よくあるFAQのデータをベクトルDBに登録するというのを考えてみる。

FAQのデータセットは、京都大学大学院情報学研究科知能情報学コース言語メディア研究室 (https://nlp.ist.i.kyoto-u.ac.jp/)様が公開されている尼崎市の市民向けFAQデータセットを例に使わせていただく。

FAQというか、QAデータセットは一般的に「質問」と「回答」のペアになっている。

余談だが、よくあるドキュメントをチャンクして・・・というのとは違うように思えるが、こう考えれば同じ。

ドキュメントをチャンクするケースとの違いは、ドキュメントの場合は大きなコンテキストを持っていて、その一部分を切り出すというところ。QAデータの場合、そのコンテキストがQAだけで完結しているというところが異なる。

とはいえ、QAデータも元は何かしらの大きなコンテキスト情報があって、それを特定の手法(頻度の高い質問)で切り出したのがFAQなので、基本的にはクエリから関連するコンテキストを持ったドキュメントを引っ張ってくる、という意味では同じになる。

で、話を元に戻して、質問から「関連度の高い」回答を検索するというのはこういうことになる。

質問と回答からそれぞれEmbeddingsを生成して、それをコサイン類似度で比較することで、質問と回答の「セマンティックな類似度が高い」≒「関連する可能性が高い」というのがベクトル検索になる。

ベクトルデータベースも含めるとこういう感じになる。

コサイン類似度のスコアでランキングして、上位k件(top-k)の検索結果を得る。ただし、欲しいのはベクトルそのものではなく、それに紐づいたテキスト情報を含む「メタデータ」になる。RAGの場合は、このメタデータをコンテキスト情報としてプロンプトに含めて、LLMに回答を生成させることになる。

で、上記の例では、「回答」をベクトル化して、「質問」との関連度を見ているわけだが、そもそもEmbeddingモデルを使ったコサイン類似度は「文と文の間のセマンティックな類似性」を見るものだと思う。そう考えた場合、以下はどれが一番近い情報になるだろうか?

実際に試してみる。

from openai import OpenAI
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
import os
from google.colab import userdata

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

query = "地域総合センター今北へはどう行けばいいですか?"
texts = [
    "地域総合センター今北へはどう行けばいいですか?",
    "地域総合センターについて知りたい",
    "地域総合センター塚口へはどう行けばいいですか?",
    "地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください",
    "各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。",
    "地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。",
]

def get_embedding(client, text):
    response = client.embeddings.create(
        input=text,
        model="text-embedding-3-small"
    )
    return response.data[0].embedding

openai_client = OpenAI()

query_embedding = get_embedding(openai_client, query)
text_embeddings = [get_embedding(openai_client, text) for text in texts]

query_embedding = np.array(query_embedding).reshape(1, -1)
text_embeddings = np.array(text_embeddings)

cosine_similarities = cosine_similarity(query_embedding, text_embeddings)

print(f"Query: {query}")
print(f"Similarity:")
for i, text in enumerate(texts):
    if len(text) > 50:
        text = f"{text[:50]}..."
    print(f"Score: {cosine_similarities[0][i]:.4f} : {text}")

結果

Query: 地域総合センター今北へはどう行けばいいですか?
Similarity:
Score: 1.0000 : 地域総合センター今北へはどう行けばいいですか?
Score: 0.6144 : 地域総合センターについて知りたい
Score: 0.7113 : 地域総合センター塚口へはどう行けばいいですか?
Score: 0.5822 : 地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立...
Score: 0.4509 : 各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図...
Score: 0.4294 : 地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください...

スコアを見ればわかるように、質問に近しいものが上位に並んで、回答に近しいものは下位になっている。つまり、人間が思う、質問に対して「適した」回答・質問の「意図にあった」回答、が高スコアになるわけではなく、テキストで使用されている単語のバラエティや類似性、テキスト全体のボリュームなども「文と文の間のセマンティックな類似性」に影響する。(ただし、対象のベクトルが回答ばかりの中で類似性を見るならば、相対的に上位になる、というのはあるとは思う)

そう考えた場合、「質問」に対して「質問」を検索すれば、総じて類似度が高いのではないか?という仮説が成り立つ。

ベクトルデータベースに登録する際に、質問をベクトル化、回答をメタデータとして、登録する。これにより、質問に最も近い形で検索ができて、かつ、ほしい情報はメタデータから取得できる、ことが予想される。ただしその反面、ここは個人的な考えになるが、

  • ピンポイントの質問、それの言い方の揺れなどには、間違いなく強くなると思う。
  • ただし、
    • 質問と少しだけ異なるような検索結果が上位に来る可能性がある。それは適切なのか?
      • 例として「地域総合センター今北へはどう行けばいいですか? 」というクエリ
        • このクエリは「地域総合センター今北」への「行き方」を問うものであり、重要なのは「地域総合センター今北」とそこへの「行き方」になる
        • 「地域総合センター塚口へはどう行けばいいですか?」「地域総合センター上ノ島へはどう行けばいいですか?」なども類似度的には高くなることが予想されるが、果たしてそれは欲しい情報なのだろうか?
        • それよりも「地域総合センターについて概要を教えて下さい」(より概要的な情報)、「地域総合センター今北には◯◯な施設はありますか?」(より詳細的な情報)というようにコンテキストが進むのではないだろうか?
    • 総じて質問よりも回答のほうがより多くの「コンテキスト」を含んでいる。想定していない質問が来た場合、それらを拾えるのか?
      • 例えば「地域総合センター今北には駐車場がありますか?」とか「阪急電車で、地域総合センター今北の最寄り駅はどこ?」とか「域総合センター今北の電話番号は?」とか
      • これらは、全部回答には含まれている情報である。

というようなデメリットもあるように思う。

そもそも、QAに限らず、情報検索の性質として、「質問」のコンテキストは少ないが、「回答」のコンテキストがボリュームがある、ここに差があるというのがある。そしてこの差が検索精度に影響する。

であれば、これを近づけてやればいい、ということで、2つのアプローチがある。

  1. クエリ拡張
  2. ドキュメント拡張

クエリ拡張は、そもそもクエリのコンテキストが小さくて、検索対象のドキュメントとの差が大きいのだから、クエリのコンテキストを広げてやればドキュメントのコンテキストに近づくだろうという発想。有名なところだとHyDE(Hypothetical Document Embeddings)がそれ。

https://arxiv.org/abs/2212.10496

クエリをそのままベクトル検索するのではなく、一度LLMを使って、検索結果に近しくなるような「仮」のドキュメントを生成して、それで検索するという手法。LLMによる回答が必ずしも正しくないとしても、質問に対して、欲しい回答の文章というのはある程度似通ってくるはずで、ボリュームやコンテキストも増えるので、それで検索すればドキュメントのコンテキストに近づくことが期待できる。

ただし、LLMを一度介することになるので、レスポンス時間が伸びる、のは当然として、あとはLLMの毎回異なる生成結果を踏まえても、果たしてそれで何処まで精度があがるのか?というところがデメリットになる。

なお、他にもクエリ拡張の手法にはいろいろある。

もう一つのドキュメント拡張、こちらは古くからある手法らしい。

https://arxiv.org/abs/2012.14005

https://arxiv.org/abs/2012.14005

最近だとこれも同じである(プロンプトキャッシュのユースケースとしてはそうなのだけど、そもそも検索精度を上げる手法としては古いということになる模様)

https://www.anthropic.com/news/contextual-retrieval

図にするとこう。

こちらは、クエリとドキュメントはそもそも違う性質のコンテキストを持っているので、クエリ拡張とは逆に、クエリに近しい情報をドキュメントに追加して拡張するということになる。ドキュメントのボリュームは更に増えるのでその分「文と文の間のセマンティックな類似度」は下がると思うのだけど、クエリに近い情報が追加されること、それにより、元のドキュメントの情報がややマイルドになり、クエリに対する検索精度が上がる、ということなのだろうと推測している。

QAデータの場合、手っ取り早いのは質問と回答を1つのテキストに結合して、それをベクトル化すればいいということになる。他にもドキュメントの内容をサマリにするとか、キーワード化するとか、いろいろな手法があると思う。

このように、比較的シンプルに思えるQAデータのベクトル検索の実装においても、回答をベクトル化するか、質問をベクトル化するか、それとも両方をベクトル化するか、というようなバリエーションが考えられる。

なぜこういうことを考えないといけないのか?

それは、ベクトルデータベースにおける1オブジェクトが持てるベクトルデータは1つになるためだと思う。言い換えると、「1つのベクトル空間」の中にあるデータはすべて「同じ方向性を持つベクトル」であり、「異なる方向性を持つベクトル」は「別々のベクトル空間に分ける」必要があるということになる。

上の方で書いたのを再度引用する

Query: 地域総合センター今北へはどう行けばいいですか?
Similarity:
Score: 1.0000 : 地域総合センター今北へはどう行けばいいですか?
Score: 0.6144 : 地域総合センターについて知りたい
Score: 0.7113 : 地域総合センター塚口へはどう行けばいいですか?
Score: 0.5822 : 地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立...
Score: 0.4509 : 各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図...
Score: 0.4294 : 地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください...

結果を見ればわかるように、質問と回答という性質の違いがスコアの幅にあらわれている。これらを同じ1つのベクトル空間に入れたとしても、クエリの性質が変わらなければ、回答のデータが使用されることはないと思われる。

であれば、用途に応じて検索対象を変える、というやり方はできないだろうか?こういう感じになる。

質問と回答をそれぞれ別々のベクトル空間として、用途に応じて検索を使い分けるというやり方。ただ、この場合はのようなデメリット、というか手間をかける必要が出てきてしまう。

  • シンプルに2回問い合わせが必要になる。
  • データの管理が複数のベクトル空間に分かれてしまう。更新等の必要が出てきた場合に、アトミックに処理することができなくなるし、管理が単純に倍になる。
  • それぞれの検索結果を何らかの方法で集約する等を行う必要が出てきてしまう。

これ以外にも、例えばタグとかキーワードとかそういうものでも検索したい、となったら、その数だけ増やさないといけなくなる。

Weaviateを使うと、これを解決することができる。それが、過去に試した「Multiple vectors/Named vectors」であり、今回新たに追加された「Multiple target vectors」になる。

まず、「Multiple vectors/Named vectors」。

QAデータにおいて、1つのQAデータは、質問と回答という2つのプロパティを持つ。Multiple vectors/Named vectorsを使うと、それぞれのプロパティを別々にベクトル化して、1つのデータが複数のベクトル空間を持てるようになる。Weaviateの場合、それぞれを別々に登録する必要はなく、すべてのプロパティを含んだオブジェクトを1度投げるだけで、事前に定義しておいたスキーマに基づいてアトミックに登録してくれる。
また、一般的なベクトルデータベースへのデータ登録は、手元でベクトル化処理を行ってから、べクトルデータベースに登録する、という2段階のステップを踏むが、Weaviateにはモジュール機能もあるので、ベクトルDB側でベクトル化処理も行ってくれる。つまり、開発者側からすれば1回のアトミックな処理で登録してくれるということになる。

検索する際は、どちらのプロパティに対して検索するか?を指定するだけで、必要な検索を行うことができるし、どちらのプロパティに対して検索したとしても、検索結果にはすべてのプロパティが含まれる。

ただし、質問と回答、それぞれのベクトル空間に対して検索を行えたとしても、複数の結果が返ってくることになるので、その結果についてはリランキングなり集約する必要があり、ここが開発者側でやらないといけないところだった。

そして今回の「Multiple target vectors」を使うと、1度の検索だけで、複数の結果を取得し、それらを一定の条件で結合・集約した結果を受け取ることができるようになるということである。

「Multiple vectors/Named vectors」と「Multiple target vectors」を使うことで、柔軟な検索スキーマの設計が可能になり、検索もとてもシンプルに行うことができるようになるという非常に強力な機能だと思う。

kun432kun432

ということで実際に試してみる。ColaboratoryでEmbedded Weaviateを使う。

FAQのデータセットは、京都大学大学院情報学研究科知能情報学コース言語メディア研究室 (https://nlp.ist.i.kyoto-u.ac.jp/)様が公開されている尼崎市の市民向けFAQデータセットを例に使わせていただく。

https://nlp.ist.i.kyoto-u.ac.jp/EN/index.php?BERT-Based_FAQ_Retrieval

なお、このデータセットを使ったranxによるretrievalの評価手順等も以下の記事でまとめている。データセットの前処理等についても記載しているので、興味があればどうぞ。

https://zenn.dev/kun432/scraps/fd4ad6051d625d

データセットのダウンロード

!wget https://tulip.kuee.kyoto-u.ac.jp/localgovfaq/localgovfaq.zip
!unzip localgovfaq.zip

データセットを前処理してpandasのデータフレームに読み込む。

import pandas as pd

def file2list(filename: str, prefix: str = "") -> tuple:
    """Q/AファイルをIDとコンテンツに分割、それぞれを配列で返す"""
    contents = []
    ids = []
    try:
        with open(filename, 'r') as file:
            for line in file:
                line = line.strip().replace(" ", "")
                id, content = line.split('\t')
                if prefix:
                    id = f"{prefix}_{id}"
                contents.append(content)
                ids.append(id)
    except Exception:
        raise

    return contents, ids

questions, ids = file2list("localgovfaq/qas/questions_in_Amagasaki.txt")
answers, _ = file2list("localgovfaq/qas/answers_in_Amagasaki.txt")

train_df = pd.DataFrame({'qa_id': ids, 'question': questions, 'answer': answers})
train_df["qa_id"] = train_df["qa_id"].astype(int)

データフレームはこういう感じ。

Weaviateに登録するために、これをpythonのオブジェクトに変換する。

faq_objs = train_df.to_dict(orient='records')
print(len(faq_objs))
print(faq_objs[1])
1786
{'qa_id': 1, 'question': '地域総合センター今北へはどう行けばいいですか?', 'answer': '■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。'}

Weaviateのインストール

!pip install -U weaviate-client
!pip freeze | grep -i "weaviate"
weaviate-client==4.8.1

Embedded Weaviateを起動する。サーバサイドでOpenAI Embeddingsによるベクトル化モジュールを使うので、APIキーもセットしておく。

import weaviate
import os
from google.colab import userdata

client = weaviate.connect_to_embedded(
    version="1.26.6",
    headers={
        "X-OpenAI-Api-Key": userdata.get('OPENAI_API_KEY')
    }
)

QAデータを登録する「コレクション」のスキーマ定義およびコレクションの作成を行う。

from weaviate.classes.config import Configure, Property, DataType

faq = client.collections.create(
    "FAQ",
    vectorizer_config=[
        Configure.NamedVectors.text2vec_openai(
            model="text-embedding-3-small",
            name="question_vector",
            source_properties=["question"],
            vectorize_collection_name=False
        ),
        Configure.NamedVectors.text2vec_openai(
            model="text-embedding-3-small",
            name="answer_vector",
            source_properties=["answer"],
            vectorize_collection_name=False,
        ),
        Configure.NamedVectors.text2vec_openai(
            model="text-embedding-3-small",
            name="question_answer_vector",
            source_properties=["question","answer"],
            vectorize_collection_name=False,
        ),
    ],
    properties=[
        Property(
            name="qa_id",
            data_type=DataType.INT,
        ),
        Property(
            name="question",
            data_type=DataType.TEXT,
            vectorize_property_name=False
        ),
        Property(
            name="answer",
            data_type=DataType.TEXT,
            vectorize_property_name=False
        ),
    ],
)

定義した内容は以下。

  • データが持つプロパティは、ID(qa_id)、質問(question)、回答(answer)の3つ。
  • Named Vectors/Multiple Vectorsで、検索で使用する各プロパティごとのベクトル空間を定義。今回は以下の3つ。
    • 「質問」検索用のベクトル空間(question_vector
    • 「回答」検索用のベクトル空間(answer_vector
    • 「質問」と「回答」を結合して、ドキュメント拡張による検索用のベクトル空間(question_answer_vector

データをコレクションに登録する

from tqdm.auto import tqdm

with faq.batch.dynamic() as batch:
    for faq_obj in tqdm(faq_objs):
        batch.add_object(
            properties=faq_obj,
        )

では検索してみる。以下のクエリを使って上位10件を拾う想定。

from weaviate.classes.query import MetadataQuery

query="地域総合センター今北へはどう行けばいいですか?"
limit = 10

まず、「質問」ベクトル空間であるquestion_vectorに対して検索。

from weaviate.classes.query import MetadataQuery

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=["question_vector"],
    return_metadata=MetadataQuery(distance=True)
)
for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()
Score: 0.999999
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: 0.857026
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: 0.855677
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。

Score: 0.847355
ID: 1099
Q: 地域総合センター神崎へはどう行けばいいですか?
A: ■阪急電鉄「園田」駅(南)から。阪神バス(尼崎市内線)23番「阪神尼崎」行きに乗車、「遊女塚」下車、西へ徒歩5分。■JR「尼崎」駅(南)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■阪神電鉄「尼崎」駅(北)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■車では、山幹通りと山陽新幹線の交差点のひとつ西側の南行き道路を、南へ300m。【関連するFAQ】。地域総合センターについて知りたい。【お問い合わせ】。地域総合センター神崎。尼崎市神崎町14-22。電話06-6499-3500。

Score: 0.830383
ID: 219
Q: 地域総合センター南武庫之荘へはどう行けばいいですか?
A: ■地域総合センター南武庫之荘には十分な駐車設備がございませんので、次のとおり市バス等をご利用ください。どちらの方面からいらっしゃいますか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神バスまたは宝塚・伊丹方面から。4.南方面から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター南武庫之荘。尼崎市南武庫之荘11丁目6-15。電話06-6438-5875。

Score: 0.829962
ID: 320
Q: 地域総合センター水堂へはどう行けばいいですか?
A: 地域総合センター水堂への行き方について、以下のいずれについて知りたいですか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。地域総合センター水堂には駐車場があります。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。●地域総合センター水堂本館。尼崎市水堂町2丁目35-1。電話06-6436-8681。●尼崎市水堂町2丁目34-21。地域総合センター水堂分館。電話06-6348-2189。

Score: 0.811545
ID: 527
Q: 地域総合センターについて知りたい。
A: ■各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。<改>。■市内に8ヵ所あります。【地域総合センター上ノ島本館】。尼崎市南塚口町8丁目7番25号。電話06-6429-7640。【地域総合センター上ノ島分館】。尼崎市南塚口町8丁目22番18号。電話06-6429-2731。【地域総合センター神崎】。尼崎市神崎町14番22号。電話06-6499-3500。【地域総合センター水堂本館】。尼崎市水堂町2丁目35番1号。電話06-6436-8681。【地域総合センター水堂分館】。尼崎市水堂町2丁目34番21号。電話06-6438-2189。【地域総合センター今北】。尼崎市西立花町3丁目14番1号。電話06-6416-5729。【地域総合センター南武庫之荘】。尼崎市南武庫之荘11丁目6番15号。電話06-6438-5875。【地域総合センター塚口】。尼崎市塚口本町2丁目28番11号。電話06-6423-5266。

Score: 0.793066
ID: 1302
Q: 〔施設見学〕北部浄化センターを見学するにはどうしたらよいのですか?
A: ■北部浄化センターを見学されるときは事前(2週間前まで)に申込みが必要です。(1)見学の内容。(2)希望される日時。(3)参加人数等をお知らせください。詳しくは尼崎市ホームページをご覧ください。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【関連するFAQ】。北部浄化センターは何をしていますか?。【お問い合わせ】。北部浄化センター。尼崎市東園田町7丁目82番地。電話06-6499-4515。

Score: 0.789371
ID: 157
Q: 尼崎市立青少年センターは、どのような施設でどこにあってどのように行けばいいですか。
A: ■青少年センターは、青少年の健全な育成と福祉の増進を図るための施設であり、青少年が、文化、スポーツ、社会参加などの活動を通じ、相互のふれあいと交流を深めるとともに、その自主的な活動を推進するための拠点施設として設置されました。<改>。■場所。尼崎市栗山町2丁目25番1号。電話06-6429-3020。FAX06-6429-3035。■利用時間。火曜日から土曜日:午前9時~午後9時。日曜日・祝日:午前9時~午後5時。■休館日。月曜日・年末年始(12月29日~1月3日)。■駐車場有(3台程度)。(駐車場スペースに限りがあるため、公共交通機関又は、自転車等でご来場くださいますようお願いします。)。<改>。■行き方。《バス》最寄のバス停は、阪神バス「立花支所」です。【阪急塚口駅から】。南側バスターミナルから14番「阪神出屋敷」30番「武庫川」31番「阪神尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【阪急武庫之荘駅から】。北側バスターミナルから48番「JR尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【JR立花駅から】。陸橋上(神戸側)バスターミナルから30番「阪急塚口」14番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【JR尼崎駅から】。南側バスターミナルから48番「阪急武庫之荘」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【阪神尼崎駅から】。北側バスターミナルから31番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。<改>。【関連するFAQ】。尼崎市立青少年センターの館内施設の案内・利用時間・休館日について。<改>。【お問い合わせ】。こども青少年本部事務局こども青少年部青少年課。尼崎市栗山町2丁目25番1号。尼崎市立青少年センター。電話06-6429-3020。■問合せ時間。火曜日から土曜日:午前9時~午後9時00分。日曜日・祝日:午前9時~午後5時30分。

Score: 0.784489
ID: 632
Q: 【保健福祉センター】北部保健福祉センターに駐車場はあるのか。
A: ■北部は、塚口さんさんタウン2番館の地下に駐車場があります。また、近隣に塚口さんさんタウン第2駐車場があります。さんさんタウン2番館に67台、第2駐車場に88台あり、また障害者用区画もあります。なお、平成33年以降は3番館分の駐車スペース128台が使用できる予定です。■南部は、リベルの4階に114台、屋上に118台の計232台分あり、障害者用区画も2台分あります。どちらの駐車場も駐車場料金を利用者に負担していただくことになります。<改>。■保健福祉センター。【北部保健福祉センター】。尼崎市南塚口町2-1-1塚口さんさんタウン1番館5階・6階。【南部保健福祉センター】。竹谷町2-183出屋敷リベル5階。■問合せ時間。午前8時45分~午後5時30分。ただし、窓口の取扱時間は午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。【お問い合わせ】。健康福祉局企画管理課。電話06-6489-6334。

次に「回答」ベクトル空間であるanswer_vectorに対して検索。

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=["answer_vector"],
    return_metadata=MetadataQuery(distance=True)
)
for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()
Score: 0.803330
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: 0.756755
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: 0.756644
ID: 1284
Q: 保健センターはどこにありますか。
A: ■保健センターは、新たに南北保健福祉センター地域保健課に移転しました。■問合せ時間。午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【問い合わせ】。【北部保健福祉センター地域保健課】。尼崎市南塚口町2丁目1番1号さんさんタウン1番館5階。電話06-4950-0637。ファックス06-6428-5110。【南部保健福祉センター地域保健課】。尼崎市竹谷町2丁目183番地リベル5階。電話06-6415-6342。ファックス06-6430-6850。

Score: 0.754281
ID: 219
Q: 地域総合センター南武庫之荘へはどう行けばいいですか?
A: ■地域総合センター南武庫之荘には十分な駐車設備がございませんので、次のとおり市バス等をご利用ください。どちらの方面からいらっしゃいますか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神バスまたは宝塚・伊丹方面から。4.南方面から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター南武庫之荘。尼崎市南武庫之荘11丁目6-15。電話06-6438-5875。

Score: 0.751857
ID: 1302
Q: 〔施設見学〕北部浄化センターを見学するにはどうしたらよいのですか?
A: ■北部浄化センターを見学されるときは事前(2週間前まで)に申込みが必要です。(1)見学の内容。(2)希望される日時。(3)参加人数等をお知らせください。詳しくは尼崎市ホームページをご覧ください。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【関連するFAQ】。北部浄化センターは何をしていますか?。【お問い合わせ】。北部浄化センター。尼崎市東園田町7丁目82番地。電話06-6499-4515。

Score: 0.747550
ID: 320
Q: 地域総合センター水堂へはどう行けばいいですか?
A: 地域総合センター水堂への行き方について、以下のいずれについて知りたいですか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。地域総合センター水堂には駐車場があります。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。●地域総合センター水堂本館。尼崎市水堂町2丁目35-1。電話06-6436-8681。●尼崎市水堂町2丁目34-21。地域総合センター水堂分館。電話06-6348-2189。

Score: 0.744458
ID: 527
Q: 地域総合センターについて知りたい。
A: ■各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。<改>。■市内に8ヵ所あります。【地域総合センター上ノ島本館】。尼崎市南塚口町8丁目7番25号。電話06-6429-7640。【地域総合センター上ノ島分館】。尼崎市南塚口町8丁目22番18号。電話06-6429-2731。【地域総合センター神崎】。尼崎市神崎町14番22号。電話06-6499-3500。【地域総合センター水堂本館】。尼崎市水堂町2丁目35番1号。電話06-6436-8681。【地域総合センター水堂分館】。尼崎市水堂町2丁目34番21号。電話06-6438-2189。【地域総合センター今北】。尼崎市西立花町3丁目14番1号。電話06-6416-5729。【地域総合センター南武庫之荘】。尼崎市南武庫之荘11丁目6番15号。電話06-6438-5875。【地域総合センター塚口】。尼崎市塚口本町2丁目28番11号。電話06-6423-5266。

Score: 0.741251
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。

Score: 0.739842
ID: 317
Q: コミュニティルームとは何ですか。
A: ■各地区内に在住・在勤・在学している人等のグループや団体がコミュニティ活動やボランティア活動などのための会議、学習、交流などのために利用してもらうために各地域振興センター内に設けられています。■利用していただける団体は、宗教、政治、営利活動に関するグループ、団体などを除き、ボランティア活動や地域コミュニティの発展に寄与することを目的に活動するグループで事前に各地区内コミュニティルーム運営委員会に登録していただく必要があります。■利用時間、利用料など、詳しくは各地域振興センターへお問い合わせください。■なお、西難波町5丁目4-30に所在する「コミュニティホールあんしん館」は、本市の施設ではありません。<改>。【関連するFAQ】。支所の会議室を借りたい。<改>。【お問い合わせ】。中央地域振興センター。尼崎市開明町2丁目1-1。電話06-6413-5371。小田地域振興センター。尼崎市長洲中通1丁目6-10。電話06-6488-5441。大庄地域振興センター。尼崎市大庄西町3丁目17-11。電話06-6419-8221。立花地域振興センター。尼崎市栗山町2丁目24-3。電話06-6427-7770。武庫地域振興センター。尼崎市武庫の里1丁目13-29。電話06-6431-7884。園田地域振興センター。尼崎市御園1丁目23-8。電話06-6491-2361。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。

Score: 0.738551
ID: 851
Q: 【保健福祉センター】保健福祉業務は各支所で手続きはできないのですか。
A: ■現在、各支所で受付している業務について、社会福祉協議会に業務委託することで、これまでと同様に手続きができるようになりますが、一部の手続きはできなくなります。詳しくは市報12月号に詳細が記載されたパンフレットを挟み込んでお知らせいたしますので、そちらにてご確認ください。<改>。■保健福祉センター。【北部保健福祉センター】。尼崎市南塚口町2-1-1塚口さんさんタウン1番館5階・6階。【南部保健福祉センター】。竹谷町2-183出屋敷リベル5階。■問合せ時間。午前8時45分~午後5時30分。ただし、窓口の取扱時間は午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。【お問い合わせ】。健康福祉局企画管理課。電話06-6489-6334。

どちらも最も関連しているものを1位で取得できているが、スコアやランキングの並びに違いがあるのがわかる。「質問」の場合は、「地域総合センター◯◯へはどう行けばいいですか?」という場所名を除けばほぼ同じ文章の「質問」が上位を占めているのに対し、「回答」の場合は、同じものが含まれてはいるもののの、やや異なるものも含まれており、内容的にもバリエーションが有るように見える(パッと見は関係なさそうなものも含まれているかもだが)

次に「質問」と「回答」を結合した「ドキュメント拡張」のベクトル空間(question_answer_vector)に対して検索。

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=["question_answer_vector"],
    return_metadata=MetadataQuery(distance=True)
)
for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()
Score: 0.829702
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: 0.774036
ID: 219
Q: 地域総合センター南武庫之荘へはどう行けばいいですか?
A: ■地域総合センター南武庫之荘には十分な駐車設備がございませんので、次のとおり市バス等をご利用ください。どちらの方面からいらっしゃいますか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神バスまたは宝塚・伊丹方面から。4.南方面から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター南武庫之荘。尼崎市南武庫之荘11丁目6-15。電話06-6438-5875。

Score: 0.773498
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: 0.766496
ID: 320
Q: 地域総合センター水堂へはどう行けばいいですか?
A: 地域総合センター水堂への行き方について、以下のいずれについて知りたいですか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。地域総合センター水堂には駐車場があります。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。●地域総合センター水堂本館。尼崎市水堂町2丁目35-1。電話06-6436-8681。●尼崎市水堂町2丁目34-21。地域総合センター水堂分館。電話06-6348-2189。

Score: 0.764231
ID: 1284
Q: 保健センターはどこにありますか。
A: ■保健センターは、新たに南北保健福祉センター地域保健課に移転しました。■問合せ時間。午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【問い合わせ】。【北部保健福祉センター地域保健課】。尼崎市南塚口町2丁目1番1号さんさんタウン1番館5階。電話06-4950-0637。ファックス06-6428-5110。【南部保健福祉センター地域保健課】。尼崎市竹谷町2丁目183番地リベル5階。電話06-6415-6342。ファックス06-6430-6850。

Score: 0.762987
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。

Score: 0.758657
ID: 1302
Q: 〔施設見学〕北部浄化センターを見学するにはどうしたらよいのですか?
A: ■北部浄化センターを見学されるときは事前(2週間前まで)に申込みが必要です。(1)見学の内容。(2)希望される日時。(3)参加人数等をお知らせください。詳しくは尼崎市ホームページをご覧ください。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【関連するFAQ】。北部浄化センターは何をしていますか?。【お問い合わせ】。北部浄化センター。尼崎市東園田町7丁目82番地。電話06-6499-4515。

Score: 0.755673
ID: 527
Q: 地域総合センターについて知りたい。
A: ■各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。<改>。■市内に8ヵ所あります。【地域総合センター上ノ島本館】。尼崎市南塚口町8丁目7番25号。電話06-6429-7640。【地域総合センター上ノ島分館】。尼崎市南塚口町8丁目22番18号。電話06-6429-2731。【地域総合センター神崎】。尼崎市神崎町14番22号。電話06-6499-3500。【地域総合センター水堂本館】。尼崎市水堂町2丁目35番1号。電話06-6436-8681。【地域総合センター水堂分館】。尼崎市水堂町2丁目34番21号。電話06-6438-2189。【地域総合センター今北】。尼崎市西立花町3丁目14番1号。電話06-6416-5729。【地域総合センター南武庫之荘】。尼崎市南武庫之荘11丁目6番15号。電話06-6438-5875。【地域総合センター塚口】。尼崎市塚口本町2丁目28番11号。電話06-6423-5266。

Score: 0.747625
ID: 1099
Q: 地域総合センター神崎へはどう行けばいいですか?
A: ■阪急電鉄「園田」駅(南)から。阪神バス(尼崎市内線)23番「阪神尼崎」行きに乗車、「遊女塚」下車、西へ徒歩5分。■JR「尼崎」駅(南)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■阪神電鉄「尼崎」駅(北)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■車では、山幹通りと山陽新幹線の交差点のひとつ西側の南行き道路を、南へ300m。【関連するFAQ】。地域総合センターについて知りたい。【お問い合わせ】。地域総合センター神崎。尼崎市神崎町14-22。電話06-6499-3500。

Score: 0.739326
ID: 455
Q: 尼崎市防災センターの見学方法を知りたい。
A: ■尼崎市防災センターの見学については、事前に尼崎市消防局企画管理課へお問い合わせください。【お問い合わせ】。消防局企画管理課。尼崎市昭和通2丁目6番75号。尼崎市防災センター4階。電話06-6481-3962。■問合せ時間。午前9時00分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。≪尼崎市防災センターの概要≫。市内2カ所の防災センターは消防署と併設され、普段は市民の皆さんに防災についての知識や技術を身につけていただき、災害時には応急活動の拠点となる施設です。尼崎市防災センターの展示ホールでは、震度7の地震体験や119番通報体験、消火体験といったいろいろな体験ができるコーナーのほか、映像やパネルにより尼崎の災害の特徴や備えを学ぶコーナーもあり、楽しみながら防災の知識や技術を習得することができます。<改>。■尼崎市防災センター。【所在地】。尼崎市昭和通2丁目6番75号。電話06-6481-0119。■問合せ時間。午前9時00分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。■尼崎市北部防災センター。【所在地】。尼崎市上ノ島3丁目2番1号。電話06-6421-0119。■開庁時間。午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。

こちらも最も関連しているものを1位で取得できているが、それ以外については「質問」とも「回答」とも異なる結果となっているのがわかる。

で、ここまでは過去にもやった「Multiple vectors/Named vectors」によるもの。これに「Multiple target vectors」を組み合わせていく。

kun432kun432

「Multiple vectors/Named vectors」に「Multiple target vectors」を組み合わせるといっても、ベクトルDB側で準備することは何もなく、単に検索の仕方を変えればいいだけで、「Multiple target vectors」の場合はtarget_vectorに複数のNamed Vectorsをリストで指定するだけである。

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=["question_vector","answer_vector"],
    return_metadata=MetadataQuery(distance=True)
)

for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()
Score: 0.999999
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: 0.857026
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: 0.855677
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。

Score: 0.847355
ID: 1099
Q: 地域総合センター神崎へはどう行けばいいですか?
A: ■阪急電鉄「園田」駅(南)から。阪神バス(尼崎市内線)23番「阪神尼崎」行きに乗車、「遊女塚」下車、西へ徒歩5分。■JR「尼崎」駅(南)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■阪神電鉄「尼崎」駅(北)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■車では、山幹通りと山陽新幹線の交差点のひとつ西側の南行き道路を、南へ300m。【関連するFAQ】。地域総合センターについて知りたい。【お問い合わせ】。地域総合センター神崎。尼崎市神崎町14-22。電話06-6499-3500。

Score: 0.830383
ID: 219
Q: 地域総合センター南武庫之荘へはどう行けばいいですか?
A: ■地域総合センター南武庫之荘には十分な駐車設備がございませんので、次のとおり市バス等をご利用ください。どちらの方面からいらっしゃいますか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神バスまたは宝塚・伊丹方面から。4.南方面から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター南武庫之荘。尼崎市南武庫之荘11丁目6-15。電話06-6438-5875。

Score: 0.829962
ID: 320
Q: 地域総合センター水堂へはどう行けばいいですか?
A: 地域総合センター水堂への行き方について、以下のいずれについて知りたいですか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。地域総合センター水堂には駐車場があります。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。●地域総合センター水堂本館。尼崎市水堂町2丁目35-1。電話06-6436-8681。●尼崎市水堂町2丁目34-21。地域総合センター水堂分館。電話06-6348-2189。

Score: 0.811545
ID: 527
Q: 地域総合センターについて知りたい。
A: ■各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。<改>。■市内に8ヵ所あります。【地域総合センター上ノ島本館】。尼崎市南塚口町8丁目7番25号。電話06-6429-7640。【地域総合センター上ノ島分館】。尼崎市南塚口町8丁目22番18号。電話06-6429-2731。【地域総合センター神崎】。尼崎市神崎町14番22号。電話06-6499-3500。【地域総合センター水堂本館】。尼崎市水堂町2丁目35番1号。電話06-6436-8681。【地域総合センター水堂分館】。尼崎市水堂町2丁目34番21号。電話06-6438-2189。【地域総合センター今北】。尼崎市西立花町3丁目14番1号。電話06-6416-5729。【地域総合センター南武庫之荘】。尼崎市南武庫之荘11丁目6番15号。電話06-6438-5875。【地域総合センター塚口】。尼崎市塚口本町2丁目28番11号。電話06-6423-5266。

Score: 0.793066
ID: 1302
Q: 〔施設見学〕北部浄化センターを見学するにはどうしたらよいのですか?
A: ■北部浄化センターを見学されるときは事前(2週間前まで)に申込みが必要です。(1)見学の内容。(2)希望される日時。(3)参加人数等をお知らせください。詳しくは尼崎市ホームページをご覧ください。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【関連するFAQ】。北部浄化センターは何をしていますか?。【お問い合わせ】。北部浄化センター。尼崎市東園田町7丁目82番地。電話06-6499-4515。

Score: 0.789371
ID: 157
Q: 尼崎市立青少年センターは、どのような施設でどこにあってどのように行けばいいですか。
A: ■青少年センターは、青少年の健全な育成と福祉の増進を図るための施設であり、青少年が、文化、スポーツ、社会参加などの活動を通じ、相互のふれあいと交流を深めるとともに、その自主的な活動を推進するための拠点施設として設置されました。<改>。■場所。尼崎市栗山町2丁目25番1号。電話06-6429-3020。FAX06-6429-3035。■利用時間。火曜日から土曜日:午前9時~午後9時。日曜日・祝日:午前9時~午後5時。■休館日。月曜日・年末年始(12月29日~1月3日)。■駐車場有(3台程度)。(駐車場スペースに限りがあるため、公共交通機関又は、自転車等でご来場くださいますようお願いします。)。<改>。■行き方。《バス》最寄のバス停は、阪神バス「立花支所」です。【阪急塚口駅から】。南側バスターミナルから14番「阪神出屋敷」30番「武庫川」31番「阪神尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【阪急武庫之荘駅から】。北側バスターミナルから48番「JR尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【JR立花駅から】。陸橋上(神戸側)バスターミナルから30番「阪急塚口」14番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【JR尼崎駅から】。南側バスターミナルから48番「阪急武庫之荘」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【阪神尼崎駅から】。北側バスターミナルから31番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。<改>。【関連するFAQ】。尼崎市立青少年センターの館内施設の案内・利用時間・休館日について。<改>。【お問い合わせ】。こども青少年本部事務局こども青少年部青少年課。尼崎市栗山町2丁目25番1号。尼崎市立青少年センター。電話06-6429-3020。■問合せ時間。火曜日から土曜日:午前9時~午後9時00分。日曜日・祝日:午前9時~午後5時30分。

Score: 0.784489
ID: 632
Q: 【保健福祉センター】北部保健福祉センターに駐車場はあるのか。
A: ■北部は、塚口さんさんタウン2番館の地下に駐車場があります。また、近隣に塚口さんさんタウン第2駐車場があります。さんさんタウン2番館に67台、第2駐車場に88台あり、また障害者用区画もあります。なお、平成33年以降は3番館分の駐車スペース128台が使用できる予定です。■南部は、リベルの4階に114台、屋上に118台の計232台分あり、障害者用区画も2台分あります。どちらの駐車場も駐車場料金を利用者に負担していただくことになります。<改>。■保健福祉センター。【北部保健福祉センター】。尼崎市南塚口町2-1-1塚口さんさんタウン1番館5階・6階。【南部保健福祉センター】。竹谷町2-183出屋敷リベル5階。■問合せ時間。午前8時45分~午後5時30分。ただし、窓口の取扱時間は午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。【お問い合わせ】。健康福祉局企画管理課。電話06-6489-6334。

結果だけ見るとわからないが、上記は「質問」(question_vector)と「回答」(answer_vector)の両方を検索して、それぞれの結果を結合したものとなっている。

結合のロジックは複数あり、上記の例のように単純にリストで複数のNamed Vectorsを指定した場合には、minimumが選択される。

結合ロジックは以下、ここはChatGPTにも少し調べてもらった。

  • minimum
    • デフォルト
    • 複数のターゲットベクトルに対する距離のうち、最小の距離を選ぶ。
    • 各クエリ/ターゲットベクトルペアで最も近い距離を持つベクトルに基づいて、検索結果がソートされる。
    • メリット: ターゲットベクトルの中のどれか1つでもクエリに非常に近いベクトルがある場合、そのベクトルが強調され、優先的に検索結果に表示される。
    • ユースケース: 複数のベクトルのいずれかがクエリに対して良好な一致を示した場合、そのオブジェクトを重要視したい場合に使用する
  • sum
    • 複数のターゲットベクトル間の距離を単純に合計し、その合計値を基に検索結果をソートする。
    • 各ベクトル間の距離が総合的に考慮される。
    • メリット: 複数のターゲットベクトル全体にわたってバランスの取れた一致を持つオブジェクトが優先される。一部のベクトルが大きく外れていても、他のベクトルでその分を補える可能性がある。
    • ユースケース: 各ターゲットベクトルがクエリに対して均等に重要であり、すべてのベクトルの距離を考慮したい場合に有効。
  • average
    • 複数のターゲットベクトル間の距離の平均を計算して、その平均値に基づいて結果をソート。距離の総計ではなく、各ベクトルの距離が平均的にどれだけクエリに近いかを測る。
    • メリット: 各ターゲットベクトルが等しく重要である場合に、合計よりも距離のバランスが重視される。一部のベクトルが他よりも非常に大きく外れている場合、その影響が緩和される。
    • ユースケース: 複数のベクトル間での一致を公平に評価したい場合や、距離のバランスが重要な場合に使用。
  • manual weights
    • 各ターゲットベクトルに対して、重み(ウェイト)を指定して、その重みをかけた距離の合計を使用して結果をソートする。あるターゲットベクトルが他のターゲットベクトルよりも重要視される。
    • メリット: 特定のベクトルが他のベクトルよりも重要である場合、その重要度に応じて検索結果に反映できる。たとえば、質問ベクトルよりも回答ベクトルに重きを置きたい場合などに使用できる。
    • ユースケース: 各ターゲットベクトルの重要度が異なる場合に、検索結果を調整するために使用。
  • relative scores
    • 各ターゲットベクトルに対して距離を正規化し、その正規化された距離にユーザーが指定した重みを掛けた合計値で結果をソートする。正規化により、異なるベクトル間のスコアを比較しやすくする。
    • メリット: 距離のスケールが異なる複数のターゲットベクトルの検索結果を公平に比較できるため、距離が大きく異なるベクトルセットにも対応可能。また、特定のベクトルに重みをかけて、その重要度を反映させることができる。
    • ユースケース: 複数のベクトルが異なるスケールや分布を持つ場合に、それらを比較するために効果的。たとえば、質問と回答のベクトルがそれぞれ異なるスケールで表現されている場合に使用する。

Weaviateの場合、類似度を示す指標として2つある。ドキュメントはここ

  • distance
    • 2つのベクトル間の距離を表す。類似度が高ければ高いほど、0に近づく。
  • certainty
    • 上記のdistanceを0〜1で正規化したもの。類似度が高ければ高いほど、1に近づく。
    • 一般的な類似度スコアはこちらが多いと思う

で、以前はcertaintyが使えていたのだが、今回試してみた限りはどうやら使えないようでNoneが返ってくる。もともとcertaintyの計算は1 - distance / 2で計算されており、また、すべてのメトリクスが0〜1で正規化できるわけではない、ということで、今はdistanceがメインになった様子。今回はスコアのほうがわかりやすいと考えたため、上記の数式で算出している。

で、結合ロジックはデフォルトだとminimumになるが、明示的に設定するならばこうなる。

from weaviate.classes.query import TargetVectors, MetadataQuery

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=TargetVectors.minimum(["question_vector", "answer_vector"]),  # `minimum`
    return_metadata=MetadataQuery(distance=True)
)

for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()

上記を実行すると1つ前の結果と全くおなじになる。

ここを他のロジックに変えていけば結果が変わる。

average

from weaviate.classes.query import TargetVectors, MetadataQuery

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=TargetVectors.average(["question_vector", "answer_vector"]),  # average
    return_metadata=MetadataQuery(distance=True)
)

for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()
Score: 0.901665
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: 0.806890
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: 0.798464
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。

Score: 0.792332
ID: 219
Q: 地域総合センター南武庫之荘へはどう行けばいいですか?
A: ■地域総合センター南武庫之荘には十分な駐車設備がございませんので、次のとおり市バス等をご利用ください。どちらの方面からいらっしゃいますか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神バスまたは宝塚・伊丹方面から。4.南方面から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター南武庫之荘。尼崎市南武庫之荘11丁目6-15。電話06-6438-5875。

Score: 0.788756
ID: 320
Q: 地域総合センター水堂へはどう行けばいいですか?
A: 地域総合センター水堂への行き方について、以下のいずれについて知りたいですか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。地域総合センター水堂には駐車場があります。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。●地域総合センター水堂本館。尼崎市水堂町2丁目35-1。電話06-6436-8681。●尼崎市水堂町2丁目34-21。地域総合センター水堂分館。電話06-6348-2189。

Score: 0.785809
ID: 1099
Q: 地域総合センター神崎へはどう行けばいいですか?
A: ■阪急電鉄「園田」駅(南)から。阪神バス(尼崎市内線)23番「阪神尼崎」行きに乗車、「遊女塚」下車、西へ徒歩5分。■JR「尼崎」駅(南)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■阪神電鉄「尼崎」駅(北)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■車では、山幹通りと山陽新幹線の交差点のひとつ西側の南行き道路を、南へ300m。【関連するFAQ】。地域総合センターについて知りたい。【お問い合わせ】。地域総合センター神崎。尼崎市神崎町14-22。電話06-6499-3500。

Score: 0.778001
ID: 527
Q: 地域総合センターについて知りたい。
A: ■各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。<改>。■市内に8ヵ所あります。【地域総合センター上ノ島本館】。尼崎市南塚口町8丁目7番25号。電話06-6429-7640。【地域総合センター上ノ島分館】。尼崎市南塚口町8丁目22番18号。電話06-6429-2731。【地域総合センター神崎】。尼崎市神崎町14番22号。電話06-6499-3500。【地域総合センター水堂本館】。尼崎市水堂町2丁目35番1号。電話06-6436-8681。【地域総合センター水堂分館】。尼崎市水堂町2丁目34番21号。電話06-6438-2189。【地域総合センター今北】。尼崎市西立花町3丁目14番1号。電話06-6416-5729。【地域総合センター南武庫之荘】。尼崎市南武庫之荘11丁目6番15号。電話06-6438-5875。【地域総合センター塚口】。尼崎市塚口本町2丁目28番11号。電話06-6423-5266。

Score: 0.772461
ID: 1302
Q: 〔施設見学〕北部浄化センターを見学するにはどうしたらよいのですか?
A: ■北部浄化センターを見学されるときは事前(2週間前まで)に申込みが必要です。(1)見学の内容。(2)希望される日時。(3)参加人数等をお知らせください。詳しくは尼崎市ホームページをご覧ください。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【関連するFAQ】。北部浄化センターは何をしていますか?。【お問い合わせ】。北部浄化センター。尼崎市東園田町7丁目82番地。電話06-6499-4515。

Score: 0.755806
ID: 632
Q: 【保健福祉センター】北部保健福祉センターに駐車場はあるのか。
A: ■北部は、塚口さんさんタウン2番館の地下に駐車場があります。また、近隣に塚口さんさんタウン第2駐車場があります。さんさんタウン2番館に67台、第2駐車場に88台あり、また障害者用区画もあります。なお、平成33年以降は3番館分の駐車スペース128台が使用できる予定です。■南部は、リベルの4階に114台、屋上に118台の計232台分あり、障害者用区画も2台分あります。どちらの駐車場も駐車場料金を利用者に負担していただくことになります。<改>。■保健福祉センター。【北部保健福祉センター】。尼崎市南塚口町2-1-1塚口さんさんタウン1番館5階・6階。【南部保健福祉センター】。竹谷町2-183出屋敷リベル5階。■問合せ時間。午前8時45分~午後5時30分。ただし、窓口の取扱時間は午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。【お問い合わせ】。健康福祉局企画管理課。電話06-6489-6334。

Score: 0.749617
ID: 157
Q: 尼崎市立青少年センターは、どのような施設でどこにあってどのように行けばいいですか。
A: ■青少年センターは、青少年の健全な育成と福祉の増進を図るための施設であり、青少年が、文化、スポーツ、社会参加などの活動を通じ、相互のふれあいと交流を深めるとともに、その自主的な活動を推進するための拠点施設として設置されました。<改>。■場所。尼崎市栗山町2丁目25番1号。電話06-6429-3020。FAX06-6429-3035。■利用時間。火曜日から土曜日:午前9時~午後9時。日曜日・祝日:午前9時~午後5時。■休館日。月曜日・年末年始(12月29日~1月3日)。■駐車場有(3台程度)。(駐車場スペースに限りがあるため、公共交通機関又は、自転車等でご来場くださいますようお願いします。)。<改>。■行き方。《バス》最寄のバス停は、阪神バス「立花支所」です。【阪急塚口駅から】。南側バスターミナルから14番「阪神出屋敷」30番「武庫川」31番「阪神尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【阪急武庫之荘駅から】。北側バスターミナルから48番「JR尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【JR立花駅から】。陸橋上(神戸側)バスターミナルから30番「阪急塚口」14番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【JR尼崎駅から】。南側バスターミナルから48番「阪急武庫之荘」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【阪神尼崎駅から】。北側バスターミナルから31番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。<改>。【関連するFAQ】。尼崎市立青少年センターの館内施設の案内・利用時間・休館日について。<改>。【お問い合わせ】。こども青少年本部事務局こども青少年部青少年課。尼崎市栗山町2丁目25番1号。尼崎市立青少年センター。電話06-6429-3020。■問合せ時間。火曜日から土曜日:午前9時~午後9時00分。日曜日・祝日:午前9時~午後5時30分。

sum

from weaviate.classes.query import TargetVectors, MetadataQuery

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=TargetVectors.sum(["question_vector", "answer_vector"]),  # sum
    return_metadata=MetadataQuery(distance=True)
)

for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()
Score: 0.803329
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: 0.613781
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: 0.596928
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。

Score: 0.584664
ID: 219
Q: 地域総合センター南武庫之荘へはどう行けばいいですか?
A: ■地域総合センター南武庫之荘には十分な駐車設備がございませんので、次のとおり市バス等をご利用ください。どちらの方面からいらっしゃいますか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神バスまたは宝塚・伊丹方面から。4.南方面から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター南武庫之荘。尼崎市南武庫之荘11丁目6-15。電話06-6438-5875。

Score: 0.577512
ID: 320
Q: 地域総合センター水堂へはどう行けばいいですか?
A: 地域総合センター水堂への行き方について、以下のいずれについて知りたいですか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。地域総合センター水堂には駐車場があります。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。●地域総合センター水堂本館。尼崎市水堂町2丁目35-1。電話06-6436-8681。●尼崎市水堂町2丁目34-21。地域総合センター水堂分館。電話06-6348-2189。

Score: 0.571618
ID: 1099
Q: 地域総合センター神崎へはどう行けばいいですか?
A: ■阪急電鉄「園田」駅(南)から。阪神バス(尼崎市内線)23番「阪神尼崎」行きに乗車、「遊女塚」下車、西へ徒歩5分。■JR「尼崎」駅(南)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■阪神電鉄「尼崎」駅(北)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■車では、山幹通りと山陽新幹線の交差点のひとつ西側の南行き道路を、南へ300m。【関連するFAQ】。地域総合センターについて知りたい。【お問い合わせ】。地域総合センター神崎。尼崎市神崎町14-22。電話06-6499-3500。

Score: 0.556002
ID: 527
Q: 地域総合センターについて知りたい。
A: ■各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。<改>。■市内に8ヵ所あります。【地域総合センター上ノ島本館】。尼崎市南塚口町8丁目7番25号。電話06-6429-7640。【地域総合センター上ノ島分館】。尼崎市南塚口町8丁目22番18号。電話06-6429-2731。【地域総合センター神崎】。尼崎市神崎町14番22号。電話06-6499-3500。【地域総合センター水堂本館】。尼崎市水堂町2丁目35番1号。電話06-6436-8681。【地域総合センター水堂分館】。尼崎市水堂町2丁目34番21号。電話06-6438-2189。【地域総合センター今北】。尼崎市西立花町3丁目14番1号。電話06-6416-5729。【地域総合センター南武庫之荘】。尼崎市南武庫之荘11丁目6番15号。電話06-6438-5875。【地域総合センター塚口】。尼崎市塚口本町2丁目28番11号。電話06-6423-5266。

Score: 0.544923
ID: 1302
Q: 〔施設見学〕北部浄化センターを見学するにはどうしたらよいのですか?
A: ■北部浄化センターを見学されるときは事前(2週間前まで)に申込みが必要です。(1)見学の内容。(2)希望される日時。(3)参加人数等をお知らせください。詳しくは尼崎市ホームページをご覧ください。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【関連するFAQ】。北部浄化センターは何をしていますか?。【お問い合わせ】。北部浄化センター。尼崎市東園田町7丁目82番地。電話06-6499-4515。

Score: 0.511611
ID: 632
Q: 【保健福祉センター】北部保健福祉センターに駐車場はあるのか。
A: ■北部は、塚口さんさんタウン2番館の地下に駐車場があります。また、近隣に塚口さんさんタウン第2駐車場があります。さんさんタウン2番館に67台、第2駐車場に88台あり、また障害者用区画もあります。なお、平成33年以降は3番館分の駐車スペース128台が使用できる予定です。■南部は、リベルの4階に114台、屋上に118台の計232台分あり、障害者用区画も2台分あります。どちらの駐車場も駐車場料金を利用者に負担していただくことになります。<改>。■保健福祉センター。【北部保健福祉センター】。尼崎市南塚口町2-1-1塚口さんさんタウン1番館5階・6階。【南部保健福祉センター】。竹谷町2-183出屋敷リベル5階。■問合せ時間。午前8時45分~午後5時30分。ただし、窓口の取扱時間は午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。【お問い合わせ】。健康福祉局企画管理課。電話06-6489-6334。

Score: 0.499234
ID: 157
Q: 尼崎市立青少年センターは、どのような施設でどこにあってどのように行けばいいですか。
A: ■青少年センターは、青少年の健全な育成と福祉の増進を図るための施設であり、青少年が、文化、スポーツ、社会参加などの活動を通じ、相互のふれあいと交流を深めるとともに、その自主的な活動を推進するための拠点施設として設置されました。<改>。■場所。尼崎市栗山町2丁目25番1号。電話06-6429-3020。FAX06-6429-3035。■利用時間。火曜日から土曜日:午前9時~午後9時。日曜日・祝日:午前9時~午後5時。■休館日。月曜日・年末年始(12月29日~1月3日)。■駐車場有(3台程度)。(駐車場スペースに限りがあるため、公共交通機関又は、自転車等でご来場くださいますようお願いします。)。<改>。■行き方。《バス》最寄のバス停は、阪神バス「立花支所」です。【阪急塚口駅から】。南側バスターミナルから14番「阪神出屋敷」30番「武庫川」31番「阪神尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【阪急武庫之荘駅から】。北側バスターミナルから48番「JR尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【JR立花駅から】。陸橋上(神戸側)バスターミナルから30番「阪急塚口」14番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【JR尼崎駅から】。南側バスターミナルから48番「阪急武庫之荘」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【阪神尼崎駅から】。北側バスターミナルから31番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。<改>。【関連するFAQ】。尼崎市立青少年センターの館内施設の案内・利用時間・休館日について。<改>。【お問い合わせ】。こども青少年本部事務局こども青少年部青少年課。尼崎市栗山町2丁目25番1号。尼崎市立青少年センター。電話06-6429-3020。■問合せ時間。火曜日から土曜日:午前9時~午後9時00分。日曜日・祝日:午前9時~午後5時30分。
kun432kun432

結合ロジックの中で、manual weightsとrelative socreは少し指定の仕方が異なる。

manual weightsは以下のようにNamed Vectorごとに重みをつける。

from weaviate.classes.query import TargetVectors, MetadataQuery

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=TargetVectors.manual_weights(
        {
            "question_vector": 1,
            "answer_vector": 1,
        }
    ),
    return_metadata=MetadataQuery(distance=True)
)

for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()
Score: 0.803329
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: 0.613781
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: 0.596928
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。

Score: 0.584664
ID: 219
Q: 地域総合センター南武庫之荘へはどう行けばいいですか?
A: ■地域総合センター南武庫之荘には十分な駐車設備がございませんので、次のとおり市バス等をご利用ください。どちらの方面からいらっしゃいますか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神バスまたは宝塚・伊丹方面から。4.南方面から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター南武庫之荘。尼崎市南武庫之荘11丁目6-15。電話06-6438-5875。

Score: 0.577512
ID: 320
Q: 地域総合センター水堂へはどう行けばいいですか?
A: 地域総合センター水堂への行き方について、以下のいずれについて知りたいですか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。地域総合センター水堂には駐車場があります。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。●地域総合センター水堂本館。尼崎市水堂町2丁目35-1。電話06-6436-8681。●尼崎市水堂町2丁目34-21。地域総合センター水堂分館。電話06-6348-2189。

Score: 0.571618
ID: 1099
Q: 地域総合センター神崎へはどう行けばいいですか?
A: ■阪急電鉄「園田」駅(南)から。阪神バス(尼崎市内線)23番「阪神尼崎」行きに乗車、「遊女塚」下車、西へ徒歩5分。■JR「尼崎」駅(南)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■阪神電鉄「尼崎」駅(北)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■車では、山幹通りと山陽新幹線の交差点のひとつ西側の南行き道路を、南へ300m。【関連するFAQ】。地域総合センターについて知りたい。【お問い合わせ】。地域総合センター神崎。尼崎市神崎町14-22。電話06-6499-3500。

Score: 0.556002
ID: 527
Q: 地域総合センターについて知りたい。
A: ■各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。<改>。■市内に8ヵ所あります。【地域総合センター上ノ島本館】。尼崎市南塚口町8丁目7番25号。電話06-6429-7640。【地域総合センター上ノ島分館】。尼崎市南塚口町8丁目22番18号。電話06-6429-2731。【地域総合センター神崎】。尼崎市神崎町14番22号。電話06-6499-3500。【地域総合センター水堂本館】。尼崎市水堂町2丁目35番1号。電話06-6436-8681。【地域総合センター水堂分館】。尼崎市水堂町2丁目34番21号。電話06-6438-2189。【地域総合センター今北】。尼崎市西立花町3丁目14番1号。電話06-6416-5729。【地域総合センター南武庫之荘】。尼崎市南武庫之荘11丁目6番15号。電話06-6438-5875。【地域総合センター塚口】。尼崎市塚口本町2丁目28番11号。電話06-6423-5266。

Score: 0.544923
ID: 1302
Q: 〔施設見学〕北部浄化センターを見学するにはどうしたらよいのですか?
A: ■北部浄化センターを見学されるときは事前(2週間前まで)に申込みが必要です。(1)見学の内容。(2)希望される日時。(3)参加人数等をお知らせください。詳しくは尼崎市ホームページをご覧ください。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【関連するFAQ】。北部浄化センターは何をしていますか?。【お問い合わせ】。北部浄化センター。尼崎市東園田町7丁目82番地。電話06-6499-4515。

Score: 0.511611
ID: 632
Q: 【保健福祉センター】北部保健福祉センターに駐車場はあるのか。
A: ■北部は、塚口さんさんタウン2番館の地下に駐車場があります。また、近隣に塚口さんさんタウン第2駐車場があります。さんさんタウン2番館に67台、第2駐車場に88台あり、また障害者用区画もあります。なお、平成33年以降は3番館分の駐車スペース128台が使用できる予定です。■南部は、リベルの4階に114台、屋上に118台の計232台分あり、障害者用区画も2台分あります。どちらの駐車場も駐車場料金を利用者に負担していただくことになります。<改>。■保健福祉センター。【北部保健福祉センター】。尼崎市南塚口町2-1-1塚口さんさんタウン1番館5階・6階。【南部保健福祉センター】。竹谷町2-183出屋敷リベル5階。■問合せ時間。午前8時45分~午後5時30分。ただし、窓口の取扱時間は午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。【お問い合わせ】。健康福祉局企画管理課。電話06-6489-6334。

Score: 0.499234
ID: 157
Q: 尼崎市立青少年センターは、どのような施設でどこにあってどのように行けばいいですか。
A: ■青少年センターは、青少年の健全な育成と福祉の増進を図るための施設であり、青少年が、文化、スポーツ、社会参加などの活動を通じ、相互のふれあいと交流を深めるとともに、その自主的な活動を推進するための拠点施設として設置されました。<改>。■場所。尼崎市栗山町2丁目25番1号。電話06-6429-3020。FAX06-6429-3035。■利用時間。火曜日から土曜日:午前9時~午後9時。日曜日・祝日:午前9時~午後5時。■休館日。月曜日・年末年始(12月29日~1月3日)。■駐車場有(3台程度)。(駐車場スペースに限りがあるため、公共交通機関又は、自転車等でご来場くださいますようお願いします。)。<改>。■行き方。《バス》最寄のバス停は、阪神バス「立花支所」です。【阪急塚口駅から】。南側バスターミナルから14番「阪神出屋敷」30番「武庫川」31番「阪神尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【阪急武庫之荘駅から】。北側バスターミナルから48番「JR尼崎」行きに乗車。「立花支所」で下車。進行方向に徒歩1分。【JR立花駅から】。陸橋上(神戸側)バスターミナルから30番「阪急塚口」14番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【JR尼崎駅から】。南側バスターミナルから48番「阪急武庫之荘」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。【阪神尼崎駅から】。北側バスターミナルから31番「阪急塚口」行きに乗車。「立花支所」で下車。進行方向逆に徒歩1分。<改>。【関連するFAQ】。尼崎市立青少年センターの館内施設の案内・利用時間・休館日について。<改>。【お問い合わせ】。こども青少年本部事務局こども青少年部青少年課。尼崎市栗山町2丁目25番1号。尼崎市立青少年センター。電話06-6429-3020。■問合せ時間。火曜日から土曜日:午前9時~午後9時00分。日曜日・祝日:午前9時~午後5時30分。

ただ、この重みの設定、単純に割合とかではなく、上で書いたように

各ターゲットベクトルに対して、重み(ウェイト)を指定して、その重みをかけた距離の合計を使用して結果をソートする。あるターゲットベクトルが他のターゲットベクトルよりも重要視される。

となっているようなので、例えば以下のように均等ではあるけど、数値が大きくなると、

from weaviate.classes.query import TargetVectors, MetadataQuery

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=TargetVectors.manual_weights(
        {
            "question_vector": 10,
            "answer_vector": 10,
        }
    ),
    return_metadata=MetadataQuery(distance=True)
)

for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()

以下のようにスコアがおかしくなる。なので、相対比ではなく、1を基準に重みを書けるのが良いと思う。

Score: -0.966707
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: -2.862193
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: -3.030717
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。
(snip)

で、relative scores。こちらも

各ターゲットベクトルに対して距離を正規化し、その正規化された距離にユーザーが指定した重みを掛けた合計値で結果をソートする。正規化により、異なるベクトル間のスコアを比較しやすくする。

とあるので、同じ感じで考えるのが良さそう。

from weaviate.classes.query import TargetVectors, MetadataQuery

response = faq.query.near_text(
    query=query,
    limit=limit,
    target_vector=TargetVectors.relative_score(
        {
            "question_vector": 1,
            "answer_vector": 1
        }
    ),
    return_metadata=MetadataQuery(distance=True)
)

for o in response.objects:
    print("Score: %f" % (1 - o.metadata.distance / 2))
    print("ID: %d" % o.properties["qa_id"])
    print("Q: %s" % o.properties["question"])
    print("A: %s" % o.properties["answer"])
    print()
Score: 1.000000
ID: 1
Q: 地域総合センター今北へはどう行けばいいですか?
A: ■地域総合センター今北には、十分な駐車場がございませんので、市バスをご利用ください。JR沿線からは「立花駅」、阪急沿線からは「塚口駅」「武庫之荘駅」、阪神沿線からは「尼崎駅」「武庫川駅」「出屋敷駅」へお越しいただき、市バスをご利用ください。どちらの駅からいらっしゃいますか?。1.JR立花駅から(位置的には、南西へ徒歩約10分です。)。2.阪急塚口駅(南)から。3.阪急武庫之荘駅(南)から。4.阪神尼崎駅(北)から。5.阪神武庫川駅から。6.阪神出屋敷駅(北)から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター今北。尼崎市西立花町3丁目14-1。電話06-6416-5729。

Score: 0.574397
ID: 48
Q: 地域総合センター上ノ島へはどう行けばいいですか?
A: ■地域総合センター上ノ島本館及び分館には十分な駐車設備がございませんので、次のとおり阪神バス(尼崎市内線)をご利用ください。以下のいずれの駅からの行き方について知りたいですか。1.阪急塚口駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター上ノ島本館。尼崎市南塚口町8丁目7-25。電話06-6429-7640。

Score: 0.528282
ID: 219
Q: 地域総合センター南武庫之荘へはどう行けばいいですか?
A: ■地域総合センター南武庫之荘には十分な駐車設備がございませんので、次のとおり市バス等をご利用ください。どちらの方面からいらっしゃいますか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神バスまたは宝塚・伊丹方面から。4.南方面から。<改>。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター南武庫之荘。尼崎市南武庫之荘11丁目6-15。電話06-6438-5875。

Score: 0.491753
ID: 320
Q: 地域総合センター水堂へはどう行けばいいですか?
A: 地域総合センター水堂への行き方について、以下のいずれについて知りたいですか。1.阪急武庫之荘駅から。2.JR立花駅から。3.阪神尼崎駅から。<改>。地域総合センター水堂には駐車場があります。【関連するFAQ】。地域総合センターについて知りたい。<改>。【お問い合わせ】。●地域総合センター水堂本館。尼崎市水堂町2丁目35-1。電話06-6436-8681。●尼崎市水堂町2丁目34-21。地域総合センター水堂分館。電話06-6348-2189。

Score: 0.489794
ID: 103
Q: 地域総合センター塚口へはどう行けばいいですか?
A: ■地域総合センター塚口には十分な駐車設備がございませんので、次のとおり徒歩またはバス等をご利用ください。以下のいずれの駅からいらっしゃいますか?。1.阪急塚口駅から。2.JR猪名寺駅から。3.阪神尼崎駅から。<改>。地域総合センターについて知りたい。<改>。【お問い合わせ】。地域総合センター塚口。尼崎市塚口本町2丁目28-11。電話06-6423-5266。

Score: 0.469260
ID: 1302
Q: 〔施設見学〕北部浄化センターを見学するにはどうしたらよいのですか?
A: ■北部浄化センターを見学されるときは事前(2週間前まで)に申込みが必要です。(1)見学の内容。(2)希望される日時。(3)参加人数等をお知らせください。詳しくは尼崎市ホームページをご覧ください。■問合せ時間。午前8時45分~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【関連するFAQ】。北部浄化センターは何をしていますか?。【お問い合わせ】。北部浄化センター。尼崎市東園田町7丁目82番地。電話06-6499-4515。

Score: 0.452483
ID: 527
Q: 地域総合センターについて知りたい。
A: ■各地区の地域総合センターは、地域住民をはじめとする市民相互の交流の促進及び人権啓発意識の普及高揚を図り、もって市民福祉の向上に寄与するためのコミュニティの拠点となる施設をめざしています。<改>。■市内に8ヵ所あります。【地域総合センター上ノ島本館】。尼崎市南塚口町8丁目7番25号。電話06-6429-7640。【地域総合センター上ノ島分館】。尼崎市南塚口町8丁目22番18号。電話06-6429-2731。【地域総合センター神崎】。尼崎市神崎町14番22号。電話06-6499-3500。【地域総合センター水堂本館】。尼崎市水堂町2丁目35番1号。電話06-6436-8681。【地域総合センター水堂分館】。尼崎市水堂町2丁目34番21号。電話06-6438-2189。【地域総合センター今北】。尼崎市西立花町3丁目14番1号。電話06-6416-5729。【地域総合センター南武庫之荘】。尼崎市南武庫之荘11丁目6番15号。電話06-6438-5875。【地域総合センター塚口】。尼崎市塚口本町2丁目28番11号。電話06-6423-5266。

Score: 0.392492
ID: 1284
Q: 保健センターはどこにありますか。
A: ■保健センターは、新たに南北保健福祉センター地域保健課に移転しました。■問合せ時間。午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。【問い合わせ】。【北部保健福祉センター地域保健課】。尼崎市南塚口町2丁目1番1号さんさんタウン1番館5階。電話06-4950-0637。ファックス06-6428-5110。【南部保健福祉センター地域保健課】。尼崎市竹谷町2丁目183番地リベル5階。電話06-6415-6342。ファックス06-6430-6850。

Score: 0.388647
ID: 1099
Q: 地域総合センター神崎へはどう行けばいいですか?
A: ■阪急電鉄「園田」駅(南)から。阪神バス(尼崎市内線)23番「阪神尼崎」行きに乗車、「遊女塚」下車、西へ徒歩5分。■JR「尼崎」駅(南)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■阪神電鉄「尼崎」駅(北)から。阪神バス(尼崎市内線)23番「戸ノ内」行きに乗車、「遊女塚」下車、西へ徒歩5分。■車では、山幹通りと山陽新幹線の交差点のひとつ西側の南行き道路を、南へ300m。【関連するFAQ】。地域総合センターについて知りたい。【お問い合わせ】。地域総合センター神崎。尼崎市神崎町14-22。電話06-6499-3500。

Score: 0.326357
ID: 632
Q: 【保健福祉センター】北部保健福祉センターに駐車場はあるのか。
A: ■北部は、塚口さんさんタウン2番館の地下に駐車場があります。また、近隣に塚口さんさんタウン第2駐車場があります。さんさんタウン2番館に67台、第2駐車場に88台あり、また障害者用区画もあります。なお、平成33年以降は3番館分の駐車スペース128台が使用できる予定です。■南部は、リベルの4階に114台、屋上に118台の計232台分あり、障害者用区画も2台分あります。どちらの駐車場も駐車場料金を利用者に負担していただくことになります。<改>。■保健福祉センター。【北部保健福祉センター】。尼崎市南塚口町2-1-1塚口さんさんタウン1番館5階・6階。【南部保健福祉センター】。竹谷町2-183出屋敷リベル5階。■問合せ時間。午前8時45分~午後5時30分。ただし、窓口の取扱時間は午前9時~午後5時30分。■休日。土・日曜日、祝日、年末年始(12月29日~1月3日)。<改>。【お問い合わせ】。健康福祉局企画管理課。電話06-6489-6334。
kun432kun432

いろいろ結合ロジックがあるが、じゃあどれがいいのか?というところで、ranxを使って少し評価をしてみる。

今回使用したデータセットには、ベクトルデータベースに登録したデータ以外に、評価用のデータも含まれているので、これでranxの評価用データを作成し、実際に検索した結果と照らし合わせて、評価を行ってみる

コードについて説明は割愛。

  • 以下に対して検索を行って比較
    • 質問のみ
    • 回答のみ
    • 質問+回答の結合(ドキュメント拡張)
    • Multi Target Vectorsで結合ロジックminimum
    • Multi Target Vectorsで結合ロジックavarage
    • Multi Target Vectorsで結合ロジックsum
  • manual weightsとrelative scoresは重み設定が必要になるので今回はなし

ベクトル検索は約4700回ぐらい行うことになるので、そこそこ時間がかかる

評価用コード
def split_ids(ids_str: str, prefix: str = "")->list:
    if ids_str != "None":
        if prefix:
            return [f"{prefix}_{id}" for id in ids_str.split()]
        return ids_str.split()
    else:
        return []


def testset2list(filename):
    queries = []
    ids_correct = []
    ids_relavant = []
    ids_irrelavant = []
    try:
        with open(filename, 'r') as file:
            for line in file:
                query, *ids = line.strip().split('\t')
                query = query.replace(" ","")
                correct_ids = split_ids(ids[0])
                relavant_ids = split_ids(ids[1])
                irrelavant_ids = split_ids(ids[2])
                queries.append(query)
                ids_correct.append(correct_ids)
                ids_relavant.append(relavant_ids)
                ids_irrelavant.append(irrelavant_ids)

    except Exception as e:
        raise

    return queries, ids_correct, ids_relavant, ids_irrelavant

queries, all_ids_correct, all_ids_relavant, all_ids_irrelavant = testset2list("localgovfaq/testset.txt")
query_ids = ["T_" + str(i) for i in range(len(queries))]
test_df = pd.DataFrame(
    {
        'QUERY_ID': query_ids,
        'QUERY': queries,
        'CORRECT_ANSWER_IDS': all_ids_correct,
        'RELAVANT_ANSWER_IDS': all_ids_relavant,
        'IRRELAVANT_ANSWER_IDS': all_ids_irrelavant,
    }
)

test_qrels = []
for _, row in test_df.iterrows():
    query_id = row["QUERY_ID"]
    correct_ids = row["CORRECT_ANSWER_IDS"]
    relavant_ids = row["RELAVANT_ANSWER_IDS"]
    irrelavant_ids = row["IRRELAVANT_ANSWER_IDS"]
    if correct_ids:
        for id in correct_ids:
            qrel = "{} 0 {} 2".format(query_id, id)
            test_qrels.append(qrel)
    if relavant_ids:
        for id in relavant_ids:
            qrel = "{} 0 {} 1".format(query_id, id)
            test_qrels.append(qrel)
    if irrelavant_ids:
        for id in irrelavant_ids:
            qrel = "{} 0 {} 0".format(query_id, id)
            test_qrels.append(qrel)

with open('test_qrels.trec', 'w') as file:
    for qrel in test_qrels:
        file.write(f"{qrel}\n")
test_df

test_runs = {}
test_runs["question_only"] = []

for idx, row in tqdm(test_df.iterrows(), total=test_df.shape[0], desc=f"question_only"):
    query_id = row["QUERY_ID"]
    query = row["QUERY"]

    response = faq.query.near_text(
        query=query,
        limit=100,
        target_vector=["question_vector"],
        return_metadata=MetadataQuery(distance=True)
    )

    for rank, o in enumerate(response.objects, start=1):
        score = 1 - o.metadata.distance / 2
        r_id = str(o.properties["qa_id"])
        run = "{} Q0 {} {} {} {}".format(query_id, r_id, rank, score, "question_only")
        test_runs["question_only"].append(run)
test_runs["answer_only"] = []

for idx, row in tqdm(test_df.iterrows(), total=test_df.shape[0], desc=f"answer_only"):
    query_id = row["QUERY_ID"]
    query = row["QUERY"]

    response = faq.query.near_text(
        query=query,
        limit=100,
        target_vector=["answer_vector"],
        return_metadata=MetadataQuery(distance=True)
    )

    for rank, o in enumerate(response.objects, start=1):
        score = 1 - o.metadata.distance / 2
        r_id = str(o.properties["qa_id"])
        run = "{} Q0 {} {} {} {}".format(query_id, r_id, rank, score, "answer_only")
        test_runs["answer_only"].append(run)
test_runs["document_expansion"] = []

for idx, row in tqdm(test_df.iterrows(), total=test_df.shape[0], desc=f"document_expansion"):
    query_id = row["QUERY_ID"]
    query = row["QUERY"]

    response = faq.query.near_text(
        query=query,
        limit=100,
        target_vector=["question_answer_vector"],
        return_metadata=MetadataQuery(distance=True)
    )

    for rank, o in enumerate(response.objects, start=1):
        score = 1 - o.metadata.distance / 2
        r_id = str(o.properties["qa_id"])
        run = "{} Q0 {} {} {} {}".format(query_id, r_id, rank, score, "document_expansion")
        test_runs["document_expansion"].append(run)
test_runs["multi_target_minimum"] = []

for idx, row in tqdm(test_df.iterrows(), total=test_df.shape[0], desc=f"multi_target_minimum"):
    query_id = row["QUERY_ID"]
    query = row["QUERY"]

    response = faq.query.near_text(
        query=query,
        limit=100,
        target_vector=TargetVectors.minimum(["question_vector", "answer_vector"]),
        return_metadata=MetadataQuery(distance=True)
    )

    for rank, o in enumerate(response.objects, start=1):
        score = 1 - o.metadata.distance / 2
        r_id = str(o.properties["qa_id"])
        run = "{} Q0 {} {} {} {}".format(query_id, r_id, rank, score, "multi_target_minimum")
        test_runs["multi_target_minimum"].append(run)
test_runs["multi_target_sum"] = []

for idx, row in tqdm(test_df.iterrows(), total=test_df.shape[0], desc=f"multi_target_sum"):
    query_id = row["QUERY_ID"]
    query = row["QUERY"]

    response = faq.query.near_text(
        query=query,
        limit=100,
        target_vector=TargetVectors.sum(["question_vector", "answer_vector"]),
        return_metadata=MetadataQuery(distance=True)
    )

    for rank, o in enumerate(response.objects, start=1):
        score = 1 - o.metadata.distance / 2
        r_id = str(o.properties["qa_id"])
        run = "{} Q0 {} {} {} {}".format(query_id, r_id, rank, score, "multi_target_sum")
        test_runs["multi_target_sum"].append(run)
test_runs["multi_target_average"] = []

for idx, row in tqdm(test_df.iterrows(), total=test_df.shape[0], desc=f"multi_target_average"):
    query_id = row["QUERY_ID"]
    query = row["QUERY"]

    response = faq.query.near_text(
        query=query,
        limit=100,
        target_vector=TargetVectors.average(["question_vector", "answer_vector"]),
        return_metadata=MetadataQuery(distance=True)
    )

    for rank, o in enumerate(response.objects, start=1):
        score = 1 - o.metadata.distance / 2
        r_id = str(o.properties["qa_id"])
        run = "{} Q0 {} {} {} {}".format(query_id, r_id, rank, score, "multi_target_average")
        test_runs["multi_target_average"].append(run)
for test_name, test_run in test_runs.items():
    file_path = f'test_run_{test_name}.trec'
    with open(file_path, 'w') as file:
        for run in test_run:
            file.write(f"{run}\n")
!pip install ranx
from ranx import Qrels, Run, evaluate, compare
import glob

qrels = Qrels.from_file("test_qrels.trec", kind="trec")
test_run_results  = []

test_run_files = [
    'test_run_question_only.trec',
    'test_run_answer_only.trec',
    'test_run_document_expansion.trec',
    'test_run_multi_target_minimum.trec',
    'test_run_multi_target_sum.trec',
    'test_run_multi_target_average.trec',
]
for run_file in test_run_files:
    test_run_results.append(Run.from_file(run_file ,kind="trec"))

for k in [3, 5, 10, 20]:
    print(f"===== @{k} =====")
    print()
    report = compare(
        qrels,
        runs=test_run_results,
        metrics=[f"hit_rate@{k}", f"mrr@{k}", f"recall@{k}", f"ndcg@{k}"],
        max_p=0.01,  # P-value threshold
    )
    print(report)
    print()
from ranx import Qrels, Run, evaluate, compare
import seaborn as sns
import matplotlib.pyplot as plt

base_metrics=["hit_rate", "mrr", "recall", "ndcg"]
cutoffs = [3,5,10,20]

for co in cutoffs:
    models = []
    data = []

    metrics = [f"{m}@{co}" for m in base_metrics]
    for r in test_run_results:
        models.append(r.name)
        data.append(list(evaluate(qrels, r, metrics).values()))

    plt.figure()
    sns.heatmap(data, annot=True, fmt=".3f", cmap="Reds", xticklabels=metrics, yticklabels=models, vmin=0.5, vmax=1)
    plt.title(f"Weaviate Mult Target Vector Comparison @{co}")

結果

===== @3 =====

#    Model                 Hit Rate@3    MRR@3      Recall@3    NDCG@3
---  --------------------  ------------  ---------  ----------  ---------
a    question_only         0.642         0.540      0.417       0.452
b    answer_only           0.622         0.512      0.410       0.424
c    document_expansion    0.643         0.550ᵇ     0.433       0.459ᵇ
d    multi_target_minimum  0.662ᵃ        0.560ᵃᵇ    0.440ᵃ      0.474ᵃᵇ
e    multi_target_sum      0.703ᵃᵇᶜᵈ     0.599ᵃᵇᶜᵈ  0.481ᵃᵇᶜᵈ   0.510ᵃᵇᶜᵈ
f    multi_target_average  0.703ᵃᵇᶜᵈ     0.599ᵃᵇᶜᵈ  0.481ᵃᵇᶜᵈ   0.510ᵃᵇᶜᵈ

===== @5 =====

#    Model                 Hit Rate@5    MRR@5      Recall@5    NDCG@5
---  --------------------  ------------  ---------  ----------  ---------
a    question_only         0.712         0.557      0.509       0.483
b    answer_only           0.699         0.529      0.503       0.456
c    document_expansion    0.714         0.567ᵇ     0.528ᵇ      0.494ᵇ
d    multi_target_minimum  0.741ᵃᵇ       0.579ᵃᵇ    0.540ᵃᵇ     0.509ᵃᵇ
e    multi_target_sum      0.761ᵃᵇᶜ      0.612ᵃᵇᶜᵈ  0.571ᵃᵇᶜᵈ   0.538ᵃᵇᶜᵈ
f    multi_target_average  0.761ᵃᵇᶜ      0.612ᵃᵇᶜᵈ  0.571ᵃᵇᶜᵈ   0.538ᵃᵇᶜᵈ

===== @10 =====

#    Model                 Hit Rate@10    MRR@10     Recall@10    NDCG@10
---  --------------------  -------------  ---------  -----------  ---------
a    question_only         0.778          0.566      0.614        0.519
b    answer_only           0.779          0.540      0.624        0.498
c    document_expansion    0.805ᵇ         0.579ᵇ     0.663ᵃᵇ      0.542ᵇ
d    multi_target_minimum  0.807ᵃ         0.588ᵃᵇ    0.661ᵃᵇ      0.551ᵃᵇ
e    multi_target_sum      0.833ᵃᵇᶜᵈ      0.622ᵃᵇᶜᵈ  0.691ᵃᵇᶜᵈ    0.580ᵃᵇᶜᵈ
f    multi_target_average  0.833ᵃᵇᶜᵈ      0.622ᵃᵇᶜᵈ  0.691ᵃᵇᶜᵈ    0.580ᵃᵇᶜᵈ

===== @20 =====

#    Model                 Hit Rate@20    MRR@20     Recall@20    NDCG@20
---  --------------------  -------------  ---------  -----------  ---------
a    question_only         0.834          0.570      0.706        0.548
b    answer_only           0.851          0.545      0.729        0.531
c    document_expansion    0.862          0.583ᵇ     0.754ᵃᵇ      0.570ᵇ
d    multi_target_minimum  0.867ᵃ         0.592ᵃᵇ    0.767ᵃᵇ      0.584ᵃᵇ
e    multi_target_sum      0.878ᵃᵇ        0.625ᵃᵇᶜᵈ  0.776ᵃᵇ      0.606ᵃᵇᶜᵈ
f    multi_target_average  0.878ᵃᵇ        0.625ᵃᵇᶜᵈ  0.776ᵃᵇ      0.606ᵃᵇᶜᵈ

Multi Target Vectorsを使うことで、検索精度が向上しているのがわかる。

kun432kun432

まとめ

Multiple vectors/Named vectorsを使っているならば、Multiple target vectorsは単に検索オプションを変えるだけで、面倒な手間なく使えて、効果も高いので積極的に使うのが良いと思う。

ただ、Multiple target vectorsの前提となる、Multiple vectors/Named vectorsは、コレクション作成時にしか設定できないので、スキーマの設計をきちんと考えておく必要がある(増やしたり減らしたりみたいなことは現時点ではできない)。とはいえ、Weaviateにおけるスキーマの設計は基本的には登録したいプロパティを全部定義しておくのが前提になるので、それにあわせてMultiple vectors/Named vectorsを設定しておけば、プロパティを増やさない限りは問題ないとは思う。

Weaviate、個人的に推しなベクトルDBなので、もっと日本で使う人が増えるといいなと思う。

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