--- id: ai-embeddings-comparison title: Embeddings 비교 — OpenAI / Cohere / 오픈소스 category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [ai, embedding, vector, vibe-coding] tech_stack: { language: "TS / OpenAI / Cohere", applicable_to: ["Backend"] } applied_in: [] aliases: [embeddings, BGE, OpenAI text-embedding-3, Cohere, MTEB, vector dimensions] --- # Embeddings 비교 > 모델 = (정확도 / 차원 / 비용 / latency) 트레이드오프. **OpenAI text-embedding-3-small** 이 baseline. Cohere embed-v3 (multilingual). 오픈소스 = BGE / Voyage. **차원 줄이기 (dimensions param)** 로 비용 줄임. ## 📖 핵심 개념 - 차원: 벡터 길이. 큼 = 정확도↑, 비용/메모리↑. - Cosine vs dot vs L2: 거리 측정. Cosine 이 가장 일반. - Normalization: 단위 벡터 — cosine = dot product. - MTEB: 임베딩 벤치마크. ## 💻 코드 패턴 ### OpenAI ```ts const r = await openai.embeddings.create({ model: 'text-embedding-3-small', // 1536 차원, 싸다 input: 'hello world', }); const emb = r.data[0].embedding; ``` ```ts // 차원 줄이기 (Matryoshka) const r = await openai.embeddings.create({ model: 'text-embedding-3-large', // 3072 base input, dimensions: 256, // 256 으로 압축 — 정확도 90% 유지 }); ``` ### Cohere (multilingual) ```ts import { CohereClient } from 'cohere-ai'; const cohere = new CohereClient({ token }); const r = await cohere.v2.embed({ model: 'embed-multilingual-v3.0', inputType: 'search_document', // 또는 search_query (asymmetric) texts: ['안녕하세요'], embeddingTypes: ['float'], }); ``` ### 오픈소스 (Sentence Transformers via Hugging Face) ```ts // 로컬 inference (Bun / Node + onnx) import { pipeline } from '@xenova/transformers'; const embedder = await pipeline('feature-extraction', 'Xenova/bge-base-en-v1.5'); const r = await embedder('hello', { pooling: 'mean', normalize: true }); const emb = Array.from(r.data); ``` ### Asymmetric search (query vs document) ```ts // 일부 모델은 query 와 doc 다른 prompt 사용 // BGE: "Represent this sentence for searching relevant passages: {query}" const docEmb = await embed('document content'); const queryEmb = await embed('Represent this sentence for searching relevant passages: ' + query); ``` ### Batch embedding (대량) ```ts const batch = await openai.embeddings.create({ model: 'text-embedding-3-small', input: texts, // up to 2048 inputs }); const embeddings = batch.data.map(d => d.embedding); ``` 또는 OpenAI batch API: 50% 할인, 24시간 내 처리. ### Normalization ```ts function normalize(v: number[]): number[] { const norm = Math.sqrt(v.reduce((s, x) => s + x * x, 0)); return v.map(x => x / norm); } // 정규화 후 cosine similarity = dot product ``` ### Cosine similarity ```ts function cosine(a: number[], b: number[]): number { let dot = 0, na = 0, nb = 0; for (let i = 0; i < a.length; i++) { dot += a[i] * b[i]; na += a[i] * a[i]; nb += b[i] * b[i]; } return dot / (Math.sqrt(na) * Math.sqrt(nb)); } ``` ### 모델 비교 매트릭스 | 모델 | 차원 | $/1M tok | latency | MTEB | 멀티 | |---|---|---|---|---|---| | text-embedding-3-small | 1536 | $0.02 | 빠름 | 62 | 보통 | | text-embedding-3-large | 3072 | $0.13 | 보통 | 64 | 보통 | | Cohere embed-v3 | 1024 | $0.10 | 보통 | - | 강 | | BGE-base-en | 768 | 무료 (self) | self | 63 | en | | BGE-M3 | 1024 | 무료 (self) | self | - | 강 | | Voyage-3 | 1024 | $0.06 | 보통 | 65+ | 보통 | ### 차원 압축 시험 ```ts // Matryoshka: 첫 N 차원만 사용 const compressed = full.slice(0, 256); // 정확도 측정 — 충분하면 OK ``` ## 🤔 의사결정 기준 | 상황 | 추천 | |---|---| | 영어 일반 | OpenAI 3-small | | 한국어 / 다국어 | Cohere embed-multilingual-v3 / BGE-M3 | | 비용 0 / on-prem | BGE / 인스트럭터 | | 정확도 최고 | text-embedding-3-large 또는 voyage-3 | | 큰 처리량 | Batch API | | Edge / browser | xenova/transformers WASM | ## ❌ 안티패턴 - **모델 mix 한 인덱스**: 비교 안 됨. 한 모델만. - **Asymmetric 모델 같은 prompt**: 의미 떨어짐. - **Dim 압축 없이 무조건 max**: 비용 / 메모리 낭비. - **Normalization 안 함 + dot 사용**: 길이 차이로 noise. - **Reranker 없이 top-K 만**: noise. Cohere rerank-3 등. - **cache 안 함**: 같은 query 매번. content-addressed cache. ## 🤖 LLM 활용 힌트 - 작은 = 3-small (1536) + dim 압축. - 한국어 = Cohere multilingual / BGE-M3. - Batch API 로 비용 절반. ## 🔗 관련 문서 - [[AI_RAG_Pattern_Basics]] - [[DB_Full_Text_Search]] - [[AI_LLM_Eval_Patterns]]