--- summary: "嵌入、图像和视频生成、网络获取和网络搜索提供商功能" read_when: - "您正在注册用于内存或搜索的嵌入提供程序" - "您正在向提供商插件添加图像、视频或音乐生成" - "您正在连接网络获取或网络搜索提供商" title: "提供商媒体和搜索" sidebarTitle: "媒体和搜索" --- 提供者插件可以与文本推理一起注册嵌入、生成和 Web 功能。在现有 `api.registerProvider(...)` 调用旁边的 `register(api)` 中注册每一个。 [构建提供商插件](/plugins/sdk-provider-plugins)指南的一部分。 捆绑的运行时适配器可以从私有 `openclaw/plugin-sdk/concurrency-runtime` 子路径使用 `createDeferred` 创建延迟承诺。它返回 `promise`、`resolve` 和 `reject`,而不加载日志记录或提供程序身份验证;适配器保留取消和终端结算的责任。 语音提供者可以使用轻量级 `openclaw/plugin-sdk/speech-provider` 子路径中的 `createSpeechDirectiveParser`。将每个覆盖字段映射到其策略密钥和接受的令牌别名;可选字段回调保留供应商验证和警告文本。共享解析器处理别名分派和策略门控并返回覆盖补丁。主机将这些补丁合并到提供商的累积覆盖中;仅当合并嵌套值(例如语音设置)时,回调才使用 `currentOverrides`。 ## 媒体和搜索功能 ```typescript // fetchAcmeEmbedding is your plugin's own vendor API call, not an SDK export. api.registerEmbeddingProvider({ id: "acme-ai", defaultModel: "acme-embed", transport: "remote", authProviderId: "acme-ai", create: async ({ model }) => ({ provider: { id: "acme-ai", model, dimensions: 1536, embed: async (input) => { const text = typeof input === "string" ? input : input.text; return fetchAcmeEmbedding(text); }, embedBatch: async (inputs) => Promise.all( inputs.map((input) => fetchAcmeEmbedding(typeof input === "string" ? input : input.text), ), ), }, }), }); ``` 在`contracts.embeddingProviders`中声明相同的id。这是可重用向量生成的通用嵌入契约,包括内存搜索。不再接受已退休的特定于内存的注册商和清单合同。 OpenAI-兼容的端点可以使用`createRemoteEmbeddingProvider`从`openclaw/plugin-sdk/memory-core-host-engine-embeddings`。其可选的`buildRequestFields(kind)`回调返回额外的JSON字段为`"query"` or `"document"`请求,例如`dimensions` or `input_type`。共享工厂始终供应客户的`model`和原来的`input`这些字段后面的数组,保留响应计数验证。 `resolveRemoteEmbeddingClient` 返回的客户端在每个 HTTP 请求之前通过 auth-profile 所有者解析 OAuth 授权。 API 密钥和显式授权标头保持静态。也通过批处理助手传递客户端的可选 `resolveRequestHeaders` 回调:它接收 `{ forceRefresh, signal }` 并返回请求标头。 `withRemoteHttpResponse` 在受保护的调度之前应用这些标头,并提供实际标头作为第二个 `onResponse` 参数以进行错误编辑。如果该处理程序针对 `401 token_expired` 引发提供程序 HTTP 错误,则帮助程序将释放响应,使用 `forceRefresh: true` 解析标头一次,然后仅重试该请求。上传必须使用可重放的正文,例如批处理助手的 `FormData`。 嵌入适配器可以使用 `openclaw/plugin-sdk/memory-core-host-engine-embeddings` 中的 `resolveEmbeddingProviderSsrFPolicy` 来应用共享模型提供程序网络策略。传递嵌入提供者ID、API、有效基URL以及配置的`request.allowPrivateNetwork`值;将返回的策略重新用于嵌入请求以及批量上传、状态和下载请求。 如果端点记录了输入数组限制,请在创建的提供程序实例上设置可选的 `maxInputsPerRequest` 字段。对所选端点和模型使用正安全整数;未知时省略。在发送内联嵌入请求之前,内存将其限制在该数量,以及现有的字节预算。当端点报告支持的限制错误时,未声明或过时的限制仍使用反应式拆分。无效声明将被忽略。提供者批处理作业有自己的限制。 本机 OpenAI 适配器声明 [2048 输入 ](https://developers.openai.com/api/reference/resources/embeddings/methods/create)。服务[embedding-3](https://docs.bigmodel.cn/cn/guide/models/embedding/embedding-3)的插件可以声明64;请勿将该限制应用于没有文档的其他模型。自定义 OpenAI- 兼容端点未声明。使用 `createRemoteEmbeddingProvider` 的捆绑适配器可以将相同的字段传递给该工厂。此可选字段保留现有插件合约、索引内容和嵌入缓存标识。 `embed` 和 `embedBatch` 接受可选的 `onUsage` 看涨期权。当响应没有有效计数时,报告使用情况的提供程序会在解析之前使用 `{ promptTokens, totalTokens }` 或 `undefined` 对每个成功的上游请求调用一次。调用者可以总结这些报告,并将任何不可用的响应视为不完整的使用。共享远程工厂报告OpenAI-style使用情况;矢量返回值和现有插件保持不变。 接受模型别名的提供者可以公开`normalizeModel(options): string`。内存使用此同步挂钩来进行创建选项和冷索引身份检查。保持仅配置:不验证或访问网络。重复标准化使已经标准化的值保持不变,并在`create`,它可能接收一个已经标准化的模型或称为外部存储器。仅当模型在发现之前仍未知时才返回空字符串;不要将无效的显式模型转变为省略的选择。对于精确的预初始化身份,`resolveIndexIdentity(options)`另外提供所需的`cacheKeyData`以及任何等效的持久别名。 图像和视频能力使用**感知模式**的结构。图像提供方声明必需的 `generate` 和 `edit` 能力块;视频提供方声明 `generate`、`imageToVideo` 和 `videoToVideo`。类似 `maxInputImages`/`maxInputVideos`/`maxDurationSeconds` 的扁平聚合字段不足以清晰地公开变换模式支持或禁用的模式。音乐生成遵循相同的 `generate`/`edit` 模式。 捆绑提供程序可以使用私有 `openclaw/plugin-sdk/video-generation` 子路径中的 `normalizeVideoGenerationDuration({ durationSeconds })` 来舍入可选持续时间,并在舍入后拒绝 1–9007199254740991 秒之外的值。遗漏返回`undefined`;提供商默认值仍归提供商所有。 `selectSupportedVideoDuration` 从非空列表中选择最接近的值,优先选择较长的平局持续时间。在提供者中保留提供者特定的界限。 ```typescript api.registerImageGenerationProvider({ id: "acme-ai", label: "Acme Images", capabilities: { generate: { maxCount: 4, supportsSize: true }, edit: { enabled: false }, }, generateImage: async (req) => ({ images: [ { buffer: await generateAcmeImageBytes(req), mimeType: "image/png", fileName: "acme-image.png", }, ], }), }); api.registerVideoGenerationProvider({ id: "acme-ai", label: "Acme Video", defaultTimeoutMs: 600_000, models: ["acme-video", "acme-image-video"], capabilities: { generate: { maxVideos: 1, maxDurationSeconds: 10, supportsResolution: true }, imageToVideo: { enabled: true, maxVideos: 1, maxInputImages: 1, maxInputImagesByModel: { "acme/reference-to-video": 9 }, maxDurationSeconds: 5, }, videoToVideo: { enabled: false }, }, catalogByModel: { "acme-image-video": { modes: ["imageToVideo"], capabilities: { imageToVideo: { enabled: true, maxVideos: 1, maxInputImages: 1, resolutions: ["480P", "720P", "1080P"], supportsResolution: true, }, videoToVideo: { enabled: false }, }, }, }, generateVideo: async (req) => ({ videos: [ { url: await generateAcmeVideoUrl(req), mimeType: "video/mp4", }, ], }), }); ``` 示例中的辅助函数代表提供方调用:图像辅助函数返回非空的编码字节,而视频辅助函数返回托管媒体 URL。视频提供方也可以改为返回非空的编码字节,或者在 URL 是传递回退时同时返回两者。空结果数组和空缓冲区会被视为候选失败,但当视频资源包含可用 URL 时,会忽略空缓冲区并继续使用该 URL。 两种提供方类型都必须使用 `capabilities`;`edit` 以及视频变换块(`imageToVideo`、`videoToVideo`)始终需要显式的 `enabled` 标志。 当列出的模型的静态模式或能力与提供方默认值不同时,使用 `catalogByModel`。这些元数据可以在不调用提供方代码的情况下,让 `video_generate action=list` 和模型目录保持准确。请求时的能力查找和强制执行仍应放在 `resolveModelCapabilities` 和 `generateVideo` 中;如有可能,两个路径应复用同一个能力常量。 以下 [ 私有本地助手](/plugins/sdk-subpaths#compatibility-and-private-local-helpers) 仅支持捆绑和单独发布的官方插件。 对于异步提供程序作业,来自 `openclaw/plugin-sdk/provider-http` 的 `pollProviderOperation` 共享有界轮询循环,同时插件提供其请求、completion/failure 检查和等待功能。 `pollProviderOperationJson` 添加了标准 HTTP JSON 传输。将供应商身份验证和截止日期范围保留在提供商适配器中。 当自定义正文读取器耗尽相同的截止日期时,重复使用 `createProviderOperationTimeoutError(deadline)`。它以共享错误格式保留操作标签和可选超时。 来自 `openclaw/plugin-sdk/media-generation-runtime` 的 `readGeneratedVideoAsset` 读取字节上限下的响应,并导出资产的 MIME 类型和文件名。设置 `validateBinaryResponse` 以拒绝非视频响应。可选的 `overflowUrl` 仅在主体超过该上限时提供交付;格式错误的媒体和传输错误仍然失败。调用者负责响应清理。 `downloadGeneratedVideoAsset` 还拥有获取、截止日期和清理功能。 ```typescript api.registerWebFetchProvider({ id: "acme-ai-fetch", label: "Acme Fetch", hint: "Fetch pages through Acme's rendering backend.", envVars: ["ACME_FETCH_API_KEY"], placeholder: "acme-...", signupUrl: "https://acme.example.com/fetch", credentialPath: "plugins.entries.acme.config.webFetch.apiKey", getCredentialValue: (fetchConfig) => fetchConfig?.acme?.apiKey, setCredentialValue: (fetchConfigTarget, value) => { const acme = (fetchConfigTarget.acme ??= {}); acme.apiKey = value; }, createTool: () => ({ description: "Fetch a page through Acme Fetch.", parameters: {}, execute: async (args) => ({ content: [] }), }), }); api.registerWebSearchProvider({ id: "acme-ai-search", label: "Acme Search", hint: "Search the web through Acme's search backend.", envVars: ["ACME_SEARCH_API_KEY"], placeholder: "acme-...", signupUrl: "https://acme.example.com/search", credentialPath: "plugins.entries.acme.config.webSearch.apiKey", getCredentialValue: (searchConfig) => searchConfig?.acme?.apiKey, setCredentialValue: (searchConfigTarget, value) => { const acme = (searchConfigTarget.acme ??= {}); acme.apiKey = value; }, createTool: () => ({ description: "Search the web through Acme Search.", parameters: {}, execute: async (args) => ({ content: [] }), }), }); ``` 两种提供方类型共享相同的凭据连接结构: `hint`、`envVars`、`placeholder`、`signupUrl`、`credentialPath`、 `getCredentialValue`、`setCredentialValue` 和 `createTool` 都是必需的。 搜索提供商可以将 `configPath` 声明为相对于其自己的搜索设置页面插件配置的路径。默认为`["webSearch"]`;当提供者没有内联设置时使用 `null`。共享插件的提供者可以公开不同的设置,而不显示仅适用于同级提供者的字段。凭证仍由 `credentialPath` 描述,并使用现有的屏蔽凭证编辑器。 使用 `openclaw/plugin-sdk/provider-web-search` 的搜索提供程序应在每次执行时解析一次 `resolveSearchCacheTtlMs(searchConfig)`,并将该值传递给 `readCachedSearchPayload(cacheKey, ttlMs)` 和 `writeCachedSearchPayload(cacheKey, payload, ttlMs)`。零 TTL 绕过读取和写入;正值 TTL 限制了进入年龄,但不延长其原始有效期。读取返回标记为 `cached: true` 的有效负载,或未命中时返回标记为 `undefined` 的有效负载。读者的 `ttlMs` 参数是可选的:现有的单参数调用继续单独使用存储的到期日。 两个工具定义都接受 `execute(args, context?)`,其中可选上下文携带 `signal?: AbortSignal`。将该信号转发给网络请求并在异步工作后检查取消情况。现有的单参数实现仍然有效; OpenClaw 在取消后拒绝延迟获取结果,然后再将其发布到其获取缓存。