임베딩
TanStack AI 는 모든 다른 활동과 동일한 트리-흔들 수 있는, 모델별 타입화 된 아키텍처를 따르는 전용 임베딩 어댑터를 통해 임베딩 생성을 제공합니다. embed() 함수는 텍스트 — 그리고 멀티모달 모델의 경우 이미지 — 를 의미론적 검색, RAG, 클러스터링, 및 분류를 위한 벡터로 변환합니다.
개요
현재 지원되는 기능:
- OpenAI: text-embedding-3-small, text-embedding-3-large (텍스트)
- Cohere: embed-v4.0 (텍스트 + 이미지, 융합 멀티모달)
- Google Gemini: gemini-embedding-001 (텍스트)
- Mistral: mistral-embed, codestral-embed (텍스트)
- Amazon Bedrock: Titan Text Embeddings V2(텍스트), Titan Multimodal Embeddings G1(텍스트 + 이미지), Bedrock의 Cohere Embed v3(텍스트)
- Ollama: nomic-embed-text, mxbai-embed-large, 및 모든 로컬 임베딩 모델 (텍스트)
- Vercel AI Gateway: openai/text-embedding-3-small(텍스트)와 같은 OpenAI 호환 임베딩 모델
기본 사용법
import { embed } from "@tanstack/ai";
import { openaiEmbedding } from "@tanstack/ai-openai";
const result = await embed({
adapter: openaiEmbedding("text-embedding-3-small"),
input: "a red guitar",
});
console.log(result.embeddings[0]?.vector); // number[]
Vercel AI Gateway 는 동일한 embed() 호출을 사용합니다. creator/model ID(예: openai/text-embedding-3-small) 를 전달합니다:
import { embed } from "@tanstack/ai";
import { vercelGatewayEmbedding } from "@tanstack/ai-vercel-gateway";
const result = await embed({
adapter: vercelGatewayEmbedding("openai/text-embedding-3-small"),
input: "a red guitar",
});
input 는 단일 항목 또는 항목의 배열을 받습니다; 결과는 항상 embeddings 배열을 포함하며, 입력 순서대로 각 입력 항목마다 하나의 벡터가 있습니다:
import { embed } from "@tanstack/ai";
import { openaiEmbedding } from "@tanstack/ai-openai";
const result = await embed({
adapter: openaiEmbedding("text-embedding-3-large"),
input: ["a red guitar", "a blue drum kit", "a vintage synthesizer"],
});
for (const embedding of result.embeddings) {
console.log(embedding.index, embedding.vector.length);
}
차원 요청
구성 가능한 (Matryoshka) 차원을 지원하는 모델은 최상위 dimensions 옵션을 받습니다:
import { embed } from "@tanstack/ai";
import { openaiEmbedding } from "@tanstack/ai-openai";
const result = await embed({
adapter: openaiEmbedding("text-embedding-3-large"),
input: "a red guitar",
dimensions: 1024,
});
고정 차원 모델 (예: mistral-embed 또는 Ollama 모델) 을 위한 어댑터는 dimensions 가 설정되면 명확한 런타임 오류를 발생시킵니다.
멀티모달 임베딩
멀티모달 모델은 이미지를 임베딩합니다 — 단독으로 또는 텍스트와 융합하여 단일 벡터로. 이미지 입력은 채팅 메시지의 콘텐츠 부분 모양을 재사용하며, 허용되는 항목 유형은 컴파일 시간에 따라 모델마다 제한됩니다: 텍스트 전용 모델에 이미지를 전달하는 것은 타입 오류입니다.
상위 input 배열은 항상 항목 목록이며, 각 항목은 정확히 하나의 벡터를 생성합니다:
- 문자열 또는 텍스트 부분은 해당 텍스트를 임베드합니다
- 이미지 부분은 해당 이미지를 임베드합니다
- 부분들의 중첩된 배열 (
[textPart, imagePart]) 은 해당 부분들을 하나의 벡터로 융합합니다 — 동일한Array<ContentPart>모양의 채팅 메시지의content가 사용하는 것과 같습니다
최상위 배열이 항목 목록이므로, 중첩하여 융합합니다: [textPart, imagePart] 는 두 벡터이고, [[textPart, imagePart]] 는 하나의 융합된 벡터입니다.
import { embed } from "@tanstack/ai";
import { cohereEmbedding } from "@tanstack/ai-cohere";
const productPhoto = "iVBORw0KGgo..."; // base64 image data
const result = await embed({
adapter: cohereEmbedding("embed-v4.0"),
input: [
"a red guitar",
{
type: "image",
source: {
type: "data",
value: productPhoto,
mimeType: "image/png",
},
},
// A nested array fuses its parts into a single vector.
[
{ type: "text", content: "Fender Stratocaster, sunburst finish" },
{
type: "image",
source: {
type: "data",
value: productPhoto,
mimeType: "image/png",
},
},
],
],
modelOptions: { inputType: "search_document" },
});
console.log(result.embeddings.length); // 3 — one vector per input item
Amazon Titan Multimodal 도 동일한 방식으로 작동합니다 — 부분들을 중첩하여 하나의 벡터로 융합합니다:
import { embed } from "@tanstack/ai";
import { bedrockEmbedding } from "@tanstack/ai-bedrock";
const productPhoto = "iVBORw0KGgo..."; // base64 image data
const result = await embed({
adapter: bedrockEmbedding("amazon.titan-embed-image-v1"),
input: [
[
{ type: "text", content: "a red guitar" },
{
type: "image",
source: {
type: "data",
value: productPhoto,
mimeType: "image/png",
},
},
],
],
dimensions: 1024,
});
어댑터는 기본적으로 원격 이미지 URL 을 가져오지 않습니다 — base64 데이터 (또는 data: URI) 를 전달합니다. Cohere 어댑터는 allowUrlFetch 설정 옵션을 사용하여 http(s) 이미지 URL 을 대신 다운로드하도록 선택할 수 있습니다.
문서 검색 vs. 쿼리
검색 최적화 모델은 문서와 쿼리를 다르게 임베딩합니다. Cohere 는 inputType 를 요구하며, TanStack AI 는 타입 레벨에서 이를 강제합니다 — modelOptions 는 필수 옵션이 있는 모델에 필요합니다:
import { embed } from "@tanstack/ai";
import { cohereEmbedding } from "@tanstack/ai-cohere";
// Index time: embed documents
const docs = await embed({
adapter: cohereEmbedding("embed-v4.0"),
input: ["doc one", "doc two"],
modelOptions: { inputType: "search_document" },
});
// Query time: embed the query
const query = await embed({
adapter: cohereEmbedding("embed-v4.0"),
input: "which doc mentions one?",
modelOptions: { inputType: "search_query" },
});
Gemini 는 taskType 를 통해 동일한 개념을 표현합니다:
import { embed } from "@tanstack/ai";
import { geminiEmbedding } from "@tanstack/ai-gemini";
const result = await embed({
adapter: geminiEmbedding("gemini-embedding-001"),
input: "a red guitar",
modelOptions: { taskType: "RETRIEVAL_DOCUMENT" },
});
사용 및 관찰 가능성
어댑터는 제공자가 보고할 때 토큰 사용량을 보고하며, embed() 미디어 활동과 동일한 observe-only 생성 미들웨어를 지원합니다 (참조 Generation Hooks):
import { embed } from "@tanstack/ai";
import { openaiEmbedding } from "@tanstack/ai-openai";
const result = await embed({
adapter: openaiEmbedding("text-embedding-3-small"),
input: ["a red guitar", "a blue drum kit"],
middleware: [
{
name: "usage-logger",
onUsage: (ctx, usage) => {
console.log(`${ctx.model}: ${usage.promptTokens} tokens`);
},
},
],
});
console.log(result.usage?.promptTokens);
오류 처리
embed() 제공자 오류로 거부합니다; 미들웨어 onError 후크는 거부 전파 전에 실행됩니다:
import { embed } from "@tanstack/ai";
import { openaiEmbedding } from "@tanstack/ai-openai";
try {
await embed({
adapter: openaiEmbedding("text-embedding-3-small"),
input: "a red guitar",
});
} catch (error) {
console.error("embedding failed", error);
}