Skip to content

Embeddings

embeddings 模組提供了用於產生和比較文字與程式碼 Embeddings 的功能性。Embeddings 是捕捉語義的向量表示,可實現高效的相似度比較。

總覽

此模組由兩個主要元件組成:

  1. embeddings-base:Embeddings 的核心介面與資料結構。
  2. embeddings-llm:使用 Ollama 進行本機 Embedding 產生的實作。

快速入門

以下章節包含如何透過以下方式使用 Embeddings 的基本範例:

  • 透過 Ollama 使用本機 Embedding 模型
  • 使用 OpenAI Embedding 模型

本機 Embeddings

若要搭配本機模型使用 Embedding 功能性,您的系統需要安裝並執行 Ollama。 有關安裝與執行指示,請參閱 官方 Ollama GitHub 存儲庫

kotlin
fun main() {
    runBlocking {
        // 建立一個 OllamaClient 執行個體
        val client = OllamaClient()
        // 建立一個 embedder
        val embedder = LLMEmbedder(client, OllamaModels.Embeddings.NOMIC_EMBED_TEXT)
        // 建立 embeddings
        val embedding = embedder.embed("This is the text to embed")
        // 將 embeddings 印出到輸出
        println(embedding)
    }
}

若要使用 Ollama Embedding 模型,請確保具備以下先決條件:

  • 已安裝並執行 Ollama

  • 使用以下指令將 Embedding 模型下載到您的本機電腦:

    bash
    ollama pull <ollama-model-id>

    <ollama-model-id> 替換為特定模型的 Ollama 識別碼。有關可用 Embedding 模型及其識別碼的更多資訊,請參閱 Ollama 模型總覽

Ollama 模型總覽

下表提供了可用 Ollama Embedding 模型的總覽。

模型 IDOllama ID參數維度上下文長度效能權衡
NOMIC_EMBED_TEXTnomic-embed-text137M7688192用於語義搜尋和文字相似度任務的高品質 Embeddings品質與效率之間的平衡
ALL_MINILMall-minilm33M384512推論速度快,對一般文字 Embeddings 具有良好的品質較小的模型尺寸且縮減了上下文長度,但非常高效
MULTILINGUAL_E5zylonai/multilingual-e5-large300M768512在 100 多種語言中表現強勁模型尺寸較大,但提供卓越的多語言能力
BGE_LARGEbge-large335M1024512非常適合英文文字檢索和語義搜尋模型尺寸較大,但提供高品質的 Embeddings
MXBAI_EMBED_LARGEmxbai-embed-large---文字資料的高維度 Embeddings專為建立高維度 Embeddings 而設計

有關這些模型的更多資訊,請參閱 Ollama 的 Embedding Models 部落格文章。

選擇模型

根據您的需求,以下是選擇 Ollama Embedding 模型的一些一般建議:

  • 對於一般文字 Embeddings,請使用 NOMIC_EMBED_TEXT
  • 對於多語言支援,請使用 MULTILINGUAL_E5
  • 追求最高品質(以效能為代價),請使用 BGE_LARGE
  • 追求最高效率(以部分品質為代價),請使用 ALL_MINILM
  • 對於高維度 Embeddings,請使用 MXBAI_EMBED_LARGE

OpenAI embeddings

若要使用 OpenAI Embedding 模型建立 Embeddings,請使用 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)
    // 建立一個 embedder
    val embedder = LLMEmbedder(client, OpenAIModels.Embeddings.TextEmbeddingAda002)
    // 建立 embeddings
    val embedding = embedder.embed(text)
    // 將 embeddings 印出到輸出
    println(embedding)
}

AWS Bedrock embeddings

若要使用 AWS Bedrock Embedding 模型建立 Embeddings,請使用 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()
    )
    // 建立一個 embedder
    val embedder = LLMEmbedder(client, BedrockModels.Embeddings.AmazonTitanEmbedText)
    // 建立 embeddings
    val embedding = embedder.embed(text)
    // 將 embeddings 印出到輸出
    println(embedding)
}

支援的 AWS Bedrock Embedding 模型

供應商模型名稱模型 ID輸入輸出維度上下文長度備註
AmazonTitan Embeddings G1 - Textamazon.titan-embed-text-v1文字Embedding1,5368192支援 25 種以上語言,針對檢索、語義相似度、分群進行優化;搜尋時建議對長文件進行分段。
AmazonTitan Text Embeddings V2amazon.titan-embed-text-v2:0文字Embedding1,0248192高準確度、彈性維度、多語言(100+);較小的維度可節省儲存空間,輸出已正規化。
CohereCohere Embed English v3cohere.embed-english-v3文字Embedding1,0248192領先的英文文字 Embeddings,用於搜尋、檢索和理解文字細微差別。
CohereCohere Embed Multilingual v3cohere.embed-multilingual-v3文字Embedding1,0248192多語言 Embeddings,在跨語言搜尋和語義理解方面處於領先地位。

如需最新的模型支援資訊,請參閱 AWS Bedrock 支援的模型文件

範例

以下範例展示了如何使用 Embeddings 來比較程式碼與文字或其他程式碼片段。

程式碼與文字比較

將程式碼片段與自然語言描述進行比較,以尋找語義匹配:

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"

    // 產生 embeddings
    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")

    // 此程式碼與 description1 的相似度應高於 description2
    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 型別
    // 以不同語言實作相同演算法的兩個版本
    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()

    // 產生 embeddings
    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 文件

有關 Embeddings 的完整 API 參考,請參閱以下模組的參考文件:

  • embeddings-base:提供用於表示與比較文字與程式碼 Embeddings 的核心介面與資料結構。
  • embeddings-llm:包含搭配本機 Embedding 模型運作的實作。