Embeddings
Embeddings
Transforme texto em vetores para pesquisa semântica, recuperação (RAG), recomendações, clustering e deduplicação, com os modelos text-embedding-3 da OpenAI a metade do preço da OpenAI. Os mesmos IDs de modelo, o mesmo pedido e a mesma resposta, os mesmos vetores: o código escrito para a OpenAI funciona assim que alterar o base URL e a chave.
/v1/embeddingsPaga o texto que envia, e os vetores são gratuitos. Ambos os modelos leem até 8,192 tokens por entrada. O Text Embedding 3 Small é o indicado para começar: barato, rápido e bom para a maioria das pesquisas e do RAG. O Text Embedding 3 Large é o modelo maior e mais preciso, para quando a qualidade da recuperação importa mais do que o armazenamento e o preço.
Guia rápido
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 10Qualquer SDK da OpenAI funciona: aponte-o para https://api.zurelay.com/v1, use a sua chave Zurelay e chame o método embeddings. A resposta é a da 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 tem um embedding por entrada, pela ordem em que as enviou, cada um com o seu index. usage.prompt_tokens é aquilo sobre o que o pedido foi faturado. Os cabeçalhos também o dizem: x-zurelay-model indica o modelo e x-zurelay-input-tokens os tokens, e x-request-id permite encontrar o pedido no seu registo de pedidos.
Parâmetros
modelstringobrigatóriotext-embedding-3-smalloutext-embedding-3-large.inputstring ou arrayobrigatório- O que colocar no embedding: uma string, um array de até 2,048 strings, um array de IDs de tokens (inteiros do tokenizer
cl100k_baseda OpenAI) ou um array de até 2,048 desses arrays. Cada entrada tem no máximo 8,192 tokens e nenhuma pode ser uma string vazia. encoding_formatstringfloat(predefinição): cada embedding é um array de números.base64: cada um é uma string base64 de números float32 little-endian, mais pequena e mais rápida de descarregar. Ver Base64.dimensionsinteger- Encurte o vetor: de 1 a 1,536 em
text-embedding-3-small, de 1 a 3,072 emtext-embedding-3-large. Omita-o para obter o comprimento total. Ver Vetores mais curtos. userstring- Opcional: um ID do utilizador final a quem o pedido se destina, como na API da OpenAI. É aceite e não altera nada nos vetores.
Pedidos em lote
Envie muitos textos num só pedido: input aceita um array de até 2,048 e as respostas chegam na mesma ordem. Um pedido com mil textos é muito mais rápido do que mil pedidos, e custa o mesmo: paga por token, não por pedido. Mantenha cada pedido abaixo de 300,000 tokens no total.
# 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 sentDivida em fragmentos os documentos com mais de 8,192 tokens antes de gerar os embeddings. Para pesquisa e RAG, fragmentos de algumas centenas de tokens, um parágrafo ou dois, costumam encontrar melhores correspondências do que documentos inteiros.
Vetores mais curtos com dimensions
Os modelos text-embedding-3 foram treinados para que um vetor encurtado continue a funcionar: peça dimensions e recebe a primeira parte do vetor completo, renormalizada para comprimento 1. Vetores mais curtos ocupam menos armazenamento e memória e pesquisam mais depressa, com um pouco menos de exatidão. O Text Embedding 3 Large com 1,024 dimensões ocupa um terço do espaço das suas 3,072 completas.
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
Com "encoding_format": "base64", cada embedding chega como uma string base64 de números float32 little-endian em vez de um array JSON: mais pequena e mais rápida de descarregar e processar. Se omitir encoding_format, o SDK Python da OpenAI pede base64 por si e descodifica-a, por isso recebe floats simples de qualquer forma. Se pedir base64 você mesmo, recebe a string, para descodificar assim:
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]Pesquisa semântica
Gere os embeddings dos seus documentos uma vez e guarde os vetores. Para pesquisar, gere o embedding da consulta com o mesmo modelo e ordene os documentos pela semelhança de cosseno com ela: quanto mais próximo de 1, mais próximos no significado, mesmo sem palavras em comum. Os vetores text-embedding-3 têm comprimento 1, por isso o produto interno dá a mesma ordenação.
# 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 firstPara mais do que alguns milhares de documentos, guarde os vetores numa base de dados vetorial ou num índice vetorial (pgvector, Qdrant, Pinecone, Weaviate, Chroma e semelhantes) e deixe que seja ela a fazer a ordenação.
Recuperação (RAG)
A geração aumentada por recuperação responde a uma pergunta a partir dos seus próprios documentos: procure as passagens mais próximas da pergunta e depois entregue-as a um modelo de chat juntamente com a pergunta. A mesma chave Zurelay serve para as duas coisas.
# 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 e o AI SDK
Os frameworks com uma classe de embeddings da OpenAI funcionam com o URL base e a chave da Zurelay, e os IDs dos modelos continuam a ser os da 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"])A OpenAIEmbeddings do LangChain para Python tokeniza os textos por si mesma por predefinição e envia os IDs dos tokens. A Zurelay aceita arrays de tokens, por isso as predefinições funcionam tal como estão.
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?")Com Settings.embed_model definido, todos os índices e retrievers que criar geram os embeddings através da Zurelay. Para o modelo de chat, consulte o guia do 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]));Aplicações e armazenamentos vetoriais
As aplicações que chamam os embeddings da OpenAI com um URL base configurável funcionam da mesma forma: defina-o como https://api.zurelay.com/v1, use a sua chave Zurelay e um dos IDs de modelo acima. Isto inclui o motor de embeddings OpenAI do Open WebUI para documentos, a API RAG do LibreChat, o nó Embeddings OpenAI do n8n e o fornecedor de modelos compatível com OpenAI do Dify.
Os mesmos vetores da OpenAI
Os pedidos para text-embedding-3-small e text-embedding-3-large correm nos próprios modelos da OpenAI. Verificámos todas as rotas contra a API da OpenAI: para o mesmo texto e modelo, os vetores coincidem com os da OpenAI, com uma semelhança de cosseno de 0.9999 ou mais. Assim, um índice criado com a API da OpenAI continua a funcionar quando gera os embeddings das suas consultas através da Zurelay, e um índice criado através da Zurelay funciona com a OpenAI. Passar de uma para a outra não exige voltar a gerar embeddings.
Mudar de modelo implica gerar novos embeddings
Vetores de modelos diferentes não podem ser comparados
text-embedding-3-small não significa nada ao lado de um de text-embedding-3-large, ou de qualquer outro modelo: cada modelo coloca o texto no seu próprio espaço. Por isso, para mudar de modelo, volte a gerar os embeddings de tudo o que guardou com o novo modelo e passe a consultar com esse modelo.Pela mesma razão, um pedido de embeddings é sempre respondido pelo modelo que indicou. O Encaminhamento inteligente nunca o passa a outro modelo, sejam quais forem as suas definições: se o modelo estiver em baixo, recebe 503 model_unavailable, para tentar de novo, em vez de vetores que não correspondem ao seu índice.
Limites
- Até 2,048 entradas por pedido.
- Até 8,192 tokens em cada entrada e 300,000 no pedido completo.
- Sem strings vazias.
dimensionsde 1 até ao comprimento total do modelo: 1,536 emtext-embedding-3-small, 3,072 emtext-embedding-3-large.- Um pedido que exceda um limite é recusado com um
400que indica o limite, e não custa nada. - Uma chave limitada a alguns modelos precisa de ter o modelo de embeddings na sua lista. Ver Limites e regras das chaves.
Pagar pelos embeddings
Os embeddings são cobrados apenas pelos tokens de entrada, contados como a OpenAI os conta, e os vetores são gratuitos. Text Embedding 3 Small custa $0.01 por 1M de tokens e Text Embedding 3 Large $0.065, metade do preço da OpenAI. Um milhão de textos de 100 tokens cada, ou seja 100M de tokens, custa $1.00 em embeddings com Text Embedding 3 Small e $6.50 com Text Embedding 3 Large, contra $2.00 e $13.00 na OpenAI.
Não há mínimo por pedido: um pedido de 10 tokens é cobrado como 10 tokens. dimensions mais curtos e base64 custam o mesmo. Os cabeçalhos usage e x-zurelay-input-tokens de cada resposta indicam o que foi cobrado, todos os pedidos ficam no seu registo de pedidos e os pedidos que falham não custam nada.
Erros
Os erros chegam na forma da OpenAI, por isso os SDKs da OpenAI lançam-nos como fariam para a OpenAI.
As chaves, o crédito, os orçamentos e os limites de taxa dão os mesmos erros que os restantes endpoints: consulte Erros. Os SDKs da OpenAI repetem automaticamente os pedidos que vale a pena repetir.
Experimente primeiro
Tem dúvidas ou falta alguma coisa? Contacte a nossa equipa de apoio e responderemos por email, normalmente num minuto.