コンテンツにスキップ

Craft Vector Search 2.0 を利用する

Craft Vector Search 2.0はデータの格納と検索をコレクション単位で管理するモジュールです。セマンティック検索・全文検索・ベクトル検索の3つの検索方式に対応しています。

データとベクトルを格納する単位をコレクションと呼びます。コレクションはリレーショナルデータベースのテーブルに似た概念です。Craft Functionsの vectorSearch2 モジュールを使用して、データの追加・取得・更新・削除と検索をします。ベクトルの生成方法として、データ格納時にベクトルを自動生成する Auto Embeddings と、自前でベクトルを用意する BYOE(Bring Your Own Embeddings) の2つの方式があります。

使用の流れは次のとおりです。

  1. コレクションを作成(管理画面)
  2. データを操作(Craft Functions)— Auto EmbeddingsまたはBYOEでベクトルを用意する
  3. データを検索(Craft Functions)— セマンティック検索・全文検索・ベクトル検索

新たにコレクションを作成する手順は次のとおりです。

  1. KARTE管理画面で「すべてのメニュー」>「Craft」>「ベクターサーチ2.0」を選択します。
  2. Vector Search 2.0の画面で「新規作成」を選択します。
  3. 以下を設定します。
    • 「コレクション名」 に任意の名前を入力します。この名前がそのまま collectionId として使われます。
    • 「データスキーマ」 に格納するデータの構造をJSON Schema形式で定義します。
    • 「ベクタースキーマ」 にベクトルフィールドを定義します。Auto Embeddingsの設定を含みます。
  4. 「作成」を選択します。
{
"type": "object",
"properties": {
"name": { "type": "string" },
"description": { "type": "string" },
"category": { "type": "string" },
"price": { "type": "number" }
}
}

スキーマに定義されていないフィールドを含むデータも格納できますが、未定義フィールドは filter の対象にできません(400エラー)。フィルタで使用するフィールドは必ずデータスキーマに定義してください。

ベクタースキーマの例(Auto Embeddings有効)

Section titled “ベクタースキーマの例(Auto Embeddings有効)”
{
"embedding": {
"denseVector": {
"dimensions": 768,
"vertexEmbeddingConfig": {
"modelId": "gemini-embedding-001",
"textTemplate": "{name} {description}",
"taskType": "RETRIEVAL_DOCUMENT"
}
}
}
}
要素説明
embeddingベクトルフィールドのキー名(任意の名前に変更可能)。search 時に vectorField パラメータでこの名前を指定する
dimensionsベクトル次元数。使用するモデルに応じた次元数を指定する
modelIdAuto Embeddingsに使用するモデル。利用可能なモデルは Craft AI Modulesモデル一覧を参照
textTemplateエンベディング対象のテキストテンプレート。{フィールド名} でデータスキーマのフィールドを参照
taskType格納側のタスクタイプ

スキーマ定義の詳細はVertex AI Vector Search 2.0コレクションを参照してください。

作成したコレクションを削除する手順は次のとおりです。

  1. KARTE管理画面で「すべてのメニュー」>「Craft」>「ベクターサーチ2.0」を選択し、ベクターサーチ2.0の管理画面を開きます。
  2. 対象コレクションの三点リーダー(…)から「削除」を選択します。

コレクションを削除すると、コレクション内の全データも一緒に削除されます。

エンベディング方式を選択する

Section titled “エンベディング方式を選択する”

ベクトル生成にはAuto EmbeddingsとBYOEの2つの方式があります。

Auto EmbeddingsBYOE
create時のベクトル生成自動自前で aiModules.gcpEmbeddingsText 等を使用
update時のベクトル再生成されない自前で再生成して vectors で指定

Auto Embeddingsが有効な場合、data のみ指定すればベクトルが自動生成されます。

次のコードは、POSTリクエストで受け取ったデータをコレクションに追加するHTTPタイプのファンクションの例です。

// 認証用のトークン。変数 TOKEN に適当な値を指定してください。
const TOKEN = "<% TOKEN %>";
// コレクションIDを変数 COLLECTION_ID に指定してください。
const collectionId = "<% COLLECTION_ID %>";
// ログレベル。DEBUG, INFO, WARN, ERROR が指定できます。
const LOG_LEVEL = "<% LOG_LEVEL %>";
export default async function (data, { MODULES }) {
const { res, req } = data;
const { vectorSearch2, initLogger } = MODULES;
const logger = initLogger({ logLevel: LOG_LEVEL });
if (req.method !== "POST") {
res.status(405).json({ error: "Method Not Allowed" });
return;
}
const headers = req.headers;
if (!headers["content-type"]) {
res.status(400).json({ error: "Content-Type header is missing" });
return;
}
const token = req.headers.authorization?.split(" ")[1];
if (!token) {
logger.warn("Authorization header is missing or Bearer token is missing");
return res.status(400).json({ error: "Authorization header is missing or Bearer token is missing" });
}
if (token !== TOKEN) {
logger.warn("Invalid token");
return res.status(401).json({ error: "Invalid token" });
}
const { dataObjectId, item } = req.body;
try {
const result = await vectorSearch2.create({
collectionId,
dataObjectId,
data: item,
});
logger.log({ dataObjectId, result });
res.json({ dataObjectId, result });
} catch (e) {
logger.error(e);
res.status(500).json({ error: e.message });
}
}

このファンクションにリクエストを行うCurlコマンドの例は次のとおりです。

curl 'https://FUNCTION_URL' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer TOKEN' \
-d '{
"dataObjectId": "product-001",
"item": {
"name": "有機抹茶",
"description": "京都産の高品質な有機抹茶パウダー。茶道から日常使いまで幅広く使えます。",
"category": "food",
"price": 2500
}
}'
  • FUNCTION_URL はファンクションのエンドポイントURLです。
  • Authorizationヘッダーの TOKEN には、変数 TOKEN の値を指定します。
  • リクエストボディ(-d オプションの値)には次の値を指定します。
    • dataObjectId: データを識別するユニークなID
    • item: データスキーマに従ったデータ

このコードでは、次の処理を行っています。

  • 受信したHTTPリクエストの検証
    • 認証用Authorizationヘッダーの検証
    • Content-Typeヘッダーの検証
  • コレクションへのデータ追加
    • リクエストボディのパラメータからデータを取得し、vectorSearch2.create() でコレクションに格納
    • Auto Embeddings有効時のベクトル自動生成
  • エラーハンドリング
    • リクエスト検証失敗時のエラーレスポンス返却
    • データ書き込み失敗時のエラーレスポンス返却

同一の dataObjectId で create を実行すると 409 Conflict エラーになります。既存データを更新するには update を使用してください。

ベクトルを明示指定して追加する(BYOE)

Section titled “ベクトルを明示指定して追加する(BYOE)”

Auto Embeddingsを使わず、自前でベクトルを生成して格納する方法です。ベクトルの生成にはCraft AI Modules(aiModules.gcpEmbeddingsText)を利用できます。生成したベクトルは vectors パラメータで指定します。

次のコードは、aiModules.gcpEmbeddingsText でベクトルを生成し、data と vectors を指定して格納する例です。

const { aiModules, vectorSearch2 } = MODULES;
// テキストからベクトルを生成
const { predictions } = await aiModules.gcpEmbeddingsText({
instances: [{ content: "京都産の高品質な有機抹茶パウダー", task_type: "RETRIEVAL_DOCUMENT" }],
parameters: { outputDimensionality: 768 },
});
const values = predictions[0].embeddings.values;
// ベクトルを明示指定してデータを追加
const result = await vectorSearch2.create({
collectionId,
dataObjectId: "product-002",
data: { name: "新商品", category: "food", price: 1000 },
vectors: {
embedding: {
dense: { values },
},
},
});

ベクトルの次元数はベクタースキーマの dimensions と一致させてください。

const result = await vectorSearch2.get({
collectionId,
dataObjectId: "product-001",
});
// result の構造:
// {
// dataObjectId: "product-001",
// createTime: "2026-04-17T04:07:14Z",
// updateTime: "2026-04-17T04:07:14Z",
// data: { name: "有機抹茶", category: "food", price: 2500, ... },
// vectors: { embedding: { dense: { values: [...] } } },
// etag: "..."
// }

存在しない dataObjectId を指定するとエラーになります。

update は部分更新です。指定したフィールドのみ更新され、未指定フィールドはそのまま保持されます。存在しない dataObjectId を指定するとエラーになります(upsert的な挙動はありません)。

// price のみ更新(name, description, category は保持される)
await vectorSearch2.update({
collectionId,
dataObjectId: "product-001",
data: { price: 2800 },
});

データとベクトルを同時に更新する

Section titled “データとベクトルを同時に更新する”

BYOE方式の場合や、Auto Embeddingsでテキストフィールドを更新する場合は、aiModules.gcpEmbeddingsText でベクトルを生成し、data と vectors を同時に更新します。

const { aiModules, vectorSearch2 } = MODULES;
const newDescription = "更新後のテキスト";
const { predictions } = await aiModules.gcpEmbeddingsText({
instances: [{ content: newDescription, task_type: "RETRIEVAL_DOCUMENT" }],
parameters: { outputDimensionality: 768 },
});
const values = predictions[0].embeddings.values;
await vectorSearch2.update({
collectionId,
dataObjectId: "product-001",
data: { description: newDescription },
vectors: {
embedding: { dense: { values } },
},
});
await vectorSearch2.delete({
collectionId,
dataObjectId: "product-001",
});

存在しない dataObjectId を指定するとエラーになります。

search はセマンティック検索・全文検索・ベクトル検索の3方式に対応します。条件での一覧取得には query を使います。

ベクトル類似度に基づいて検索します。Auto Embeddingsが有効な場合、テキストを指定するだけで検索できます。BYOEの場合は「ベクトルを指定して検索する」を使用してください。

次のコードは、POSTリクエストで受け取ったテキストでコレクションをセマンティック検索し、結果を返すHTTPタイプのファンクションの例です。

// 認証用のトークン。変数 TOKEN に適当な値を指定してください。
const TOKEN = "<% TOKEN %>";
// コレクションIDを変数 COLLECTION_ID に指定してください。
const collectionId = "<% COLLECTION_ID %>";
// ログレベル。DEBUG, INFO, WARN, ERROR が指定できます。
const LOG_LEVEL = "<% LOG_LEVEL %>";
export default async function (data, { MODULES }) {
const { res, req } = data;
const { vectorSearch2, initLogger } = MODULES;
const logger = initLogger({ logLevel: LOG_LEVEL });
if (req.method !== "POST") {
res.status(405).json({ error: "Method Not Allowed" });
return;
}
const headers = req.headers;
if (!headers["content-type"]) {
res.status(400).json({ error: "Content-Type header is missing" });
return;
}
const token = req.headers.authorization?.split(" ")[1];
if (!token) {
logger.warn("Authorization header is missing or Bearer token is missing");
return res.status(400).json({ error: "Authorization header is missing or Bearer token is missing" });
}
if (token !== TOKEN) {
logger.warn("Invalid token");
return res.status(401).json({ error: "Invalid token" });
}
const { text, category } = req.body;
try {
const searchParams = {
collectionId,
query: {
vectorField: "embedding",
text,
},
topK: 5,
};
if (category) {
searchParams.filter = { category: { $eq: category } };
}
const { results } = await vectorSearch2.search(searchParams);
const items = results.map((r) => ({
id: r.dataObject.dataObjectId,
name: r.dataObject.data.name,
distance: r.distance,
}));
logger.log({ items });
res.json({ items });
} catch (e) {
logger.error(e);
res.status(500).json({ error: e.message });
}
}

このファンクションにリクエストを行うCurlコマンドの例は次のとおりです。

curl 'https://FUNCTION_URL' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer TOKEN' \
-d '{
"text": "お茶に関する商品",
"category": "food"
}'
  • FUNCTION_URL はファンクションのエンドポイントURLです。
  • Authorizationヘッダーの TOKEN には、変数 TOKEN の値を指定します。
  • リクエストボディ(-d オプションの値)には次の値を指定します。
    • text: 検索テキスト
    • category: カテゴリで絞り込む場合に指定(省略可)

このコードでは、次の処理を行っています。

  • 受信したHTTPリクエストの検証
    • 認証用Authorizationヘッダーの検証
    • Content-Typeヘッダーの検証
  • コレクション内のセマンティック検索
    • リクエストで受け取ったテキストに意味的に類似する上位5件のデータを検索
    • カテゴリ指定時はそのカテゴリ内で絞り込み
  • エラーハンドリング
    • リクエスト検証失敗時のエラーレスポンス返却
    • 検索失敗時のエラーレスポンス返却

レスポンスの例です。

{
"items": [
{ "id": "product-001", "name": "有機抹茶", "distance": 0.1940 },
{ "id": "product-004", "name": "玄米グラノーラ", "distance": 0.2098 }
]
}

検索結果には distance フィールドが含まれます。値が小さいほど関連度が高いことを示します。

テキストの文字列一致で検索します。セマンティック検索とは異なり、検索テキストを含むデータのみが返却されます。

const { results } = await vectorSearch2.search({
collectionId,
query: {
searchText: "抹茶",
searchFields: ["name", "description"],
},
});
  • searchFields で指定したフィールドのみが検索対象になります(searchFields は必須。省略するとエラーになります)
  • filter との組み合わせも可能です
  • 日本語テキストは形態素解析でトークナイズされます。「抹茶」は1つのトークンとして扱われるため、「抹」や「茶」単体では検索できません
  • 検索演算子や全文検索の詳細はVertex AI Vector Search 2.0のドキュメントを参照してください

ベクトル値を直接指定して類似検索します。既存データのベクトルを使って類似データを検索する場合などに利用します。

// 既存アイテムのベクトルで類似検索する例
const item = await vectorSearch2.get({
collectionId,
dataObjectId: "product-001",
});
const { results } = await vectorSearch2.search({
collectionId,
query: {
vectorField: "embedding",
vector: item.vectors.embedding.dense.values,
},
topK: 5,
});

フィルタで一覧取得する(query)

Section titled “フィルタで一覧取得する(query)”

query はフィルタ条件でデータを一覧取得します。SQLの WHERE 句のように条件を指定してデータを絞り込みます。ベクトル検索は行いません。

// 全件取得
const result = await vectorSearch2.query({
collectionId,
});
// result.dataObjects → DataObject の配列

フィルタは $eq / $gt / $and 等の演算子を使用します。演算子の指定は必須です。{ category: "food" } のように演算子を省略すると400エラーになります。

// 文字列一致
const result = await vectorSearch2.query({
collectionId,
filter: { category: { $eq: "food" } },
});
// 数値比較
const result = await vectorSearch2.query({
collectionId,
filter: { price: { $gt: 5000 } },
});
// 複合条件(AND)
const result = await vectorSearch2.query({
collectionId,
filter: {
$and: [
{ category: { $eq: "food" } },
{ price: { $lt: 2000 } },
],
},
});

フィルタ式は2階層より深くネストできません。利用可能な演算子の一覧やフィルタの詳細はVertex AI Vector Search 2.0のドキュメントを参照してください。

大量のデータがある場合は pageSize と pageToken でページ単位で取得できます。

// 1ページ目(10件ずつ取得)
const page1 = await vectorSearch2.query({
collectionId,
pageSize: 10,
});
// 2ページ目
if (page1.nextPageToken) {
const page2 = await vectorSearch2.query({
collectionId,
pageSize: 10,
pageToken: page1.nextPageToken,
});
}

レスポンスフィールドを制御する(outputFields)

Section titled “レスポンスフィールドを制御する(outputFields)”

query と search の両方で、レスポンスに含めるフィールドを制御できます。outputFields はオブジェクト形式で指定します。ベクトルデータはサイズが大きいため、不要な場合は省略することを推奨します。

const result = await vectorSearch2.query({
collectionId,
outputFields: {
dataFields: ["name", "price"], // data 内の返却フィールドを指定
vectorFields: [], // 空配列でベクトルを省略
},
});
フィールド説明
dataFieldsdata内の返却フィールドを配列で指定。未指定フィールドは省略される
vectorFields返却するベクトルフィールドを配列で指定。ベクトルを省略するには [](空配列)を明示指定する必要がある
metadataFieldsメタデータ(createTime等)の返却を制御

インデックスは、セマンティック検索とベクトル検索を高速化するための任意の設定です。

作成しなくても、これまで説明したデータの登録・取得・検索はそのまま利用できます。インデックスがないときは、コレクション内のベクトルを全件比較して類似度を計算します。

件数が増えて検索速度に影響が出てきたら、インデックスの作成を検討してください。

新たにインデックスを作成する手順は次のとおりです。

  1. KARTE管理画面で「すべてのメニュー」>「Craft」>「ベクターサーチ2.0」を選択し、対象コレクションを開きます。
  2. 「インデックス」タブを開き、「新規作成」をクリックします。
  3. 表示される「インデックス作成」画面で、以下を設定します。
    • インデックスID(必須): 管理画面での識別子
      • 英字で始まる識別子を入力します(1〜63文字。英数字・ハイフン・アンダースコアのみ)
    • インデックスフィールド(必須): ベクトル類似検索を高速化する対象
      • ベクタースキーマのキー名から選びます(例: embedding)
    • フィルタフィールド(任意): search 時の絞り込みに使うフィールド
      • データスキーマのフィールド名をカンマ区切りで入力します(例: category, price)
      • 入力しない場合は、文字列・数値・ブール型のフィールドがすべて対象になります
    • ストアフィールド(任意): 絞り込みには使わず、検索結果として返すデータをインデックス内に保持するフィールド
      • インデックス内に保持しておくことで、検索時のデータ取得を効率化します
      • データスキーマのフィールド名をカンマ区切りで入力します(例: name, price)
  4. 「作成」をクリックします。

作成後も vectorSearch2.search() の呼び出し方は変わりません。インデックスIDをAPIに渡す必要はなく、一覧の 状態 が「作成中」から「有効」に変われば適用されます。

フィールド名は、前述のデータスキーマ・ベクタースキーマで定義した名称と一致させてください。

インデックスの作成には数十分かかる場合があります。

  1. 対象コレクションの「インデックス」タブを開きます。
  2. 削除するインデックスの三点リーダー(…)から「削除」を選択します。

インデックスを削除してもコレクション内のデータは削除されません。インデックスなしの検索は引き続き可能です。

Craft Vector Search 2.0