Skip to content

エンベデディング (Embeddings)

embeddings モジュールは、テキストやコードのエンベデディング(埋め込み)を生成および比較する機能を提供します。エンベデディングは、意味的な内容を捉えたベクトル表現であり、効率的な類似性の比較を可能にします。

概要

このモジュールは、主に次の 2 つのコンポーネントで構成されています。

  1. embeddings-base: エンベデディングのためのコアインターフェースとデータ構造。
  2. embeddings-llm: ローカルでのエンベデディング生成のために Ollama を使用した実装。

はじめに

以下のセクションでは、エンベデディングを使用する基本的な例を以下の方法で紹介します。

  • Ollama を介したローカルのエンベデディングモデル
  • OpenAI エンベデディングモデルの使用

ローカルエンベデディング

ローカルモデルでエンベデディング機能を使用するには、システムに Ollama がインストールされ、実行されている必要があります。 インストールと実行の手順については、公式の Ollama GitHub リポジトリを参照してください。

kotlin
fun main() {
    runBlocking {
        // OllamaClient インスタンスを作成
        val client = OllamaClient()
        // エンベッダー (embedder) を作成
        val embedder = LLMEmbedder(client, OllamaModels.Embeddings.NOMIC_EMBED_TEXT)
        // エンベデディングを作成
        val embedding = embedder.embed("This is the text to embed")
        // 出力にエンベデディングを表示
        println(embedding)
    }
}

Ollama のエンベデディングモデルを使用するには、以下の前提条件を満たしていることを確認してください。

  • Ollama がインストールされ、実行されていること

  • 以下のコマンドを使用して、ローカルマシンにエンベデディングモデルをダウンロードしていること:

    bash
    ollama pull <ollama-model-id>

    <ollama-model-id> は、特定のモデルの Ollama 識別子に置き換えてください。利用可能なエンベデディングモデルとその識別子の詳細については、Ollama モデルの概要を参照してください。

Ollama モデルの概要

以下の表は、利用可能な Ollama エンベデディングモデルの概要を示しています。

モデル IDOllama IDパラメータ次元数コンテキスト長パフォーマンストレードオフ
NOMIC_EMBED_TEXTnomic-embed-text137M7688192セマンティック検索やテキスト類似性タスク向けの高品質なエンベデディング品質と効率のバランスが良い
ALL_MINILMall-minilm33M384512一般的なテキストエンベデディングにおいて、優れた品質と高速な推論を実現モデルサイズが小さくコンテキスト長は短いが、非常に効率的
MULTILINGUAL_E5zylonai/multilingual-e5-large300M768512100以上の言語で強力なパフォーマンスを発揮モデルサイズは大きいが、優れた多言語対応能力を提供
BGE_LARGEbge-large335M1024512英語のテキスト検索とセマンティック検索に最適モデルサイズは大きいが、高品質なエンベデディングを提供
MXBAI_EMBED_LARGEmxbai-embed-large---テキストデータの高次元エンベデディング高次元エンベデディングの作成用に設計

これらのモデルの詳細については、Ollama の Embedding Models ブログ記事を参照してください。

モデルの選択

要件に応じて、どの Ollama エンベデディングモデルを選択すべきかについての一般的なヒントを以下に示します。

  • 一般的なテキストエンベデディングには、NOMIC_EMBED_TEXT を使用します。
  • 多言語サポートが必要な場合は、MULTILINGUAL_E5 を使用します。
  • (パフォーマンスを犠牲にしても)最高の品質を求める場合は、BGE_LARGE を使用します。
  • (多少の品質を犠牲にしても)最高の効率を求める場合は、ALL_MINILM を使用します。
  • 高次元エンベデディングが必要な場合は、MXBAI_EMBED_LARGE を使用します。

OpenAI エンベデディング

OpenAI エンベデディングモデルを使用してエンベデディングを作成するには、以下の例に示すように OpenAILLMClient インスタンスの embed メソッドを使用します。

kotlin
suspend fun openAIEmbed(text: String) {
    // OPENAI_KEY 環境変数から OpenAI API トークンを取得
    val token = System.getenv("OPENAI_KEY") ?: error("Environment variable OPENAI_KEY is not set")
    // OpenAILLMClient インスタンスを作成
    val client = OpenAILLMClient(token)
    // エンベッダーを作成
    val embedder = LLMEmbedder(client, OpenAIModels.Embeddings.TextEmbeddingAda002)
    // エンベデディングを作成
    val embedding = embedder.embed(text)
    // 出力にエンベデディングを表示
    println(embedding)
}

AWS Bedrock エンベデディング

AWS Bedrock エンベデディングモデルを使用してエンベデディングを作成するには、BedrockLLMClient インスタンスと選択したモデルの embed メソッドを使用します。例:

kotlin
suspend fun bedrockEmbed(text: String) {
    // 環境変数/設定から AWS 認証情報を取得
    val awsAccessKeyId = System.getenv("AWS_ACCESS_KEY_ID") ?: error("AWS_ACCESS_KEY_ID not set")
    val awsSecretAccessKey = System.getenv("AWS_SECRET_ACCESS_KEY") ?: error("AWS_SECRET_ACCESS_KEY not set")
    // (オプション) 一時的な認証情報のための AWS_SESSION_TOKEN
    val awsSessionToken = System.getenv("AWS_SESSION_TOKEN")
    // BedrockLLMClient インスタンスを作成
    val client = BedrockLLMClient(
        identityProvider = StaticCredentialsProvider {
            this.accessKeyId = awsAccessKeyId
            this.secretAccessKey = awsSecretAccessKey
            awsSessionToken?.let { this.sessionToken = it }
        },
        settings = BedrockClientSettings()
    )
    // エンベッダーを作成
    val embedder = LLMEmbedder(client, BedrockModels.Embeddings.AmazonTitanEmbedText)
    // エンベデディングを作成
    val embedding = embedder.embed(text)
    // 出力にエンベデディングを表示
    println(embedding)
}

サポートされている AWS Bedrock エンベデディングモデル

プロバイダーモデル名モデル ID入力出力次元数コンテキスト長備考
AmazonTitan Embeddings G1 - Textamazon.titan-embed-text-v1テキストエンベデディング1,536819225以上の言語に対応。検索、セマンティック類似性、クラスタリングに最適化。検索のために長いドキュメントを分割することを推奨。
AmazonTitan Text Embeddings V2amazon.titan-embed-text-v2:0テキストエンベデディング1,0248192高精度、柔軟な次元数、多言語対応(100以上)。次元数を小さくすることでストレージを節約でき、正規化された出力を提供。
CohereCohere Embed English v3cohere.embed-english-v3テキストエンベデディング1,0248192検索、取得、およびテキストのニュアンス理解のための SOTA(最先端)な英語テキストエンベデディング。
CohereCohere Embed Multilingual v3cohere.embed-multilingual-v3テキストエンベデディング1,0248192多言語エンベデディング。言語を跨いだ検索とセマンティック理解において SOTA。

最新のモデルサポートについては、AWS Bedrock でサポートされているモデルのドキュメントを参照してください。

以下の例は、エンベデディングを使用してコードをテキストや他のコードスニペットと比較する方法を示しています。

コードとテキストの比較

コードスニペットを自然言語の説明と比較して、意味的な一致を見つけます:

kotlin
suspend fun compareCodeToText(embedder: Embedder) { // Embedder 型
    // コードスニペット
    val code = """
        fun factorial(n: Int): Int {
            return if (n <= 1) 1 else n * factorial(n - 1)
        }
    """.trimIndent()

    // テキストによる説明
    val description1 = "A recursive function that calculates the factorial of a number"
    val description2 = "A function that sorts an array of integers"

    // エンベデディングを生成
    val codeEmbedding = embedder.embed(code)
    val desc1Embedding = embedder.embed(description1)
    val desc2Embedding = embedder.embed(description2)

    // 差分を計算(値が小さいほど類似度が高い)
    val diff1 = embedder.diff(codeEmbedding, desc1Embedding)
    val diff2 = embedder.diff(codeEmbedding, desc2Embedding)

    println("Difference between code and description 1: $diff1")
    println("Difference between code and description 2: $diff2")

    // コードは description2 よりも description1 により類似しているはずです
    if (diff1 < diff2) {
        println("The code is more similar to: '$description1'")
    } else {
        println("The code is more similar to: '$description2'")
    }
}

コード間の比較

構文の違いに関係なく、コードスニペットを比較して意味的な類似性を見つけます:

kotlin
suspend fun compareCodeToCode(embedder: Embedder) { // Embedder 型
    // 異なる言語による同じアルゴリズムの 2 つの実装
    val kotlinCode = """
        fun fibonacci(n: Int): Int {
            return if (n <= 1) n else fibonacci(n - 1) + fibonacci(n - 2)
        }
    """.trimIndent()

    val pythonCode = """
        def fibonacci(n):
            if n <= 1:
                return n
            else:
                return fibonacci(n-1) + fibonacci(n-2)
    """.trimIndent()

    val javaCode = """
        public static int bubbleSort(int[] arr) {
            int n = arr.length;
            for (int i = 0; i < n-1; i++) {
                for (int j = 0; j < n-i-1; j++) {
                    if (arr[j] > arr[j+1]) {
                        int temp = arr[j];
                        arr[j] = arr[j+1];
                        arr[j+1] = temp;
                    }
                }
            }
            return arr;
        }
    """.trimIndent()

    // エンベデディングを生成
    val kotlinEmbedding = embedder.embed(kotlinCode)
    val pythonEmbedding = embedder.embed(pythonCode)
    val javaEmbedding = embedder.embed(javaCode)

    // 差分を計算
    val diffKotlinPython = embedder.diff(kotlinEmbedding, pythonEmbedding)
    val diffKotlinJava = embedder.diff(kotlinEmbedding, javaEmbedding)

    println("Difference between Kotlin and Python implementations: $diffKotlinPython")
    println("Difference between Kotlin and Java implementations: $diffKotlinJava")

    // Kotlin と Python の実装の方が類似しているはずです
    if (diffKotlinPython < diffKotlinJava) {
        println("The Kotlin code is more similar to the Python code")
    } else {
        println("The Kotlin code is more similar to the Java code")
    }
}

API ドキュメント

エンベデディングに関連する完全な API リファレンスについては、以下のモジュールのリファレンスドキュメントを参照してください。

  • embeddings-base: テキストおよびコードのエンベデディングを表現および比較するためのコアインターフェースとデータ構造を提供します。
  • embeddings-llm: ローカルのエンベデディングモデルを操作するための実装が含まれています。