Cherry Studio ai-core 新增 Rerank 运行时:OpenAI 兼容重排模型接入指南
【免费下载链接】cherry-studioAI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs项目地址: https://gitcode.com/GitHub_Trending/ch/cherry-studio
导读
本文围绕 Cherry Studio 仓库中@cherrystudio/ai-core包的 changeset 变更(.changeset/aicore-rerank-runtime.md),完整解析其引入的 rerank(重排序)运行时支持:包括rerank运行时辅助函数、RerankParams/RerankResult类型、RuntimeExecutor.rerank方法,以及面向 OpenAI 兼容服务商的OpenAICompatibleRerankingModel提供者模型(含createOpenAICompatibleRerankingModel及其配置/设置类型)。读完本文,你将掌握如何在 Cherry Studio 的 ai-core 运行时中调用重排模型、理解底层请求/响应协议与校验规则,以及 Provider 扩展如何把重排能力挂载到统一运行时上。该功能在项目中主要用于 RAG(检索增强生成)场景下对候选文档进行二次精排,也服务于知识库检索结果的排序优化。
变更概览:一次 patch 级别的运行时能力扩充
该 changeset 声明对@cherrystudio/ai-core包的影响级别为patch,核心内容是:
Add rerank runtime support. Exposes a
rerankruntime helper (plusRerankParams/RerankResulttypes andRuntimeExecutor.rerank) and anOpenAICompatibleRerankingModelprovider model (withcreateOpenAICompatibleRerankingModeland its config/settings types) so OpenAI-compatible providers can serve reranking through the standard runtime.
由此可归纳出本次变更交付的两大能力面:
- 运行时(Runtime)层:新增
rerank辅助函数与RuntimeExecutor.rerank方法,并配套RerankParams/RerankResult类型,使重排调用与既有的streamText、generateText、generateImage、embedMany等能力并列,统一走 ai-core 的运行时管线。 - 提供者模型(Provider Model)层:新增 OpenAI 兼容的
OpenAICompatibleRerankingModel及工厂函数createOpenAICompatibleRerankingModel,让任何遵循 OpenAI 兼容协议的服务商(如 Jina、Cohere 等提供/rerank端点的服务)都能通过标准运行时对外提供重排能力。
Runtime 层:rerank 如何接入统一执行器
导出链路与公开 API
rerank从 ai-core 包顶部即作为一等公民导出:
- packages/aiCore/src/index.ts 从
./core/runtime导出rerank函数以及RerankParams、RerankResult等类型; - packages/aiCore/src/core/runtime/index.ts 提供顶层
rerank(providerId, options, params, plugins?)便捷函数,内部先经extensionRegistry创建对应 provider 的RuntimeExecutor,再委托给executor.rerank(params); - packages/aiCore/src/core/runtime/types.ts 定义了
RerankParams与RerankResult类型。
RerankParams的定义要点(见 types.ts):
export type RerankParams<VALUE extends JSONObject | string = string> = Omit< Parameters<typeof rerank<VALUE>>[0], 'model' > & { model: string | RerankingModelV3 onProviderCall?: RuntimeProviderCallHandler }关键设计:
- 泛型
VALUE默认为string,也可为JSONObject,对应 AI SDKrerank的输入文档类型; model字段支持字符串模型 ID或预创建的RerankingModelV3实例两种形态,字符串 ID 会通过 RuntimeExecutor 的 provider 注册表解析;- 额外提供
onProviderCall?: RuntimeProviderCallHandler观测回调,用于采集重排调用的运行时指标。
RuntimeExecutor.rerank 的实现
核心实现在 packages/aiCore/src/core/runtime/executor.ts:
async rerank<VALUE extends JSONObject | string = string>(params: RerankParams<VALUE>): Promise<RerankResult<VALUE>> { const { model: modelOrId, onProviderCall, ...options } = params const rerankingModel = typeof modelOrId === 'string' ? this.registry.rerankingModel(`${this.config.providerId}:${modelOrId}` as `${string}:${string}`) : modelOrId const startedAt = performance.now() const result = await _rerank<VALUE>({ model: rerankingModel, ...options }) emitProviderCall(onProviderCall, { modality: 'rerank', requestId: `ai-core:rerank:${crypto.randomUUID()}`, providerId: this.config.providerId, modelId: rerankingModel.modelId, metrics: { timeCompletionMs: Math.max(0, Math.round(performance.now() - startedAt)) }, completedAt: Date.now() }) return result }其行为要点:
- 字符串模型 ID 解析:
RuntimeExecutor内部通过createProviderRegistry构建了以providerId为键的 provider 注册表(见 executor.ts),此处以`${providerId}:${modelId}`的形式调用registry.rerankingModel(...),与embedMany的字符串解析路径完全对齐; - 预创建模型直通:若调用方直接传入
RerankingModelV3实例,则跳过注册表,直接委托给 AI SDK 的_rerank; - 可观测性:重排完成(无论成功与否都通过 best-effort 方式触发)后,向
onProviderCall发出modality: 'rerank'事件,携带providerId、modelId、timeCompletionMs、completedAt与requestId。事件类型定义见 types.ts,其emitProviderCall的容错逻辑(异常不影响 AI 结果)见 executor.ts。
典型调用示例
import { createExecutor, rerank } from '@cherrystudio/ai-core' // 方式一:顶层便捷函数(自动创建 executor) const result = await rerank('openai-compatible', { apiKey: 'YOUR_API_KEY', baseURL: 'https://api.example.com/v1', name: 'my-reranker-provider' }, { model: 'jina-reranker-v2-base-multilingual', query: '什么是重排序模型?', documents: ['候选文档A……', '候选文档B……', '候选文档C……'], topN: 2, maxRetries: 0, headers: { 'x-custom': 'value' }, providerOptions: { jina: { returnDocuments: false } }, onProviderCall: (event) => console.log(event.metrics.timeCompletionMs) }) console.log(result.rerankedDocuments) // 按相关性降序的文档数组 console.log(result.ranking) // [{ originalIndex, score, document }]参数说明(对应 AI SDKrerank的标准参数,均可透传):
| 参数 | 说明 | 取值/默认 |
|---|---|---|
model | 模型 ID 字符串或RerankingModelV3实例 | 必填 |
query | 查询文本 | 必填 |
documents | 待排序文档数组(string[]或JSONObject[]) | 必填 |
topN | 返回前 N 个结果,可选 | 由服务端决定 |
headers | 附加请求头 | 可选 |
maxRetries | 最大重试次数 | 可选,默认由 AI SDK 决定 |
providerOptions | 服务商特定选项 | 可选 |
abortSignal | 中止信号 | 可选 |
onProviderCall | ai-core 扩展的观测回调 | 可选 |
Provider 模型层:OpenAICompatibleRerankingModel
工厂函数与类型
createOpenAICompatibleRerankingModel(modelId, settings)及配套类型定义在 packages/ai-sdk-provider/src/openai-compatible-reranking-model.ts,并经由 packages/aiCore/src/core/providers/openaiCompatible/rerankingModel.ts 从@cherrystudio/ai-sdk-provider原样再导出,供 ai-core 内部统一引用。
OpenAICompatibleRerankingModelSettings从OpenAICompatibleProviderSettings中挑选了与重排最相关的字段(见 openai-compatible-reranking-model.ts):
| 设置项 | 作用 |
|---|---|
name | 提供者名称,用于生成 provider 标识(见下文) |
baseURL | 服务端基础地址,必填,缺省会直接抛错 |
apiKey | 密钥,存在时以Authorization: Bearer <apiKey>发送 |
headers | 自定义请求头,与上述 Authorization 合并 |
queryParams | 附加到 URL 的查询参数 |
fetch | 自定义 fetch 实现(可用于代理、日志等) |
OpenAICompatibleRerankingModelConfig则是模型实例的底层配置(provider 标识、URL 构造器、header 工厂、fetch),由工厂函数内部生成,通常无需调用方直接构造。
doRerank:请求与响应协议
模型实现RerankingModelV3(specificationVersion = 'v3'),核心逻辑位于doRerank(见 openai-compatible-reranking-model.ts):
- 输入约束:仅接受
documents.type === 'text'的文本文档,否则抛出 "OpenAI-compatible reranking model only supports text documents"; - 请求构造:POST 到
url({ path: '/rerank', modelId }),请求体为:
{ "model": "<modelId>", "query": "<query>", "documents": ["<doc1>", "<doc2>"], "top_n": 2 }- 响应解析:期望响应体形如
{ "results": [{ "index": 0, "relevance_score": 0.9 }, ...] },由parseRerankResponse转换为{ index, relevanceScore }数组。
响应校验规则
parseRerankResponse(见 openai-compatible-rerank-model.ts)对服务端响应做了严格校验,任何不满足都会抛错:
- 响应必须包含
results数组; - 每个
results元素必须是对象; index与relevance_score必须是数字;index必须是非负整数,且小于本次请求的文档总数(documentCount),防止越界引用。
这些校验保证了上游服务返回脏数据时不会静默污染下游排序结果。
provider 标识与 URL 细节
工厂函数createOpenAICompatibleRerankingModel(见 openai-compatible-reranking-model.ts)还有两个值得注意的实现细节:
- provider 标识:固定为
`${settings.name}.rerank`,因此来自openai-compatible提供者的重排模型,其 provider 为openai-compatible.rerank,测试用例也对此做了断言(见 rerankingModel.test.ts); - baseURL 归一化:先经
withoutTrailingSlash去掉末尾斜杠,再拼接/rerank路径,随后应用queryParams;若baseURL缺失则直接抛错 "OpenAI-compatible reranking model requires baseURL"。
与 Provider 扩展体系的集成
重排能力并非孤立存在,而是通过 ai-core 的ProviderExtension体系自动挂载到每个 OpenAI 兼容 provider 上:
- ProviderExtension.ts 的扩展配置新增可选钩子
createRerankingModel?: (modelId, settings) => RerankingModelV3; - 在创建 provider 的
_doCreateProvider流程中,基座 provider 与 variant 变换后的最终 provider 都会调用attachRerankingModel(见 ProviderExtension.ts); attachRerankingModel的语义是:仅在createRerankingModel已配置且目标 provider 尚未原生暴露rerankingModel时,才为其补挂provider.rerankingModel = (modelId) => createRerankingModel(modelId, settings)。也就是说,如果某个 SDK 自身已提供原生重排模型,则不会覆盖。
对于openai-compatible扩展,钩子实现在 initialization.ts,其内部使用createLazyOpenAICompatibleRerankingModel:
- 该函数返回一个 v3 占位模型(见 initialization.ts),
doRerank首次被调用时才通过动态import('../openaiCompatible/rerankingModel')惰性加载真实实现,避免在未使用重排时拉入额外代码; - 同时它再次校验
baseURL,确保配置完整性。
这意味着:只要通过 ai-core 的扩展机制创建 OpenAI 兼容 provider,RuntimeExecutor.rerank中`providerId:modelId`的字符串解析路径即可直接工作,无需调用方手动装配模型。
测试验证:三条关键路径均有覆盖
仓库为本次变更提供了完整的测试佐证:
- 字符串模型 ID 经
provider.rerankingModel解析:测试resolves a string model id through provider.rerankingModel(见 packages/aiCore/src/core/runtime/tests/rerank.test.ts)断言mockProvider.rerankingModel收到模型 ID,且 AI SDKrerank收到解析后的模型实例与完整参数(query、documents、topN、headers、maxRetries、providerOptions、abortSignal); - 预创建模型直通:测试
accepts a pre-created reranking model(见 rerank.test.ts)确认传入RerankingModelV3实例时不会再次触发 provider 的rerankingModel工厂; - 注册表路径:测试
resolves CherryIN rerank models through the provider registry(见 rerank.test.ts)验证了通过createExecutor('cherryin', { endpointType: 'jina-rerank' })创建的执行器能正确解析BAAI/bge-reranker-v2-m3(free)这类模型 ID,生成provider: 'cherryin.rerank'的模型实例。
此外,createOpenAICompatibleRerankingModel的再导出行为也有专门测试覆盖(见 packages/aiCore/src/core/providers/openaiCompatible/tests/rerankingModel.test.ts)。
使用前提与注意事项
- 服务端协议要求:目标服务商必须提供 OpenAI 兼容的
POST {baseURL}/rerank端点,并返回results: [{ index, relevance_score }]结构,同时要求index为文档数组内的合法下标; - 输入类型限制:当前实现仅支持文本文档(
documents.type === 'text'),传入其他类型(如图像)会抛错; - baseURL 是硬性要求:
createOpenAICompatibleRerankingModel与扩展钩子都会在缺少baseURL时抛错; - 事件观测为 best-effort:
onProviderCall回调内的异常会被静默吞掉,不会影响重排结果本身; - AI SDK 版本前提:类型定义明确基于 AI SDK v6(
types.ts中注释 "AI SDK v6 only has embedMany, no embed"),rerank运行时包装的也是该版本 SDK 的rerank函数。
小结
aicore-rerank-runtime这一变更让 Cherry Studio 的 ai-core 包在streamText、generateImage、embedMany之外补齐了第四种运行时能力——重排序。它既提供了对调用方友好的rerank辅助函数与类型安全的RerankParams/RerankResult,又通过ProviderExtension.createRerankingModel钩子 + 懒加载占位模型,让任意 OpenAI 兼容服务商的/rerank端点零成本接入统一运行时,并全程附带可观测指标与严格的响应校验。对于知识库、RAG 流水线或任何需要"先召回、后精排"的检索场景,这一能力可直接复用 ai-core 既有的 provider 注册表与插件管线,是值得优先采用的统一入口。
【免费下载链接】cherry-studioAI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs项目地址: https://gitcode.com/GitHub_Trending/ch/cherry-studio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考