Interfejs Gemini API udostępnia modele wektorów dystrybucyjnych do generowania wektorów dystrybucyjnych tekstu, obrazów, filmów i innych treści. Powstałe w ten sposób wektory dystrybucyjne można następnie wykorzystać w zadaniach takich jak wyszukiwanie semantyczne, klasyfikacja i klastrowanie, co pozwala uzyskać dokładniejsze wyniki uwzględniające kontekst niż w przypadku podejść opartych na słowach kluczowych.
Najnowszy model, gemini-embedding-2, to pierwszy multimodalny model osadzania w interfejsie Gemini API. Mapuje tekst, obrazy, filmy, dźwięk i dokumenty w ujednoliconej przestrzeni osadzania, umożliwiając wyszukiwanie, klasyfikowanie i grupowanie w różnych trybach w ponad 100 językach. Więcej informacji znajdziesz w sekcji poświęconej osadzaniu multimodalnemu. W przypadku zastosowań obejmujących tylko tekst gemini-embedding-001 pozostaje dostępny.
Tworzenie systemów generowania rozszerzonego przez wyszukiwanie w zapisanych informacjach (RAG) jest typowym zastosowaniem usług AI. Osadzanie odgrywa kluczową rolę w znacznym ulepszaniu wyników modelu dzięki większej dokładności faktów, spójności i bogactwu kontekstowemu. Jeśli wolisz korzystać z zarządzanego rozwiązania RAG, stworzyliśmy narzędzie File Search, które ułatwia zarządzanie RAG i zmniejsza koszty.
Generowanie wektorów dystrybucyjnych
Aby wygenerować osadzenia tekstu, użyj metody 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();
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?"
}]
}
}'
Określ typ zadania, które ma poprawić skuteczność
Możesz używać wektorów do wielu różnych zadań, od klasyfikacji po wyszukiwanie dokumentów. Określenie właściwego typu zadania pomaga zoptymalizować osadzanie pod kątem zamierzonych relacji, co zwiększa dokładność i wydajność.
Typy zadań z wektorami dystrybucyjnymi 2
W przypadku zadań tekstowych z gemini-embedding-2 zdecydowanie zalecamy dodanie instrukcji do promptu. Możesz to zrobić, formatując zapytanie i dokument za pomocą odpowiedniego prefiksu zadania.
W tabelach poniżej znajdziesz przykłady formatowania zapytań i dokumentów w przypadku zastosowań symetrycznych i asymetrycznych z użyciem modelu gemini-embedding-2.
Przypadki użycia wyszukiwania (format asymetryczny)
W przypadku asymetrycznych przypadków użycia dodaj do zapytania prefiks zadania i zastosuj strukturę dokumentu do treści, które chcesz osadzić i pobrać.
| Przypadek użycia | Struktura zapytania | Struktura dokumentu |
|---|---|---|
| Zapytanie | task: search result | query: {content} |
title: {title} | text: {content}Jeśli nie ma tytułu, użyj title: none. |
| Odpowiadanie na pytania | task: question answering | query: {content} |
title: {title} | text: {content} |
| Weryfikowanie informacji | task: fact checking | query: {content} |
title: {title} | text: {content} |
| Odzyskiwanie kodu | task: code retrieval | query: {content} |
title: {title} | text: {content} |
Przykładowe użycie
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}"
Przypadki użycia z 1 wejściem (format symetryczny)
W przypadku symetrycznych przypadków użycia wykonuj to samo zadanie, stosując to samo formatowanie zapytania i dokumentu.
| Przypadek użycia | Struktura danych wejściowych |
|---|---|
| Klasyfikacja | task: classification | query: {content} |
| Grupowanie | task: clustering | query: {content} |
| Podobieństwo semantyczne | task: sentence similarity | query: {content}Nie używaj tej funkcji do wyszukiwania ani pobierania. Jest on przeznaczony do określania podobieństwa semantycznego tekstu. |
Przykładowe użycie
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}'
Ważne jest, aby zadanie było używane konsekwentnie. Jeśli np. dokumenty są osadzone za pomocą funkcji f'task: classification | query: {content}', zapytanie również powinno być osadzone zgodnie z formatem tego zadania.
Typy zadań z osadzaniem 1
W przypadku gemini-embedding-001 możesz określić task_type w metodzie embedContent. Pełną listę obsługiwanych typów zadań znajdziesz w tabeli Obsługiwane typy zadań.
Przykład poniżej pokazuje, jak za pomocą funkcji SEMANTIC_SIMILARITY sprawdzić, jak podobne są do siebie ciągi tekstów.
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();
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?"
}
]
}
}'
Fragmenty kodu pokażą, jak podobne są do siebie różne fragmenty tekstu po uruchomieniu.
Obsługiwane typy zadań
Obsługiwane typy zadań w przypadku gemini-embedding-001:
| Typ zadania | Opis | Przykłady |
|---|---|---|
| SEMANTIC_SIMILARITY | Osadzanie zoptymalizowane pod kątem oceny podobieństwa tekstu. | Systemy rekomendacji, wykrywanie duplikatów |
| KLASYFIKACJA | Osadzanie zoptymalizowane pod kątem klasyfikowania tekstów według wstępnie ustawionych etykiet. | Analiza nastawienia, wykrywanie spamu |
| KLASYFIKACJA | Osadzanie zoptymalizowane pod kątem grupowania tekstów na podstawie ich podobieństwa. | Porządkowanie dokumentów, badania rynku, wykrywanie anomalii |
| RETRIEVAL_DOCUMENT | Osadzanie zoptymalizowane pod kątem wyszukiwania dokumentów. | indeksowanie artykułów, książek lub stron internetowych na potrzeby wyszukiwania; |
| RETRIEVAL_QUERY |
Osadzanie zoptymalizowane pod kątem ogólnych zapytań.
Używaj symbolu RETRIEVAL_QUERY w przypadku zapytań, a symbolu RETRIEVAL_DOCUMENT w przypadku dokumentów do pobrania.
|
Twoja wyszukiwarka |
| CODE_RETRIEVAL_QUERY |
Osadzanie zoptymalizowane pod kątem wyszukiwania bloków kodu na podstawie zapytań w języku naturalnym.
Używaj znaku CODE_RETRIEVAL_QUERY w przypadku zapytań, a znaku RETRIEVAL_DOCUMENT w przypadku bloków kodu, które mają zostać pobrane.
|
Sugestie dotyczące kodu i wyszukiwanie |
| QUESTION_ANSWERING |
Osadzanie pytań w systemie odpowiadania na pytania, zoptymalizowane pod kątem znajdowania dokumentów, które zawierają odpowiedź na pytanie.
Używaj symbolu QUESTION_ANSWERING w przypadku pytań, a symbolu RETRIEVAL_DOCUMENT w przypadku dokumentów do pobrania.
|
Chatbox |
| FACT_VERIFICATION |
Osadzenia dla stwierdzeń, które wymagają weryfikacji, zoptymalizowane pod kątem wyszukiwania dokumentów zawierających dowody potwierdzające lub obalające to stwierdzenie.
Użyj FACT_VERIFICATION w przypadku tekstu docelowego, a RETRIEVAL_DOCUMENT w przypadku dokumentów do pobrania.
|
Automatyczne systemy weryfikacji informacji |
Określanie rozmiaru wektora dystrybucyjnego
Zarówno gemini-embedding-001, jak i gemini-embedding-2 są trenowane przy użyciu techniki uczenia reprezentacji Matrioszka (MRL), która uczy model tworzenia osadzeń o wysokiej liczbie wymiarów, których początkowe segmenty (lub prefiksy) są również przydatnymi, prostszymi wersjami tych samych danych.
Użyj parametru output_dimensionality, aby kontrolować rozmiar wyjściowego wektora dystrybucyjnego. Wybór mniejszej liczby wymiarów wyjściowych może zaoszczędzić miejsce na dane i zwiększyć wydajność obliczeniową w przypadku aplikacji podrzędnych, przy niewielkiej utracie jakości. Domyślnie oba modele generują 3072-wymiarowe osadzanie, ale możesz je skrócić do mniejszego rozmiaru bez utraty jakości, aby zaoszczędzić miejsce na dane. Zalecamy używanie wymiarów wyjściowych 768, 1536 lub 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();
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
}'
Przykładowe dane wyjściowe z fragmentu kodu:
Length of embedding: 768
Zapewnianie jakości w przypadku mniejszych wymiarów
Domyślne 3072-wymiarowe osadzanie jest zawsze normalizowane, ale Gemini Embedding 2 automatycznie normalizuje też obcięte wymiary (np. 768, 1536). Dzięki temu podobieństwo semantyczne jest obliczane na podstawie kierunku wektora, a nie jego wielkości, co zapewnia większą dokładność wyników od razu po wyjęciu z pudełka.
Starsze modele: jeśli używasz modelu gemini-embedding-001, musisz ręcznie znormalizować wymiary inne niż 3072 w ten sposób:
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
Przykładowe dane wyjściowe tego fragmentu kodu:
Normed embedding length: 768
Norm of normed embedding: 1.000000
W tabeli poniżej znajdziesz wyniki MTEB, czyli powszechnie stosowanego testu porównawczego dla osadzania, w przypadku różnych wymiarów. Wyniki pokazują, że skuteczność nie jest ściśle związana z rozmiarem wymiaru osadzania, ponieważ mniejsze wymiary osiągają wyniki porównywalne z większymi.
| Wymiar MRL | Wynik MTEB (Gemini Embedding 001) |
|---|---|
| 2048 | 68,16 |
| 1536 | 68,17 |
| 768 | 67,99 |
| 512 | 67,55 |
| 256 | 66,19 |
| 128 | 63,31 |
Multimodalne wektory dystrybucyjne
Model gemini-embedding-2 obsługuje dane wejściowe multimodalne, co umożliwia osadzanie treści w formie obrazów, filmów, dźwięku i dokumentów obok tekstu. Wszystkie rodzaje danych są mapowane na tę samą przestrzeń osadzania, co umożliwia wyszukiwanie i porównywanie różnych rodzajów danych.
Obsługiwane rodzaje i limity
Ogólny maksymalny limit tokenów wejściowych to 8192 tokeny.
| Modalność | Specyfikacje i limity |
|---|---|
| Text | Obsługuje do 8192 tokenów. |
| Obraz | Maksymalnie 6 obrazów na żądanie. Obsługiwane formaty: PNG, JPEG. |
| Dźwięk | Maksymalny czas trwania to 180 sekund. Obsługiwane formaty: MP3, WAV. |
| Film | Maksymalny czas trwania to 120 sekund. Obsługiwane formaty: MP4, MOV. Obsługiwane kodeki: H264, H265, AV1, VP9. System przetwarza maksymalnie 32 klatki na film: w przypadku krótkich filmów (≤32 s) próbkowanie odbywa się z częstotliwością 1 klatki na sekundę, a w przypadku dłuższych filmów próbkowanie jest jednolite i obejmuje 32 klatki. Ścieżki audio nie są przetwarzane w plikach wideo. |
| Dokumenty (PDF) | Maksymalnie 1 plik na żądanie, do 6 stron. |
Umieszczanie obrazów
Poniższy przykład pokazuje, jak umieścić obraz za pomocą tagu
gemini-embedding-2.
Obrazy można przesyłać jako dane wbudowane lub jako przesłane pliki za pomocą interfejsu 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();
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}"'"
}
}]
}
}'
Agregacja wektorów dystrybucyjnych
Podczas pracy z treściami multimodalnymi struktura danych wejściowych wpływa na wygenerowane wektory dystrybucyjne:
- Wiele części (zagregowanych): dodanie wielu danych wejściowych bezpośrednio do parametru
contentspowoduje utworzenie jednego zagregowanego osadzenia dla wszystkich danych wejściowych. - Wiele obiektów
Content(osobnych): umieszczenie każdego wejścia w obiekcieContenti przekazanie ich w parametrzecontentszwraca osobne wektory osadzeń dla każdego wpisu. - Reprezentacja na poziomie posta: w przypadku złożonych obiektów, takich jak posty w mediach społecznościowych zawierające wiele elementów multimedialnych, zalecamy agregowanie oddzielnych osadzeń (np. przez uśrednianie), aby utworzyć spójną reprezentację na poziomie posta.
W przykładzie poniżej pokazujemy, jak utworzyć 1 zagregowane osadzenie dla tekstu i obrazu. Wystarczy dodać wiele danych wejściowych do parametru 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();
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}"'"
}
}
]
}
}'
Z drugiej strony, jeśli użyjesz obiektów Content w parametrze contents, zwróci on oddzielne wektory. W tym przykładzie tworzymy wiele wektorów dystrybucyjnych w jednym wywołaniu:
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="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: '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();