mcpField
V
vecscope

vecscope

ローカル
github.com/076923開発ツール1今日更新

vecscope について

vecscopeは、埋め込み空間とベクトル検索インデックスを診断するローカルCLIです。検索システムやエージェントを構築するチーム向けに、モデルやネットワークなしで再現可能な測定値、判定、確認案を返します。

主な機能

  1. 01ハブネス、崩壊、異方性の測定
  2. 02ANN再現率と厳密近傍の比較
  3. 03クエリ埋め込みとクラスタの分析
  4. 04HNSWとIVFの設定をスイープ
  5. 05スクリプトやエージェント向けJSON出力

活用シーン

  1. 01検索結果の重複や到達不能の診断
  2. 02ANNインデックスの近傍欠落の確認
  3. 03クエリとコーパスの埋め込み空間の比較
  4. 04再現率の目標に沿った設定選び

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"076923-vecscope": {
"command": "uvx",
"args": [
"vecscope"
]
}
}
}
起動コマンドuvx vecscope

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypivecscope0.12.0

ツール

4

掲載時のツール一覧 · 今日に更新

パラメーター型必須説明
kintegerいいえ
pathstringはい
sampleintegerいいえ
verbosebooleanいいえ
ann_pathanyいいえ
baselineanyいいえ
clustersintegerいいえ
qrels_pathanyいいえ
thresholdsanyいいえ
tolerancesanyいいえ
ranked_pathanyいいえ
near_dup_cosnumberいいえ
queries_pathanyいいえ
sample_repeatsintegerいいえ
ann_from_sourcebooleanいいえ
query_baseline_pathanyいいえ

詳細

English · 한국어

vecscope

エージェントのための埋め込み空間のエビデンス。

エージェントがベクトルインデックスを信頼する前に、検索対象の空間を見せましょう。

PyPI version Python CI MIT license

クイックスタート · 測定内容 · クエリとクラスタ · インデックスの一括検査 · 2つの埋め込みを比較 · 検索品質と修正の優先順 · ベクトルストアから読み込む · エージェントと使用する · CIで使用する · 入力形式 · 実際の埋め込み · FAQ

pip install vecscope


エージェントは毎日、RAG パイプライン、セマンティック検索、レコメンデーション検索を構築していますが、検索対象の埋め込み空間を見ることはできません。

検索に問題が起きても、バグのようには見えないことがほとんどです。次のような状態に見えます。

  • 「何を検索しても同じ3つのチャンクが返る」
  • 「スコアがどれも0.8台」
  • 「top-k がコピーで埋まっている」
  • 「総当たり検索では見つかるのに、HNSW では見つからない」

これらの問題にはそれぞれ、文献で知られている決定的な診断方法があります。vecscope は、それらを1つのコマンドと1つの JSON にまとめます。

  • 測定結果
  • ok / warn / fail の判定
  • エージェントが対処できる説明

NumPy 上でローカルに実行でき、モデルもネットワークも必要ありません。毎回同じ数値を報告します。

vecscope が診断するのは、ベクトル検索の実装です。モデルが生成した幾何構造、コーパスの健全性、距離メトリック、インデックス、クエリパイプラインを診断します。

関連性は測定しません。質問に対して適切なドキュメントが返るかどうかを調べるには、ラベル付きクエリが必要です。監査に問題がないことは、検索が取得を妨げていない証拠であり、取得の質が高いことの証明ではありません。

クイックスタート

1. インストールする
pip install vecscope
2. 埋め込みファイルを用意する

vecscope は、行ごとに1つの埋め込みベクトルを持つファイルを読み込みます。これは、モデルの encode が返す (n, dim) 配列を .npy、.parquet、.jsonl、.json、.csv として保存したものです(すべての形式)。

import numpy as np
embeddings = model.encode(texts)          # shape (n, dim), e.g. (3000, 128)
np.save("embeddings.npy", embeddings)

埋め込みが手元にありませんか? 合成行列を3種類(健全、異方性、崩壊)生成できます。

python -c "import urllib.request as u; u.urlretrieve('https://raw.githubusercontent.com/076923/vecscope/main/examples/make_examples.py', 'make_examples.py')"
python make_examples.py
3. 監査を実行する
vecscope audit embeddings.npy
vecscope x.y.z  n=3000 dim=128 k=10  verdict=FAIL
  [ok  ] hubness                skewness=1.1661  (ok < 2, warn >= 2, fail >= 4)
                               k-occurrence skewness 1.17; top 1% of items take 3.9% of all neighbor slots (max N_k=51, expected 10).
  [WARN] antihubs               antihub_excess=0.0523  (ok < 0.05, warn >= 0.05, fail >= 0.2)
                               5.2% of items are never anyone's neighbor (random data at k=10 would give 0.0%); the excess is unreachable through k-NN retrieval.
                               try: inspect a sample of never-retrieved items; drop empty inputs, then apply the hubness fix
  [FAIL] anisotropy             mean_random_cosine=0.8732  (ok < 0.5, warn >= 0.5, fail >= 0.85)
                               random pairs have mean cosine 0.873 (isotropic ~0); mean unit vector has norm 0.93; centering would bring the cosine to -0.000.
                               try: subtract the corpus mean vector and re-normalize, applying the same transform to queries; details.mean_random_cosine_after_centering shows the expected result
  [ok  ] effective_rank         effective_rank_ratio=0.5407  (ok >= 0.1, warn < 0.1, fail < 0.05)
                               effective rank 69.2 of 128 attainable (128 dims; 54.1%); low values mean most dimensions carry nothing.
  [ok  ] collapse               near_duplicate_ratio=0.0000  (ok < 0.02, warn >= 0.02, fail >= 0.1)
                               0.0% of items have a neighbor with cosine >= 0.99 or an exact copy (exact duplicates 0.0%); no row has a near-duplicate.
  [ok  ] rogue_dimensions       top1_dim_variance_ratio=1.3070  (ok < 10, warn >= 10, fail >= 50)
                               dimension 94 alone holds 1.0% of variance, 1.3x the uniform share of 0.78%; top 3 dims hold 3.0%. Rogue dimensions dominate cosine.
  [ok  ] norms                  norm_cv=0.0000  (ok < 0.1, warn >= 0.1, fail >= 0.3)
                               vector norms vary with CV 0.000 (median 1.000, range 1.000-1.000); 0.00% are zero vectors. Unequal norms bias inner-product search toward long vectors.
  [ok  ] metric_mismatch        topk_overlap=1.0000  (ok >= 0.9, warn < 0.9, fail < 0.7)
                               cosine and inner-product top-10 share 100.0% of neighbors; 100.0% of items get identical lists. Low overlap means the index metric changes the results.
  [ok  ] distance_concentration contrast_over_noise=2.2784  (ok >= 1.4, warn < 1.4, fail < 1.1)
                               on 3000 rows a random item is 3.27x farther than the nearest neighbor (random distance 0.127); isotropic noise at 128-d and the same rows would give 1.44x, so the contrast is 2.28x that of noise. On all rows the contrast is 3.27x (median NN distance 0.039). Near 1.0 means distances carry no signal.
  [ok  ] outliers               outlier_ratio=0.0030  (ok < 0.01, warn >= 0.01, fail >= 0.05)
                               0.30% of items have no neighbor within cosine distance 0.050 (median 0.039); see details.sample_ids. Typically junk, empty or foreign-language content.
  [ok  ] connectivity           island_ratio=0.0000  (ok < 0.01, warn >= 0.01, fail >= 0.1)
                               0.00% of items sit in 0 small island(s) of the k-NN graph (fewer than 15 items; 60 components in total). Graph-based ANN (HNSW) attaches islands to the wrong region or never reaches them.
4. 結果を読む
  • 先頭行には全体の verdict が表示されます。これは検出結果のうち最も悪い判定です。
  • 各検出結果には、測定値、ok となる範囲、その数値が検索に何を意味するかを説明する文が表示されます。ok でない検出結果には、最初に試すべき最小限の変更を示す try: 行が追加されます。
  • FAIL の場合、終了コードは 1 です。同じコマンドを CI のゲートとして使用できます。
  • --json を追加すると、エージェントやスクリプトで使えるよう、同じエビデンスを JSON 形式で取得できます。

vecscope の測定内容

検出項目指標正常警告異常異常時の意味
hubnessk 回出現分布の歪度< 2.02.0 から 4.0≥ 4.0一部のアイテムが全員の k-NN リストに現れ、あらゆるクエリで上位に表示されます
antihubsランダムなベースライン e^-k を超えて、近傍として一度も取得されないアイテムの割合< 5%5 から 20%≥ 20%コーパスの一部に k-NN 経由で到達できません
anisotropyランダムなペアのコサイン類似度の平均< 0.850.85 から 0.95≥ 0.95ベクトルが狭い円錐状の領域に密集するため、スコアが狭い範囲に圧縮されます。優れた検索器は nDCG を損なうことなく、この値を十分低く保つため、極端な値のみが警告対象になります
effective_rank共分散スペクトルの参加率/達成可能なランク(次元数、または行数が次元数以下の場合は行数 − 1)≥ 0.100.05 から 0.10< 0.05ほとんどの次元に情報がありません
collapseコサイン類似度 ≥ 0.99 の近傍がある行、または完全な複製(ゼロベクトルを含む)の割合。詳細には重複グループとサンプルペアが表示されます< 2%2 から 10%≥ 10%top-k が同じアイテムの複製で埋まります
ann_recallANN の近傍と正確な k-NN の recall@k。距離で判定するため、完全に同距離の項目(重複)は相互に置き換え可能です。同距離とみなす許容差は 1e-6 + 2e-6 x 距離で、float32 の丸め誤差の 2〜3 倍です≥ 0.950.85 から 0.95< 0.85モデルではなく、インデックスによって検索結果が失われています
rogue_dimensions最大分散を、均等な 1/dim の比率に対する倍率で表した値< 10x10 から 50x≥ 50x少数の座標がすべてのコサイン類似度スコアを決定します
normsベクトルノルムの変動係数< 0.100.10 から 0.30≥ 0.30内積検索では長いベクトルが優先されます。ゼロベクトルも報告されます
metric_mismatchコサイン類似度と内積の top-k 重複率≥ 0.900.70 から 0.90< 0.70インデックスのメトリックによって返される結果が変わります
distance_concentration相対コントラスト(ランダムな距離/最近傍距離)を、同じ次元数と行数の等方性ノイズの相対コントラストで割った値≥ 1.41.1 から 1.4< 1.1最近傍がランダムなアイテムよりわずかに近いだけです。1.0 は純粋なノイズです
outliers最近傍が異常に遠いアイテムの割合< 1%1 から 5%≥ 5%不要なアイテム、空のアイテム、または異なるデータ由来のアイテムです。ID は details に一覧表示されます
connectivityk-NN グラフの小さな孤立領域に属するアイテムの割合< 1%1 から 10%≥ 10%クラスターと呼ぶには小さすぎる独立したグループです。HNSW が適切に接続できないか、到達できません
query_gapクエリからコーパスへの最近傍距離の中央値を、コーパス内の最近傍距離の中央値で割った値< 2.62.6 から 3.0≥ 3.0クエリとコーパスが同じ空間を共有していません。通常は、異なるモデルでクエリを埋め込んでいます(5 から 10)。公開済みの nDCG@10 を再現するパイプラインでは 0.94 から 2.52 です。クエリプレフィックスの欠落によって値が確実に変わるわけではありません
query_shift参照クエリセットの中央値 + 3 MAD よりコーパスから遠いクエリの割合(ベースラインが必要)< 20%20 から 30%≥ 30%参照時点からクエリのパイプラインが変化しています。別のモデルやバージョンを使っているか、コーパスがカバーしていないトピックのトラフィックが発生しています。健全なクエリセットのスコアは 0 から 9% です
ood_queries非推奨です。query_gap を参照してください。クエリ同士の距離の 99% よりもコーパスから遠いクエリの割合< 50%50 から 80%≥ 80%query_gap と同じ問題を示しますが、短いクエリと長いパッセージの間に通常生じる距離もカウントします(BEIR で良好なモデルのスコアは 0 から 65%)。再現した 18 のパイプラインのうち 4 つで誤警告が発生しました
query_hubnessクエリ結果における、コーパス内アイテムの k 回出現数の歪度< 4.04.0 から 10.0≥ 10.0同じ少数のアイテムが大半のクエリに回答します。この値はモデル間の nDCG@10 と連動します(Spearman −0.5 から −0.9)。言語が誤っているモデルのスコアは 11 から 30 です。コーパスのサイズに伴って増加します。英語の優れたモデルのスコアは、文書数が 26k までの場合は 1.5 から 3.4、58k の場合は 4.0 から 4.8 です。そのため、大規模なコーパスではベースラインと比較してください
JSON 内の各検出結果には、healthy_range、warn_at、fail_at と、生の数値を含む details
ブロックが含まれています。anisotropy の場合、このブロックには、ベクトルを中心化した場合のコサイン類似度も含まれるため、中心化だけで問題が解決するかどうかをエージェントが確認できます。

一部の検出結果は、入力を渡した場合にのみ表示されます。

  • ann_recall:--ann で ANN の近傍ファイルを指定します
  • query_gap、query_hubness、ood_queries:--queries でクエリー埋め込みを指定します
  • query_shift:クエリー埋め込みを指定し、さらに --baseline で、クエリーを含む以前の監査実行を指定します

各検出結果には、likely_causes、suggested_action、verify_by も含まれます。これらは仮説であり、指示ではありません。

  • 変更は最小限にします
  • 再監査します
  • 採用する前に、実際のクエリーで検索結果を比較します

エージェントスキルで、この一連の手順を詳しく説明しています。

しきい値

しきい値はデフォルト値です。

  • 7 つの公開モデルで調整されています
  • 2 言語の 9 つのラベル付きデータセットで、19 モデルを対象に再検証されています (検証結果)

診断の出発点であり、普遍的な品質基準ではありません。埋め込み空間はモデル、言語、ドメイン、次元数によって異なるため、優れたモデルで warn が出るのは正常であり、監査結果に問題がなくても、検索品質が高いとは限りません。

実行ごとに任意のしきい値ペアを上書きするか、独自のデータから vecscope calibrate でしきい値を導出できます。

vecscope audit vectors.npy --thresholds my_thresholds.json
# my_thresholds.json: {"anisotropy.mean_random_cosine": [0.4, 0.7], "hubness.skewness": [2.5, 5]}

キーは src/vecscope/evidence.py の THRESHOLDS に一覧表示されており、各 JSON 結果の thresholds にも記載されています。

クエリーとクラスタ

クエリー埋め込みも渡すと、vecscope はクエリーがコーパスと同じ場所に分布しているかを確認します。

  • クエリー側で異なるモデルを使っている場合は、query_gap に表示されます。
  • 同じ少数のチャンクがすべての回答に使われている場合は、query_hubness に表示されます。コーパスの言語に対応していない埋め込みモデルでも、同じ検出結果が出ます。
  • クエリーが正常であることが分かっている実行をベースラインにすると、query_shift は、今回のクエリーのうち、以前と比べてコーパスから離れたものの数を報告します。これにより、一部のトラフィックで別のモデルや新しいトピックが使われている場合も検出できます。
vecscope audit corpus.npy --queries queries.npy
vecscope audit corpus.npy --queries good_queries.npy --json > baseline.json
vecscope audit corpus.npy --queries todays_queries.npy --baseline baseline.json   # adds query_shift

クエリープレフィックス(bge、e5)の欠落は、これらの検出結果では検出できません。SciFact と NFCorpus では、nDCG@10 が -0.014 から +0.007 まで変化し、クエリー距離もどちらの方向にも変化しました (検証結果)。 クエリーを埋め込むコードでプレフィックスを確認してください。

--clusters 10 を追加すると、クラスタごとのマップが出力に追加されます。

  • サイズ
  • 密集度
  • ほぼ重複するデータの割合
  • 各クラスタが占めるハブトラフィックの割合
  • エージェントが参照できるサンプル ID

判定結果は含まれません。問題が「どこに」存在するのかをエージェントに示します。

  clusters (3):
     id   size  share  cos2ctr  neardup  hubshare  sample_ids
      2   1113  37.1%    0.217     0.0%     37.0%  [1282, 1611, 496, 283, 2041]
      0   1023  34.1%    0.232     0.0%     34.2%  [1855, 2932, 1786, 1025, 2476]
      1    864  28.8%    0.222     0.0%     28.9%  [2505, 647, 2740, 2499, 2965]

インデックスのスイープ

vecscope sweep は、小規模なパラメーターグリッドで HNSW インデックスと IVF インデックスを構築し、このコーパスで各設定について次の項目を報告します。

  • 厳密な k-NN に対する recall@k
  • 構築時間
  • 1 秒あたりのクエリ数
  • 単一クエリのレイテンシパーセンタイル(p50/p95/p99)
  • シリアライズされたインデックスのサイズ

次に、目標リコール(デフォルトは 0.95)に達する最速の設定を推奨し、その目標に対する margin も報告します。

margin が 0.02 未満の場合、推奨設定に tight のマークを付け、十分な余裕がある最速の設定も示します。固定パラメーターでのリコールはコーパスが大きくなるにつれて低下するためです。5 万行のサンプルで目標をかろうじて超える設定は、通常、コーパス全体では目標に届きません。

faiss-cpu の追加パッケージが必要です。

pip install "vecscope[index]"
vecscope sweep embeddings.npy -k 10 --target-recall 0.95
  index params                                        recall  build s       qps  p50 ms  p95 ms     MiB  dev
 *hnsw  M=8, ef_construction=100, ef_search=16         0.987     0.35    237954   0.034   0.051     0.6  cpu
 *hnsw  M=16, ef_construction=100, ef_search=32        0.998     1.23    165139   0.084   0.108     0.8  cpu
 *ivf   nlist=76, nprobe=64                            0.999     0.14     33251   0.087   0.095     0.4  cpu
  recommendation: hnsw (M=8, ef_construction=100, ef_search=16)  recall=0.987  qps=237954  p95=0.051ms  index=0.6MiB  margin=+0.037  (fastest configuration with recall@5 >= 0.95)
  note: recall is measured on 200 queries drawn from the corpus itself; real query traffic can differ, pass it as queries when available
  note: HNSW recall at fixed parameters falls as the corpus grows, so a sweep on a sample is optimistic for HNSW; IVF nlist is set from the row count (4*sqrt(n)), so its recall at a given nprobe can move either way with size. Re-run at production size before fixing parameters
  note: queries_per_second is the median of 3 runs on this machine with one query batch; it ranks settings against each other and is not a serving throughput
  note: latency_ms_p50/p95/p99 time 200 queries one at a time in this process, with no network, concurrency or serving stack; compare settings with them, do not quote them as service latency
  note: index_bytes is the serialized index (vectors plus graph or lists); the process needs more while building, and a product-quantized index would be smaller

クエリはデフォルトで、コーパスからシード付きでサンプリングされます。実際のクエリを計測するには --queries を指定してください。クエリログがある場合は必ず指定してください。コーパスから抽出したクエリで目標リコールを最速で達成する設定と、実際のトラフィックに必要な設定は異なる場合があります。

  • 各設定を 3 回計測し、中央値を採用します(--timing-repeats)。
  • パーセンタイルの計測には、--latency-queries(デフォルトは 200、0 でスキップ)も使用し、クエリを 1 件ずつ検索します。
  • index_bytes はシリアライズされたインデックスのサイズです。速度だけでなくメモリの観点からも設定を評価できます。
  • IVF の nlist は行数に応じて決まります(4*sqrt(n))。--nlist を指定すると固定されます。既存のインデックスの nprobe を調整するには、そのインデックスの nlist を渡してください。

末尾の注記は caveats として JSON に含まれます。MCP ツールは sweep_index で、同じオプションをパラメーターとして受け取ります(n_queries、target_recall、device、margin、timing_repeats、latency_queries、nlist)。

このスイープで分かるのは、どのパラメーター設定がこのコーパスとクエリで目標リコールに達し、そのためにどの程度のコストがかかるかです。数値はこのマシンとプロセスを基準としています。設定を確定する前に、実際のサービング環境でレイテンシ、スループット、メモリを独自に計測し、選んだ設定を確認してください。

faiss の GPU ビルド(pip install "vecscope[index-gpu]"、CUDA 12.6 以降を搭載した Linux x86_64 向けの Meta 製 faiss-gpu)では、IVF インデックスと厳密なベースラインが自動的に GPU で実行されます。出力ヘッダーにはデバイス名が表示されます。faiss に HNSW の GPU 実装はないため、HNSW は CPU で実行されます。デバイスを指定するには --device cpu|gpu を使用します。index と index-gpu はどちらも faiss モジュールをインストールするため、どちらか一方だけをインストールしてください。stores には index が含まれるため、GPU マシンではストア用の追加パッケージを個別に選んでください("vecscope[index-gpu,qdrant]")。古いドライバーを使用している場合は、index-gpu の代わりにコミュニティビルドの faiss-gpu-cu12(CUDA 12.1)または faiss-gpu-cu11 をインストールしてください。

2つの埋め込みを比較する

2つのモデルで同じアイテムを埋め込んだ場合や、変更の前後で同じモデルを使って埋め込んだ場合、vecscope compare は、2つの空間で近傍関係がどの程度一致するかを示します。次の項目をレポートします。

  • 最近傍と上位 k 件のリストがどの程度一致するか
  • 各空間と両方の空間における近重複の割合
  • 両方の空間で同じ重複相手が選ばれるか
  • 最も大きく食い違う行

判定は行いません。アイテムの問題とモデルの問題を切り分けることが目的です。

  • 両方の空間が同じ相手を重複として示す 10%の崩壊は、アイテム自体の性質です (たとえば、同じ画像に複数の ID が付いている場合)。
  • 片方の空間だけが重複を示す場合は、そのモデルに原因があると考えられます。
vecscope compare clip.npy lens.npy -k 10          # rows must be the same items in the same order
vecscope x.y.z  compare  n=3000 dim=128/128 k=10  neighbors=recomputed/full
  nn1_agreement=0.7050  topk_overlap=0.8537  topk_overlap_p10=0.7000  rows_with_no_overlap=0.0000
  near_dup A=0.0400  B=0.0400  both=0.0400  only_A=0.0000  only_B=0.0000  same_nearest_among_both=1.0000
    the two spaces share the nearest neighbor for 70.5% of rows and 85.4% of their top-10 lists
    on average (0.0% of rows share nothing). Near-duplicates: 4.0% in A, 4.0% in B, 4.0% in both,
    and 100.0% of those agree on the partner. Duplicates flagged by both spaces with the same
    partner are a property of the items; duplicates flagged by one space only point at that model.
  largest disagreements (row: nearest in A / nearest in B, top-k overlap):
    1769: 1340 / 1340  0.50
    1810: 1229 / 1229  0.50

一致度を引用する前に、neighbor_scope を確認してください。

--sample の行数(デフォルトは 100k)を超える場合は、シード値に基づいて抽出したサブセットを比較します。デフォルトでは、近傍もそのサブセット内で正確に再計算されます。真の近傍がサンプル外にあるアイテムは代替候補と比較されますが、代替候補は実際の近傍よりも一致率が高くなります。

2,000 行の合成空間ペアで 500 行のサンプルを使うと、上位 10 件の重複率は 0.75 になりますが、コーパス全体では 0.57 です。このような結果には neighbor_scope: sample と示され、説明にもその旨が記載されます。

コーパス全体のランキングをサンプル行で比較するには、各空間でコーパス全体を対象に計算した近傍リストを渡します。リストは正確なものでも、本番インデックスから取得したものでも構いません((n x >= k) の ID ファイル。自身の ID と負の埋め草は除外されます)。

vecscope compare clip.npy lens.npy -k 10 --neighbors-a clip_knn.npy --neighbors-b lens_knn.npy

結果は neighbors=supplied/full になります。行はサンプリングされる場合がありますが、近傍はサンプリングされません。一致度は、計算方法が正確か近似かにかかわらず、指定したリスト同士の一致度です。MCP ツールは compare_embeddings(neighbors_a_path、neighbors_b_path)です。

検索品質と修正の順序

検出結果が説明するのはベクトル空間です。適切なドキュメントが取得されるかどうかを確認するには、ラベルが必要です。

クエリに対する関連性の判定を渡すと、監査結果に retrieval ブロックが追加されます。

  • すべての行を対象にした正確なコサイン検索の nDCG@k、recall@k、MRR@k、hit rate(検出結果がサンプリングされる場合も同様)
  • duplicate_result_share。上位にランクされた結果の近重複が占める結果枠の割合

--ranked を指定すると、本番インデックスが返した上位 k 件のスコアを正確な検索と比較し、overlap_with_exact を表示します。

--ranked には、クエリを処理するシステムが返す最終的な上位 k 件を指定します。ANN インデックス、フィルター付きストアクエリ、ハイブリッド検索、リランカーなどが対象です。正確なベースラインは、フィルター、キーワードスコア、リランキングを適用せず、すべての行を対象にした単純なコサイン検索です。

  • これらのステージをパイプラインに含める場合、overlap_with_exact が測るのはベクトル検索からのパイプライン全体の乖離であり、ANN の再現率だけではありません。
  • vecscope はステージごとのスコアを計算しません。品質を落としているステージを特定するには、各ステージの出力を順番に --ranked として渡してください。
vecscope audit corpus.npy --queries queries.npy --qrels qrels.tsv
vecscope audit corpus.npy --queries queries.npy --qrels qrels.tsv --ranked prod_topk.npy

qrels には、次のいずれかを指定します。

  • 1 行につき query row, corpus row, grade(.tsv/.csv。ヘッダーはスキップされます)
  • .json の場合は {"query row": {"corpus row": grade}}
  • .jsonl の場合は 1 行につき 1 つのオブジェクト

BEIR の query-id/corpus-id/score という名前も使用できます。行はクエリファイルとコーパスファイル内の位置を指します。

スコアは、関連性(grade > 0)の判定が少なくとも 1 件あるクエリについて平均されます。判定がない場合、nDCG と recall は定義されないためです。該当する判定がないクエリ、または判定がまったくないクエリは unscored_queries に数えられ、説明にも示されます。

--baseline を指定すると、差分に検出結果の変更と並んで retrieval_changes が表示されます。そのため、変更が意図した検出結果の修正に役立ったかどうかだけでなく、検索にもどう影響したかを評価できます。

  retrieval vs baseline:
    exact   duplicate_result_share   0.0512 -> 0.0000  (-0.0512)
    exact   hit_rate_at_k            1.0000 -> 1.0000  (+0.0000)
    exact   mrr_at_k                 1.0000 -> 1.0000  (+0.0000)
    exact   ndcg_at_k                1.0000 -> 1.0000  (+0.0000)
    exact   recall_at_k              1.0000 -> 1.0000  (+0.0000)

2つの実行で異なる qrels または k を使用した場合、retrieval_comparable は false になります。

修正の順序

各監査には plan も含まれます。これは、ok ではない検出結果を、共通している可能性の高い原因ごとにまとめ、修正する順に並べたものです。各ステップには、次の項目が記載されています。

  • 値を含む検出結果
  • 確認すべき共通の原因
  • それを検証する最小限の変更
  • 再測定する数値
  • その順番に置かれている理由
  plan (fix in this order; each step is a hypothesis to test):
    1. metric: metric_mismatch=0.0329 fail
       cause: vector norms vary, so cosine and inner product rank differently
       first: decide the index metric; L2-normalize if cosine is intended
       check: norm_cv near 0 and topk_overlap 1.0 on re-audit
    2. shared_direction: anisotropy=0.926 warn, antihubs=0.061 warn, collapse=0.108 fail
       cause: a large component shared by all vectors (a mean offset or a few high-variance coordinates) that compresses scores and creates hubs
       first: subtract the corpus mean and re-normalize (anisotropy.details shows the expected cosine after centering); if rogue_dimensions fails, z-score dimensions instead. Apply the same transform to queries and rebuild the index
       check: anisotropy and rogue_dimensions below warn_at, hubness.skewness down; retrieval ndcg_at_k not lower than before

これは、正規化されていないベクトルに共通のオフセットを加えた合成コーパス(2,000 行、32 次元)です。上記の差分は、両方のステップを適用し、正規化されたコーパスと比較した同じコーパスです。ラベル付きクエリ 80 件は nDCG が 1.0 を保つほど簡単なため、変化を示すのは重複の割合だけです。

この順序は、修正間の依存関係に基づいています。

  • まず、壊れた入力(ゼロベクトル、複製)です。すべての統計値を歪めるためです。
  • 次に、支配的な座標です(異常な次元がすべての距離を決め、それに伴ってノルム、外れ値、ハブも決まるため、正規化より先に z スコア化を行います)。
  • 次に、メトリックです。
  • 次に、近傍グラフを再構築する、センタリングなどの変換です。
  • 次に、モデルです。
  • 次に、コーパスの構造とインデックスです。
  • 最後にクエリ側を、修正後のコーパスを基準に測定します。

原因がその検出結果を生み出す可能性があるステップに移される検出結果もあります。

  • 共通の方向が原因の近似重複率(カットオフを超えるコサイン類似度がすべてのベクトルで見られ、完全な複製はない)は、重複排除ではなく、その方向のステップに含めます。
  • 重複の近くにある query_gap は、重複のステップに含めます。近似複製により、query_gap の分母となるコーパス距離が縮小するため、クエリが原因と判断する前に重複排除後に再測定します。
  • 島のサイズより小さい近似重複グループの近くにある島は、複製が島である可能性があるため、重複のステップに含めます。

ルールは固定されており、src/vecscope/plan.py に記載されています。各ステップは、その再測定項目で検証する仮説であり、診断ではありません。

各ステップの検出結果には placed_because があり、次のいずれかの値を取ります。

  • 「このグループの原因がこれを説明できる」
  • その検出結果を配置する根拠となった別の検出結果。たとえば「rogue_dimensions が ok ではないため、1 つの座標がこの検出結果にも影響しています」。これは同時発生に基づくグループ化なので、そのステップの再測定値で確認してください。

実際の埋め込みで修正が検索結果に与えた影響については、検証を参照してください。

ベクトルストアから読み込む

パスには、埋め込みファイルの代わりに faiss インデックスファイルまたはベクトルデータベースを指定できます。

  • 行は ID の昇順で読み込まれるため、内容が変わっていなければ、2 回読み込んでも同じ行列が得られます。
  • エビデンスには、読み込んだ内容のフィンガープリントを使ってソースが記録されます。
  • details.sample_ids の行 ID には、ストア固有の ID を示す sample_source_ids が付随します。
pip install "vecscope[qdrant]"     # or [chroma], [milvus], [weaviate], [index] for faiss, [stores] for all
vecscope audit index.faiss --ann-from-source --sample 0
vecscope audit "qdrant://localhost:6333/docs?vector=dense" --save-ids ids.json
vecscope audit "qdrant+local:///data/qdrant?collection=docs"
vecscope audit "chroma+local:///data/chroma?collection=docs"
vecscope audit "milvus+local:///data/milvus.db?collection=docs"
vecscope audit "milvus://milvus.internal:19530/docs?api_key_env=MILVUS_TOKEN"
vecscope audit "weaviate://localhost:8080/Docs?grpc_port=50051"

--ann-from-source は、保存されている各ベクトルについてストア固有のインデックスにクエリを送信し、--ann と同じ方法でスコアを計算します。これにより、近傍リストをエクスポートせずに、本番環境でのインデックスの再現率を測定できます。

オプションはクエリ文字列に指定します。

  • vector=(名前付きベクトル、または Milvus のフィールド)
  • https=1
  • pk=(Milvus の主キー)
  • api_key_env=NAME(キーはその環境変数から読み込みます。URI 内のキーは使用されません)
  • timeout= ネットワークストアへのリクエストごとのタイムアウト(秒、既定値は 60)

読み込みは読み取り専用です。ただし、読み込まれていない Milvus コレクションは、読み込みのためにロードされ、読み込み後に再び解放されます。

シークレットが出力に含まれることはありません。

  • エビデンスには、ユーザー情報を含めず、上記のオプション以外のすべてのクエリ値を REDACTED に置き換えた URI が記録されます。
  • ストアのクライアントから返されたエラーは、API キーと該当する値を伏せたうえで再送出されます。
  • Chroma の HTTP クライアントには独自のタイムアウトがないため、接続後にセッションへ timeout= が設定されます。クライアント作成時に行われる接続確認には、タイムアウトが適用されません。

MCP サーバーは、許可されたディレクトリ内のローカルストアを読み込みます。ネットワークストアを読み込むのは、--allow-network を指定して起動した場合のみです。

大規模コーパス:増分監査

すべての行を監査すると、行数に対して二次の計算量になります。コーパスへの追加や行の埋め込みの差し替えを行う場合、--knn-cache は実行間で近傍リストを正確に保持し、変更された行に対する計算だけを行います。

vecscope audit day1.npy --sample 0 --knn-cache knn.npz    # created: all rows
vecscope audit day2.npy --sample 0 --knn-cache knn.npz    # extended: only the appended rows
vecscope audit day3.npy --sample 0 --knn-cache knn.npz    # updated: changed rows and their neighbors

キャッシュには、計算対象となった各行のダイジェストが保存されます。キャッシュは次のように処理されます。

  • 同じ行に対して再利用されます
  • 行が追加され、キャッシュ済みの行に変更がない場合は拡張されます
  • キャッシュ済みの一部の行に新しいベクトルがある場合は更新されます。その行と、近傍リストにその行が含まれていた行は、すべての行を対象に再計算されます。それ以外の行は、変更された行と追加された行のみを対象にします
  • それ以外の場合は再構築されます。再計算が必要な行が全体の半数を超える場合(その場合、更新のコストは再構築とほぼ同じになります)、行が削除された場合、または dim が変更された場合です。 knn_cache.reason にその理由が示されます。

変更の影響は広がります。k=10 の場合、変更された各行は約10個の他のリストに含まれます。行の1%をランダムに変更すると約10%が再計算され、5%を変更すると約半数が再計算されます。そのため、小規模で分散した再埋め込みや行の追加では、更新によって処理を効率化できます。

近傍リストは、距離が完全に同値の場合を除き、全件計算と一致します。また、検出結果は float32 の丸め誤差の範囲で一致します。Python では、 vecscope.incremental.cached_knn_for_audit(x, k, path) が audit(x, knn=...) 用のリストを返します。

100,000行 × 768次元の場合(パフォーマンス表と同じマシン):

  • 5,000行の追加では、キャッシュの拡張に11秒、キャッシュからの監査に4秒かかりました。全件監査では94秒でした
  • 20,000行の追加では、43秒と4秒かかりました。全件監査では123秒でした

判定はすべて全件監査と一致し、相対値の最大差は7e-5でした。キャッシュの作成には全件監査とほぼ同じ時間がかかります(ここでは83秒)。

100,000行のうち1,000行をその場で再埋め込みした場合、10,625行が再計算されました。キャッシュの更新に15秒、キャッシュからの監査に5秒かかり、全件監査では95秒でした。判定は同じでした。10,000行を変更すると、更新では68,933行が再計算されて83秒かかり、全件監査の89秒とほぼ同じ時間になるため、代わりにキャッシュが再構築されます。このルールで再実行すると、10,000行の変更ではキャッシュの再構築に87秒かかり、全件監査も87秒でした。

エージェントでの使用

vecscope には、読み取り専用の4つのツール audit_embeddings、sweep_index、compare_embeddings、describe_findings を備えた MCP サーバーが含まれています。任意の MCP クライアントに登録してください。

pip install vecscope
claude mcp add vecscope -- vecscope-mcp --allow-dir /data/embeddings     # Claude Code
claude mcp add vecscope -- uvx vecscope mcp --allow-dir /data/embeddings # or without installing

vecscope mcp と vecscope-mcp は、同じオプションを持つ同一のサーバーです。MCP レジストリ には io.github.076923/vecscope として登録されています。

{ "mcpServers": { "vecscope": { "command": "vecscope-mcp", "args": ["--allow-dir", "/data/embeddings"] } } }

JSON 形式の設定は、Cursor では .cursor/mcp.json に、Claude Code のプロジェクトでは .mcp.json に記述します。Codex は ~/.codex/config.toml から TOML を読み込みます。

[mcp_servers.vecscope]
command = "vecscope-mcp"
args = ["--allow-dir", "/data/embeddings"]

次に、以下のように尋ねます。

Audit the embeddings in data/chunks.npy before we tune the retriever, and tell me
which finding to fix first.
ツールと応答
  • audit_embeddings は、CLI と同じ入力で監査を実行します。
  • sweep_index は、インデックススイープを実行します。
  • compare_embeddings は、比較を実行します。
  • describe_findings は、各指摘事項のしきい値、原因、対応策をすべて一覧表示します。

応答は、1 行の summary と audit_id から始まります。summary には、ok でない指摘事項、検索の nDCG、最初の計画ステップ、および再監査の場合はベースラインとの比較が記載されます。

変更後に再監査するときは、その ID を baseline として渡してください。すると応答に baseline_diff(判定と値の変化、regressions、improvements、検索の変化)が含まれます。これは CLI の --baseline と同じ動作で、エージェントが以前の応答を保存する必要はありません。サーバーは直近 32 件の監査をメモリに保持します。保存した応答や --json ファイルを使うこともできます。

verbose=false にすると、ok の指摘事項に関する詳細、説明、対応策が省略されます。MCP を利用できないエージェントは、CLI を --json 付きで実行すれば、同じエビデンスを確認できます。

.agents/skills/vecscope/SKILL.md にあるエージェントスキルでは、エージェントがいつ監査を実行すべきか、また各判定に対して何をすべきかを説明しています。モデルのセンタリングまたは入れ替え、重複排除、再ランク付け、インデックスの再構築などが含まれます。サーバーにも同じ手順が含まれているため、MCP 接続しか利用できないエージェントも同じサイクルに従います。

サーバーが読み取る可能性のあるもの

ツールは読み取り専用ですが、エージェントが指定したパスを読み取るため、サーバーは読み取り可能な範囲を制限します。許可されたディレクトリの外にあるパスは(.. とシンボリックリンクを解決した後)、開く前に拒否されます。

  • デフォルトでは、サーバーを起動したディレクトリとその配下のみです。
  • --allow-dir DIR を指定すると、上記のセットアップのように、そのディレクトリが許可されます。複数回指定できます。環境変数 VECSCOPE_ALLOWED_DIRS(Unix では :、Windows では ; でパスを区切ります)でも同じ設定ができます。
  • --allow-any(または VECSCOPE_ALLOW_ANY=1)を指定すると制限が解除され、サーバープロセスが読み取れるすべてのファイルにアクセスできるようになります。ご自身のマシンでのみ使用してください。
  • ネットワーク上のベクトルストアには、さらに --allow-network が必要です。読み取り専用でもアクセスが無害になるわけではないため、サーバーのネットワークアクセスが意図したものである場合にのみ許可してください。

各ファイルは、開いた後に検証する単一のハンドルを通じて読み取られます。ファイルは通常のファイルであり、許可されたディレクトリ内でパスが解決するものと同一でなければなりません。検証と読み取りの間に差し替えられたシンボリックリンク、FIFO、ディレクトリは拒否されます。

ローカルデータベースのディレクトリ(qdrant+local:// など)は、クライアントが自らファイルを開くため、パスのみが検証されます。

1 回のリクエストでサーバーのメモリを使い果たすことはありません。

  • --max-read-mb(デフォルトは 4096、VECSCOPE_MAX_READ_MB、0 で無制限)を超えるファイルは、読み取り前に拒否されます。
  • ストアのベクトルが同じサイズを超えると、そのストアの読み取りは停止します。
  • ファイルは検証済みのハンドルから直接解析され、先にメモリへコピーされることはありません。500,000 x 384 の .npy ファイル(0.72 GiB)では、MCP の読み取り時のメモリ使用量のピークは 0.79 GiB で、CLI と同じです。

並列実行やコストの高い設定を使う呼び出しも制限されます。

  • サーバーは各ツール呼び出しを独自のスレッドで実行します。監査、スイープ、比較は --max-concurrent の枠を 1 つ使用します(デフォルトは 1、VECSCOPE_MAX_CONCURRENT)。それ以上の呼び出しは待機します。そのため、エージェントが 3 件の監査を同時に開始しても、メモリ上に保持されるコーパスは 1 つであり、3 つにはなりません。
  • 1 回の呼び出しのコストを増大させる設定には、呼び出しごとに上限があります。k と clusters は 1,000、sample_repeats と timing_repeats は 10、n_queries は 100,000、latency_queries は 10,000 です。CLI には上限がありません。

監査、スイープ、比較のたびに、サーバーの stderr に 1 行が書き込まれ、MCP クライアントはそれをログに保存します。そこには、ツール名と読み取ったすべてのファイルまたはストア(認証情報はマスキングされます)、判定結果またはエラー、枠の待機時間を含む所要時間が記録されます。

vecscope-mcp: audit_embeddings path=/data/run/corpus.npy qrels_path=/data/run/qrels.tsv: fail in 2.1 s

baseline が参照する最近の監査結果は、ロックをかけて保持されます。stdio サーバーは、起動した 1 つのクライアントにサービスを提供します。並列実行するエージェントは、それぞれ独自のサーバーを起動します。

テスト済みクライアント

診断、変更、再検証のループは、MCP stdio プロトコル(tests/test_agent_workflow.py)でテストされており、Claude Code のヘッドレスモード(上記のサーバーを使った claude -p)でエンドツーエンド実行されました。

共有オフセットのあるコーパスを監査し、計画どおりに正規化とセンタリングを行って再監査した後、修正を依頼されていない残りのステップで停止しました。Cursor と Codex は同じプロトコルを使用しますが、実行テストは行っていません。

docs/agent_case.md には、実際の SciFact 埋め込みを使った 2 つのケースが記録されており、それぞれ 2 回実行されています。

  • 2 つの取り込み不具合:バッチが二重に取り込まれたケースと、ワーカーが正規化をスキップしたケースです。症状だけからエージェントが両方を見つけ、コーパスを修正し、最初の audit_id と照合して再監査しました。本番の nDCG@10 は 0.100 から 0.713 に向上しました。
  • nprobe=1 で検索した IVF インデックス:監査により埋め込みは正常であり、本番のランキングは厳密検索より nDCG が 0.29 低いことが判明しました。エージェントはインデックスをスイープして nprobe を選択し、本番の nDCG@10 は 0.422 から 0.700、さらに 0.711 に向上しました。
サーバーが接続しなくなった場合

「vecscope-mcp not found」は通常、インストール先の Python 環境が置き換えられたことを意味します。これは、ホスト型ノートブックやクラスターで環境が再構築される際に発生します。

クライアントが使用するインタープリターで pip show vecscope を実行して確認し、その環境に再インストールしてください。その後、そのインタープリターを通じてサーバーを登録すると、エラーに正しい環境が表示されます。

{ "mcpServers": { "vecscope": { "command": "/path/to/env/bin/python", "args": ["-m", "vecscope.mcp_server"] } } }

ライブラリとして使用する

import numpy as np
from vecscope import audit

embeddings = np.load("embeddings.npy")    # any (n, dim) float array

ev = audit(embeddings, k=10)
ev.verdict                                # "ok" | "warn" | "fail"
ev.findings[0].value                      # measured value of the first finding
ev.to_dict()                              # the full evidence, same as --json

CI で使用する

JSON 出力は実行ごとに安定しており、schema_version が含まれているため、ベースラインとしてコミットし、インデックスを再構築するたびに差分を確認できます。

--baseline は各検出結果の変化を出力し、いずれかの判定が悪化した場合(または --fail-on の条件に該当した場合)に終了コード 1 で終了します。これにより、すでに存在する warn ではなく、リグレッションが発生したときにパイプラインが失敗します。

vecscope audit embeddings.npy --json > baseline.json          # once, reviewed and committed
vecscope audit embeddings.npy --baseline baseline.json        # on every rebuild
  baseline baseline.json: verdict ok -> fail  (n, dim, k, sampling, thresholds or near-dup cutoff differ: values and verdicts are not directly comparable)
    hubness                1.0454 -> 0.8594  (-0.1860)  ok -> ok
    antihubs               0.0383 -> 0.0105  (-0.0278)  ok -> ok
    anisotropy             0.0105 -> 0.0127  (+0.0022)  ok -> ok
    collapse               0.0000 -> 0.8000  (+0.8000)  ok -> fail  WORSE
    ...
  regressions: collapse

この例では、行数の異なる healthy.npy と collapsed.npy を比較しているため、1 行目に注記が表示されます。同じ設定で同じコーパスを再構築した場合は、注記は表示されません。

--json を指定すると、差分は baseline_diff に含まれます。ライブラリでは diff_evidence(new, old) を呼び出します。古い schema_version で書き込まれたベースラインは、再作成するようメッセージを表示して拒否されます。

ベースラインとチェックの両方で、すべての行を監査するために --sample 0 を指定し、2 回の実行で同じ行が対象になるようにしてください。両方の実行で --queries を指定すると、ベースラインのクエリ距離から query_shift も算出されます(クエリとクラスターを参照)。ベースライン自体には参照値がないため、差分では only_in_new の下に表示されます。

ドリフトの許容値

判定は大まかな指標です。値がしきい値を超えないまま、何か月もそのしきい値に近づき続けることがあります。そのため、変更行にはそれぞれ次の項目が含まれます。

  • worsened:値が悪い方向に動いたかどうか
  • worsening:どれだけ悪化したか(指標の単位で表示。正の値は悪化を意味します)

--tolerances を使うと、判定のしきい値とは別に、このドリフトをゲートとして設定できます。

# tolerances.json: {"collapse": 0.01, "ann_recall": 0.02, "hubness": 0.3}
vecscope audit embeddings.npy --baseline baseline.json --tolerances tolerances.json --require-comparable
  • 許容値を超えて悪化した検出結果は value_regressions に一覧表示されます(テキスト出力:VALUE WORSE by 0.0300 > 0.01)。判定が変わらなくても、終了コード 1 で終了します。
  • 許容値が設定されていない検出結果は、判定のみで評価されます。
  • 値が改善した場合、リグレッションにはなりません。

許容値は、コミット済みのベースラインに対する再構築ごとの予算です。変更がレビューされ、承認されたら、ベースラインを再コミットしてください。

実行結果には comparable も報告されます。n、dim、k、サンプリング、しきい値、または近似重複のカットオフがベースラインと異なる場合、値は false になります。

--require-comparable を指定すると、注記ではなくエラー(終了コード 2)になります。異なる設定間の差分はコーパスではなく設定を測定するため、ゲートではこのポリシーが適切です。ライブラリでは diff_evidence(new, old, tolerances={...}) を呼び出します。

実行を失敗させたルール

実行を失敗させるルールは 2 種類あり、出力ではそれぞれが分けて表示されます。

  • 絶対ルールは、しきい値に対する判定です(デフォルトでは --fail-on fail、厳格にする場合は --fail-on warn)。
  • ベースラインルールは regressions(判定が悪化した)と value_regressions(値が許容値を超えて悪化した)です。

デフォルト値は公開モデルを基準に調整されているため、正常なコーパスで一部の検出結果が warn または fail になるドメインでは、絶対ルールによってブロックしないようにしてください。 --fail-on none --baseline baseline.json を指定すると、レビュー済みベースラインに対する変化のみを評価します。

各実行の最後には、判定を決定したルールを示す gate ブロック(JSON)または行(テキスト)が出力されます。

  gate: FAIL; verdict fail reaches --fail-on fail; verdict worse than baseline: collapse
  gate: pass (baseline)

まずはゲートを傾向の追跡に利用してください。どの程度の許容値を「大きすぎる」とするかは、検出結果が独自のクエリにおける検索品質とどのように関連するかによって異なります。

検索品質の調査では、その関連性を公開データセットについて示しています。また、しきい値の調整では、マージをブロックする前に、独自のデータでそれを測定する方法を説明しています。

CLI オプション

vecscope audit vectors.npy -k 20                       # neighbors per item (default 10)
vecscope audit vectors.parquet --json                  # JSON evidence
vecscope audit vectors.npy --ann hnsw_neighbors.npy    # score ANN recall against exact k-NN
vecscope audit vectors.npy --queries queries.npy       # add query-side findings
vecscope audit vectors.npy --queries q.npy --qrels qrels.tsv   # add nDCG/recall/MRR of exact search
vecscope audit vectors.npy --queries q.npy --qrels qrels.tsv --ranked topk.npy   # and of the production ranking
vecscope audit index.faiss --ann-from-source --sample 0     # read a faiss index or store; score its own neighbors
vecscope audit "qdrant://host:6333/docs" --save-ids ids.json   # vector store URI; write ids in row order
vecscope audit vectors.npy --sample 0 --knn-cache knn.npz   # reuse / extend / update exact neighbor lists between runs
vecscope audit vectors.npy --clusters 10               # append a per-cluster report (at most n/10 clusters)
vecscope audit vectors.npy --thresholds th.json         # override (warn, fail) pairs
vecscope audit vectors.npy --fail-on warn              # exit 1 on WARN as well
vecscope audit vectors.npy --fail-on none --baseline old.json   # ignore the absolute thresholds; fail only on regressions
vecscope audit vectors.npy --baseline old.json         # diff against an earlier --json run; exit 1 on regression
vecscope audit vectors.npy --baseline old.json --tolerances tol.json   # also exit 1 when a value worsens beyond its tolerance
vecscope audit vectors.npy --baseline old.json --require-comparable    # exit 2 when the baseline used different settings
vecscope audit vectors.npy --near-dup 0.98             # cosine threshold for near-duplicates
vecscope audit vectors.npy --sample 0                  # audit every row (default samples 100k)
vecscope audit vectors.npy --sample-repeats 3          # re-audit 3 samples; report value ranges and verdict stability
vecscope sweep vectors.npy --target-recall 0.95        # HNSW/IVF parameter sweep (faiss extra)
vecscope sweep vectors.npy --device gpu                # IVF on the GPU (faiss GPU build)
vecscope sweep vectors.npy --margin 0.05               # headroom under which the pick is marked tight (default 0.02)
vecscope sweep vectors.npy --n-queries 2000 --timing-repeats 5   # queries to time (default 1000), timing runs per setting (default 3)
vecscope sweep vectors.npy --latency-queries 0         # skip the single-query latency percentiles (default 200 queries)
vecscope sweep vectors.npy --nlist 128                 # sweep nprobe on the production index's list count
vecscope compare a.npy b.npy -k 10                     # agreement between two embeddings of the same rows
vecscope compare a.npy b.npy --neighbors-a a_knn.npy --neighbors-b b_knn.npy   # full-corpus neighbors on a sample of rows
vecscope calibrate fit_*.json --min-quality 0.45 --out th.json   # gate thresholds from your own pipeline states
vecscope calibrate fit_*.json --min-quality 0.45 --holdout hold_*.json --include-low-confidence   # check on held-out states; also write exploratory pairs

入力形式

埋め込みファイルには、1 行につき 1 つのベクトルが格納されています。監査の前に、すべての形式は形状 (n, dim) の 2 次元 float32 配列に変換されます。

値は有限である必要があります。NaN、Inf、および絶対値が 1e16 を超える値(その二乗が float32 の範囲を超えるため)は、メッセージとともに拒否されます。

例では、embeddings はその配列を指します。たとえば、モデルの encode の出力です。

embeddings = model.encode(texts)        # shape (n, dim), e.g. (3000, 128)
embeddings[0]                           # the vector of the first item
# array([ 0.0312, -0.1187,  0.0459, ...], dtype=float32)
拡張子想定されるレイアウト例
.npy2 次元の数値配列np.save("vectors.npy", embeddings)
.npzアーカイブ内の最初の配列を使用np.savez("vectors.npz", emb=embeddings)
.parquet、.pqfloat のリスト列。列名に emb または vec を含むもの。その他の列(id、テキスト)は無視されますpd.DataFrame({"id": ids, "embedding": list(embeddings)}).to_parquet("vectors.parquet")
.jsonl1 行につき 1 つの JSON オブジェクト。最初に見つかったリスト値のフィールドがベクトルです{"id": 7, "text": "...", "embedding": [0.1, -0.3, ...]}
.json上記の形式のオブジェクトの JSON 配列、またはリストの配列[[0.1, -0.3, ...], [0.2, 0.5, ...]]
.csv、.tsv、.txt1 行につき 1 つのベクトル。数値のみで、ヘッダーや id 列はありません0.1,-0.3,0.8,...

50,000 x 384 個の float32 ベクトル(73 MiB の行列)で測定した、各形式の読み込みに必要なメモリ量:

形式読み込み方法最大メモリ使用量
.npy保存時の形式のまま0.10 GiB
.csv行をチャンク単位で読み込み0.18 GiB
.jsonl1 行ずつ読み込み、行ブロック単位で変換0.34 GiB
.parquetベクトル列のみをバッチ単位で 1 つの配列に読み込み0.39 GiB
.jsonファイル全体を一度に解析1.13 GiB

大規模なコーパスには .npy、.csv、または .parquet を使用してください。.json はファイル全体を解析するため、行列サイズの数倍のメモリが必要です。

任意の入力:

  • --ann(MCP では ann_path):形状 (n, k) の整数配列です。行 i には、ANN インデックスが項目 i に対して返した k 個の近傍の id が、埋め込みファイルと同じ行順で格納されます。上記のいずれの形式も使用できます。
  • --queries(MCP では queries_path):コーパスと同じ dim のクエリ埋め込みです。上記と同じいずれの形式も使用できます。
  • query_shift の参照データ:--queries を指定して監査を実行した際の、以前の --json 出力(--baseline、または MCP では baseline もしくは query_baseline_path)。

ANN の id は行位置を参照するため、このファイルはまったく同じ行から構築されたインデックスから取得する必要があり、すべての行を監査する必要があります。既定の --sample のサイズ(100k 行)を超える場合は --sample 0 を指定してください。指定しないと監査は拒否されます。項目自身を指す id は無視されるため、先頭に自身を返すインデックスは k + 1 で検索する必要があります。

query_shift の参照データは、同じコーパス、または変更されていないその先頭部分を対象に監査された場合にのみ使用されます(行の SHA-256 である corpus_fingerprint で確認)。正規化または中心化の後では、以前のクエリ距離は別の空間の値になるため、query_shift はスキップされ、その理由が query_reference_note に記載されます。

パフォーマンス

厳密な k-NN の計算量は行数に対して二次的です。行数が2倍になると、所要時間はおよそ4倍になります。 100k行の全件監査(--sample 0)には、ノートPCで数分かかります。

k-NN の処理では、行数にかかわらず距離行列が約1 GiBに収まるよう、行をブロック単位で処理します。それ以外の処理では、行列の float32 コピーがいくつか必要になるため、ピークメモリは行数 x 次元数に応じて増加し、行列サイズの約4倍になります。

8 BLAS スレッドを使用した8-vCPU AMD EPYC 7R13での測定結果です(NumPy のみ、単一プロセス、クラスタリングした合成コーパス、k=10)。メモリは監査処理自体が割り当てるピーク値で、入力行列の分は含まれません。別プロセスで3回実行した中央値は、これらの単回実行の結果と2%以内で一致し、OS のピークメモリとも0.04 GiB以内で一致しました。

行数次元数秒数ピークメモリ(入力を除く)
10,0003841.30.40 GiB
10,0007682.00.41 GiB
10,0001,5363.60.44 GiB
50,000384171.63 GiB
50,000768231.70 GiB
50,0001,536361.84 GiB
100,000384651.71 GiB
100,000768861.85 GiB
100,0001,5361303.45 GiB
200,0007683383.46 GiB
200,000、デフォルトの100kサンプル768852.14 GiB
  • 時間はおおむね n² に比例して増加します(50k行以降、2倍あたり3.5~3.9倍)。
  • 384次元および768次元では、n の増加に伴って k-NN のブロックが小さくなるため、50k行からメモリ使用量は横ばいです。1,536次元および200k行では増加します。
  • デフォルトでは100k行をサンプリングするため、コーパスの行数が多くても監査対象は約100k行に抑えられます。
  • --queries はクエリバッチごとにコーパス全体をもう1回処理します。また、ベクトルノルムにばらつきがある場合に限り、metric_mismatch は k-NN の処理をもう1回行います。

お使いのマシンで、必要なサイズの測定を再度行うには、次のコマンドを実行してください。

python examples/benchmark_scale.py --rows 50000 100000 --dim 768   # the audit table above
python examples/benchmark_sweep.py                                 # the index sweep

どちらのコマンドも --corpus(clustered、isotropic、anisotropic、duplicates、lowrank、zipf)を受け取り、JSON にマシン情報を記録します。

サンプル監査

ブロッキングで制限できるのはメモリ使用量であり、処理量ではありません。厳密なパスには、引き続き約 n² × dim 回の積和演算が必要です。そのため、768 次元の 100 万行では、10 万行の場合の約 100 倍になります。

この規模のコーパスでは、デフォルトのサンプル(または --sample-repeats で複数のサンプル)を監査し、すべての行が必要な調査に限って --sample 0 を使用してください。サンプル監査で得られるのは、サンプルに関する結果です。すべての行が必要となる調査は次のとおりです。

調査結果サンプルから得られるものすべての行が必要か
anisotropy、effective_rank、rogue_dimensions、norms、metric_mismatch、distance_concentration分布の推定値です。200k x 384 のデータで 100k、50k、20k のサンプルを使った場合、全体の値との差は 2.3% 以内で、判定も変わりませんいいえ
hubness、antihubs下限値です。k-occurrence は密度が高いほど集中するため、同じコーパスでも小さなサンプルでは hubness が低くなります(全 200k 行では歪度 2.6 で warn、4 分の 1 では 1.15、10 分の 1 では 0.16)。fail 以外の判定は「確定不能」として示されますコーパス自体の hubness を測定するには必要です
collapseサンプル内で確認された重複の 割合です。2 行とも抽出された場合にのみペアとして数えられるため、サンプルでの割合は、サンプル率 × 全体の割合の 0.96~1.03 倍です。判定には推定された全体の割合を使い、少なくともすべての行を対象に数えた完全一致のコピーを反映します近似重複をすべて数える、または列挙するには必要です
outliers小さなサンプルでは過大計上される推定値です(サンプル率が 10 分の 1 の場合、3.9 倍)。ok 以外の判定は「確定不能」として示されます外れ値をすべて見つけるには必要です
connectivityサンプル自体の k-NN グラフにおける島です。コーパス内の島の大半は検出されません(コーパスでは島に属する行が 37% ですが、4 分の 1 のサンプルでは 0.08% と判定されました)。fail 以外の判定は「確定不能」として示されますconnectivity を評価するには必要です
ann_recallサンプルでは利用できません。ID が ANN ファイルと一致している必要がありますはい(--sample 0)
query_gap、query_shift、query_hubness、ood_queriesサンプルから得た参照距離です。すべてのクエリを評価します。query_gap は、どちらも小さなサンプルで大きくなる 2 つの距離の比率です。query_shift は、同じサンプルサイズのベースラインとのみ比較してくださいいいえ

そのため、サンプル監査では次の処理が行われます。

  • inconclusive_findings(表で「確定不能」と示されている判定)を列挙します
  • テキスト出力ではそれらに INCONCLUSIVE (sampled) のフラグを付け、ゲート行にも名前を表示します
  • collapse の判定には details.estimated_full_share を使用します(下記参照)
  • 各調査結果の説明で、数値の横に注意事項を繰り返し記載します

estimated_full_share は、サンプルでの割合をサンプル率で割った値です。ただし、すべての行を対象に数えた完全一致のコピーの割合(details.full_corpus_exact_copy_share)のほうが大きい場合は、そちらが使われます。コーパス全体から完全一致のコピーを数える処理は、各行のダイジェストを 1 つ計算するだけなので低コストです。そのため、サンプルで見逃したまれなコピーも数えられます。完全一致ではない近似重複は、サンプルでのみ検出されます。

200k 行の数値は 検証に基づいています。tests/test_regression_injection.py は、実行のたびに 6k 行で同じ特性を確認します。

どの数値も、実際に確認した行については厳密です。vecscope は、厳密な近傍検索を近似近傍検索で代用することはありません。唯一の近似は、対象とする行の選び方です。

vecscope の仕組み

vecscope は行列全体に対して正確な k-NN を一度計算し、そこからすべての診断結果を導き出します。

  • k 回出現する頻度の分布から、ハブネスとアンチハブを求めます
  • 最近傍のコサイン類似度から、崩壊、外れ値、距離集中を求めます
  • k-NN グラフから、連結性を求めます
  • ランダムペアと共分散スペクトルから、異方性、有効ランク、異常な次元を求めます
  • ベクトルのノルムから、ノルムのばらつきを求めます
  • 2 回目の内積計算(ノルムが一様な場合は省略)から、距離尺度の不一致を求めます
  • ANN の近傍ファイルがある場合は、正確な近傍と比較して再現率を求めます

クエリ埋め込みがある場合は、コーパスに対する独自の正確な検索を行い、クエリ側の所見を得ます。

すべて決定論的です。シードは固定され、近傍は正確で、学習済みコンポーネントはなく、ネットワークにも接続しません。 同じファイルで 2 回実行すると、同じ JSON が得られます。

正確な k-NN の計算量は行数に対して二次関数となるため、--sample 0 を指定しない限り、100,000 行を超える入力はシード付きのランダムサンプルを使って監査されます。

実際の埋め込み

しきい値は、8 つのデータセットにわたる 7 つのモデルの公開済み事前計算埋め込みで調整されています。対象モデルは、OpenAI ada-002 と text-embedding-3-large、Cohere embed-v3(韓国語版と英語版の Wikipedia)、all-MiniLM-L6-v2、bge-m3、mxbai-embed-large-v1、gte-base-en-v1.5 です。

この表は各データセットの先頭 40k 行で測定した値を示しています。ラベルのないセルは ok です。python examples/real_models.py を実行すると再現できます。モデルのダウンロードは不要です。

所見Cohere v3(韓国語版 Wikipedia)Cohere v3(英語版 Wikipedia)ada-002(dbpedia)3-large(dbpedia)MiniLM-L6(Wikipedia)bge-m3(Wikipedia)mxbai-large(Wikipedia)gte-base(arXiv)
ハブネス1.471.161.561.211.591.851.432.28
warn
アンチハブ0.0090.0050.0130.0050.0220.0260.0190.013
異方性0.3330.2280.6920.0860.0260.3070.3300.210
effective_rank0.1580.1780.090
warn
0.1480.2850.1420.087
warn
0.136
崩壊0.0020.0020.0000.0000.0010.0000.0170.000
異常な次元3.23.23.02.51.71.82.01.8
ノルム0.0000.0000.0000.0000.0000.0000.0000.007
距離尺度の不一致1.0001.0001.0001.0001.0001.0001.0000.952
距離集中1.721.741.741.431.781.842.211.62
外れ値0.0010.0010.0000.0000.0010.0020.0030.000
連結性0.0000.0000.0000.0000.0000.0000.0000.000

各データセットの先頭 40k 行で監査を再実行すると、88 件すべての判定が再現されます。warn が付くのは、gte-base のハブネスと、ada-002 および mxbai-large の effective_rank のみです。

ada-002 でよく知られている異方性(0.692)は、warn しきい値の 0.85 を下回っています。平均単位ベクトルのノルムが 0.83 であるため、無関係な文書間でもコサイン類似度が約 0.7 から始まります。同じコーパス上で、その後継モデルは等方的です(ノルム 0.29)。ここに示したすべてのモデルは、中心化するとランダムペアのコサイン類似度が 0.00 になるため、この所見ではその値を報告しています。

テキスト埋め込みのハブネスの歪度は 1.2〜1.9 が通常の範囲であるため、warn しきい値は 2.0 です。arXiv の要約に対する gte-base は、このしきい値をわずかに上回っています。異方性のしきい値(0.85、0.95)は、以下の検索品質に関する研究に基づいています。

検出結果は検索品質を予測しますか?

ある程度は予測しますが、特定の形で予測します。docs/retrieval_quality.md では、ラベル付き BEIR データセット 2 つ(SciFact、NFCorpus)での nDCG@10 を基準に、8 種類の公開モデルそれぞれと、最良モデルに意図的に注入した制御された欠陥について、各検出結果を測定しています。python examples/retrieval_quality.py で再現できます。

  • 1 つのパイプライン内では、検出結果は損傷を捉えます。 異常な次元の注入、ランクの削減、ノイズの追加、行の重複により、nDCG@10 が低下するのと同時に、監視対象の検出結果が fail に変わります(ok から、またはコーパスにすでに少数の重複が含まれている場合は warn から)。欠陥の度合いが大きくなるほど、低下も単調に進みます。

    無関係なモデルで埋め込まれたクエリの query_gap は 8~10(fail、nDCG@10 はほぼ 0)になります。空間を共有する gte-base コーパスに対する bge-base のクエリは 2.9~3.9 となり、nDCG@10 を維持します。

    重複により除算に使うコーパス距離が小さくなるため、近似重複が大量にある場合も query_gap が上昇します。プランでは重複とともに一覧表示し、重複排除後に再確認できるようにしています。

  • 良好なモデル間では、幾何学的な検出結果でモデルを順位付けできません。 両方のデータセットで最良のモデル(gte-base、bge、e5)は、検証対象の 19 モデルで最も高い異方性(0.58~0.82)を示し、有効ランクも通常の範囲です。

    低品質モデルを区別するのは、metric_mismatch を伴う norms(正規化されていない出力)と hubness であり、nDCG@10 とのスピアマン相関係数 |rho| は 0.4~0.8 です。

  • 異方性だけではランキングに悪影響を与えません。 ランダムペアのコサインが 0.98 になるまで共通のオフセットを加えても、nDCG@10 は変わりません。スコアが圧縮されるため、絶対コサインしきい値とスコアのキャリブレーションは機能しなくなります。信号自体が失われたときに変化する検出結果は distance_concentration です。

anisotropy、query_hubness、query_gap、query_shift のしきい値は、検証の結果に基づいています。ラベル付きデータセット 3 つで 19 モデルと注入したクエリーの障害を検証し、さらに別の 3 つで再確認しました。

この評価でカバーしていないのは、ほかのドメインや本番環境のクエリログで、warn と fail が品質低下をどの程度予測できるかです。ご自身のドメインで測定するまでは、判定を調査のきっかけとして、ベースラインからの回帰を検索結果と比較する理由として捉えてください。品質スコアとして捉えるべきではありません。

ドメインに合わせたしきい値の調整

デフォルト値は公開モデルと公開データセットに基づいて調整されています。コーパスで fail が出ても、それは確認する理由であり、検索が不適切だという証拠ではありません。また、すべてが ok でも、適切なドキュメントが返される証拠にはなりません。

しきい値や許容値をブロッキングゲートとして使用する前に、独自のデータでそれらの予測精度を測定してください。

  1. ドメインからラベル付きクエリを収集し(関連ドキュメント ID を付けた数百件で十分です)、しきい値の選定用と、しきい値を検証する保留データに分けます。
  2. パイプラインの候補状態(モデル、チャンク分割器、変換、インデックス設定)ごとに vecscope audit --json を実行し、同じ状態で同じクエリを使って検索品質(nDCG@k、Recall@k、MRR)を計算します。examples/retrieval_quality.py は公開データセットに対して両方を実行でき、独自のデータセットを指定することもできます。
  3. 各指摘の値を、それらの状態における品質指標と関連付けます。ドメイン内で品質とともに変化しない指摘は、デフォルト値にかかわらず、ゲートに使用しないでください。
  4. 品質が許容範囲だった状態を基に、最初のデータ分割のみを使用して --thresholds と --tolerances を設定します。
  5. 保留データで、しきい値が許容範囲内の状態とそれ以外の状態を分けられることを確認します。同じクエリでしきい値を調整して検証すると、実際以上に良い結果に見えます。

vecscope calibrate は、手順 2 の監査結果を使って手順 3 から 5 を実行します。調整用クエリと保留用クエリで、それぞれ各状態を監査してください。

vecscope audit state_a.npy --queries q_fit.npy --qrels qrels_fit.tsv --json > fit_a.json
vecscope audit state_a.npy --queries q_hold.npy --qrels qrels_hold.tsv --json > hold_a.json
# ... the same for every state, then:
vecscope calibrate fit_*.json --min-quality 0.45 --holdout hold_*.json --out th.json
vecscope audit vectors.npy --thresholds th.json

各指摘について、次の内容が報告されます。

  • 状態全体での検索指標とのスピアマン相関(デフォルトでは nDCG@k。--metric で指定)、その 95% ブートストラップ区間、および相関の符号が指摘の示す方向と一致するかどうか
  • その方向での片側置換検定 p 値。検定対象のすべての指摘に対してホルム補正済み
  • 許容範囲内の状態における最悪値と、それ以外の状態における最良値
  • 指摘が品質の変動を追跡し、2 つのグループを分離できる場合に限り、(警告、失敗)のペア。そのペアは、隔たりの幅の 3 分の 1 と 3 分の 2 の位置に設定されます。

データ上で品質に応じて変化しない、または逆方向に変化する指摘には、ペアが設定されません。デフォルト値は確認する理由として残してください。

一度に約 15 件の指摘を検定すると、そのうち 1 件が、少数の状態では偶然に品質を追跡することがあります。そのため、補正後の p 値が 0.05 未満の場合に限り、ペアが --out に出力されます。

  • それ以外のペアは exploratory として報告され、ゲートファイルから除外されます。--include-low-confidence を指定すると、それらも出力されます。
  • 5 つの状態では、その基準に達することはできません(補正前の最小の片側 p 値は 1/120 です)。10 以上の状態が推奨されており、状態がそれより少ない場合はレポートにその旨が記載されます。

調整に使用していない状態で、次の 2 つのチェックによって提案が評価されます。

  • leave_one_out は、すべての状態のうち 1 つを除いて調整し、除外した状態を評価します。これを各状態について行います。
  • 保留行では、ゲートが捕捉した許容範囲外の --holdout 状態の数と、許容範囲内の状態に対する誤検知の数がカウントされます。別のデータセットの保留状態を使うと、しきい値が別のデータセットにも適用できるかを確認できます。

調整には、少なくとも 3 つの状態が必要で、--min-quality を境に両側に状態が存在する必要があります。異なる qrels または k で評価された状態は、品質値を比較できないため拒否されます(--allow-mixed-qrels で上書きできます)。

同じ手順は suggested_action にも適用されます。これは原因に関する仮説であり、ベクトルの中心化、標準化、切り詰めによってランキングが変わります。

  • 元のベクトルと検索結果は、ベースラインとして保持します。
  • 変換をコピーに適用します。
  • 両方について、品質、レイテンシ、メモリを測定します。
  • 指摘が ok になったときではなく、ラベル付きクエリの結果が改善した場合にのみ変更を採用します。

FAQ

ベクトルが外部に送信されますか?

いいえ。vecscope はお使いのマシン上で NumPy を使ってすべての計算を行います。モデルを読み込むことも、ネットワーク接続を開くこともありません。

どれくらい大きな行列を処理できますか?

厳密な k-NN の計算量は行数に対して二次です。デフォルトでは、入力が 100,000 行を超える場合、vecscope はシード付きのランダムサンプルを監査し、出力にその旨を示します(sampled: true、n_total)。

サンプリング結果が示すのはサンプルについてであり、コーパス全体についてではありません。まれなクラスター、小さな孤立領域、少数の外れ値を見落とすことがあります。

details 内の行 ID(sample_ids、sample_pairs、クラスターのレポート)は、サンプリング時も常に入力ファイルの行を参照します。すべてを監査するには --sample 0 を使用してください。必要なコストについてはパフォーマンスをご覧ください。

サンプル自体によって数値がどれほど変動するか確認するには、--sample-repeats 3 を渡します(MCP:sample_repeats)。すると vecscope は、シードを変えた独立したサンプルを3つ監査し、各検出結果に value_range(サンプル間の最小値から最大値)と verdict_stable を付加し、トップレベルに unstable_findings を一覧表示します。

サンプル間で判定が変わる検出結果は、コーパスの性質ではなく、境界的なものとして解釈してください。コストは3回分の監査です。

value_range はサンプル間のばらつきを示すもので、コーパス全体の値を含む範囲ではありません。ハブネスはすべてのサンプルで下限値となり、非常に安定した検出結果であっても、3つのサンプルの範囲からわずかに外れることがあります。

サンプル上で、すべての検出結果が同じ意味を持つわけではありません。ハブネスは過小評価され、外れ値は過大に数えられ、孤立領域はほとんど見えません。パフォーマンスの表には、各検出結果が何を示し得るか、またサンプル監査でどの判定が inconclusive となるかが記載されています。

本番環境のモデルが異方性チェックに失敗します。モデルに問題があるのでしょうか?

必ずしもそうとは限りません。広く使われているテキスト埋め込みモデルの多くは、設計上、強い異方性を持っています。

この検出結果は、生のコサインスコアが狭い範囲に圧縮されていることを示します。通常、ベクトルの中心化や白色化、または再ランキングによって識別性能が回復します。details ブロックには中心化後のコサインが報告されるため、それで十分か確認できます。この判定はエージェントにとっての根拠であり、モデルの評価ではありません。

どのエージェントで使えますか?

ローカル MCP サーバーに対応したエージェント、およびシェルコマンドを実行して JSON を読み取れるエージェントであれば使用できます。スキルファイルでは、どちらの方法も説明しています。

ドキュメント

  • エージェントスキル:監査を実行するタイミングと、各判定への対処方法
  • 検索品質の調査:ラベル付きデータにおける、各検出結果と nDCG@10 の比較
  • 検証:厳密性、再現率のスコアリング、サンプリングに関する主張、クエリの検出結果、介入、エージェントとの統合、9つのラベル付きデータセットにおける19モデル
  • エージェントの事例:MCP 経由で、エージェントが2つの取り込み時の不具合と、調整が不適切な IVF インデックスを検出して修正する事例。ツール呼び出しと数値も掲載しています
  • 例:合成行列、キャリブレーションスクリプト、検索品質の調査
  • 変更履歴

貢献

課題報告とプルリクエストを歓迎します。テストの実行方法と、望ましい変更についてはCONTRIBUTING.mdをご覧ください。セキュリティに関する報告はSECURITY.mdからお寄せください。

ライセンス

MIT

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。