feat: add OpenAI Compatible provider and enhance provider configuration

- Introduced a new OpenAI Compatible provider to the AiProviderRegistry, allowing for integration with the @ai-sdk/openai-compatible package.
- Updated provider configuration logic to support the new provider, including adjustments to API host formatting and options management.
- Refactored middleware to streamline handling of OpenAI-specific configurations.
This commit is contained in:
suyao 2025-06-21 22:19:10 +08:00
parent e421b81fca
commit 09080f0755
No known key found for this signature in database
3 changed files with 24 additions and 4 deletions

View File

@ -106,6 +106,13 @@ export class AiProviderRegistry {
creatorFunctionName: 'createOpenAI',
supportsImageGeneration: true
},
{
id: 'openai-compatible',
name: 'OpenAI Compatible',
import: () => import('@ai-sdk/openai-compatible'),
creatorFunctionName: 'createOpenAICompatible',
supportsImageGeneration: true
},
{
id: 'anthropic',
name: 'Anthropic',

View File

@ -20,6 +20,8 @@ import {
import { isDedicatedImageGenerationModel } from '@renderer/config/models'
import { createVertexProvider, isVertexAIConfigured, isVertexProvider } from '@renderer/hooks/useVertexAI'
import type { GenerateImageParams, Model, Provider } from '@renderer/types'
import { formatApiHost } from '@renderer/utils/api'
import { cloneDeep } from 'lodash'
import AiSdkToChunkAdapter from './AiSdkToChunkAdapter'
import LegacyAiProvider from './index'
@ -35,7 +37,7 @@ function providerToAiSdkConfig(provider: Provider): {
options: ProviderSettingsMap[keyof ProviderSettingsMap]
} {
// 如果是 vertexai 类型且没有 googleCredentials转换为 VertexProvider
let actualProvider = provider
let actualProvider = cloneDeep(provider)
if (provider.type === 'vertexai' && !isVertexProvider(provider)) {
if (!isVertexAIConfigured()) {
throw new Error('VertexAI is not configured. Please configure project, location and service account credentials.')
@ -43,10 +45,17 @@ function providerToAiSdkConfig(provider: Provider): {
actualProvider = createVertexProvider(provider)
}
if (actualProvider.type === 'openai') {
actualProvider.apiHost = formatApiHost(actualProvider.apiHost)
}
const aiSdkProviderId = getAiSdkProviderId(actualProvider)
if (aiSdkProviderId !== 'openai-compatible') {
const options = ProviderConfigFactory.fromProvider(aiSdkProviderId, actualProvider)
const options = ProviderConfigFactory.fromProvider(aiSdkProviderId, {
...actualProvider,
baseURL: actualProvider.apiHost
})
return {
providerId: aiSdkProviderId as ProviderId,
@ -58,7 +67,10 @@ function providerToAiSdkConfig(provider: Provider): {
return {
providerId: 'openai-compatible',
options
options: {
...options,
name: actualProvider.id
}
}
}
}
@ -112,6 +124,7 @@ export default class ModernAiProvider {
// 检查是否应该使用现代化客户端
// if (this.modernClient && model && isModernSdkSupported(this.provider, model)) {
// try {
console.log('completions', modelId, params, middlewareConfig)
return await this.modernCompletions(modelId, params, middlewareConfig)
// } catch (error) {
// console.warn('Modern client failed, falling back to legacy:', error)

View File

@ -142,7 +142,7 @@ function addProviderSpecificMiddlewares(builder: AiSdkMiddlewareBuilder, config:
case 'openai':
builder.add({
name: 'thinking-tag-extraction',
aiSdkMiddlewares: [extractReasoningMiddleware({ tagName: 'think', separator: '\n', startWithReasoning: true })]
aiSdkMiddlewares: [extractReasoningMiddleware({ tagName: 'think' })]
})
break
case 'gemini':