From ead0e22c601c12a3bf4b4cb57061518946159141 Mon Sep 17 00:00:00 2001 From: MyPrototypeWhat Date: Mon, 25 Aug 2025 19:46:51 +0800 Subject: [PATCH] [WIP]refactor(aiCore): restructure models and introduce ModelResolver - Removed outdated ConfigManager and factory files to streamline model management. - Added ModelResolver for improved model ID resolution, supporting both traditional and namespaced formats. - Introduced DynamicProviderRegistry for dynamic provider management, enhancing flexibility in model handling. - Updated index exports to reflect the new structure and maintain compatibility with existing functionality. --- .../aiCore/src/core/models/ConfigManager.ts | 37 ----- .../aiCore/src/core/models/ModelResolver.ts | 110 ++++++++++++++ packages/aiCore/src/core/models/factory.ts | 45 ------ packages/aiCore/src/core/models/index.ts | 17 +-- .../core/providers/DynamicProviderRegistry.ts | 136 ++++++++++++++++++ packages/aiCore/src/core/providers/index.ts | 51 +++---- packages/aiCore/src/core/runtime/executor.ts | 25 ++-- 7 files changed, 280 insertions(+), 141 deletions(-) delete mode 100644 packages/aiCore/src/core/models/ConfigManager.ts create mode 100644 packages/aiCore/src/core/models/ModelResolver.ts delete mode 100644 packages/aiCore/src/core/models/factory.ts create mode 100644 packages/aiCore/src/core/providers/DynamicProviderRegistry.ts diff --git a/packages/aiCore/src/core/models/ConfigManager.ts b/packages/aiCore/src/core/models/ConfigManager.ts deleted file mode 100644 index bfcb91862e..0000000000 --- a/packages/aiCore/src/core/models/ConfigManager.ts +++ /dev/null @@ -1,37 +0,0 @@ -// /** -// * 配置管理器 -// * 整合options、plugins、middlewares等配置 -// */ -// import { LanguageModelV2Middleware } from '@ai-sdk/provider' - -// import { ProviderId, ProviderSettingsMap } from '../../types' -// import { createMiddlewares } from '../middleware/manager' -// import { AiPlugin } from '../plugins' -// import { ResolvedConfig } from './types' - -// /** -// * 解析配置 -// * 整合provider配置、插件、中间件、provider选项等 -// */ -// export function resolveConfig( -// providerId: ProviderId, -// modelId: string, -// providerSettings: ProviderSettingsMap[ProviderId], -// plugins: AiPlugin[] = [], -// middlewares: LanguageModelV2Middleware[] = [] -// ): ResolvedConfig { -// // 使用独立的中间件管理器处理中间件 -// const resolvedMiddlewares = createMiddlewares(middlewares) - -// return { -// provider: { -// id: providerId, -// options: providerSettings -// }, -// model: { -// id: modelId -// }, -// plugins, -// middlewares: resolvedMiddlewares -// } -// } diff --git a/packages/aiCore/src/core/models/ModelResolver.ts b/packages/aiCore/src/core/models/ModelResolver.ts new file mode 100644 index 0000000000..f0f2974a88 --- /dev/null +++ b/packages/aiCore/src/core/models/ModelResolver.ts @@ -0,0 +1,110 @@ +/** + * 模型解析器 - models模块的核心 + * 负责将modelId解析为AI SDK的LanguageModel实例 + * 支持传统格式和命名空间格式 + */ + +import { EmbeddingModelV2, ImageModelV2, LanguageModelV2 } from '@ai-sdk/provider' + +import { globalDynamicRegistry } from '../providers/DynamicProviderRegistry' + +export class ModelResolver { + /** + * 核心方法:解析任意格式的modelId为语言模型 + * + * @param modelId 模型ID,支持 'gpt-4' 和 'anthropic>claude-3' 两种格式 + * @param fallbackProviderId 当modelId为传统格式时使用的providerId + * @param providerOptions provider配置选项(暂时保留,可能在未来使用) + */ + async resolveLanguageModel( + modelId: string, + fallbackProviderId: string, + _providerOptions?: any + ): Promise { + // 检查是否是命名空间格式 (aihubmix>anthropic>claude-3) + if (modelId.includes('>')) { + return this.resolveNamespacedModel(modelId) + } + + // 传统格式:使用fallbackProviderId + modelId (openai + gpt-4) + return this.resolveTraditionalModel(fallbackProviderId, modelId) + } + + /** + * 解析文本嵌入模型 + */ + async resolveTextEmbeddingModel( + modelId: string, + fallbackProviderId: string, + _providerOptions?: any + ): Promise> { + if (modelId.includes('>')) { + return this.resolveNamespacedEmbeddingModel(modelId) + } + + return this.resolveTraditionalEmbeddingModel(fallbackProviderId, modelId) + } + + /** + * 解析图像模型 + */ + async resolveImageModel(modelId: string, fallbackProviderId: string, _providerOptions?: any): Promise { + if (modelId.includes('>')) { + return this.resolveNamespacedImageModel(modelId) + } + + return this.resolveTraditionalImageModel(fallbackProviderId, modelId) + } + + /** + * 解析命名空间格式的语言模型 + * aihubmix>anthropic>claude-3 -> globalDynamicRegistry.languageModel('aihubmix>anthropic>claude-3') + */ + private resolveNamespacedModel(modelId: string): LanguageModelV2 { + return globalDynamicRegistry.languageModel(modelId) + } + + /** + * 解析传统格式的语言模型 + * providerId: 'openai', modelId: 'gpt-4' -> globalDynamicRegistry.languageModel('openai>gpt-4') + */ + private resolveTraditionalModel(providerId: string, modelId: string): LanguageModelV2 { + const fullModelId = `${providerId}>${modelId}` + return globalDynamicRegistry.languageModel(fullModelId) + } + + /** + * 解析命名空间格式的嵌入模型 + */ + private resolveNamespacedEmbeddingModel(modelId: string): EmbeddingModelV2 { + return globalDynamicRegistry.textEmbeddingModel(modelId) + } + + /** + * 解析传统格式的嵌入模型 + */ + private resolveTraditionalEmbeddingModel(providerId: string, modelId: string): EmbeddingModelV2 { + const fullModelId = `${providerId}>${modelId}` + return globalDynamicRegistry.textEmbeddingModel(fullModelId) + } + + /** + * 解析命名空间格式的图像模型 + */ + private resolveNamespacedImageModel(modelId: string): ImageModelV2 { + return globalDynamicRegistry.imageModel(modelId) + } + + /** + * 解析传统格式的图像模型 + */ + private resolveTraditionalImageModel(providerId: string, modelId: string): ImageModelV2 { + const fullModelId = `${providerId}>${modelId}` + return globalDynamicRegistry.imageModel(fullModelId) + } +} + +/** + * 全局模型解析器实例 + */ +export const globalModelResolver = new ModelResolver() diff --git a/packages/aiCore/src/core/models/factory.ts b/packages/aiCore/src/core/models/factory.ts deleted file mode 100644 index 835ae606b9..0000000000 --- a/packages/aiCore/src/core/models/factory.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * 模型工厂函数 - * 统一的模型创建和配置管理 - */ -import { LanguageModelV2 } from '@ai-sdk/provider' -import { LanguageModel } from 'ai' - -import { wrapModelWithMiddlewares } from '../middleware' -import { createBaseModel } from './ModelCreator' -import { ModelConfig } from './types' - -/** - * 创建模型 - 核心函数 - */ -export async function createModel(config: ModelConfig): Promise { - validateModelConfig(config) - - // 1. 创建基础模型 - const baseModel = await createBaseModel(config) - - // 2. 应用中间件(如果有) - return config.middlewares?.length ? wrapModelWithMiddlewares(baseModel, config.middlewares) : baseModel -} - -/** - * 批量创建模型 - */ -export async function createModels(configs: ModelConfig[]): Promise { - return Promise.all(configs.map((config) => createModel(config))) -} - -/** - * 验证模型配置 - */ -function validateModelConfig(config: ModelConfig): void { - if (!config.providerId) { - throw new Error('ModelConfig: providerId is required') - } - if (!config.modelId) { - throw new Error('ModelConfig: modelId is required') - } - if (!config.providerSettings) { - throw new Error('ModelConfig: providerSettings is required') - } -} diff --git a/packages/aiCore/src/core/models/index.ts b/packages/aiCore/src/core/models/index.ts index 38273140f0..439d3d0f41 100644 --- a/packages/aiCore/src/core/models/index.ts +++ b/packages/aiCore/src/core/models/index.ts @@ -1,18 +1,9 @@ /** - * Models 模块统一导出 + * Models 模块统一导出 - 简化版 */ -// Model 创建相关 -export { - createBaseModel, - createImageModel, - getProviderInfo, - getSupportedProviders, - ModelCreationError -} from './ModelCreator' +// 核心模型解析器 +export { globalModelResolver, ModelResolver } from './ModelResolver' -// Model 配置和工厂 -export { createModel } from './factory' - -// 类型定义 +// 保留的类型定义(可能被其他地方使用) export type { ModelConfig as ModelConfigType } from './types' diff --git a/packages/aiCore/src/core/providers/DynamicProviderRegistry.ts b/packages/aiCore/src/core/providers/DynamicProviderRegistry.ts new file mode 100644 index 0000000000..bd44e55780 --- /dev/null +++ b/packages/aiCore/src/core/providers/DynamicProviderRegistry.ts @@ -0,0 +1,136 @@ +/** + * 动态Provider注册表 - 完全基于AI SDK原生 + * 每次变更都重建registry,让AI SDK处理所有逻辑 + */ + +import { EmbeddingModelV2, ImageModelV2, LanguageModelV2, ProviderV2 } from '@ai-sdk/provider' +import { createProviderRegistry } from 'ai' + +export class DynamicProviderRegistry { + private providers: Record = {} + private separator: string + private registry: any | null = null + + constructor(options: { separator?: string } = {}) { + this.separator = options.separator || '>' + } + + /** + * 动态注册provider - 立即重建registry + */ + registerProvider(id: string, provider: ProviderV2): this { + this.providers[id] = provider + this.rebuildRegistry() + return this + } + + /** + * 批量注册providers + */ + registerProviders(providers: Record): this { + Object.assign(this.providers, providers) + this.rebuildRegistry() + return this + } + + /** + * 移除provider + */ + unregisterProvider(id: string): this { + delete this.providers[id] + this.rebuildRegistry() + return this + } + + /** + * 立即重建registry - 每次变更都重建 + */ + private rebuildRegistry(): void { + if (Object.keys(this.providers).length === 0) { + this.registry = null + return + } + + this.registry = createProviderRegistry(this.providers, { + separator: this.separator + }) + } + + /** + * 获取语言模型 - AI SDK原生方法 + */ + languageModel(id: string): LanguageModelV2 { + if (!this.registry) { + throw new Error('No providers registered') + } + return this.registry.languageModel(id) + } + + /** + * 获取文本嵌入模型 - AI SDK原生方法 + */ + textEmbeddingModel(id: string): EmbeddingModelV2 { + if (!this.registry) { + throw new Error('No providers registered') + } + return this.registry.textEmbeddingModel(id) + } + + /** + * 获取图像模型 - AI SDK原生方法 + */ + imageModel(id: string): ImageModelV2 { + if (!this.registry) { + throw new Error('No providers registered') + } + return this.registry.imageModel(id) + } + + /** + * 获取转录模型 - AI SDK原生方法 + */ + transcriptionModel(id: string): any { + if (!this.registry) { + throw new Error('No providers registered') + } + return this.registry.transcriptionModel(id) + } + + /** + * 获取语音模型 - AI SDK原生方法 + */ + speechModel(id: string): any { + if (!this.registry) { + throw new Error('No providers registered') + } + return this.registry.speechModel(id) + } + + /** + * 获取已注册的provider列表 + */ + getRegisteredProviders(): string[] { + return Object.keys(this.providers) + } + + /** + * 检查是否有已注册的providers + */ + hasProviders(): boolean { + return Object.keys(this.providers).length > 0 + } + + /** + * 清除所有providers + */ + clear(): this { + this.providers = {} + this.registry = null + return this + } +} + +/** + * 全局动态registry实例 + */ +export const globalDynamicRegistry = new DynamicProviderRegistry({ separator: '>' }) diff --git a/packages/aiCore/src/core/providers/index.ts b/packages/aiCore/src/core/providers/index.ts index 6dab65805b..59c3b1ce89 100644 --- a/packages/aiCore/src/core/providers/index.ts +++ b/packages/aiCore/src/core/providers/index.ts @@ -1,41 +1,22 @@ /** - * Providers 模块统一导出 + * Providers 模块统一导出 - 现代化架构 */ -// Provider 注册表 -export { - aiProviderRegistry, - getAllProviders, - getAllValidProviderIds, - getProvider, - isProviderSupported, - registerProvider, - validateProviderIdRegistry -} from './registry' +// ==================== 新版动态Registry(推荐使用)==================== -// Provider 创建 +// 基于AI SDK原生的动态Provider注册表 +export { DynamicProviderRegistry, globalDynamicRegistry } from './DynamicProviderRegistry' + +// ==================== 保留的导出(兼容性)==================== + +// 基础Provider数据源 +export { baseProviderIds, baseProviders } from './schemas' + +// 类型定义(可能被其他模块使用) +export type { ProviderConfig, ProviderId, ProviderSettingsMap } from './types' + +// Provider创建功能(可能被其他地方使用) export { createImageProvider, createProvider, ProviderCreationError, validateProviderConfig } from './creator' -// 类型定义 -export type { - BaseProviderId, - DynamicProviderId, - DynamicProviderRegistration, - ProviderConfig, - ProviderError, - ProviderId, - ProviderSettingsMap -} from './types' - -// Zod Schemas 和验证 -export { - baseProviderIds, - baseProviders, - isBaseProviderId, - isValidDynamicProviderId, - validateDynamicProviderRegistration, - validateProviderId -} from './schemas' - -// 工厂和配置 -export * from './factory' +// 验证功能(可能被其他地方使用) +export { validateProviderId } from './schemas' diff --git a/packages/aiCore/src/core/runtime/executor.ts b/packages/aiCore/src/core/runtime/executor.ts index 0cc1b331f9..0ee79e1b4f 100644 --- a/packages/aiCore/src/core/runtime/executor.ts +++ b/packages/aiCore/src/core/runtime/executor.ts @@ -13,7 +13,8 @@ import { } from 'ai' import { type ProviderId } from '../../types' -import { createImageModel, createModel, getProviderInfo } from '../models' +import { globalModelResolver } from '../models' +import { getProviderInfo } from '../models/ModelCreator' import { type ModelConfig } from '../models/types' import { type AiPlugin, type AiRequestContext, definePlugin } from '../plugins' import { ImageGenerationError, ImageModelResolutionError } from './errors' @@ -275,14 +276,12 @@ export class RuntimeExecutor { extraModelConfig?: Record ): Promise { if (typeof modelOrId === 'string') { - // 字符串modelId,需要创建模型 - return await createModel({ - providerId: this.config.providerId, - modelId: modelOrId, - providerSettings: this.config.providerSettings, - middlewares, - extraModelConfig - }) + // 字符串modelId,使用新的ModelResolver解析 + return await globalModelResolver.resolveLanguageModel( + modelOrId, // 支持 'gpt-4' 和 'aihubmix>anthropic>claude-3' + this.config.providerId, // fallback provider + this.config.providerSettings // provider options + ) } else { // 已经是模型,直接返回 return modelOrId @@ -295,8 +294,12 @@ export class RuntimeExecutor { private async resolveImageModel(modelOrId: ImageModelV2 | string): Promise { try { if (typeof modelOrId === 'string') { - // 字符串modelId,需要创建图像模型 - return await createImageModel(this.config.providerId, modelOrId, this.config.providerSettings) + // 字符串modelId,使用新的ModelResolver解析 + return await globalModelResolver.resolveImageModel( + modelOrId, // 支持 'dall-e-3' 和 'aihubmix>openai>dall-e-3' + this.config.providerId, // fallback provider + this.config.providerSettings // provider options + ) } else { // 已经是模型,直接返回 return modelOrId