Files
openclaw/extensions/openai/embedding-provider.ts
2026-04-17 02:57:18 +01:00

60 lines
1.8 KiB
TypeScript

import {
createRemoteEmbeddingProvider,
resolveRemoteEmbeddingClient,
type MemoryEmbeddingProvider,
type MemoryEmbeddingProviderCreateOptions,
} from "openclaw/plugin-sdk/memory-core-host-engine-embeddings";
import type { SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
import { OPENAI_DEFAULT_EMBEDDING_MODEL } from "./default-models.js";
export type OpenAiEmbeddingClient = {
baseUrl: string;
headers: Record<string, string>;
ssrfPolicy?: SsrFPolicy;
fetchImpl?: typeof fetch;
model: string;
};
const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
export const DEFAULT_OPENAI_EMBEDDING_MODEL = OPENAI_DEFAULT_EMBEDDING_MODEL;
const OPENAI_MAX_INPUT_TOKENS: Record<string, number> = {
"text-embedding-3-small": 8192,
"text-embedding-3-large": 8192,
"text-embedding-ada-002": 8191,
};
export function normalizeOpenAiModel(model: string): string {
const trimmed = model.trim();
if (!trimmed) {
return DEFAULT_OPENAI_EMBEDDING_MODEL;
}
return trimmed.startsWith("openai/") ? trimmed.slice("openai/".length) : trimmed;
}
export async function createOpenAiEmbeddingProvider(
options: MemoryEmbeddingProviderCreateOptions,
): Promise<{ provider: MemoryEmbeddingProvider; client: OpenAiEmbeddingClient }> {
const client = await resolveOpenAiEmbeddingClient(options);
return {
provider: createRemoteEmbeddingProvider({
id: "openai",
client,
errorPrefix: "openai embeddings failed",
maxInputTokens: OPENAI_MAX_INPUT_TOKENS[client.model],
}),
client,
};
}
export async function resolveOpenAiEmbeddingClient(
options: MemoryEmbeddingProviderCreateOptions,
): Promise<OpenAiEmbeddingClient> {
return await resolveRemoteEmbeddingClient({
provider: "openai",
options,
defaultBaseUrl: DEFAULT_OPENAI_BASE_URL,
normalizeModel: normalizeOpenAiModel,
});
}