mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 10:21:34 +00:00
92 lines
3.3 KiB
TypeScript
92 lines
3.3 KiB
TypeScript
// Openai plugin module implements memory embedding adapter behavior.
|
|
import {
|
|
isMissingEmbeddingApiKeyError,
|
|
mapBatchEmbeddingsByIndex,
|
|
sanitizeEmbeddingCacheHeaders,
|
|
type MemoryEmbeddingProviderAdapter,
|
|
} from "openclaw/plugin-sdk/memory-core-host-engine-embeddings";
|
|
import { OPENAI_BATCH_ENDPOINT, runOpenAiEmbeddingBatches } from "./embedding-batch.js";
|
|
import {
|
|
createOpenAiEmbeddingProvider,
|
|
DEFAULT_OPENAI_EMBEDDING_MODEL,
|
|
} from "./embedding-provider.js";
|
|
|
|
function resolveEmbeddingCacheExcludedHeaders(providerId: string, baseUrl: string): string[] {
|
|
const excludedHeaders = ["authorization"];
|
|
if (providerId !== "openai") {
|
|
return excludedHeaders;
|
|
}
|
|
try {
|
|
if (new URL(baseUrl).hostname.toLowerCase().replace(/\.+$/, "") === "api.openai.com") {
|
|
// Native attribution changes on every upgrade; cache identity must describe embeddings,
|
|
// not the OpenClaw build that requested them.
|
|
excludedHeaders.push("version", "user-agent");
|
|
}
|
|
} catch {
|
|
// Invalid URLs are handled by the embedding client; keep existing custom-header identity.
|
|
}
|
|
return excludedHeaders;
|
|
}
|
|
|
|
export const openAiMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {
|
|
id: "openai",
|
|
defaultModel: DEFAULT_OPENAI_EMBEDDING_MODEL,
|
|
transport: "remote",
|
|
authProviderId: "openai",
|
|
autoSelectPriority: 20,
|
|
allowExplicitWhenConfiguredAuto: true,
|
|
shouldContinueAutoSelection: isMissingEmbeddingApiKeyError,
|
|
create: async (options) => {
|
|
const resolvedProvider = options.provider ?? "openai";
|
|
const { provider, client } = await createOpenAiEmbeddingProvider({
|
|
...options,
|
|
provider: resolvedProvider,
|
|
fallback: "none",
|
|
});
|
|
return {
|
|
provider,
|
|
runtime: {
|
|
id: "openai",
|
|
sourceWideBatchEmbed: true,
|
|
cacheKeyData: {
|
|
provider: resolvedProvider,
|
|
baseUrl: client.baseUrl,
|
|
model: client.model,
|
|
outputDimensionality: client.outputDimensionality,
|
|
documentInputType: client.documentInputType ?? client.inputType,
|
|
headers: sanitizeEmbeddingCacheHeaders(
|
|
client.headers,
|
|
resolveEmbeddingCacheExcludedHeaders(resolvedProvider, client.baseUrl),
|
|
),
|
|
},
|
|
batchEmbed: async (batch) => {
|
|
const inputType = client.documentInputType ?? client.inputType;
|
|
const byCustomId = await runOpenAiEmbeddingBatches({
|
|
openAi: client,
|
|
agentId: batch.agentId,
|
|
requests: batch.chunks.map((chunk, index) => ({
|
|
custom_id: String(index),
|
|
method: "POST",
|
|
url: OPENAI_BATCH_ENDPOINT,
|
|
body: {
|
|
model: client.model,
|
|
input: chunk.text,
|
|
...(typeof client.outputDimensionality === "number"
|
|
? { dimensions: client.outputDimensionality }
|
|
: {}),
|
|
...(inputType ? { input_type: inputType } : {}),
|
|
},
|
|
})),
|
|
wait: batch.wait,
|
|
concurrency: batch.concurrency,
|
|
pollIntervalMs: batch.pollIntervalMs,
|
|
timeoutMs: batch.timeoutMs,
|
|
debug: batch.debug,
|
|
});
|
|
return mapBatchEmbeddingsByIndex(byCustomId, batch.chunks.length);
|
|
},
|
|
},
|
|
};
|
|
},
|
|
};
|