Skip to content

임베딩 (Embeddings)

embeddings 모듈은 텍스트와 코드의 임베딩을 생성하고 비교하는 기능을 제공합니다. 임베딩은 의미론적 의미를 포착하는 벡터 표현(vector representations)으로, 효율적인 유사도 비교를 가능하게 합니다.

개요 (Overview)

이 모듈은 두 가지 주요 구성 요소로 이루어져 있습니다:

  1. embeddings-base: 임베딩을 위한 핵심 인터페이스 및 데이터 구조.
  2. embeddings-llm: 로컬 임베딩 생성을 위해 Ollama를 사용하는 구현체.

시작하기 (Getting started)

다음 섹션에는 다음과 같은 방식으로 임베딩을 사용하는 기본적인 예제가 포함되어 있습니다:

  • Ollama를 통한 로컬 임베딩 모델 사용
  • OpenAI 임베딩 모델 사용

로컬 임베딩 (Local embeddings)

로컬 모델과 함께 임베딩 기능을 사용하려면 시스템에 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-models-overview)]를 참조하세요.

Ollama 모델 개요 (Ollama models overview)

다음 표는 사용 가능한 Ollama 임베딩 모델에 대한 개요를 제공합니다.

모델 ID (Model ID)Ollama ID파라미터차원컨텍스트 길이성능트레이드오프 (Tradeoffs)
NOMIC_EMBED_TEXTnomic-embed-text137M7688192시맨틱 검색 및 텍스트 유사도 작업을 위한 고품질 임베딩품질과 효율성 사이의 균형
ALL_MINILMall-minilm33M384512일반적인 텍스트 임베딩에 적합한 품질과 빠른 추론모델 크기가 작고 컨텍스트 길이가 짧지만 매우 효율적임
MULTILINGUAL_E5zylonai/multilingual-e5-large300M768512100개 이상의 언어에서 강력한 성능 발휘모델 크기가 더 크지만 뛰어난 다국어 기능 제공
BGE_LARGEbge-large335M1024512영어 텍스트 검색 및 시맨틱 검색에 탁월함모델 크기가 더 크지만 고품질 임베딩 제공
MXBAI_EMBED_LARGEmxbai-embed-large---텍스트 데이터의 고차원 임베딩 생성고차원 임베딩 생성을 위해 설계됨

이 모델들에 대한 자세한 정보는 Ollama의 Embedding Models 블로그 포스트를 참조하세요.

모델 선택하기 (Choosing a model)

요구 사항에 따라 어떤 Ollama 임베딩 모델을 선택할지에 대한 일반적인 팁은 다음과 같습니다:

  • 일반적인 텍스트 임베딩의 경우, NOMIC_EMBED_TEXT를 사용하세요.
  • 다국어 지원이 필요한 경우, MULTILINGUAL_E5를 사용하세요.
  • (성능을 희생하더라도) 품질을 극대화하려면, BGE_LARGE를 사용하세요.
  • (품질을 일부 희생하더라도) 효율성을 극대화하려면, ALL_MINILM을 사용하세요.
  • 고차원 임베딩이 필요한 경우, MXBAI_EMBED_LARGE를 사용하세요.

OpenAI 임베딩 (OpenAI embeddings)

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)
    // 임베더(embedder) 생성
    val embedder = LLMEmbedder(client, OpenAIModels.Embeddings.TextEmbeddingAda002)
    // 임베딩 생성
    val embedding = embedder.embed(text)
    // 출력창에 임베딩 출력
    println(embedding)
}

AWS Bedrock 임베딩 (AWS Bedrock embeddings)

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()
    )
    // 임베더(embedder) 생성
    val embedder = LLMEmbedder(client, BedrockModels.Embeddings.AmazonTitanEmbedText)
    // 임베딩 생성
    val embedding = embedder.embed(text)
    // 출력창에 임베딩 출력
    println(embedding)
}

지원되는 AWS Bedrock 임베딩 모델 (Supported AWS Bedrock embedding models)

제공업체모델 이름모델 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 지원 모델 문서를 참조하세요.

예제 (Examples)

다음 예제는 임베딩을 사용하여 코드를 텍스트 또는 다른 코드 스니펫과 비교하는 방법을 보여줍니다.

코드와 텍스트 비교 (Code-to-text comparison)

코드 스니펫을 자연어 설명과 비교하여 의미론적 일치를 찾습니다:

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'")
    }
}

코드 간 비교 (Code-to-code comparison)

구문(syntax) 차이에 관계없이 의미론적 유사성을 찾기 위해 코드 스니펫을 비교합니다:

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()

    // 임베딩 생성
    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 documentation)

임베딩과 관련된 전체 API 참조는 다음 모듈의 참조 문서를 확인하세요:

  • embeddings-base: 텍스트 및 코드 임베딩을 표현하고 비교하기 위한 핵심 인터페이스 및 데이터 구조를 제공합니다.
  • embeddings-llm: 로컬 임베딩 모델 작업을 위한 구현체를 포함합니다.