@@ -239,15 +239,16 @@ export class SemanticEmbeddings {
239239 }
240240
241241 // v2.1.0: 加载本地模型(可独立调用,支持切换模型)
242- async loadLocalModel ( _retried = false ) : Promise < void > {
242+ // v3.1.1: _wasmFallback — DLL/native binding 失败后自动回退 WASM backend
243+ async loadLocalModel ( _retried = false , _wasmFallback = false ) : Promise < void > {
243244 const modelInfo = LOCAL_MODELS . find ( m => m . id === this . localModelId ) || LOCAL_MODELS [ 0 ] ;
244245 this . modelLoading = true ;
245246 this . _cancelRequested = false ;
246247 this . downloadProgress = 0 ;
247248 this . downloadFile = '' ;
248249 this . lastError = '' ;
249250 this . notifyStatus ( ) ;
250- this . onProgress ?.( `[RAG] 🧠 Loading transformers.js...` ) ;
251+ this . onProgress ?.( `[RAG] 🧠 Loading transformers.js${ _wasmFallback ? ' (WASM fallback)' : '' } ...` ) ;
251252
252253 try {
253254 const { pipeline : tfPipeline , env } = await import ( '@huggingface/transformers' ) ;
@@ -274,7 +275,8 @@ export class SemanticEmbeddings {
274275 this . onProgress ?.( `[RAG] 📥 首次下载模型: ${ modelInfo . name } (~${ modelInfo . sizeMB } MB)...` ) ;
275276 }
276277
277- this . pipeline = await tfPipeline ( 'feature-extraction' , this . localModelId , {
278+ // v3.1.1: WASM fallback — native DLL 失败时用 WASM backend
279+ const pipelineOptions : any = {
278280 progress_callback : isCached ? undefined : ( progress : any ) => {
279281 // v3.0.0: 检查取消请求
280282 if ( this . _cancelRequested ) {
@@ -305,15 +307,21 @@ export class SemanticEmbeddings {
305307 this . notifyStatus ( ) ;
306308 }
307309 }
308- } ) ;
310+ } ;
311+ if ( _wasmFallback ) {
312+ pipelineOptions . device = 'wasm' ;
313+ }
314+
315+ this . pipeline = await tfPipeline ( 'feature-extraction' , this . localModelId , pipelineOptions ) ;
309316
310317 this . localDimensions = modelInfo . dimensions ;
311318 this . modelReady = true ;
312319 this . modelLoading = false ;
313320 this . downloadProgress = 100 ;
314321 await this . loadCache ( ) ;
315322 this . initialized = true ;
316- this . onProgress ?.( `[RAG] 🧠 Semantic engine ready: ${ modelInfo . name } (${ modelInfo . dimensions } d)` ) ;
323+ const backendLabel = _wasmFallback ? 'WASM' : 'native' ;
324+ this . onProgress ?.( `[RAG] 🧠 Semantic engine ready: ${ modelInfo . name } (${ modelInfo . dimensions } d, ${ backendLabel } )` ) ;
317325 this . notifyStatus ( ) ;
318326 } catch ( err : any ) {
319327 const cancelled = this . _cancelRequested || ( err . message && err . message . includes ( 'DOWNLOAD_CANCELLED' ) ) ;
@@ -329,8 +337,14 @@ export class SemanticEmbeddings {
329337 this . notifyStatus ( ) ;
330338 return ; // 取消不抛异常
331339 }
332- // v3.0.0: 检测缓存损坏(Protobuf parsing failed / failed to load 等),自动清理并重试一次
333340 const errMsg = err . message || '' ;
341+ // v3.1.1: 检测 native DLL 加载失败 — 自动回退 WASM backend
342+ const isDllFailure = / D L L i n i t i a l i z a t i o n | o n n x r u n t i m e _ b i n d i n g | n a t i v e .* f a i l e d | \. n o d e / i. test ( errMsg ) ;
343+ if ( isDllFailure && ! _wasmFallback ) {
344+ this . onProgress ?.( `[RAG] ⚠️ Native ONNX runtime failed, falling back to WASM backend...` ) ;
345+ return this . loadLocalModel ( _retried , true ) ;
346+ }
347+ // v3.0.0: 检测缓存损坏(Protobuf parsing failed / failed to load 等),自动清理并重试一次
334348 const isCorrupted = / p r o t o b u f p a r s i n g f a i l e d | f a i l e d t o l o a d .* o n n x | i n v a l i d m o d e l | c o r r u p t e d / i. test ( errMsg ) ;
335349 if ( isCorrupted && ! _retried ) {
336350 this . onProgress ?.( `[RAG] ⚠️ Model cache corrupted, cleaning and retrying...` ) ;
@@ -345,7 +359,7 @@ export class SemanticEmbeddings {
345359 this . onProgress ?.( `[RAG] ⚠️ Cache cleanup failed: ${ cleanErr . message } ` ) ;
346360 }
347361 // 重试一次
348- return this . loadLocalModel ( true ) ;
362+ return this . loadLocalModel ( true , _wasmFallback ) ;
349363 }
350364 this . lastError = errMsg || 'Failed to load model' ;
351365 this . onProgress ?.( `[RAG] ❌ Model load failed: ${ this . lastError } ` ) ;
0 commit comments