Embedding入門|埋め込みベクトル実装

Claude Code活用

※ この記事にはアフィリエイトリンクが含まれています。詳細はプライバシーポリシーをご確認ください。

「ChatGPTに自社ドキュメントを読ませたいが、検索精度が安定しない」と感じている方は多いはずです。その壁を越える鍵がEmbedding(埋め込みベクトル)です。

RAGや社内ナレッジ検索、AIエージェントといった2026年のAIアプリ実装で必ず登場する基礎技術です。ここが分かると「AIがどうやってテキストの意味を理解しているか」が初めて腑に落ちます。

本記事は、コードが書けるエンジニア向けにEmbeddingを実装視点で整理します。「テキストを数値に変える」というぼんやりした理解を、API呼び出し・コサイン類似度計算・簡易セマンティック検索のコードまで一気通貫でつなげる構成にしました。

僕は普段、Claude CodeやCursorで自動化スクリプトを書きながら、社内ドキュメントの検索や記事ネタの分類にEmbeddingを組み込んでいます。その実務感覚から、最低限押さえるべき概念とコード例だけを抜き出しました。

本記事はAI学び直し|エンジニアの実務スキル4階層のシリーズ第3回(第2階層:データ・機械学習基礎)にあたります。

こんな方に読んでほしい

  • OpenAIやVoyage AIのEmbedding APIを叩いてみたいが、概念が曖昧な方
  • セマンティック検索やRAGの「前段の処理」が何をしているか整理したい方
  • キーワード検索の限界を感じ、意味検索に移行したいエンジニアの方
  • 次元数・モデル選定・チャンク化の判断軸を実装視点で知りたい方

Embedding(埋め込みベクトル)とは何か

結論:テキストの意味を保持した数値ベクトル

Embeddingとは、テキスト(あるいは画像・音声)を意味を保持したまま高次元の数値ベクトルに変換する技術です。「猫」と「ネコ」と「子猫」が空間上で近い位置に配置される、と言うとイメージしやすいはずです。

キーワード一致では「猫」と「ネコ」は別物として扱われます。しかしEmbeddingでは、表記が違っても意味が近ければベクトル空間上で近接します。これが意味検索(セマンティック検索)の基礎になります。

なぜ今、Embeddingを学ぶ必要があるか

RAG(Retrieval-Augmented Generation)が普及し、社内ドキュメントをLLMに読ませる構成が一般化しました。その前段で必ず使われるのがEmbeddingです。RAGを扱うなら避けては通れません。

分類・クラスタリング・レコメンドといったタスクも、Embeddingベースで実装すると一段精度が上がります。従来の機械学習で特徴量を手作りしていた部分が、Embedding APIの呼び出し1行で済むようになりました。

ベクトル空間とコサイン類似度

Embeddingを理解するうえで避けて通れないのが、ベクトル空間と類似度の概念です。ここを押さえると、後段の実装がすっと入ってきます。

次元数とは何か

Embeddingは固定長の数値配列として返ってきます。OpenAIのtext-embedding-3-smallなら1536次元、text-embedding-3-largeなら3072次元です。

「次元」は座標軸の数だと考えると分かりやすいです。1536次元の空間に、テキストの意味が点として配置されているイメージです。次元数が多いほど表現力は増しますが、ストレージ容量と検索コストも比例して増えます。

コサイン類似度で意味の近さを測る

2つのベクトル間の「意味の近さ」を測る代表的な指標がコサイン類似度です。値の範囲は-1〜1で、1に近いほど意味が近いと判定します。

計算式は(A・B) / (|A| × |B|)で、内積をそれぞれのノルムで割るだけです。ライブラリに頼らずとも、JavaScriptで10行程度で実装できます。

ユークリッド距離との使い分け

類似度の指標にはユークリッド距離もありますが、テキストEmbeddingではコサイン類似度が事実上のデファクトです。OpenAIもVoyage AIも、コサイン類似度を前提に学習されています。

ユークリッド距離はベクトルの長さに影響を受けますが、コサイン類似度は方向だけを見ます。テキストの意味は方向に乗っているため、コサインを使うのが自然です。

主要なEmbedding APIと選び方

Embeddingモデルは選択肢が増えました。商用APIとオープンソースの両方を押さえておくと、要件に合わせて選べます。

商用API:OpenAIとVoyage AI

もっとも普及しているのがOpenAIのEmbedding APIです。text-embedding-3-smallは100万トークンあたり3円程度(約0.02ドル、2026年5月時点)と安価で、精度も実用十分です。日本語の扱いも安定しています。仕様詳細はOpenAI Embeddings ガイドが一次情報です。

精度を上げたい場合はVoyage AIが選択肢に入ります。RAG向けに最適化されたvoyage-3系は、社内ドキュメント検索で体感の精度差が出ます。Anthropic(Claude)公式が連携を推奨しているのも特徴で、詳細はVoyage AI Embeddings ドキュメントで確認できます。

オープンソース:sentence-transformers系

ローカルで動かしたい・APIコストを抑えたいなら、オープンソースモデルが選択肢です。all-MiniLM-L6-v2は384次元と軽量で、PoCに向きます。

精度重視ならmultilingual-e5-largeBGE-M3です。日本語を含む多言語対応で、商用APIに近い精度が出るケースもあります。Hugging Faceから無料でダウンロードできます。

選び方の判断軸

選定の判断軸は次の3点に集約されます。

  • 精度:RAGの検索精度に直結。商用APIのほうが安定する傾向
  • コスト:大量処理ならローカルモデル、軽量利用ならOpenAIで十分
  • データ持ち出し制約:機密データを扱うならローカル一択

最初はOpenAIで試作し、要件が固まってからローカル化を検討する流れが現実的です。最初からローカルでチューニングしようとすると、本筋でない部分に時間を取られます。

Embeddingの仕組み|テキスト→ベクトル変換→類似度計算→検索/分類への活用

実装パターン(最小コード例)

概念を押さえたら、実際にコードで触るのが早道です。OpenAI APIを使った3つの最小例を順に見ていきます。

パターン1:Embedding APIの最小呼び出し

まずはAPIを叩いてベクトルを取得するだけのコードです。

import OpenAI from "openai";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function getEmbedding(text: string): Promise<number[]> {
  const res = await openai.embeddings.create({
    model: "text-embedding-3-small",
    input: text,
  });
  return res.data[0].embedding;
}

const vec = await getEmbedding("猫はかわいい");
console.log(vec.length); // 1536
console.log(vec.slice(0, 5)); // [0.012, -0.034, ...]

返ってくるのは1536個の浮動小数点数の配列です。これを保存・比較することで、検索や分類に使います。

パターン2:2文のコサイン類似度を計算する

次に、2つのテキストの意味的な近さを測ります。コサイン類似度の関数は外部ライブラリ不要で書けます。

function cosineSimilarity(a: number[], b: number[]): number {
  let dot = 0, normA = 0, normB = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    normA += a[i] * a[i];
    normB += b[i] * b[i];
  }
  return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}

const v1 = await getEmbedding("猫はかわいい");
const v2 = await getEmbedding("ネコは愛らしい");
const v3 = await getEmbedding("自動車のエンジン整備");

console.log(cosineSimilarity(v1, v2)); // 0.85前後(高い)
console.log(cosineSimilarity(v1, v3)); // 0.20前後(低い)

表記が違う「猫」と「ネコ」が高い類似度を示し、無関係な文は低くなります。これがキーワード検索では実現できない部分です。

パターン3:簡易セマンティック検索

3つ目は、複数文書の中からクエリに最も近いものを返す検索です。RAGの最小骨格にあたります。

const documents = [
  "Pythonでデータ分析の基礎を学ぶ",
  "TypeScriptで型安全なAPIを実装する",
  "機械学習の評価指標を理解する",
  "Reactでフロントエンドを構築する",
];

// 事前に全文書をベクトル化(実運用ではDBに保存)
const docVectors = await Promise.all(
  documents.map(async (d) => ({ text: d, vec: await getEmbedding(d) }))
);

async function search(query: string, topK = 2) {
  const qVec = await getEmbedding(query);
  return docVectors
    .map((d) => ({ text: d.text, score: cosineSimilarity(qVec, d.vec) }))
    .sort((a, b) => b.score - a.score)
    .slice(0, topK);
}

const results = await search("分類精度の測り方を知りたい");
console.log(results);
// [{ text: "機械学習の評価指標を理解する", score: 0.78 }, ...]

クエリ「分類精度の測り方」に対し、「評価指標を理解する」が上位に来ます。キーワードが一致していなくても意味で引けるのがEmbedding検索の本質です。

パターン4:ローカル埋め込みの選択肢

機密データを外部APIに送れないケースでは、sentence-transformers(Python)や@xenova/transformers(JS)でローカル実行できます。PythonならSentenceTransformer("all-MiniLM-L6-v2").encode(texts)の1行で済みます。

初回はモデルダウンロード(数百MB)が走るため、サーバー環境では事前にキャッシュを準備しておくと安全です。実運用ではONNXやllama.cppでの推論最適化も視野に入ります。

よくある失敗パターン

Embeddingを実装するときに、初学者が踏みやすい落とし穴があります。先回りで知っておくと回り道を減らせます。

失敗1:キーワード一致と意味検索を混同する

「Embeddingを使えば検索精度が上がる」と聞いて飛びつくと、用途を見誤ります。商品名や型番の完全一致検索なら、従来のキーワード検索のほうが速くて正確です。

Embeddingが効くのは、表現の揺れがあるテキストや、概念ベースで引きたいケースです。実務ではキーワード検索とEmbedding検索のハイブリッド(BM25との組み合わせ)が定石になっています。

失敗2:次元数を理解せずモデルを選ぶ

「次元数が多い=高精度」と単純化すると、コストが膨らみます。1536次元のベクトルを100万件保存すれば、それだけで6GB以上のストレージが必要です。

OpenAIのtext-embedding-3系はdimensionsパラメータで次元削減ができます。実用上は512〜1024次元でも精度差が小さいケースが多く、まずは小さい次元から試すのが定石です。

失敗3:チャンク粒度を考えずに長文を1ベクトル化

RAGで長文ドキュメントを扱うとき、1ファイル全体を1ベクトルにすると検索精度が大きく落ちます。意味の異なる複数の話題が1点に圧縮され、どのクエリにも中途半端にしか反応しなくなるからです。

定石は500〜1000トークン程度のチャンクに分割し、それぞれをベクトル化することです。チャンク間に少しオーバーラップ(50〜100トークン)を入れると、境界をまたぐ文脈の取りこぼしが減ります。

このチャンク化戦略は次回扱うRAGの中核トピックです。Embeddingだけ単独で語るのは難しく、検索の使い方とセットで設計するのが現実的です。

もっと深く学ぶなら

独学のステップを踏んだうえで、データ分析・機械学習を体系的に学びたいフェーズに入ったら、スタアカ(スタビジアカデミー)が選択肢になります。Embeddingの背景にある統計・線形代数・評価指標まで一気通貫でカバーします。

  • デメリット:数学・SQLが薄い人には序盤がしんどい
  • メリット:月額固定で長期の学び直しに耐える/評価指標まで踏み込む内容

スタアカ(スタビジアカデミー)の有料プランを確認する

シリーズの位置づけと次回予告

本記事はAI学び直し|エンジニアの実務スキル4階層シリーズの第3回です。第2階層「データ・機械学習基礎」のうち、Embeddingを取り上げました。

前回はコンテキストウィンドウを扱いました。LLMが一度に処理できる量と、それを越えるための分割戦略を整理した回です。今回のEmbeddingと組み合わせると、長文処理の全体像が見えてきます。

次回(5月5日公開予定)は、Embeddingを実用に落とし込むRAG(Retrieval-Augmented Generation)を扱います。チャンク化・ベクトルDB・検索品質の評価まで、実装視点で踏み込みます。

まとめ|Embeddingは意味検索の基礎技術

Embeddingは「テキストを意味を保持した数値ベクトルに変換する」基礎技術です。コサイン類似度で近さを測り、検索・分類・レコメンドに使うのが基本パターンです。

OpenAIのAPIなら数行のコードで触れます。まずはtext-embedding-3-smallで2文の類似度を計算するところから始めると、概念と実装が一気につながります。次元数・モデル選定・チャンク粒度といった実務の判断軸も、手を動かしてはじめて腹落ちします。

明日からの実務で、まず社内のFAQやドキュメント10件をベクトル化し、簡易セマンティック検索を回してみてください。キーワード検索との違いを体感できるはずです。

進展があったらこのブログで共有します。チャンク戦略やベクトルDBの実運用知見についても、できたら定点観測の記事を書いてみたいと考えています。

コメント

タイトルとURLをコピーしました