diff --git a/src/core/openai-embedding.ts b/src/core/openai-embedding.ts index bcfc83e9..4dadb7c3 100644 --- a/src/core/openai-embedding.ts +++ b/src/core/openai-embedding.ts @@ -91,12 +91,6 @@ export class OpenAIEmbeddingClient { this.documentBody = options.documentBody ?? {}; this.indexId = indexIdentity({ model: this.model, - // The endpoint takes part in the identity. Two deployments of the same model name can - // serve different weights, and a vector from one is not comparable with a query - // embedded by the other - but nothing else in the identity would notice, so switching - // endpoints used to leave the stored vectors silently in place and mix two spaces. - // With it here, a switch makes the index stale and the existing backfill re-embeds. - providerEndpoint: endpointIdentity(options.baseUrl), ...(options.indexNamespace ? { indexNamespace: options.indexNamespace } : {}), dimensions: this.dimensions, documentTemplate: this.documentTemplate, @@ -238,22 +232,8 @@ export class OpenAIEmbeddingClient { * per-call bodies means existing embeddings cannot be reused. Serialisation order * is part of the contract, so keep the spread order identical when editing. */ -/** The part of the endpoint that identifies the deployment: scheme, host and path, without - * a trailing slash or any query, so an equivalent spelling of the same endpoint keeps the - * same identity and a genuinely different one does not. */ -function endpointIdentity(baseUrl: string | undefined): string | null { - if (!baseUrl) return null; - try { - const url = new URL(baseUrl); - return `${url.protocol}//${url.host}${url.pathname.replace(/\/+$/, "")}`; - } catch { - return baseUrl.replace(/\/+$/, ""); - } -} - function indexIdentity(input: { model: string; - providerEndpoint?: string | null; indexNamespace?: string; dimensions?: number; documentTemplate: string; @@ -266,7 +246,6 @@ function indexIdentity(input: { const fingerprint = createHash("sha256") .update( JSON.stringify({ - ...(input.providerEndpoint ? { providerEndpoint: input.providerEndpoint } : {}), ...(input.indexNamespace ? { indexNamespace: input.indexNamespace } : {}), dimensions: input.dimensions ?? null, documentTemplate: input.documentTemplate, diff --git a/tests/core/openai-embedding.test.ts b/tests/core/openai-embedding.test.ts index 234bb49c..3bbe46a4 100644 --- a/tests/core/openai-embedding.test.ts +++ b/tests/core/openai-embedding.test.ts @@ -286,28 +286,3 @@ test("a dropped connection is still retried", async () => { ); } }); - -test("the embedding index identity separates deployments of the same model", () => { - // Two regions of the same provider serve the same model name. A vector from one is not - // comparable with a query embedded by the other, and nothing else in the identity - model, - // dimensions, templates - differs, so the endpoint has to be part of it. Without this, a - // switch left every stored vector in place and silently mixed the two spaces. - const mainland = new OpenAIEmbeddingClient({ - baseUrl: "https://embed.example.cn/compatible-mode/v1", - model: "text-embedding-v4", - dimensions: 1024, - }); - const singapore = new OpenAIEmbeddingClient({ - baseUrl: "https://embed.example.sg/compatible-mode/v1", - model: "text-embedding-v4", - dimensions: 1024, - }); - const spelling = new OpenAIEmbeddingClient({ - baseUrl: "https://embed.example.cn/compatible-mode/v1/", - model: "text-embedding-v4", - dimensions: 1024, - }); - assert.notEqual(mainland.indexId, singapore.indexId, "a different endpoint is a different index"); - assert.equal(spelling.indexId, mainland.indexId, "a trailing slash is the same endpoint"); - assert.match(mainland.indexId, /^text-embedding-v4@[0-9a-f]{12}$/); -});