RAG と検索向けのテキスト埋め込み - Python、Ollama、OpenAI 互換 API

RAG エンベッディング - Python、Ollama、OpenAI API。

目次

検索拡張生成 (RAG) を実装されている方に向けて、このセクションではテキスト埋め込み(text embeddings)について平易な言葉で解説します。埋め込みとは何か、検索や検索(リトリバル)にどのように組み込まれるか、そしてOllamallama.cppベースのサーバーが提供するOpenAI 互換の HTTP API を使用して、Pythonから 2 つの一般的なローカル環境を呼び出す方法を説明します。

テキスト埋め込みと検索

Ollama 向けのGoクライアントと SDK の比較については、Go SDKs for Ollama — comparison with examples を参照してください。

テキスト埋め込みとは何ですか?

テキスト埋め込みとは、埋め込みモデルが生成するベクトル(浮動小数点数のリスト)です。このモデルは可変長のテキストを固定次元の空間にマッピングし、意味的に類似したテキストが距離または類似度(多くの場合L2 正規化ベクトルにおける余弦類似度)により近い位置に配置されるようにします。

埋め込みはトークン ID とは異なり、チャット完了(チャット生成)の出力とも異なります。これは検索、クラスタリング、重複排除、そして RAG における検索(リトリバル)のために使用する表現層です。

一般的なユースケース

ユースケース 埋め込みの役割
意味検索 / RAG 検索 クエリとドキュメントチャンクを埋め込み、類似度でランク付けして関連する段落を取得します。
埋め込みモデルによる再ランク付け クエリと各候補を埋め込み、類似度でペアをスコア付けします(埋め込みモデルによる再ランク付け を参照)。
クラスタリングと重複排除 手動でラベル付けすることなく、埋め込み空間内でアイテムをグループ化または重複排除します。
分類スタイルのスコア付け 同じ空間内でテキストをプロトタイプ記述やクラス名と比較します(パターンはモデルによって異なります)。

マルチモーダル設定(画像 - テキストおよび関連アイデア)については、クロスモーダル埋め込み を参照してください。

RAG パイプライン内の埋め込み

典型的なオフラインのパスは以下の通りです:

  1. ドキュメントをチャンク化します(サイズ、オーバーラップ、構造が重要です — RAG におけるチャンキング戦略 を参照)。
  2. 各チャンクを埋め込みます。オプションでメタデータ(ソース ID、セクション、ACL)を保存します。
  3. ベクトルをメモリ上、ライブラリインデックス、またはベクトルデータベースインデックスします(トレードオフについては RAG 用のベクトルストレージ — 比較 を参照)。

クエリ実行時:

  1. ユーザーのクエリを埋め込みます(1 つの短い文字列または小さなバッチ)。
  2. ベクトル検索で上位 k 個の類似チャンクを検索します(オプションでキーワード/ハイブリッド検索も併用)。
  3. 取得されたプレーンテキストチャンクからプロンプトを作成し、チャットモデルを呼び出します。

重要なニュアンス — チャット API での大規模言語モデルは、任意の埋め込みテンソルではなくテキスト(およびツール)を消費します。埋め込みはどのテキストを注入するかを選択するために使用します。「事前計算された埋め込みで LLM にクエリを送る」という表現を目にすることがありますが、実際には埋め込みで検索し、選択されたテキストを LLM に送信することを意味します。

Ollama を使用して埋め込みを取得する(Python)

Ollama は HTTP API を公開しています。埋め込みを取得するには、Ollama ホスト(デフォルトは**http://127.0.0.1:11434)のPOST /api/embedを呼び出します。JSON 本体にはmodel名とinput(文字列または文字列のリスト)が含まれます。レスポンスには、入力と対応したベクトルのリストであるembeddings**が含まれます。

**httpxをインストールします(または同様にrequests**を使用します)。

import httpx

OLLAMA = "http://127.0.0.1:11434"
MODEL = "nomic-embed-text"  # プル済みの埋め込みモデルに置き換えてください

def embed_ollama(texts: list[str]) -> list[list[float]]:
    r = httpx.post(
        f"{OLLAMA}/api/embed",
        json={"model": MODEL, "input": texts},
        timeout=120.0,
    )
    r.raise_for_status()
    data = r.json()
    return data["embeddings"]

if __name__ == "__main__":
    q = "検索拡張生成とは何ですか?"
    chunks = [
        "RAG は検索と生成を組み合わせます。",
        "埋め込みはテキストを類似度検索のためのベクトル空間にマッピングします。",
    ]
    qv = embed_ollama([q])[0]
    doc_vs = embed_ollama(chunks)
    print(len(qv), len(doc_vs), len(doc_vs[0]))

運用上の注意事項

OpenAI 互換サーバーを使用して埋め込みを取得する(Python)

多くのローカルサーバー(一般的なllama.cpp HTTP セットアップを含む)は、POST /v1/embeddingsなどのOpenAI 互換ルートを公開しています。公式の**openaiPython パッケージを使用し、base_urlをサーバーの…/v1**ルートを指すように設定できます。

from openai import OpenAI

# 例 — ホスト、ポート、モデル ID をサーバーの値に置き換えてください
client = OpenAI(
    base_url="http://127.0.0.1:8080/v1",
    api_key="not-needed",  # 多くのローカルサーバーではこれを無視します
)

def embed_openai_compatible(text: str, model: str) -> list[float]:
    r = client.embeddings.create(model=model, input=text)
    return r.data[0].embedding

if __name__ == "__main__":
    v = embed_openai_compatible("hello from llama.cpp", "your-embedding-model-id")
    print(len(v))

なぜ両方のパターンを 1 つのページにまとめるのか? 概念(チャンク化、埋め込み、インデックス作成、クエリ、テキスト検索)は同一ですが、HTTP インターフェースだけが異なります。ワークショップスタイルの 1 つの記事であれば、同じナラティブを 2 つの URL で重複させることを避けることができます。

ベクトルの永続化とクエリ

少なくとも、チャンクごとに 3 つの要素を保存する必要があります — ベクトルテキスト、およびメタデータ(ソース ID、オフセット、ACL)です。クイックプロトタイプの場合、すべてを Python リストに保持し、NumPyまたはscikit-learnを使用して余弦類似度を計算できます。データが成長する場合、ベクトルデータベースまたはライブラリインデックス(FAISS など)を使用します。製品レベルのトレードオフについては、RAG 用のベクトルストレージ — 比較 を参照してください。

概念的なクエリループ:

  1. query_vec = embed(query)
  2. neighbors = index.search(query_vec, k)
  3. context = "\n\n".join(chunk.text for chunk in neighbors)
  4. contextとユーザーの質問をチャットAPI に送信します。

検索後の再ランク付け(Reranking)

再ランク付けモデル(多くの場合クロスエンコーダーまたは 2 つ目のスコアモデル)は、ベクトル検索後に上位候補の順序を再配置できます。このサイトには、埋め込みモデルによる再ランク付けOllama と Qwen3 埋め込みを使用した Go での再ランク付け などのPythonGoの例があります。

関連記事

トピック 記事
完全な RAG アーキテクチャ RAG チュートリアル — アーキテクチャ、実装、プロダクション
埋め込み前のチャンキング RAG におけるチャンキング戦略
ベクトル DB の選択 RAG 用のベクトルストレージ — 比較
Ollama 上の Qwen3 Ollama 上の Qwen3 埋め込みと再ランク付け
クロスモーダル クロスモーダル埋め込み
Ollama CLI & ヒント Ollama チートシート
Go + Ollama Go での Ollama の使用 — SDK 比較

便利なリンク