OllamaのEmbedding APIでテキスト埋め込みを取得する方法|nomic-embed-textとmxbai-embed-largeで類似検索をローカル環境に構築する手順

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)ローカルLLM > OllamaのEmbedding APIでテキスト埋め込みを取得する方法|nomic-embed-textとmxbai-embed-largeで類似検索をローカル環境に構築する手順
「OllamaのAPIにテキストを送ったら数字の配列が返ってきた。これは何に使えるのか」
「社内文書をローカルで意味検索したいが、クラウドのEmbedding APIにデータを送るのは情報漏洩リスクが気になる」

そんな課題を抱えるインフラエンジニアや情シス担当者は多いはずです。この記事では、OllamaのEmbedding APIを使ってテキストをベクトル化し、ローカル環境で意味的な類似検索を実現する手順を解説します。
curlによるAPIの基本的な呼び出し方から、PythonでのEmbedding取得、SQLiteを使った簡易ベクトルDB構築まで、実務で使える形でまとめました。

この記事のポイント

・OllamaのEmbedding APIは/api/embedエンドポイントでテキストをベクトル化できる
・nomic-embed-text(768次元)またはmxbai-embed-large(1024次元)をモデルとして使う
・取得したベクトルとコサイン類似度でキーワード一致なしの意味検索が実現できる
・SQLiteに埋め込みを保存することで数千件規模の社内文書検索DBを低コストで構築できる


OllamaのEmbedding APIでテキスト埋め込みを取得する方法|nomic-embed-textとmxbai-embed-largeで類似検索をローカル環境に構築する手順

「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

OllamaのEmbedding APIとは何か|テキスト生成APIとの違い

Ollamaは「テキストを生成するAPI」と「テキストをベクトル化するAPI」の2種類を提供しています。チャット・テキスト生成に使う/api/chat/api/generateとは別に、Embedding専用のエンドポイント/api/embedがあります。

Embedding APIは、入力されたテキストを「数値の配列(ベクトル)」として出力します。このベクトルはテキストの意味を多次元の数値空間で表現したもので、意味が近いテキスト同士は空間的にも近い位置に配置される性質があります。

主な活用場面は3つです。

意味的な類似検索:キーワードが一致しなくても意味が近い文書を探す
RAGの前処理:社内ドキュメントをベクトル化して質問応答システムに活用する
テキスト分類・クラスタリング:問い合わせ内容を自動カテゴリ分けする

クラウドのEmbedding API(OpenAIのtext-embedding-3-smallなど)はトークン数に応じて課金されます。Ollamaをローカルで動かせば、同じ処理をコストゼロで実行できます。機密性の高い社内文書を外部サーバーに送らずに処理できる点も実務上の大きなメリットです。
(Ollamaのサーバー自体のセットアップが済んでいない場合は、まずUbuntu ServerへのローカルLLM構築手順を参照してください)

Embeddingモデルをインストールする手順

テキスト生成用のモデル(Llama3.3など)とEmbedding専用モデルは別物です。Embedding専用モデルはテキストを出力せず、ベクトルを返すことに特化した軽量モデルです。

Ollamaで主に使われるEmbeddingモデルは以下の2つです。

nomic-embed-text:約274MB、768次元。速度重視。日本語を含む多言語テキストに対応
mxbai-embed-large:約669MB、1024次元。英語テキストの精度が高い

1. nomic-embed-textをpullする

# nomic-embed-text をインストールする $ ollama pull nomic-embed-text pulling manifest pulling 970aa74c0a90... 274 MB / 274 MB ████████████ 100% verifying sha256 digest writing manifest success # インストール済みモデルを確認する $ ollama list NAME ID SIZE MODIFIED nomic-embed-text:latest 0a109f422b47 274 MB 10 seconds ago

精度重視の場合はollama pull mxbai-embed-largeでもインストールできます。どちらを選ぶか迷う場合は、まずnomic-embed-textで試し、精度が不十分であればmxbai-embed-largeに切り替える方法が現実的です。

2. Ollamaサービスの起動を確認する

# Ollamaサービスの状態を確認する $ systemctl status ollama ollama.service - Ollama Service Loaded: loaded (/etc/systemd/system/ollama.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2026-07-05 09:00:00 JST; 3h 20min ago Main PID: 1234 (ollama) # APIが応答するか確認する $ curl -s http://localhost:11434/api/version {"version":"0.9.0"}

Active: active (running)であれば、次のステップへ進めます。

curlでEmbedding APIを呼び出す基本手順

OllamaのEmbedding APIは2種類のエンドポイントがあります。Ollama 0.3.0以降では/api/embedが推奨です(旧エンドポイント/api/embeddingsも引き続き動作しますが、新規実装では新しい方を使ってください)。

1. 単一テキストのベクトル化

# /api/embed エンドポイントで単一テキストをベクトル化する $ curl http://localhost:11434/api/embed \ -X POST \ -H "Content-Type: application/json" \ -d '{"model": "nomic-embed-text", "input": "LinuxのcronジョブがPermission deniedで失敗する"}'

レスポンスは以下のようなJSON形式で返ってきます。

{ "model": "nomic-embed-text", "embeddings": [ [0.12341234, -0.56785678, 0.90120012, -0.34563456, 0.78907890, ...] ], "total_duration": 14143917, "load_duration": 1019200, "prompt_eval_count": 12 }

embeddingsフィールドに768次元の浮動小数点配列が入っています。テキストの生成結果は含まれず、数値だけが返ってきます。この数値列がテキストの意味をエンコードしたベクトルです。

2. 複数テキストのバッチ処理

inputフィールドに配列を渡すと、複数のテキストをまとめてベクトル化できます。ドキュメントを一括登録する際に使います。

# 複数テキストを一度にベクトル化する(バッチ処理) $ curl http://localhost:11434/api/embed \ -X POST \ -H "Content-Type: application/json" \ -d '{ "model": "nomic-embed-text", "input": [ "LinuxのcronジョブがPermission deniedで失敗する", "SSH接続がタイムアウトする問題の対処法", "NFSマウントが自動的に切断される原因" ] }'

レスポンスのembeddingsに、送ったテキスト数分のベクトル配列が返ってきます。curlで動作を確認できたら、次はPythonから呼び出す実装に移ります。

PythonでOllamaのEmbeddingを取得する実装手順

curlで動作が確認できたら、Pythonで埋め込みを取得する実装に移ります。2通りの方法があります。

1. ollama Pythonライブラリを使う方法(推奨)

# ollama Pythonライブラリとnumpyをインストールする $ pip install ollama numpy

import ollama # 単一テキストのEmbeddingを取得する response = ollama.embed( model='nomic-embed-text', input='LinuxのcronジョブがPermission deniedで失敗する' ) vector = response['embeddings'][0] print(f"次元数: {len(vector)}") print(f"先頭5要素: {vector[:5]}") # 出力例 # 次元数: 768 # 先頭5要素: [0.12341234, -0.56785678, 0.90120012, -0.34563456, 0.78907890]

2. requestsライブラリで直接呼び出す方法

ollama Pythonライブラリが使えない環境や、既存の社内スクリプトにOllamaを組み込む場合はrequestsを使います。

import requests def get_embedding(text, model='nomic-embed-text', host='http://localhost:11434'): """テキストをベクトルに変換して返す""" response = requests.post( f"{host}/api/embed", json={"model": model, "input": text} ) response.raise_for_status() return response.json()['embeddings'][0] # 使い方 vec = get_embedding("SSH接続がタイムアウトする問題") print(f"次元数: {len(vec)}") # 768

どちらの方法でも同じベクトルが返ってきます。実装コードの動作確認が取れたら、取得したベクトルを使って類似度計算に進みます。

コサイン類似度でテキストの意味的な近さを計算する方法

ベクトルが取得できたら、次はベクトル間の距離を計算してテキストの類似度を測ります。最もよく使われる指標が「コサイン類似度」です。値が1に近いほど意味が近く、0に近いほど意味が遠いです。

1. numpyでコサイン類似度を実装する

import numpy as np import ollama def get_embedding(text, model='nomic-embed-text'): response = ollama.embed(model=model, input=text) return np.array(response['embeddings'][0]) def cosine_similarity(vec_a, vec_b): """コサイン類似度を計算する(値域: -1~1)""" return float(np.dot(vec_a, vec_b) / (np.linalg.norm(vec_a) * np.linalg.norm(vec_b)))

2. 類似文書検索の動作確認

# 検索クエリと候補ドキュメント query = "SSHが途中で切れてしまう" docs = [ "SSH接続が切断される場合はClientAliveIntervalを設定してください", "cronジョブが実行されない場合はPATH環境変数を確認してください", "SSHのキープアライブを設定してセッションを維持する方法", "NFSマウントのタイムアウトエラーを解消する手順", ] query_vec = get_embedding(query) results = [] for doc in docs: doc_vec = get_embedding(doc) score = cosine_similarity(query_vec, doc_vec) results.append((score, doc)) results.sort(reverse=True) for score, text in results: print(f"{score:.4f} {text}")

0.9187 SSHのキープアライブを設定してセッションを維持する方法 0.8834 SSH接続が切断される場合はClientAliveIntervalを設定してください 0.4012 NFSマウントのタイムアウトエラーを解消する手順 0.3756 cronジョブが実行されない場合はPATH環境変数を確認してください

「SSHが途中で切れてしまう」というクエリに対して、「キープアライブ」の記事が最も高スコアで返ってきています。キーワードが一致していなくても、意味が近いドキュメントを上位に持ってくる。これがEmbeddingの実力です。

SQLiteにベクトルを保存して社内文書の検索DBを構築する手順

実務では、社内ドキュメントをあらかじめベクトル化して保存しておき、検索時に類似度を計算する形が基本です。ここではSQLiteとPythonで簡易なベクトルDBを構築します。

1. ドキュメントのベクトル化と保存

import sqlite3 import json import numpy as np import ollama # DBの初期化 conn = sqlite3.connect('knowledge_base.db') cursor = conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS documents ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL, model TEXT NOT NULL, embedding TEXT NOT NULL ) ''') conn.commit() def store_document(title, content, model='nomic-embed-text'): """ドキュメントをベクトル化してDBに保存する""" response = ollama.embed(model=model, input=content) vec = response['embeddings'][0] cursor.execute( 'INSERT INTO documents (title, content, model, embedding) VALUES (?, ?, ?, ?)', (title, content, model, json.dumps(vec)) ) conn.commit() print(f"保存完了: {title}") # 社内FAQの例 faq_entries = [ ("SSH切断対処", "SSH接続が切断される場合はsshd_configのClientAliveIntervalを30に設定してください"), ("cronPATH問題", "cronジョブが動かない場合はcrontabの先頭でPATH=/usr/local/bin:/usr/binを設定してください"), ("NFSタイムアウト", "NFSマウントがタイムアウトする場合はmountオプションのtimeoとretransを調整してください"), ("Apache起動失敗", "Apacheが起動しない場合はhttpd -tで設定ファイルの構文チェックを実行してください"), ("ディスク容量不足", "ディスクが満杯の場合はdu -sh /* で使用量の多いディレクトリを特定してください"), ] for title, content in faq_entries: store_document(title, content)

2. 類似文書の検索

def search_similar(query, top_k=3, model='nomic-embed-text'): """クエリに意味的に近いドキュメントをスコア順で返す""" response = ollama.embed(model=model, input=query) query_vec = np.array(response['embeddings'][0]) cursor.execute( 'SELECT title, content, embedding FROM documents WHERE model = ?', (model,) ) rows = cursor.fetchall() results = [] for title, content, emb_json in rows: doc_vec = np.array(json.loads(emb_json)) score = float(np.dot(query_vec, doc_vec) / ( np.linalg.norm(query_vec) * np.linalg.norm(doc_vec) )) results.append((score, title, content)) results.sort(reverse=True) return results[:top_k] # 検索テスト results = search_similar("SSHがしばらくすると切れる") for score, title, content in results: print(f"スコア {score:.4f} [{title}]") print(f" {content}") print()

スコア 0.9134 [SSH切断対処] SSH接続が切断される場合はsshd_configのClientAliveIntervalを30に設定してください スコア 0.5201 [NFSタイムアウト] NFSマウントがタイムアウトする場合はmountオプションのtimeoとretransを調整してください スコア 0.4103 [cronPATH問題] cronジョブが動かない場合はcrontabの先頭でPATH=/usr/local/bin:/usr/binを設定してください

文書数が数百件を超える規模では、ChromaDBやLanceDBなど専用のベクトルDBへの移行を検討してください。SQLiteはデータが数千件程度までの小規模な用途には十分実用的です。SQLiteはサーバー不要で導入が簡単なため、まず動作確認用として使い始めるのに向いています。

本番運用で注意すべきトラブルと対処法

Embedding APIを実運用に組み込む際、現場でよく遭遇する問題と対処法をまとめます。

モデルの初回ロードによるレイテンシ問題

Ollamaはモデルを初回呼び出し時にメモリにロードします。nomic-embed-textは軽量ですが、初回リクエストだけ1秒以上かかる場合があります。サービス起動後にwarm-upリクエストを1回送っておくことで、実際のリクエストを安定して処理できます。

# サービス起動後のウォームアップリクエスト例 $ curl -s http://localhost:11434/api/embed \ -X POST \ -H "Content-Type: application/json" \ -d '{"model": "nomic-embed-text", "input": "warmup"}' > /dev/null \ && echo "ウォームアップ完了"

systemdのExecStartPostディレクティブを使ってOllama起動直後に自動実行する方法もあります。

バッチサイズが大きすぎる場合のタイムアウト

一度に送るテキスト数が多すぎると処理が遅くなり、クライアント側のタイムアウトに引っかかる場合があります。1バッチあたりのテキスト数を10件程度に分割して送る実装が安全です。

def embed_in_batches(texts, batch_size=10, model='nomic-embed-text'): """テキストリストをバッチ分割してEmbeddingを取得する""" all_embeddings = [] for i in range(0, len(texts), batch_size): batch = texts[i:i + batch_size] response = ollama.embed(model=model, input=batch) all_embeddings.extend(response['embeddings']) print(f"進捗: {min(i + batch_size, len(texts))}/{len(texts)}件") return all_embeddings # 使い方(100件のテキストを10件ずつ処理) embeddings = embed_in_batches(large_text_list) print(f"取得完了: {len(embeddings)}件")

モデルの次元数不一致によるエラー

nomic-embed-text(768次元)とmxbai-embed-large(1024次元)のベクトルを同じDBに混在させると、コサイン類似度の計算で次元数不一致エラーが発生します。DBのmodel列を必ず記録し、検索時は同一モデルのベクトルだけを対象にすることが鉄則です。モデルを切り替える場合はDBの全データを再ベクトル化してください。

どのEmbeddingモデルを選ぶかは、まず処理速度と精度のトレードオフで決めます。日本語テキストが多い社内環境ではnomic-embed-textから試すことを推奨します。モデル選定の詳細はローカルLLMのモデル比較手順も参考にしてください。

クラウドAIの利用制限がある環境でのローカルLLM全体の導入判断については、社内ChatGPT禁止時のローカルLLM活用も合わせて読むと判断軸が整います。

本記事のまとめ

OllamaのEmbedding APIを使うと、テキストをベクトル化してローカル環境で意味的な類似検索を実現できます。クラウドAPIへのデータ送信が不要なため、機密情報を含む社内文書の処理に適しています。

やりたいこと コマンド・方法
Embeddingモデルをインストールする ollama pull nomic-embed-text
curlでベクトルを取得する curl http://localhost:11434/api/embed -X POST -H "Content-Type: application/json" -d '{"model":"nomic-embed-text","input":"テキスト"}'
Pythonでベクトルを取得する ollama.embed(model='nomic-embed-text', input='テキスト')
コサイン類似度を計算する np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
SQLiteにベクトルを保存する json.dumps(vec)でTEXT型カラムに保存する
nomic-embed-textの次元数 768次元
mxbai-embed-largeの次元数 1024次元

ローカルEmbeddingと類似検索を2日間のハンズオンで体験する

OllamaのEmbedding APIやRAGシステムの構築を、設定から動作確認まで手を動かして習得したい方向けに、「ローカルAIマスターセミナー」を開催しています。
少人数(最大8名)ZOOMハンズオン形式で実施しています。

>> ローカルAIマスターセミナーの詳細を確認する
ローカルLLMの構築・運用に関する関連記事もあわせて参考にしてください。

Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。