Pythonでembedding(ベクトル化)を生成する方法|OpenAI APIとsentence-transformers
embedding(埋め込み)は、文章や単語を「意味の近さ」を測れる数値ベクトルに変換する技術です。検索・分類・レコメンド・RAGなど、テキストを扱う機械学習の土台になります。Pythonでembeddingを作る現実的な選択肢は、クラウドのOpenAI Embedding APIと、ローカルで無料に動くsentence-transformersの2つです。この記事では、APIキーの取得からコード、コサイン類似度の計算、日本語モデルの選び方、料金比較までを実装ベースでまとめます。
まとめ:Pythonでembeddingを作る2つの手段と選び方
結論から言うと、少量〜中量のデータを手早く高精度でベクトル化したいならOpenAI Embedding API(text-embedding-3-smallが既定)、大量処理・オフライン・データを社外に出せない要件ならsentence-transformers(日本語はmultilingual-e5系)を選びます。どちらも数行のコードでベクトルを得られ、得たベクトル同士のコサイン類似度で意味の近さを測る流れは共通です。以下でembeddingの仕組み、ライブラリの使い分け、それぞれの実装手順、類似度計算、代表的な活用先の順に解説します。
embeddingとは:テキストを意味ベクトルに変換する仕組み
embedding(埋め込み表現、エンベディング)とは、単語や文章を数百〜数千次元の実数ベクトルに変換したものです。意味が近いテキストほどベクトル空間上で近い位置に配置されるため、「文字列が一致するか」ではなく「意味が似ているか」でテキストを比較できます。キーワード検索が苦手だった表記ゆれや言い換えに強いのが、ベクトル化(vectorization)の狙いです。
初期の手法である word2vec は単語単位のベクトルでしたが、現在主流のモデルは文脈を踏まえた文(センテンス)単位の埋め込みを返します。「銀行の口座」と「川の土手(bank)」のように同じ綴りでも文脈で意味が変わる語を、文全体の情報から区別できる点が実用上の差になります。次元数はモデルごとに固定で、OpenAIのtext-embedding-3-smallなら1536次元、multilingual-e5-largeなら1024次元です。次元が大きいほど表現力は上がりますが、保存容量と検索コストも増えます。
PythonでembeddingするライブラリとAPIの選び方
「python embedding library」で探す人が最初に迷うのが、どの手段を使うかです。用途で決まるので、代表的な3つを軸で比較します。ライブラリの前にモデルをどう選ぶかは埋め込みモデルとは?仕組みと日本語モデルの選び方・RAG実装での判断基準【2026年版】にまとめました。
| 手段 | 実行環境 | 費用 | 日本語精度 | 向くケース |
|---|---|---|---|---|
| OpenAI Embedding API | クラウド | 従量($0.02〜/1Mトークン) | 高い | 手軽に高精度・少量〜中量 |
| sentence-transformers | ローカル/GPU | 無料(自前の計算資源) | 高い(e5系) | 大量・オフライン・社外送信不可 |
| gensim(word2vec) | ローカル | 無料 | 中(単語単位) | 軽量・単語ベクトルで足りる |
判断の分かれ目はデータ量とデータの機密性です。APIは初期構築が最短でモデル更新も自動追従しますが、大量のテキストを繰り返し埋め込むとトークン課金が積み上がり、テキストを外部に送る前提になります。社内の個人情報や機密文書を扱う、あるいは数百万件を定期的に再計算するなら、GPUを用意してでもローカルのsentence-transformersを選ぶべきです。逆に、プロトタイプや数万件規模で精度を早く確かめたい段階でローカルGPU環境を組むのは過剰投資で、ここではAPIが正解です。word2vecは新規採用の第一候補にはなりませんが、単語の類似語抽出だけが目的なら軽量で十分機能します。
OpenAI Embedding APIでベクトル化する手順
OpenAIのAPIは、APIキーの取得とライブラリのインストールさえ済めば数行で使えます。旧来のopenai.Embedding.createは廃止済みで、現在はOpenAIクライアント経由のclient.embeddings.create()を使います。
APIキーの取得と安全な管理
APIキーはOpenAIのダッシュボード(platform.openai.com)の「API keys」から発行します。発行時に一度だけ表示される文字列を控え、コードに直書きせず環境変数(OPENAI_API_KEY)に入れて読み込むのが基本です。キーが漏れると課金が発生するため、リポジトリへのコミットは避け、漏洩時はダッシュボードから即時失効させます。
pip install openai
from openai import OpenAI
client = OpenAI() # 環境変数 OPENAI_API_KEY を自動で参照
resp = client.embeddings.create(
model="text-embedding-3-small",
input="Pythonでembeddingを生成する",
)
vector = resp.data[0].embedding # 1536次元のfloatリスト
print(len(vector)) # 1536
複数テキストをまとめて埋め込むときはinputにリストを渡すと、1回のリクエストで全件分のベクトルが返り、トークン効率もよくなります。
text-embedding-3-small / large の使い分けと料金
新規実装ではtext-embedding-3-smallを既定にし、精度が足りない場合だけtext-embedding-3-largeに上げます。text-embedding-ada-002はレガシーで、新規採用の理由はほぼありません。
| モデル | 次元 | 料金/1Mトークン | 位置づけ |
|---|---|---|---|
| text-embedding-3-small | 1536 | $0.02 | 既定・大半の用途 |
| text-embedding-3-large | 3072 | $0.13 | 高精度が必要な場合 |
| text-embedding-ada-002 | 1536 | $0.10 | 2024年の3系登場以降レガシー |
料金は入力トークンのみの課金で、出力側のコストはありません。価格は改定されることがあるため、最新の単価は公式の料金ページで確認してください。
dimensionsパラメータによる次元削減
text-embedding-3系はMatryoshka表現に対応し、dimensionsパラメータで出力次元を256や512などに短縮できます。次元を減らすとベクトルDBの保存容量と検索コストを抑えられ、意味表現の劣化は緩やかです。ストレージや検索速度がボトルネックのときに有効です。
resp = client.embeddings.create(
model="text-embedding-3-large",
input="次元を256に削減する例",
dimensions=256,
)
print(len(resp.data[0].embedding)) # 256
sentence-transformersによるローカル・無料のembedding生成
APIを使わずローカルで完結させるなら、Hugging Faceの学習済みモデルを扱うsentence-transformers(SBERT)が実務で広く使われます。モデルをダウンロードすれば以降はオフラインで動き、トークン課金もありません。
pip install sentence-transformers
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("intfloat/multilingual-e5-large")
texts = [
"query: Pythonでembeddingを作る方法",
"passage: sentence-transformersはローカルで動くライブラリです",
]
embeddings = model.encode(texts, normalize_embeddings=True)
print(embeddings.shape) # (2, 1024)
日本語を含む多言語ならintfloat/multilingual-e5-large(1024次元)が扱いやすく、軽量にしたいならmultilingual-e5-base(768次元)やsmall(384次元)を選びます。e5系モデルは接頭辞が精度を左右するのが実務のハマりどころで、検索クエリにはquery:、検索対象の文書にはpassage:を必ず付けます。付け忘れると類似度が体感で落ちるため、最初に確認すべきポイントです。normalize_embeddings=Trueでベクトルを正規化しておくと、後述の類似度計算が内積だけで済みます。
生成したembeddingのコサイン類似度計算
embeddingを作る目的の多くは「2つのテキストがどれだけ意味的に近いか」を測ることです。ベクトル間の近さはコサイン類似度(-1〜1、1に近いほど類似)で求めます。NumPyがあれば数行で書けます。
import numpy as np
def cosine_similarity(a, b):
a, b = np.array(a), np.array(b)
return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
sim = cosine_similarity(vector_a, vector_b)
print(sim) # 例: 0.87
ベクトルを事前に正規化していれば、分母のノルム計算は不要でnp.dot(a, b)だけで同じ値になります。大量の文書から類似上位を探す段階になると、この総当たり計算は重くなるため、次に挙げるベクトルデータベースへ移行します。
embeddingの主な使いどころ:意味検索・RAG・分類
ベクトル化したテキストは、そのまま意味検索・分類・レコメンドなどの入力になります。代表的な使い道を用途別に整理します。
意味検索(セマンティック検索)とRAG
クエリと文書をembeddingに変換し、コサイン類似度が高い順に並べれば、キーワード一致に頼らない意味検索が作れます。文書数が増えたら、ベクトルを保存して近似最近傍探索を行うベクトルデータベースとグラフデータベースの違いを押さえたうえで専用DBを導入します。生成AIに検索結果を渡して回答させるRAGでは、キーワード検索とベクトル検索を組み合わせ、順位を統合するRRF(Reciprocal Rank Fusion)で精度を底上げする構成が王道です。Azure環境ならAzure CosmosDB for NoSQLにおけるベクトル検索のようにDB内で完結させる選択肢もあります。Google CloudではFirestoreのベクトル検索(KNN)実装手順が同じ役割を担い、生成したベクトルをそのままFirestoreのベクトル型フィールドへ保存できます。
分類・クラスタリング
ラベルごとの代表文をembeddingにしておき、入力文と最も近いラベルへ割り当てれば、少ない実装で分類器になります。教師ラベルが無い場合でも、ベクトルをk-meansなどでクラスタリングすれば、問い合わせ内容やレビューを意味の近いグループへ自動的にまとめられます。大量のembeddingを本番でAPI提供する規模になれば、推論基盤の設計としてLLM Servingとは?で触れるサービング技術が必要になります。
よくある質問
embeddingとは何ですか?
テキストや単語を「意味の近さ」を計算できる数値ベクトルに変換したものです。意味が近い文ほどベクトル空間で近くに配置されるため、表記ゆれや言い換えに強い意味検索・分類が実現できます。
OpenAIのembeddingは無料で使えますか?
OpenAI Embedding APIは従量課金で、text-embedding-3-smallが入力100万トークンあたり$0.02です。完全に無料でembeddingを作りたい場合は、ローカルで動くsentence-transformersを使います。
日本語のembeddingはどのモデルがよいですか?
APIならtext-embedding-3-small/largeが日本語でも高精度です。ローカルならintfloat/multilingual-e5-largeなど多言語e5系が扱いやすく、検索用途ではquery:/passage:の接頭辞を付けて使います。
embeddingの次元数はどう決めればよいですか?
基本はモデル既定の次元(3-smallなら1536)で問題ありません。保存容量や検索速度が課題なら、text-embedding-3系のdimensionsパラメータで256や512へ削減して調整します。
word2vecとの違いは何ですか?
word2vecは単語単位の固定ベクトルで、文脈で意味が変わる語を区別できません。現在主流のembeddingモデルは文全体の文脈を踏まえた文単位のベクトルを返すため、実タスクでの精度が高くなります。