refactor(ocr): restructure ocr provider config handling

move provider configs from individual providers to a centralized config map
add migration for new ocr config structure
This commit is contained in:
icarus 2025-10-20 01:26:37 +08:00
parent 90e02e64b7
commit 9386a4d482
5 changed files with 69 additions and 25 deletions

View File

@ -1,10 +1,14 @@
import type {
BuiltinOcrProvider,
BuiltinOcrProviderId,
OcrOvConfig,
OcrOvProvider,
OcrPpocrConfig,
OcrPpocrProvider,
OcrProviderCapability,
OcrSystemConfig,
OcrSystemProvider,
OcrTesseractConfig,
OcrTesseractProvider,
TesseractLangCode,
TranslateLanguageCode
@ -17,22 +21,12 @@ const tesseract: OcrTesseractProvider = {
name: 'Tesseract',
capabilities: {
image: true
},
config: {
langs: {
chi_sim: true,
chi_tra: true,
eng: true
}
}
} as const
const systemOcr: OcrSystemProvider = {
id: 'system',
name: 'System',
config: {
langs: isWin ? ['en-us'] : undefined
},
capabilities: {
image: true
// pdf: true
@ -42,9 +36,6 @@ const systemOcr: OcrSystemProvider = {
const ppocrOcr: OcrPpocrProvider = {
id: 'paddleocr',
name: 'PaddleOCR',
config: {
apiUrl: ''
},
capabilities: {
image: true
// pdf: true
@ -54,15 +45,31 @@ const ppocrOcr: OcrPpocrProvider = {
const ovOcr: OcrOvProvider = {
id: 'ovocr',
name: 'Intel OV(NPU) OCR',
config: {
langs: isWin ? ['en-us', 'zh-cn'] : undefined
},
capabilities: {
image: true
// pdf: true
}
} as const satisfies OcrOvProvider
export const BUILTIN_OCR_PROVIDER_CONFIG_MAP = {
tesseract: {
langs: {
chi_sim: true,
chi_tra: true,
eng: true
}
} satisfies OcrTesseractConfig,
system: {
langs: isWin ? ['en-us'] : undefined
} satisfies OcrSystemConfig,
paddleocr: {
apiUrl: ''
} satisfies OcrPpocrConfig,
ovocr: {
langs: isWin ? ['en-us', 'zh-cn'] : undefined
} satisfies OcrOvConfig
} as const satisfies Record<BuiltinOcrProviderId, any>
export const BUILTIN_OCR_PROVIDERS_MAP = {
tesseract,
system: systemOcr,

View File

@ -69,7 +69,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
version: 163,
version: 164,
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs'],
migrate
},

View File

@ -11,7 +11,12 @@ import {
isNotSupportedTextDelta,
SYSTEM_MODELS
} from '@renderer/config/models'
import { BUILTIN_OCR_PROVIDERS, BUILTIN_OCR_PROVIDERS_MAP, DEFAULT_OCR_PROVIDER } from '@renderer/config/ocr'
import {
BUILTIN_OCR_PROVIDER_CONFIG_MAP,
BUILTIN_OCR_PROVIDERS,
BUILTIN_OCR_PROVIDERS_MAP,
DEFAULT_OCR_PROVIDER
} from '@renderer/config/ocr'
import {
isSupportArrayContentProvider,
isSupportDeveloperRoleProvider,
@ -31,7 +36,7 @@ import type {
TranslateLanguageCode,
WebSearchProvider
} from '@renderer/types'
import { isSystemProvider, SystemProviderIds } from '@renderer/types'
import { isBuiltinOcrProvider, isSystemProvider, SystemProviderIds } from '@renderer/types'
import { getDefaultGroupName, getLeadingEmoji, runAsyncFunction, uuid } from '@renderer/utils'
import { defaultByPassRules } from '@shared/config/constant'
import { TRANSLATE_PROMPT } from '@shared/config/prompts'
@ -2233,6 +2238,7 @@ const migrateConfig = {
},
'137': (state: RootState) => {
try {
// @ts-expect-error old migration
state.ocr = {
providers: BUILTIN_OCR_PROVIDERS,
imageProviderId: DEFAULT_OCR_PROVIDER.image.id
@ -2685,6 +2691,34 @@ const migrateConfig = {
logger.error('migrate 163 error', error as Error)
return state
}
},
'164': (state: RootState) => {
try {
state.ocr.providers.forEach((p) => {
if (isBuiltinOcrProvider(p)) {
switch (p.id) {
case 'ovocr':
state.ocr.configs.ovocr = p.config ?? BUILTIN_OCR_PROVIDER_CONFIG_MAP.ovocr
break
case 'paddleocr':
state.ocr.configs.paddleocr = p.config ?? BUILTIN_OCR_PROVIDER_CONFIG_MAP.paddleocr
break
case 'system':
state.ocr.configs.system = p.config ?? BUILTIN_OCR_PROVIDER_CONFIG_MAP.system
break
case 'tesseract':
state.ocr.configs.tesseract = p.config ?? BUILTIN_OCR_PROVIDER_CONFIG_MAP.tesseract
break
default:
logger.warn(`Unknown ocr provider ${p.id}. Skipped.`)
}
}
})
return state
} catch (error) {
logger.error('migrate 164 error', error as Error)
return state
}
}
}

View File

@ -1,15 +1,22 @@
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice } from '@reduxjs/toolkit'
import { BUILTIN_OCR_PROVIDERS, DEFAULT_OCR_PROVIDER } from '@renderer/config/ocr'
import type { OcrProvider, OcrProviderConfig } from '@renderer/types'
import { BUILTIN_OCR_PROVIDER_CONFIG_MAP, BUILTIN_OCR_PROVIDERS, DEFAULT_OCR_PROVIDER } from '@renderer/config/ocr'
import type { BuiltinOcrProviderId, OcrProvider, OcrProviderConfig } from '@renderer/types'
export interface OcrState {
providers: OcrProvider[]
configs: Record<BuiltinOcrProviderId, OcrProviderConfig>
imageProviderId: string
}
const initialState: OcrState = {
providers: BUILTIN_OCR_PROVIDERS,
configs: {
tesseract: BUILTIN_OCR_PROVIDER_CONFIG_MAP.tesseract,
system: BUILTIN_OCR_PROVIDER_CONFIG_MAP.system,
paddleocr: BUILTIN_OCR_PROVIDER_CONFIG_MAP.paddleocr,
ovocr: BUILTIN_OCR_PROVIDER_CONFIG_MAP.ovocr
},
imageProviderId: DEFAULT_OCR_PROVIDER.image.id
}

View File

@ -162,7 +162,6 @@ export type OcrTesseractConfig = OcrProviderBaseConfig & {
export type OcrTesseractProvider = {
id: 'tesseract'
config: OcrTesseractConfig
} & ImageOcrProvider &
BuiltinOcrProvider
@ -179,7 +178,6 @@ export type OcrSystemConfig = OcrProviderBaseConfig & {
export type OcrSystemProvider = {
id: 'system'
config: OcrSystemConfig
} & ImageOcrProvider &
// PdfOcrProvider &
BuiltinOcrProvider
@ -196,7 +194,6 @@ export type OcrPpocrConfig = OcrProviderBaseConfig & {
export type OcrPpocrProvider = {
id: 'paddleocr'
config: OcrPpocrConfig
} & ImageOcrProvider &
// PdfOcrProvider &
BuiltinOcrProvider
@ -212,7 +209,6 @@ export type OcrOvConfig = OcrProviderBaseConfig & {
export type OcrOvProvider = {
id: 'ovocr'
config: OcrOvConfig
} & ImageOcrProvider &
// PdfOcrProvider &
BuiltinOcrProvider