एम्बेडिंग्स
एम्बेडिंग्स
टेक्स्ट को वेक्टर में बदलें — सेमांटिक सर्च, रिट्रीवल (RAG), सुझाव, क्लस्टरिंग और डुप्लीकेट हटाने के लिए। OpenAI के text-embedding-3 मॉडल, OpenAI की कीमत से आधी कीमत पर। वही मॉडल ID, वही रिक्वेस्ट और रिस्पॉन्स, वही वेक्टर: OpenAI के लिए लिखा कोड बेस URL और की बदलते ही चल पड़ता है।
/v1/embeddingsआप जो टेक्स्ट भेजते हैं उसका भुगतान करते हैं, वेक्टर मुफ़्त हैं। दोनों मॉडल प्रति इनपुट 8,192 टोकन तक पढ़ते हैं। शुरुआत के लिए Text Embedding 3 Small सही है: सस्ता, तेज़, और ज़्यादातर सर्च और RAG के लिए अच्छा। Text Embedding 3 Large बड़ा और ज़्यादा सटीक मॉडल है — जब रिट्रीवल की क्वालिटी स्टोरेज और कीमत से ज़्यादा मायने रखे।
झटपट शुरुआत
import osfrom openai import OpenAIclient = OpenAI( base_url="https://api.zurelay.com/v1", api_key=os.environ["ZURELAY_API_KEY"],)response = client.embeddings.create( model="text-embedding-3-small", input="The food was delicious and the waiter was friendly.",)vector = response.data[0].embedding # a list of 1,536 floatsprint(len(vector), response.usage.prompt_tokens) # 1536 10कोई भी OpenAI SDK चलेगा: उसे https://api.zurelay.com/v1 पर सेट करें, अपनी Zurelay की डालें और उसका embeddings मेथड कॉल करें। जवाब बिल्कुल OpenAI वाला मिलता है:
{ "object": "list", "data": [ { "object": "embedding", "index": 0, "embedding": [-0.0022748, -0.0093183, 0.0158532, ..., -0.0028842] } ], "model": "text-embedding-3-small", "usage": { "prompt_tokens": 10, "total_tokens": 10 }}data में हर इनपुट के लिए एक एम्बेडिंग होता है, उसी क्रम में जिसमें आपने भेजा, और हर एक के साथ उसका index। usage.prompt_tokens वही है जिस पर रिक्वेस्ट का बिल बना। हेडर भी यही बताते हैं: x-zurelay-model मॉडल का नाम देता है और x-zurelay-input-tokens टोकन का, और x-request-id आपके रिक्वेस्ट लॉग में वह रिक्वेस्ट ढूंढ देता है।
पैरामीटर
modelstringज़रूरीtext-embedding-3-smallयाtext-embedding-3-large।inputstring या arrayज़रूरी- क्या एम्बेड करें: एक स्ट्रिंग, 2,048 स्ट्रिंग तक की ऐरे, टोकन ID की ऐरे (OpenAI के
cl100k_baseटोकनाइज़र से पूर्णांक), या ऐसी 2,048 ऐरे तक की ऐरे। हर इनपुट ज़्यादा से ज़्यादा 8,192 टोकन का हो, और कोई भी खाली स्ट्रिंग न हो। encoding_formatstringfloat(डिफ़ॉल्ट): हर एम्बेडिंग संख्याओं का एक ऐरे होती है।base64: हर एक little-endian float32 संख्याओं की base64 स्ट्रिंग होती है — छोटी, और डाउनलोड करने में तेज़। देखें Base64।dimensionsinteger- वेक्टर छोटा करें:
text-embedding-3-smallपर 1 से 1,536,text-embedding-3-largeपर 1 से 3,072। पूरी लंबाई के लिए इसे छोड़ दें। देखें छोटे वेक्टर। userstring- वैकल्पिक: उस अंतिम उपयोगकर्ता की ID जिसके लिए अनुरोध है, जैसे OpenAI के API में। स्वीकार किया जाता है, और वेक्टर पर कोई असर नहीं पड़ता।
बैचिंग
एक ही अनुरोध में कई टेक्स्ट भेजें: input अधिकतम 2,048 का ऐरे लेता है, और नतीजे उसी क्रम में लौटते हैं। हज़ार टेक्स्ट वाला एक अनुरोध हज़ार अनुरोधों से कहीं तेज़ है, और खर्च भी उतना ही: आप प्रति टोकन चुकाते हैं, प्रति अनुरोध नहीं। हर अनुरोध कुल मिलाकर 300,000 टोकन से कम रखें।
# pip install tiktokenimport tiktoken# The tokenizer text-embedding-3 counts with, to keep each request under the limitsenc = tiktoken.get_encoding("cl100k_base")def batches(texts, max_inputs=2048, max_tokens=300_000): batch, tokens = [], 0 for text in texts: count = len(enc.encode(text)) if batch and (len(batch) == max_inputs or tokens + count > max_tokens): yield batch batch, tokens = [], 0 batch.append(text) tokens += count if batch: yield batchvectors = []for batch in batches(texts): response = client.embeddings.create(model="text-embedding-3-small", input=batch) vectors += [item.embedding for item in response.data] # in the order sent8,192 टोकन से लंबे दस्तावेज़ों को एम्बेड करने से पहले टुकड़ों में बाँटें। सर्च और RAG के लिए, कुछ सौ टोकन के टुकड़े — एक-दो पैराग्राफ़ — पूरे दस्तावेज़ों से आमतौर पर बेहतर मैच ढूँढते हैं।
dimensions के साथ छोटे वेक्टर
text-embedding-3 मॉडल ऐसे प्रशिक्षित हैं कि छोटा किया गया वेक्टर भी काम करता है: dimensions माँगें और आपको पूरे वेक्टर का पहला हिस्सा मिलता है, जो लंबाई 1 पर फिर से नॉर्मलाइज़ किया गया है। छोटे वेक्टर कम स्टोरेज और मेमोरी लेते हैं और तेज़ी से सर्च होते हैं, थोड़ी कम सटीकता के साथ। Text Embedding 3 Large, 1,024 dimensions पर अपने पूरे 3,072 की एक-तिहाई जगह लेता है।
response = client.embeddings.create( model="text-embedding-3-large", input="The food was delicious and the waiter was friendly.", dimensions=1024,)print(len(response.data[0].embedding)) # 1024Base64
"encoding_format": "base64" के साथ हर एम्बेडिंग JSON ऐरे की जगह little-endian float32 संख्याओं की base64 स्ट्रिंग के रूप में लौटती है: छोटी, और डाउनलोड व पार्स करने में तेज़। जब आप encoding_format छोड़ देते हैं, तो OpenAI का Python SDK खुद base64 माँगता है और उसे आपके लिए डिकोड कर देता है, यानी दोनों तरह आपको सादे floats ही मिलते हैं। अगर आप खुद base64 माँगते हैं, तो आपको स्ट्रिंग मिलती है, जिसे ऐसे डिकोड करें:
import base64import numpy as npresponse = client.embeddings.create( model="text-embedding-3-small", input=["First text", "Second text"], encoding_format="base64",)# Each embedding is a base64 string of little-endian float32 numbersvectors = [np.frombuffer(base64.b64decode(item.embedding), dtype="<f4") for item in response.data]सिमैंटिक सर्च
अपने दस्तावेज़ एक बार एम्बेड करें और वेक्टर सहेज लें। सर्च करने के लिए, क्वेरी को उसी मॉडल से एम्बेड करें और दस्तावेज़ों को उससे cosine similarity के हिसाब से रैंक करें: 1 के जितना करीब, अर्थ में उतना ही करीब, चाहे कोई शब्द समान न हो। text-embedding-3 के वेक्टर की लंबाई 1 होती है, इसलिए dot product वही रैंकिंग देता है।
# pip install openai numpyimport osimport numpy as npfrom openai import OpenAIclient = OpenAI(base_url="https://api.zurelay.com/v1", api_key=os.environ["ZURELAY_API_KEY"])MODEL = "text-embedding-3-small"docs = [ "To change your password, open Settings, choose Security and click Change password.", "Invoices are emailed on the first day of each month and can be downloaded under Billing.", "Invite teammates from the Team page; each person signs in with their own email.", "API keys can be limited to a monthly budget, a rate limit and a list of models.",]def embed(texts): response = client.embeddings.create(model=MODEL, input=texts) return np.array([item.embedding for item in response.data])doc_vectors = embed(docs) # embed once, and store the vectors beside the textdef search(query, k=2): query_vector = embed([query])[0] # The vectors have length 1, so the dot product is the cosine similarity scores = doc_vectors @ query_vector best = np.argsort(-scores)[:k] return [(docs[i], float(scores[i])) for i in best]for text, score in search("How can I change my password?"): print(f"{score:.3f} {text}") # the password article comes firstकुछ हज़ार से ज़्यादा दस्तावेज़ों के लिए, वेक्टर किसी वेक्टर डेटाबेस या वेक्टर इंडेक्स (pgvector, Qdrant, Pinecone, Weaviate, Chroma वगैरह) में रखें और रैंकिंग उसी से कराएँ।
रिट्रीवल (RAG)
रिट्रीवल-ऑगमेंटेड जनरेशन आपके ही दस्तावेज़ों से सवाल का जवाब देता है: सवाल से सबसे करीब के पैसेज खोजें, फिर उन्हें सवाल के साथ चैट मॉडल को दें। दोनों काम एक ही Zurelay की से हो जाते हैं।
# After the search example above: retrieve, then answer from what was foundquestion = "How do I stop a key from spending too much?"notes = "\n".join(text for text, _ in search(question))answer = client.chat.completions.create( model="gpt-6-luna", messages=[ { "role": "system", "content": "Answer from these notes only. If they don't say, say so.\n\n" + notes, }, {"role": "user", "content": question}, ],)print(answer.choices[0].message.content)LangChain, LlamaIndex और AI SDK
जिन फ़्रेमवर्क में OpenAI embeddings क्लास है, वे Zurelay के base URL और की के साथ काम करते हैं, और मॉडल ID OpenAI की ही रहती हैं।
LangChain
# pip install langchain-openaiimport osfrom langchain_openai import OpenAIEmbeddingsembeddings = OpenAIEmbeddings( model="text-embedding-3-small", base_url="https://api.zurelay.com/v1", api_key=os.environ["ZURELAY_API_KEY"],)query_vector = embeddings.embed_query("How can I change my password?")doc_vectors = embeddings.embed_documents(["First document", "Second document"])LangChain का Python OpenAIEmbeddings डिफ़ॉल्ट रूप से टेक्स्ट को खुद टोकनाइज़ करता है और टोकन ID भेजता है। Zurelay टोकन ऐरे स्वीकार करता है, इसलिए डिफ़ॉल्ट सेटिंग्स जैसी हैं वैसी ही काम करती हैं।
LlamaIndex
# pip install llama-index-embeddings-openaiimport osfrom llama_index.core import Settingsfrom llama_index.embeddings.openai import OpenAIEmbeddingSettings.embed_model = OpenAIEmbedding( model="text-embedding-3-small", api_base="https://api.zurelay.com/v1", api_key=os.environ["ZURELAY_API_KEY"],)vector = Settings.embed_model.get_text_embedding("How can I change my password?")Settings.embed_model सेट होने पर, आपका बनाया हर इंडेक्स और रिट्रीवर Zurelay के ज़रिए एम्बेड करता है। चैट मॉडल के लिए, LlamaIndex गाइड देखें।
Vercel AI SDK
// npm install ai @ai-sdk/openaiimport { createOpenAI } from "@ai-sdk/openai";import { cosineSimilarity, embed, embedMany } from "ai";const zurelay = createOpenAI({ baseURL: "https://api.zurelay.com/v1", apiKey: process.env.ZURELAY_API_KEY,});const model = zurelay.embedding("text-embedding-3-small");const { embeddings } = await embedMany({ model, values: ["First document", "Second document"] });const { embedding } = await embed({ model, value: "How can I change my password?" });console.log(cosineSimilarity(embedding, embeddings[0]));ऐप्स और वेक्टर स्टोर
जो ऐप्स अपनी सेट की जा सकने वाली base URL के साथ OpenAI की embeddings कॉल करते हैं, वे भी इसी तरह काम करते हैं: उसे https://api.zurelay.com/v1 पर सेट करें, अपनी Zurelay की और ऊपर की कोई मॉडल ID इस्तेमाल करें। इनमें Open WebUI का दस्तावेज़ों के लिए OpenAI embedding इंजन, LibreChat का RAG API, n8n का Embeddings OpenAI नोड और Dify का OpenAI-संगत मॉडल प्रोवाइडर शामिल हैं।
OpenAI जैसे ही वेक्टर
text-embedding-3-small और text-embedding-3-large के अनुरोध OpenAI के अपने मॉडलों पर चलते हैं। हमने हर रूट को OpenAI के API के सामने जाँचा: एक ही टेक्स्ट और मॉडल के लिए वेक्टर OpenAI से मेल खाते हैं, 0.9999 या उससे ज़्यादा की cosine similarity के साथ। यानी OpenAI के API से बनाया आपका इंडेक्स तब भी काम करता है जब आप अपनी क्वेरी Zurelay से एम्बेड करते हैं, और Zurelay से बनाया इंडेक्स OpenAI के साथ चलता है। दोनों के बीच जाने पर दोबारा एम्बेड करने की ज़रूरत नहीं।
मॉडल बदलने का मतलब है दोबारा एम्बेडिंग
अलग-अलग मॉडलों के वेक्टर की तुलना नहीं हो सकती
text-embedding-3-small का वेक्टर text-embedding-3-large के वेक्टर के बगल में, या किसी भी दूसरे मॉडल के वेक्टर के बगल में, कुछ मायने नहीं रखता: हर मॉडल टेक्स्ट को अपनी अलग जगह में रखता है। इसलिए मॉडल बदलने के लिए, अपना सारा सहेजा हुआ डेटा नए मॉडल से दोबारा एम्बेड करें, और आगे से उसी मॉडल से क्वेरी करें।इसी वजह से, एम्बेडिंग का अनुरोध हमेशा उसी मॉडल से पूरा होता है जिसका आपने नाम दिया। स्मार्ट रूटिंग इसे कभी किसी दूसरे मॉडल को नहीं देता, आपकी सेटिंग्स कुछ भी हों: अगर मॉडल डाउन है तो आपको 503 model_unavailable मिलता है, दोबारा कोशिश करने के लिए, न कि ऐसे वेक्टर जो आपके इंडेक्स से मेल न खाएँ।
सीमाएँ
- एक अनुरोध में अधिकतम 2,048 इनपुट।
- हर इनपुट में अधिकतम 8,192 टोकन, और पूरे अनुरोध में 300,000।
- खाली स्ट्रिंग नहीं।
dimensions1 से लेकर मॉडल की पूरी लंबाई तक:text-embedding-3-smallपर 1,536,text-embedding-3-largeपर 3,072।- सीमा से बढ़ा अनुरोध
400के साथ अस्वीकार होता है जिसमें सीमा का नाम होता है, और उसका कोई खर्च नहीं लगता। - कुछ मॉडलों तक सीमित की में एम्बेडिंग मॉडल उसकी सूची में होना चाहिए। देखें की की सीमाएँ और नियम।
एम्बेडिंग का भुगतान
एम्बेडिंग्स का बिल सिर्फ़ इनपुट टोकन पर लगता है, जो OpenAI की तरह गिने जाते हैं, और वेक्टर मुफ़्त हैं। Text Embedding 3 Small का दाम $0.01 प्रति 1M टोकन है और Text Embedding 3 Large $0.065, यानी OpenAI के दाम से आधा। 100 टोकन वाले दस लाख टेक्स्ट, कुल 100M टोकन, Text Embedding 3 Small से एम्बेड करने पर $1.00 में पड़ेंगे और $6.50 के साथ Text Embedding 3 Large, जबकि OpenAI पर $2.00 और $13.00।
प्रति रिक्वेस्ट कोई न्यूनतम नहीं है: 10-टोकन वाली रिक्वेस्ट का बिल 10 टोकन ही है। छोटे dimensions और base64 का भी वही शुल्क है। हर जवाब के usage और x-zurelay-input-tokens हेडर बताते हैं कि बिल किस पर लगा, हर रिक्वेस्ट आपके रिक्वेस्ट लॉग में रहती है, और जो रिक्वेस्ट फेल होती हैं उनका कुछ भी नहीं लगता।
गड़बड़ियाँ
एरर OpenAI के ढाँचे में आते हैं, इसलिए OpenAI के SDK उन्हें वैसे ही रेज़ करते हैं जैसे OpenAI के लिए करते।
कीज़, क्रेडिट, बजट और रेट लिमिट पर वही एरर आते हैं जो बाकी सभी endpoints पर आते हैं: देखें एरर। OpenAI के SDKs उन एरर को दोबारा आज़माते हैं जिन्हें दोबारा आज़माना ठीक रहता है।
पहले आज़माकर देखें
कोई सवाल है, या कुछ छूट गया है? हमारी सहायता टीम से पूछें और हम ईमेल से जवाब देंगे, आम तौर पर एक मिनट के भीतर.