การฝัง

Gemini API มีโมเดลการฝังเพื่อสร้างการฝังสำหรับข้อความ รูปภาพ วิดีโอ และเนื้อหาอื่นๆ จากนั้นจะใช้การฝังที่ได้เหล่านี้สำหรับงานต่างๆ เช่น การค้นหาเชิงความหมาย การจัดประเภท และการจัดกลุ่ม ซึ่งจะให้ผลลัพธ์ที่แม่นยำและรับรู้บริบทมากกว่าแนวทางที่อิงตามคีย์เวิร์ด

โมเดลล่าสุดอย่าง gemini-embedding-2 เป็นโมเดลการฝังแบบหลายรูปแบบตัวแรกใน Gemini API โดยจะแมปข้อความ รูปภาพ วิดีโอ เสียง และเอกสารลงในพื้นที่การฝังแบบรวม ซึ่งช่วยให้ค้นหา จัดประเภท และจัดกลุ่มข้ามโมดอลได้ในกว่า 100 ภาษา ดูข้อมูลเพิ่มเติมได้ที่ส่วนการฝังแบบมัลติโมดัล สำหรับกรณีการใช้งานที่มีเฉพาะข้อความ gemini-embedding-001 จะยังคงใช้งานได้

การสร้างระบบ Retrieval Augmented Generation (RAG) เป็นกรณีการใช้งานทั่วไปสำหรับผลิตภัณฑ์ AI Embedding มีบทบาทสำคัญในการปรับปรุงเอาต์พุตของโมเดลอย่างมาก ด้วยความถูกต้องตามข้อเท็จจริง ความสอดคล้อง และความสมบูรณ์ตามบริบทที่ดียิ่งขึ้น หากต้องการใช้โซลูชัน RAG ที่มีการจัดการ เราได้สร้างเครื่องมือค้นหาไฟล์ ซึ่งช่วยให้การทำ RAG จัดการได้ง่ายขึ้นและคุ้มค่ามากขึ้น

การสร้างการฝัง

ใช้embedContent วิธีการต่อไปนี้เพื่อสร้างการฝังข้อความ

Python

from google import genai

client = genai.Client()

result = client.models.embed_content(
        model="gemini-embedding-2",
        contents="What is the meaning of life?"
)

print(result.embeddings)

JavaScript

import { GoogleGenAI } from "@google/genai";

async function main() {

    const ai = new GoogleGenAI({});

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-2',
        contents: 'What is the meaning of life?',
    });

    console.log(response.embeddings);
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

Go

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"

    "google.golang.org/genai"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    contents := []*genai.Content{
        genai.NewContentFromText("What is the meaning of life?", genai.RoleUser),
    }
    result, err := client.Models.EmbedContent(ctx,
        "gemini-embedding-2",
        contents,
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }

    embeddings, err := json.MarshalIndent(result.Embeddings, "", "  ")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(embeddings))
}

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-2:embedContent" \
    -H "Content-Type: application/json" \
    -H "x-goog-api-key: ${GEMINI_API_KEY}" \
    -d '{
        "model": "models/gemini-embedding-2",
        "content": {
        "parts": [{
            "text": "What is the meaning of life?"
        }]
        }
    }'

ระบุประเภทงานเพื่อปรับปรุงประสิทธิภาพ

คุณใช้การฝังสำหรับงานที่หลากหลายได้ ตั้งแต่การจัดประเภทไปจนถึงการค้นหาเอกสาร การระบุประเภทงานที่ถูกต้องจะช่วยเพิ่มประสิทธิภาพการฝังสำหรับ ความสัมพันธ์ที่ต้องการ ซึ่งจะช่วยเพิ่มความแม่นยำและประสิทธิภาพ

ประเภทงานที่มี Embeddings 2

สำหรับงานที่มีเฉพาะข้อความซึ่งมี gemini-embedding-2 เราขอแนะนำอย่างยิ่งให้คุณ เพิ่มวิธีการของงานในพรอมต์ ซึ่งทำได้โดยการจัดรูปแบบ คำค้นหาและเอกสารด้วยคำนำหน้าที่ถูกต้องของงาน

เมื่อสร้างการฝังรายการเดียวตาม อินพุตหลายรูปแบบ โดยทั่วไปเราไม่แนะนำให้เติมคำนำหน้าส่วน ข้อความของอินพุตด้วยวิธีการของงาน ในบางกรณีจะช่วยปรับปรุง ประสิทธิภาพ แต่ในบางกรณีจะลดประสิทธิภาพ

ตารางต่อไปนี้แสดงตัวอย่างวิธีจัดรูปแบบการค้นหาและเอกสารสำหรับ กรณีการใช้งานแบบสมมาตรและอสมมาตรโดยใช้โมเดล gemini-embedding-2

กรณีการใช้งานการดึงข้อมูล (รูปแบบอสมมาตร)

ในกรณีการใช้งานแบบอสมมาตร ให้เพิ่มคำนำหน้างานไปยังคำค้นหาและใช้ โครงสร้างเอกสารกับเนื้อหาที่ต้องการฝังและดึงข้อมูล

กรณีการใช้งาน โครงสร้างการค้นหา โครงสร้างเอกสาร
คำค้นหา task: search result | query: {content} title: {title} | text: {content}
หากไม่มีชื่อ ให้ใช้ title: none
การตอบคำถาม task: question answering | query: {content} title: {title} | text: {content}
การตรวจสอบข้อเท็จจริง task: fact checking | query: {content} title: {title} | text: {content}
การดึงรหัส task: code retrieval | query: {content} title: {title} | text: {content}

ตัวอย่างการใช้งาน

Python

# Generate embedding for a task's query. Use your correct task here:
def prepare_query(query):
    # return f"task: question answering | query: {query}"
    # return f"task: fact checking | query: {query}"
    # return f"task: code retrieval | query: {query}"
    return f"task: search result | query: {query}"

# Generate embedding for document of an asymmetric retrieval task:
def prepare_document(content, title=None):
    if title is None:
        title = "none"
    return f"title: {title} | text: {content}"

Use Case แบบอินพุตเดียว (รูปแบบสมมาตร)

ในกรณีการใช้งานแบบสมมาตร ให้ใช้การจัดรูปแบบเดียวกันสำหรับคำค้นหาและเอกสารในงานเดียวกัน

กรณีการใช้งาน โครงสร้างอินพุต
การจัดประเภท task: classification | query: {content}
การจัดกลุ่ม task: clustering | query: {content}
ความคล้ายคลึงกันเชิงความหมาย task: sentence similarity | query: {content}
อย่าใช้เพื่อการค้นหาหรือการดึงข้อมูล มีไว้สำหรับความคล้ายคลึงกันของข้อความเชิงความหมาย

ตัวอย่างการใช้งาน

Python

# Generate embedding for query & document of your task.
def prepare_query_and_document(content):
    # return f'task: clustering | query: {content}'
    # return f'task: sentence similarity | query: {content}'
    return f'task: classification | query: {content}'

คุณต้องใช้ฟีเจอร์นี้อย่างสม่ำเสมอ เช่น หากฝังเอกสารด้วย f'task: classification | query: {content}' การค้นหาก็ควรฝังตามรูปแบบงานนี้ด้วย

ประเภทงานที่มีการฝัง 1

สำหรับ gemini-embedding-001 คุณระบุ task_type ในเมธอด embedContent ได้ ดูรายการประเภทงานที่รองรับทั้งหมดได้ที่ตารางประเภทงานที่รองรับ

ตัวอย่างต่อไปนี้แสดงวิธีใช้ SEMANTIC_SIMILARITY เพื่อตรวจสอบว่าสตริงข้อความมีความหมายคล้ายกันมากน้อยเพียงใด

Python

from google import genai
from google.genai import types
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

client = genai.Client()

texts = [
    "What is the meaning of life?",
    "What is the purpose of existence?",
    "How do I bake a cake?",
]

result = client.models.embed_content(
    model="gemini-embedding-001",
    contents=texts,
    config=types.EmbedContentConfig(task_type="SEMANTIC_SIMILARITY")
)

# Create a 3x3 table to show the similarity matrix
df = pd.DataFrame(
    cosine_similarity([e.values for e in result.embeddings]),
    index=texts,
    columns=texts,
)

print(df)

JavaScript

import { GoogleGenAI } from "@google/genai";
// npm i compute-cosine-similarity
import * as cosineSimilarity from "compute-cosine-similarity";

async function main() {
    const ai = new GoogleGenAI({});

    const texts = [
        "What is the meaning of life?",
        "What is the purpose of existence?",
        "How do I bake a cake?",
    ];

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-001',
        contents: texts,
        config: { taskType: 'SEMANTIC_SIMILARITY' },
    });

    const embeddings = response.embeddings.map(e => e.values);

    for (let i = 0; i < texts.length; i++) {
        for (let j = i + 1; j < texts.length; j++) {
            const text1 = texts[i];
            const text2 = texts[j];
            const similarity = cosineSimilarity(embeddings[i], embeddings[j]);
            console.log(`Similarity between '${text1}' and '${text2}': ${similarity.toFixed(4)}`);
        }
    }
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

Go

package main

import (
    "context"
    "fmt"
    "log"
    "math"

    "google.golang.org/genai"
)

// cosineSimilarity calculates the similarity between two vectors.
func cosineSimilarity(a, b []float32) (float64, error) {
    if len(a) != len(b) {
        return 0, fmt.Errorf("vectors must have the same length")
    }

    var dotProduct, aMagnitude, bMagnitude float64
    for i := 0; i < len(a); i++ {
        dotProduct += float64(a[i] * b[i])
        aMagnitude += float64(a[i] * a[i])
        bMagnitude += float64(b[i] * b[i])
    }

    if aMagnitude == 0 || bMagnitude == 0 {
        return 0, nil
    }

    return dotProduct / (math.Sqrt(aMagnitude) * math.Sqrt(bMagnitude)), nil
}

func main() {
    ctx := context.Background()
    client, _ := genai.NewClient(ctx, nil)
    defer client.Close()

    texts := []string{
        "What is the meaning of life?",
        "What is the purpose of existence?",
        "How do I bake a cake?",
    }

    var contents []*genai.Content
    for _, text := range texts {
        contents = append(contents, genai.NewContentFromText(text, genai.RoleUser))
    }

    result, _ := client.Models.EmbedContent(ctx,
        "gemini-embedding-001",
        contents,
        &genai.EmbedContentRequest{TaskType: genai.TaskTypeSemanticSimilarity},
    )

    embeddings := result.Embeddings

    for i := 0; i < len(texts); i++ {
        for j := i + 1; j < len(texts); j++ {
            similarity, _ := cosineSimilarity(embeddings[i].Values, embeddings[j].Values)
            fmt.Printf("Similarity between '%s' and '%s': %.4f\n", texts[i], texts[j], similarity)
        }
    }
}

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-001:embedContent" \
    -H "Content-Type: application/json" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -d '{
    "taskType": "SEMANTIC_SIMILARITY",
    "content": {
        "parts": [
        {
            "text": "What is the meaning of life?"
        },
        {
            "text": "How much wood would a woodchuck chuck?"
        },
        {
            "text": "How does the brain work?"
        }
        ]
    }
    }'

ข้อมูลโค้ดจะแสดงให้เห็นว่าข้อความแต่ละส่วนมีความคล้ายคลึงกันมากน้อยเพียงใดเมื่อเรียกใช้

ประเภทงานที่รองรับ

ประเภทงานที่รองรับสำหรับ gemini-embedding-001 มีดังนี้

ประเภทงาน คำอธิบาย ตัวอย่าง
SEMANTIC_SIMILARITY การฝังที่เพิ่มประสิทธิภาพเพื่อประเมินความคล้ายคลึงของข้อความ ระบบการแนะนำ การตรวจหาเนื้อหาที่ซ้ำกัน
การจัดประเภท การฝังที่เพิ่มประสิทธิภาพเพื่อจัดประเภทข้อความตามป้ายกำกับที่ตั้งค่าไว้ล่วงหน้า การวิเคราะห์ความเห็น การตรวจจับสแปม
การจัดกลุ่ม การฝังที่ได้รับการเพิ่มประสิทธิภาพเพื่อจัดกลุ่มข้อความตามความคล้ายคลึงกัน การจัดระเบียบเอกสาร การวิจัยตลาด การตรวจจับความผิดปกติ
RETRIEVAL_DOCUMENT การฝังที่เพิ่มประสิทธิภาพสำหรับการค้นหาเอกสาร จัดทำดัชนีบทความ หนังสือ หรือหน้าเว็บสำหรับการค้นหา
RETRIEVAL_QUERY การฝังที่เพิ่มประสิทธิภาพสําหรับคําค้นหาทั่วไป ใช้ RETRIEVAL_QUERY สำหรับการค้นหา และ RETRIEVAL_DOCUMENT สำหรับเอกสารที่จะดึงข้อมูล โฆษณาการค้นหาที่กำหนดเอง
CODE_RETRIEVAL_QUERY การฝังที่เพิ่มประสิทธิภาพสำหรับการดึงข้อมูลโค้ดบล็อกตามคำค้นหาที่เป็นภาษาธรรมชาติ ใช้ CODE_RETRIEVAL_QUERY สำหรับคำค้นหา และ RETRIEVAL_DOCUMENT สำหรับบล็อกโค้ดที่จะดึงข้อมูล คำแนะนำและการค้นหาโค้ด
QUESTION_ANSWERING การฝังสำหรับคำถามในระบบตอบคำถาม ซึ่งได้รับการเพิ่มประสิทธิภาพเพื่อค้นหาเอกสารที่ตอบคำถาม ใช้ QUESTION_ANSWERING สำหรับคำถาม และ RETRIEVAL_DOCUMENT สำหรับเอกสารที่จะดึงข้อมูล แชทบ็อกซ์
FACT_VERIFICATION การฝังสำหรับข้อความที่ต้องได้รับการยืนยัน ซึ่งได้รับการเพิ่มประสิทธิภาพสำหรับการดึงเอกสารที่มีหลักฐานสนับสนุนหรือหักล้างข้อความ ใช้ FACT_VERIFICATION สำหรับข้อความเป้าหมาย RETRIEVAL_DOCUMENT สำหรับเอกสารที่จะดึงข้อมูล ระบบตรวจสอบข้อเท็จจริงอัตโนมัติ

การควบคุมขนาดการฝัง

ทั้ง gemini-embedding-001 และ gemini-embedding-2 ได้รับการฝึกโดยใช้เทคนิค Matryoshka Representation Learning (MRL) ซึ่งสอนโมเดลให้ เรียนรู้การฝังที่มีมิติข้อมูลสูงซึ่งมีส่วนเริ่มต้น (หรือคำนำหน้า) ที่ เป็นเวอร์ชันที่ง่ายกว่าและมีประโยชน์เช่นกันของข้อมูลเดียวกัน

ใช้พารามิเตอร์ output_dimensionality เพื่อควบคุมขนาดของ เวกเตอร์การฝังเอาต์พุต การเลือกมิติข้อมูลเอาต์พุตที่เล็กลงจะช่วยประหยัด พื้นที่เก็บข้อมูลและเพิ่มประสิทธิภาพการคำนวณสำหรับแอปพลิเคชันดาวน์สตรีม โดยที่คุณภาพไม่ลดลงมากนัก โดยค่าเริ่มต้น โมเดลทั้ง 2 จะแสดงผลการฝังที่มีมิติข้อมูล 3072 แต่คุณสามารถตัดให้มีขนาดเล็กลงได้โดยไม่สูญเสียคุณภาพเพื่อประหยัดพื้นที่เก็บข้อมูล เราขอแนะนำให้ใช้ขนาดเอาต์พุต 768, 1536 หรือ 3072

Python

from google import genai
from google.genai import types

client = genai.Client()

result = client.models.embed_content(
    model="gemini-embedding-2",
    contents="What is the meaning of life?",
    config=types.EmbedContentConfig(output_dimensionality=768)
)

[embedding_obj] = result.embeddings
embedding_length = len(embedding_obj.values)

print(f"Length of embedding: {embedding_length}")

JavaScript

import { GoogleGenAI } from "@google/genai";

async function main() {
    const ai = new GoogleGenAI({});

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-2',
        contents: 'What is the meaning of life?',
        config: { outputDimensionality: 768 },
    });

    const embeddingLength = response.embeddings[0].values.length;
    console.log(`Length of embedding: ${embeddingLength}`);
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

Go

package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
)

func main() {
    ctx := context.Background()
    // The client uses Application Default Credentials.
    // Authenticate with 'gcloud auth application-default login'.
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    contents := []*genai.Content{
        genai.NewContentFromText("What is the meaning of life?", genai.RoleUser),
    }

    result, err := client.Models.EmbedContent(ctx,
        "gemini-embedding-2",
        contents,
        &genai.EmbedContentRequest{OutputDimensionality: 768},
    )
    if err != nil {
        log.Fatal(err)
    }

    embedding := result.Embeddings[0]
    embeddingLength := len(embedding.Values)
    fmt.Printf("Length of embedding: %d\n", embeddingLength)
}

REST

curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-2:embedContent" \
    -H 'Content-Type: application/json' \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -d '{
        "content": {"parts":[{ "text": "What is the meaning of life?"}]},
        "output_dimensionality": 768
    }'

ตัวอย่างเอาต์พุตจากข้อมูลโค้ด

Length of embedding: 768

การดูแลคุณภาพสำหรับขนาดที่เล็กลง

แม้ว่าการฝังที่มีมิติข้อมูล 3072 จะได้รับการทำให้เป็นมาตรฐานเสมอ แต่ Gemini Embedding 2 ก็จะทำให้มิติข้อมูลที่ถูกตัดทอนเป็นมาตรฐานโดยอัตโนมัติเช่นกัน (เช่น 768, 1536) ซึ่งจะช่วยให้มั่นใจได้ว่าระบบจะคำนวณความคล้ายกันเชิงความหมายผ่านทิศทางเวกเตอร์แทนที่จะเป็นขนาด จึงให้ผลลัพธ์ที่แม่นยำยิ่งขึ้นตั้งแต่เริ่มต้น

รุ่นเก่า: หากใช้ gemini-embedding-001 คุณต้องปรับขนาดที่ไม่ใช่ 3072 ด้วยตนเองโดยทำดังนี้

Python

import numpy as np
from numpy.linalg import norm

# Only for embeddings from `gemini-embedding-001`
embedding_values_np = np.array(embedding_obj.values)
normed_embedding = embedding_values_np / np.linalg.norm(embedding_values_np)

print(f"Normed embedding length: {len(normed_embedding)}")
print(f"Norm of normed embedding: {np.linalg.norm(normed_embedding):.6f}") # Should be very close to 1

ตัวอย่างเอาต์พุตจากข้อมูลโค้ดนี้

Normed embedding length: 768
Norm of normed embedding: 1.000000

ตารางต่อไปนี้แสดงคะแนน MTEB ซึ่งเป็นเกณฑ์มาตรฐานที่ใช้กันโดยทั่วไปสำหรับ การฝังสำหรับมิติข้อมูลต่างๆ ผลลัพธ์ที่น่าสังเกตคือ ประสิทธิภาพ ไม่ได้เชื่อมโยงกับขนาดของมิติข้อมูลการฝังอย่างเคร่งครัด โดยมิติข้อมูลที่ต่ำกว่า จะให้คะแนนเทียบเท่ากับมิติข้อมูลที่สูงกว่า

มิติข้อมูล MRL คะแนน MTEB (การฝัง Gemini 001)
2048 68.16
1536 68.17
768 67.99
512 67.55
256 66.19
128 63.31

การฝังแบบหลายรูปแบบ

gemini-embedding-2 โมเดลรองรับอินพุตแบบหลายรูปแบบ ซึ่งช่วยให้คุณ ฝังเนื้อหารูปภาพ วิดีโอ เสียง และเอกสารควบคู่ไปกับข้อความได้ ระบบจะแมปรูปแบบข้อมูลทั้งหมด ลงในพื้นที่ฝังเดียวกัน ซึ่งช่วยให้ค้นหาและ เปรียบเทียบข้ามรูปแบบได้

รูปแบบที่รองรับและขีดจำกัด

ขีดจำกัดโทเค็นอินพุตสูงสุดโดยรวมคือ 8,192 โทเค็น

รูปแบบ ข้อกำหนดและขีดจำกัด
Text รองรับโทเค็นสูงสุด 8,192 รายการ
รูปภาพ สูงสุด 6 รูปภาพต่อคำขอ รูปแบบที่รองรับ ได้แก่ PNG, JPEG
เสียง ระยะเวลาสูงสุด 180 วินาที รูปแบบที่รองรับ: MP3, WAV
วิดีโอ ระยะเวลาสูงสุด 120 วินาที รูปแบบที่รองรับ: MP4, MOV ตัวแปลงรหัสที่รองรับ: H264, H265, AV1, VP9
ระบบจะประมวลผลเฟรมสูงสุด 32 เฟรมต่อวิดีโอ โดยวิดีโอ Shorts (≤32 วินาที) จะสุ่มตัวอย่างที่ 1 FPS ส่วนวิดีโอที่ยาวกว่านั้นจะสุ่มตัวอย่างอย่างสม่ำเสมอเป็น 32 เฟรม ระบบจะไม่ประมวลผลแทร็กเสียงในไฟล์วิดีโอ
เอกสาร (PDF) สูงสุด 1 ไฟล์ต่อคำขอ ไม่เกิน 6 หน้า

การฝังรูปภาพ

ตัวอย่างต่อไปนี้แสดงวิธีฝังรูปภาพโดยใช้ gemini-embedding-2

คุณระบุรูปภาพเป็นข้อมูลแบบอินไลน์หรือเป็นไฟล์ที่อัปโหลดผ่าน Files API ได้

Python

from google import genai
from google.genai import types

with open('example.png', 'rb') as f:
    image_bytes = f.read()

client = genai.Client()

result = client.models.embed_content(
    model='gemini-embedding-2',
    contents=[
        types.Part.from_bytes(
            data=image_bytes,
            mime_type='image/png',
        ),
    ]
)

print(result.embeddings)

JavaScript

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

async function main() {
    const ai = new GoogleGenAI({});

    const imgBase64 = fs.readFileSync("example.png", { encoding: "base64" });

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-2',
        contents: [{
            inlineData: {
                mimeType: 'image/png',
                data: imgBase64,
            },
        }],
    });

    console.log(response.embeddings);
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

REST

IMG_PATH="/path/to/your/image.png"
IMG_BASE64=$(base64 -w0 "${IMG_PATH}")

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-2:embedContent" \
    -H "Content-Type: application/json" \
    -H "x-goog-api-key: ${GEMINI_API_KEY}" \
    -d '{
        "content": {
            "parts": [{
                "inline_data": {
                    "mime_type": "image/png",
                    "data": "'"${IMG_BASE64}"'"
                }
            }]
        }
    }'

การรวมการฝัง

เมื่อทำงานกับเนื้อหาหลายรูปแบบ วิธีที่คุณจัดโครงสร้างอินพุตจะมีผลต่อเอาต์พุตการฝัง ดังนี้

  • หลายส่วน (รวม): การเพิ่มอินพุตหลายรายการลงในพารามิเตอร์ contents โดยตรงจะสร้างการฝังแบบรวม 1 รายการสำหรับอินพุตทั้งหมด
  • ออบเจ็กต์ Content หลายรายการ (แยกกัน): การรวมอินพุตแต่ละรายการไว้ในออบเจ็กต์ Content และการส่งผ่านอินพุตเหล่านั้นในพารามิเตอร์ contents จะส่งคืน การฝังแยกกันสำหรับแต่ละรายการ
  • การแสดงระดับโพสต์: สำหรับออบเจ็กต์ที่ซับซ้อน เช่น โพสต์โซเชียลมีเดีย ที่มีรายการสื่อหลายรายการ เราขอแนะนำให้รวบรวมการฝังแยกกัน (เช่น โดยการหาค่าเฉลี่ย) เพื่อสร้างการแสดงระดับโพสต์ที่สอดคล้องกัน

ตัวอย่างต่อไปนี้แสดงวิธีสร้างการฝังแบบรวมสำหรับข้อความและ อินพุตรูปภาพ เพียงเพิ่มอินพุตหลายรายการลงในพารามิเตอร์ contents ดังนี้

Python

from google import genai
from google.genai import types

client = genai.Client()

with open('dog.png', 'rb') as f:
    image_bytes = f.read()

result = client.models.embed_content(
    model='gemini-embedding-2',
    contents=[
        "An image of a dog",
        types.Part.from_bytes(
            data=image_bytes,
            mime_type='image/png',
        ),
    ]
)

# This produces one embedding
for embedding in result.embeddings:
    print(embedding.values)

JavaScript

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

async function main() {
    const ai = new GoogleGenAI({});

    const imgBase64 = fs.readFileSync("dog.png", { encoding: "base64" });

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-2',
        contents: [
            'An image of a dog',
            {
                inlineData: {
                    mimeType: 'image/png',
                    data: imgBase64,
                },
            },
        ],
    });

    // This produces one embedding
    for (const embedding of response.embeddings) {
        console.log(embedding.values);
    }
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

REST

IMG_PATH="/path/to/your/dog.png"
IMG_BASE64=$(base64 -w0 "${IMG_PATH}")

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-2:embedContent" \
    -H "Content-Type: application/json" \
    -H "x-goog-api-key: ${GEMINI_API_KEY}" \
    -d '{
        "content": {
            "parts": [
                {"text": "An image of a dog"},
                {
                    "inline_data": {
                        "mime_type": "image/png",
                        "data": "'"${IMG_BASE64}"'"
                    }
                }
            ]
        }
    }'

ในทางกลับกัน หากคุณใช้ออบเจ็กต์ Content ภายในพารามิเตอร์ contents ระบบจะแสดงผลการฝังแยกกัน ตัวอย่างนี้สร้างการฝังหลายรายการในการเรียกใช้การฝังครั้งเดียว

Python

from google import genai
from google.genai import types

client = genai.Client()

with open('dog.png', 'rb') as f:
    image_bytes = f.read()

result = client.models.embed_content(
    model="gemini-embedding-2",
    contents=[
        types.Content(parts=[types.Part.from_text(text="task: classification | query: An image of a dog")]),
        types.Content(
            parts=[
                types.Part.from_bytes(
                    data=image_bytes,
                    mime_type="image/png",
                ),
            ]
        ),
    ],
)

# This produces two embeddings
for embedding in result.embeddings:
    print(embedding.values)

JavaScript

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

async function main() {
    const ai = new GoogleGenAI({});

    const imgBase64 = fs.readFileSync("dog.png", { encoding: "base64" });

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-2',
        contents: [
            { parts: [{ text: 'task: classification | query: An image of a dog' }] },
            {
                parts: [{
                    inlineData: {
                        mimeType: 'image/png',
                        data: imgBase64,
                    },
                }],
            },
        ],
    });

    // This produces two embeddings
    for (const embedding of response.embeddings) {
        console.log(embedding.values);
    }
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

REST

IMG_PATH="/path/to/your/dog.png"
IMG_BASE64=$(base64 -w0 "${IMG_PATH}")

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-2:batchEmbedContents" \
    -H "Content-Type: application/json" \
    -H "x-goog-api-key: ${GEMINI_API_KEY}" \
    -d '{
        "requests": [
            {
                "model": "models/gemini-embedding-2",
                "content": {"parts": [{"text": "task: classification | query: An image of a dog"}]}
            },
            {
                "model": "models/gemini-embedding-2",
                "content": {"parts": [{"inline_data": {"mime_type": "image/png", "data": "'"${IMG_BASE64}"'"}}]}
            }
        ]
    }'

การฝังเสียง

ตัวอย่างต่อไปนี้แสดงวิธีฝังไฟล์เสียงโดยใช้ gemini-embedding-2

คุณระบุไฟล์เสียงเป็นข้อมูลแบบอินไลน์หรือเป็นไฟล์ที่อัปโหลดผ่าน Files API ได้

Python

from google import genai
from google.genai import types

with open('example.mp3', 'rb') as f:
    audio_bytes = f.read()

client = genai.Client()

result = client.models.embed_content(
    model='gemini-embedding-2',
    contents=[
        types.Part.from_bytes(
            data=audio_bytes,
            mime_type='audio/mpeg',
        ),
    ]
)

print(result.embeddings)

JavaScript

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

async function main() {
    const ai = new GoogleGenAI({});

    const audioBase64 = fs.readFileSync("example.mp3", { encoding: "base64" });

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-2',
        contents: [{
            inlineData: {
                mimeType: 'audio/mpeg',
                data: audioBase64,
            },
        }],
    });

    console.log(response.embeddings);
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

REST

AUDIO_PATH="/path/to/your/example.mp3"
AUDIO_BASE64=$(base64 -w0 "${AUDIO_PATH}")

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-2:embedContent" \
    -H "Content-Type: application/json" \
    -H "x-goog-api-key: ${GEMINI_API_KEY}" \
    -d '{
        "content": {
            "parts": [{
                "inline_data": {
                    "mime_type": "audio/mpeg",
                    "data": "'"${AUDIO_BASE64}"'"
                }
            }]
        }
    }'

การฝังวิดีโอ

ตัวอย่างต่อไปนี้แสดงวิธีฝังวิดีโอโดยใช้ gemini-embedding-2

คุณระบุวิดีโอเป็นข้อมูลแบบอินไลน์หรือเป็นไฟล์ที่อัปโหลดได้ ผ่าน Files API

Python

from google import genai
from google.genai import types

client = genai.Client()

with open('example.mp4', 'rb') as f:
    video_bytes = f.read()

result = client.models.embed_content(
    model='gemini-embedding-2',
    contents=[
        types.Part.from_bytes(
            data=video_bytes,
            mime_type='video/mp4',
        ),
    ]
)

print(result.embeddings[0].values)

JavaScript

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

async function main() {
    const ai = new GoogleGenAI({});

    const videoBase64 = fs.readFileSync("example.mp4", { encoding: "base64" });

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-2',
        contents: [{
            inlineData: {
                mimeType: 'video/mp4',
                data: videoBase64,
            },
        }],
    });

    console.log(response.embeddings);
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

REST

VIDEO_PATH="/path/to/your/video.mp4"
VIDEO_BASE64=$(base64 -w0 "${VIDEO_PATH}")

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-2:embedContent" \
    -H "Content-Type: application/json" \
    -H "x-goog-api-key: ${GEMINI_API_KEY}" \
    -d '{
        "content": {
            "parts": [{
                "inline_data": {
                    "mime_type": "video/mp4",
                    "data": "'"${VIDEO_BASE64}"'"
                }
            }]
        }
    }'

หากต้องการฝังวิดีโอที่มีความยาวมากกว่า 120 วินาที คุณสามารถแบ่งวิดีโอออกเป็น ส่วนที่ทับซ้อนกันและฝังแต่ละส่วนแยกกันได้

การฝังเอกสาร

คุณฝังเอกสารในรูปแบบ PDF ได้โดยตรง โมเดลจะประมวลผลเนื้อหาภาพและข้อความ ของแต่ละหน้า

คุณระบุ PDF เป็นข้อมูลแบบอินไลน์หรือเป็นไฟล์ที่อัปโหลดผ่าน Files API ได้

วิธีที่โมเดลประมวลผล PDF

เมื่อฝัง PDF โมเดลจะประมวลผลเอกสารโดยใช้ทั้งฟีเจอร์ภาพและข้อความ

  • การแสดงภาพ: โมเดลจะแสดงผลแต่ละหน้าเป็นรูปภาพ ซึ่งใช้โทเค็น 258 โทเค็นต่อหน้า
  • การแยกข้อความ: โมเดลจะแยกข้อความจากเอกสาร สำหรับ PDF เนทีฟ (ซึ่งมีข้อความดิจิทัล) โมเดลจะดึงข้อความโดยตรง สำหรับ PDF ที่สแกน (ซึ่งมีรูปภาพของข้อความ) โมเดลจะเรียกใช้การรู้จำอักขระด้วยภาพ (OCR) โดยอัตโนมัติเพื่อดึงข้อความ

หากต้องการคำนวณจำนวนโทเค็นทั้งหมดสำหรับ PDF ให้เพิ่มโทเค็นภาพ (258 ต่อหน้า) ลงในโทเค็นข้อความ อินพุตต้องอยู่ภายในขีดจำกัดโทเค็น 8,192 รายการของโมเดล (ใช้ร่วมกันในทุกรูปแบบ) ระบบจะตัดอินพุตที่เกินขีดจำกัดนี้โดยไม่แจ้งให้ทราบ

ขีดจำกัดของ PDF

  • ไฟล์ต่อคำขอ: คุณส่งไฟล์ PDF ได้สูงสุด 1 ไฟล์
  • ขีดจํากัดหน้า: คุณส่งได้สูงสุด 6 หน้าต่อไฟล์ เราขอแนะนำอย่างยิ่งให้ใช้ 1 หน้าต่อ PDF เพื่อคุณภาพที่ดีที่สุด

ตัวอย่างต่อไปนี้แสดงวิธีฝัง PDF โดยใช้ gemini-embedding-2

Python

from google import genai
from google.genai import types

with open('example.pdf', 'rb') as f:
    pdf_bytes = f.read()

client = genai.Client()

result = client.models.embed_content(
    model='gemini-embedding-2',
    contents=[
        types.Part.from_bytes(
            data=pdf_bytes,
            mime_type='application/pdf',
        ),
    ]
)

print(result.embeddings)

JavaScript

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

async function main() {
    const ai = new GoogleGenAI({});

    const pdfBase64 = fs.readFileSync("example.pdf", { encoding: "base64" });

    const response = await ai.models.embedContent({
        model: 'gemini-embedding-2',
        contents: [{
            inlineData: {
                mimeType: 'application/pdf',
                data: pdfBase64,
            },
        }],
    });

    console.log(response.embeddings);
}

main();

Java

import com.google.genai.Client;
import com.google.genai.types.EmbedContentResponse;
import java.util.Collections;

Client client = new Client();

EmbedContentResponse response =
    client.models.embedContent("text-embedding-004", "Why is the sky blue?", null);

response.embeddings().ifPresent(list -> {
  for (var emb : list) {
    System.out.println("Embedding values: " + emb.values().orElse(Collections.emptyList()));
  }
});

REST

PDF_PATH="/path/to/your/example.pdf"
PDF_BASE64=$(base64 -w0 "${PDF_PATH}")

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-2:embedContent" \
    -H "Content-Type: application/json" \
    -H "x-goog-api-key: ${GEMINI_API_KEY}" \
    -d '{
        "content": {
            "parts": [{
                "inline_data": {
                    "mime_type": "application/pdf",
                    "data": "'"${PDF_BASE64}"'"
                }
            }]
        }
    }'

กรณีการใช้งาน

การฝังข้อความมีความสําคัญอย่างยิ่งสําหรับกรณีการใช้งาน AI ทั่วไปที่หลากหลาย เช่น

  • การสร้างผลลัพธ์ที่เสริมด้วยการดึงข้อมูล (RAG): การฝังจะช่วยเพิ่มคุณภาพ ของข้อความที่สร้างขึ้นโดยการดึงและรวมข้อมูลที่เกี่ยวข้องเข้ากับ บริบทของโมเดล
  • การดึงข้อมูล: ค้นหาข้อความหรือเอกสารที่มีความหมายคล้ายกันมากที่สุดเมื่อได้รับข้อความนำเข้า

    บทแนะนำการค้นหาเอกสาร

  • การจัดอันดับผลการค้นหาใหม่: จัดลำดับความสำคัญของรายการที่เกี่ยวข้องที่สุดโดยใช้การให้คะแนนความหมายของผลลัพธ์เริ่มต้นเทียบกับคำค้นหา

    บทแนะนำการจัดอันดับใหม่ของการค้นหา

  • การตรวจจับความผิดปกติ: การเปรียบเทียบกลุ่มการฝังจะช่วยระบุ แนวโน้มที่ซ่อนอยู่หรือค่าผิดปกติ

    บทแนะนำการตรวจจับความผิดปกติ

  • การจัดประเภท: จัดหมวดหมู่ข้อความโดยอัตโนมัติตามเนื้อหา เช่น การวิเคราะห์ความเห็นหรือการตรวจจับสแปม

    บทแนะนำการจัดประเภท

  • การจัดกลุ่ม: ทำความเข้าใจความสัมพันธ์ที่ซับซ้อนได้อย่างมีประสิทธิภาพโดยการสร้างคลัสเตอร์ และการแสดงภาพของ Embedding

    บทแนะนำการแสดงภาพการจัดกลุ่ม

การจัดเก็บการฝัง

เมื่อนำการฝังไปใช้ในเวอร์ชันที่ใช้งานจริง คุณมักจะใช้ฐานข้อมูลเวกเตอร์เพื่อจัดเก็บ จัดทำดัชนี และเรียกข้อมูลการฝังที่มีมิติสูงได้อย่างมีประสิทธิภาพ Google Cloud มีบริการข้อมูลที่มีการจัดการซึ่ง ใช้เพื่อวัตถุประสงค์นี้ได้ ซึ่งรวมถึง การค้นหาเวกเตอร์ 2.0 ในแพลตฟอร์มเอเจนต์ Gemini Enterprise BigQuery AlloyDB และ Cloud SQL

บทแนะนำต่อไปนี้แสดงวิธีใช้ฐานข้อมูลเวกเตอร์ของบุคคลที่สามอื่นๆ กับ Gemini Embedding

เวอร์ชันของโมเดล

Gemini Embedding 2

พร็อพเพอร์ตี้ คำอธิบาย
รหัสโมเดล

Gemini API

gemini-embedding-2

ประเภทข้อมูลที่รองรับ

อินพุต

ข้อความ, รูปภาพ, วิดีโอ, เสียง, PDF

เอาต์พุต

การฝังข้อความ

ขีดจำกัดของโทเค็น[*]

ขีดจำกัดโทเค็นอินพุต

8,192

ขนาดมิติข้อมูลเอาต์พุต

ยืดหยุ่น รองรับ: 128 - 3072, แนะนำ: 768, 1536, 3072

เวอร์ชัน
อ่านรายละเอียดเพิ่มเติมได้ในรูปแบบเวอร์ชันของโมเดล
  • เสถียร: gemini-embedding-2
การอัปเดตล่าสุด เมษายน 2026

การฝัง Gemini

พร็อพเพอร์ตี้ คำอธิบาย
รหัสโมเดล

Gemini API

gemini-embedding-001

ประเภทข้อมูลที่รองรับ

อินพุต

ข้อความ

เอาต์พุต

การฝังข้อความ

ขีดจำกัดของโทเค็น[*]

ขีดจำกัดโทเค็นอินพุต

2,048

ขนาดมิติข้อมูลเอาต์พุต

ยืดหยุ่น รองรับ: 128 - 3072, แนะนำ: 768, 1536, 3072

เวอร์ชัน
อ่านรายละเอียดเพิ่มเติมได้ในรูปแบบเวอร์ชันของโมเดล
  • เสถียร: gemini-embedding-001
การอัปเดตล่าสุด มิถุนายน 2025

สำหรับโมเดลการฝังที่เลิกใช้งานแล้ว โปรดไปที่หน้าการเลิกใช้งาน

การย้ายข้อมูลจาก gemini-embedding-001

พื้นที่ฝังระหว่าง gemini-embedding-001 กับ gemini-embedding-2 ใช้ร่วมกันไม่ได้ ซึ่งหมายความว่าคุณไม่สามารถเปรียบเทียบการฝังที่โมเดลหนึ่งสร้างขึ้นกับการฝังที่อีกโมเดลหนึ่งสร้างขึ้นได้โดยตรง หากอัปเกรดเป็น gemini-embedding-2 คุณต้อง ฝังข้อมูลที่มีอยู่ทั้งหมดอีกครั้ง

นอกเหนือจากความไม่เข้ากันแล้ว ยังมีความแตกต่างที่สำคัญอื่นๆ ระหว่าง ทั้ง 2 รุ่น ดังนี้

  • ข้อกำหนดประเภทงาน: เมื่อใช้ gemini-embedding-001 คุณจะระบุประเภทงานโดยใช้พารามิเตอร์ task_type (เช่น SEMANTIC_SIMILARITY, RETRIEVAL_DOCUMENT) เมื่อใช้ gemini-embedding-2 ระบบจะไม่รองรับพารามิเตอร์ task_type แต่คุณควรใส่คำสั่งงาน ลงในพรอมต์โดยตรงสำหรับงานที่เป็นข้อความเท่านั้น ดูรายละเอียดเกี่ยวกับวิธีจัดรูปแบบพรอมต์สำหรับกรณีการใช้งานต่างๆ ได้ที่ ประเภทงานที่มีการฝัง 2

  • การรวมการฝัง: gemini-embedding-001 สร้างการฝังแต่ละรายการ สำหรับแต่ละสตริงในรายการอินพุต ในทางตรงกันข้าม gemini-embedding-2 จะสร้างการฝังแบบรวมรายการเดียวเมื่อมีการระบุอินพุตหลายรายการ (เช่น ข้อความและรูปภาพ) ในคำขอเดียวโดยตรง หากต้องการ สร้างการฝังแยกกันสำหรับอินพุตแต่ละรายการ ให้ห่ออินพุตแต่ละรายการใน Content ออบเจ็กต์ หรือใช้ Batch API ดูข้อมูลเพิ่มเติมได้ที่ การฝังการรวม

  • การปรับให้เป็นมาตรฐาน: หากใช้ output_dimensionality เพื่อขอ Embedding ที่มีมิติน้อยกว่า 3072 มิติ gemini-embedding-2 จะปรับ Embedding ที่ถูกตัดทอนเหล่านี้ให้เป็นมาตรฐาน โดยอัตโนมัติ เมื่อใช้ gemini-embedding-001 คุณ ต้องทําการปรับให้เป็นมาตรฐานด้วยตนเองสําหรับมิติข้อมูลอื่นๆ นอกเหนือจาก 3072 ดูรายละเอียดได้ที่ การรับประกันคุณภาพสำหรับขนาดที่เล็กลง

การฝังแบบกลุ่ม

หากไม่กังวลเรื่องเวลาในการตอบสนอง ให้ลองใช้โมเดล Gemini Embeddings กับ Batch API ซึ่งจะช่วยให้มีอัตราการส่งข้อมูลที่สูงขึ้นมากที่ 50% ของราคาการฝังเริ่มต้น ดูตัวอย่างวิธีเริ่มต้นใช้งานได้ในสูตรการใช้ Batch API

ประกาศเกี่ยวกับการใช้งานอย่างมีความรับผิดชอบ

โมเดลการฝัง Gemini มีไว้เพื่อเปลี่ยนรูปแบบข้อมูลอินพุตให้เป็นการแสดงตัวเลขเท่านั้น ซึ่งแตกต่างจากโมเดล Generative AI ที่สร้างเนื้อหาใหม่ แม้ว่า Google จะมีหน้าที่รับผิดชอบในการจัดหาโมเดลการฝัง ที่แปลงรูปแบบของข้อมูลอินพุตเป็นรูปแบบตัวเลขที่ร้องขอ แต่ผู้ใช้ยังคงมีหน้าที่รับผิดชอบอย่างเต็มที่ต่อข้อมูลที่ป้อนและการฝังที่ได้ การใช้โมเดลการฝังของ Gemini เป็นการยืนยันว่าคุณมีสิทธิ์ที่จำเป็นในเนื้อหาใดๆ ที่คุณอัปโหลด อย่าสร้างเนื้อหาที่ ละเมิดสิทธิในทรัพย์สินทางปัญญาหรือสิทธิด้านความเป็นส่วนตัวของผู้อื่น การใช้บริการนี้เป็นไปตามนโยบายการใช้งานที่ไม่อนุญาตและข้อกำหนดในการให้บริการของ Google

เริ่มสร้างด้วยการฝัง

ดูสมุดบันทึกการเริ่มต้นใช้งานอย่างรวดเร็วของ Embedding เพื่อสำรวจความสามารถของโมเดลและดูวิธีปรับแต่งและแสดงภาพ Embedding