Embedding(埋め込み)とは?意味の近さを数値で測る仕組み
Embedding(埋め込み)とは、文章を数値のベクトルに変換して、意味の近さを計算できるようにする技術です。
「解約したい」と「サービスをやめる方法」は、共通する単語がほぼありません。キーワード検索では結びつきませんが、埋め込みならベクトルが近いので拾えます。これがRAGや意味検索の土台になっています。
仕組み
埋め込みモデルに文章を渡すと、決まった長さの数値の配列が返ります。
"解約したい" → [0.021, -0.118, 0.077, ... ] (例: 768個の数値)
"サービスをやめる方法" → [0.019, -0.121, 0.081, ... ] ← 近い
"今日の天気は?" → [-0.204, 0.331, -0.015, ... ] ← 遠い
この配列をベクトルと呼び、近さはコサイン類似度で測ります。2つのベクトルの向きがどれだけ揃っているかを −1〜1 の数値で表すもので、1に近いほど意味が似ています。
大事なのは、この数値そのものに意味はないということです。1番目の数値が何を表すのかは誰にも分かりません。意味を持つのはベクトル同士の距離だけです。
次元数
ベクトルの長さを次元数と呼びます。384、768、1024、1536あたりが一般的です。
| 次元が少ない | 次元が多い | |
|---|---|---|
| 精度 | やや落ちる | 高い |
| 保存容量 | 小さい | 大きい |
| 検索速度 | 速い | 遅い |
多ければ良いというものではありません。 100万チャンクを1536次元で持つと、保存も検索も相応に重くなります。近年のモデルには次元数を後から削る機能を持つものもあり、精度と容量を天秤にかけられます。
まずは中間のあたりから始めて、精度が足りなければ上げるのが実務的です。
チャンク分割が精度を決める
実装で最も効くのがここです。埋め込みは渡した単位でベクトルになるので、切り方がそのまま検索の粒度になります。
細かすぎる場合 — 「同社はこれを2026年に開始した」というチャンクだけを取り出しても、「同社」も「これ」も分かりません。文脈が失われます。
大きすぎる場合 — 1万字の章を1つのベクトルにすると、その中の1文だけが関連していても、ベクトル全体は「章全体の平均的な意味」を表してしまい、狙った箇所が拾えません。
実務的には、
- 見出しや段落の切れ目で切る — 文の途中で切らない
- 数百〜千数百字を目安にする
- 前後を少し重ねる(オーバーラップ)— 境界に跨がる情報を拾えるようにする
- 見出しをチャンクの先頭に付ける — 「同社」が誰か分かるようになります
検索精度が出ないとき、犯人はたいてい埋め込みモデルではなくチャンク分割です。モデルを変える前に切り方を見直してください。
途中でモデルを変えられない
見落とされがちな制約です。埋め込みモデルを変えたら、全ての文書を作り直さなければなりません。 別のモデルが作ったベクトルどうしは比較できないからです。
これは実務上、次を意味します。
- 100万チャンクを抱えてからのモデル変更は、100万回の再計算になります
- 検索側と保存側で同じモデル・同じ設定を使う必要があります
- だからこそ、最初に少量で比較してから決める価値があります
生成モデルは model を差し替えるだけで乗り換えられますが、埋め込みモデルはそうはいきません。ここが両者の決定的な違いです。
どこで入手するか
選択肢は3つあります。
1. ローカルで動かす
Ollamaで埋め込みモデルを動かせます。埋め込みは生成に比べて軽い処理なので、ノートPCでも実用的な速度が出ます。
from openai import OpenAI
emb = OpenAI(api_key="ollama", base_url="http://localhost:11434/v1")
r = emb.embeddings.create(model="nomic-embed-text", input="解約したい")
vec = r.data[0].embedding
print(len(vec))
利用可能なモデル名はOllamaのライブラリで確認してください。大量に回すぶん、ローカルが合理的な場面が多い部品です。 費用は電気代だけで、社外にデータが出ません。
2. 埋め込み専業のサービス
高い検索精度が要る場合や、自前で動かしたくない場合の選択肢です。日本語の性能はモデルによって差があるので、自分のデータで比べてから決めてください。
3. 主要プロバイダーのAPI
OpenAIなどが埋め込みAPIを提供しています。生成と同じ契約で済むのが利点です。
FastMetalは埋め込みを提供していません
正直に書きます。FastMetalは埋め込みモデルを提供していません。予定もありません。
理由は市場構造にあります。2026年8月時点で、世界最大のAIゲートウェイであるOpenRouterは396のモデルを扱いながら、埋め込みモデルは1つも提供していません。 これは見落としではなく、ゲートウェイが埋め込みを扱う経済的な理由が薄いということです。
- 埋め込みは単価が桁違いに安く、仲介の手数料は誤差の範囲にしかなりません
- 生成とは課金の仕組みが別で、価格管理の対象だけが増えます
- 大量に使う人はローカルか専業サービスを選びます
役割で分けるのが素直です。 埋め込みはローカルか専業サービス、生成はFastMetal。実際、この組み合わせが実装としても自然です。
from openai import OpenAI
emb = OpenAI(api_key="ollama", base_url="http://localhost:11434/v1")
gen = OpenAI(api_key="<FASTMETAL_API_KEY>", base_url="https://api.fastmetal.ai/v1")
# 検索は手元で(無料・データは外に出ない)
qvec = emb.embeddings.create(model="nomic-embed-text", input=question).data[0].embedding
chunks = search_by_vector(qvec, top_k=5) # pgvector など
# 答えを作るところだけ良いモデルで
resp = gen.chat.completions.create(
model="anthropic-claude-haiku-4-5",
max_tokens=800,
messages=[
{"role": "system", "content": "以下の資料だけを根拠に答えてください。"},
{"role": "user", "content": "\n\n".join(chunks) + f"\n\n質問: {question}"},
],
)
埋め込みは量、生成は質という性質の違いに沿った分担です。
埋め込みは「もう古い」のか
ロングコンテキストのモデルが出たとき、「全部プロンプトに入れればいいので埋め込みは不要になる」という見方が広がりました。そうはなっていません。
資料の量が増えると、全部渡す方式はコストでも精度でも成立しなくなります。実際の数字を並べた比較はRAG vs ロングコンテキストにまとめました。現在の実務的な答えは、検索で絞ってから長いコンテキストで考えさせるハイブリッドです。つまり埋め込みは、置き換えられるどころか前段として残っています。
よくある質問
Q. 埋め込みモデルは途中で変更できますか? できません。別のモデルが作ったベクトルは比較できないため、全文書の作り直しが必要です。規模が大きくなる前に、少量で比較して決めてください。
Q. 次元数は多いほうがいいですか? 必ずしもそうではありません。次元が増えると精度は上がる傾向ですが、保存容量と検索コストも増えます。中間から始めて、精度が足りなければ上げるのが実務的です。
Q. 検索精度が出ません。モデルを変えるべきですか? まずチャンク分割を疑ってください。細かすぎて文脈が失われているか、大きすぎて焦点がぼけているかのどちらかであることが多く、モデル変更は最後の手段です。
Q. FastMetalで埋め込みは使えますか? 提供していません。埋め込みはローカル(Ollama)や専業サービスで作り、生成をFastMetalで行う構成をおすすめします。
まとめ
Embeddingは文章をベクトルに変え、意味の近さを距離として計算できるようにする技術です。実装の勘所はモデル選定よりチャンク分割で、途中でモデルを変えられないという制約があるため最初の比較が重要になります。
FastMetalは埋め込みを提供していませんが、生成側は円建て・プリペイドで使えます。埋め込みは手元、生成はモデルカタログから——という分担で組んでみてください。