diff --git a/src/database/database-manager.ts b/src/database/database-manager.ts index 532c313..8a0b3b4 100644 --- a/src/database/database-manager.ts +++ b/src/database/database-manager.ts @@ -21,9 +21,9 @@ export class DBManager { this.app = app } - static async create(app: App): Promise { + static async create(app: App, filesystem: string): Promise { const dbManager = new DBManager(app) - dbManager.db = await createAndInitDb() + dbManager.db = await createAndInitDb(filesystem) dbManager.vectorManager = new VectorManager(app, dbManager) dbManager.CommandManager = new CommandManager(app, dbManager) diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 4f67b2e..53f7d96 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -383,6 +383,10 @@ export default { // RAG Section RAG: { title: 'RAG(advanced)', + filesystem: 'Filesystem', + filesystemDescription: 'Choose the filesystem backend for storing vector embeddings. IDB uses IndexedDB (better compatibility), OPFS uses Origin Private File System (better performance).', + idb: 'IndexedDB', + opfs: 'OPFS', includePatterns: 'Include patterns', includePatternsDescription: 'If any patterns are specified, ONLY files matching at least one pattern will be included in indexing. One pattern per line. Uses glob patterns (e.g., "notes/*", "*.md"). Leave empty to include all files not excluded by exclude patterns. After changing this, use the command "Rebuild entire vault index" to apply changes.', testPatterns: 'Test patterns', diff --git a/src/lang/locale/zh-cn.ts b/src/lang/locale/zh-cn.ts index 98ce708..db55eab 100644 --- a/src/lang/locale/zh-cn.ts +++ b/src/lang/locale/zh-cn.ts @@ -384,6 +384,10 @@ export default { // RAG 部分 RAG: { title: 'RAG(高级)', + filesystem: '文件系统', + filesystemDescription: '选择存储向量嵌入的文件系统后端。IDB 使用 IndexedDB(更好的兼容性),OPFS 使用 Origin Private File System(更好的性能)。', + idb: 'IndexedDB', + opfs: 'OPFS', includePatterns: '包含模式', includePatternsDescription: '如果指定了任何模式,则只有匹配至少一个模式的文件才会被包含在索引中。每行一个模式。使用 glob 模式(例如,"notes/*", "*.md")。留空以包含所有未被排除模式排除的文件。更改后,请使用命令 "重建整个 Vault 索引" 来应用更改。', testPatterns: '测试模式', diff --git a/src/main.ts b/src/main.ts index 802746f..351f69f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -436,15 +436,15 @@ export default class InfioPlugin extends Plugin { new Notice('EmbeddingManager 未初始化', 5000); return; } - + // 加载模型 await this.embeddingManager.loadModel("Xenova/all-MiniLM-L6-v2", true); - + // 测试嵌入 "hello world" const testText = "hello world"; - + const result = await this.embeddingManager.embed(testText); - + // 显示结果 const resultMessage = ` 嵌入测试完成! @@ -453,15 +453,15 @@ export default class InfioPlugin extends Plugin { 向量维度: ${result.vec.length} 向量前4个值: [${result.vec.slice(0, 4).map(v => v.toFixed(4)).join(', ')}...] `.trim(); - + console.log('本地嵌入测试结果:', result); - + // 创建模态框显示结果 const modal = new Modal(this.app); modal.titleEl.setText('本地嵌入测试结果'); modal.contentEl.createEl('pre', { text: resultMessage }); modal.open(); - + } catch (error) { console.error('嵌入测试失败:', error); new Notice(`嵌入测试失败: ${error.message}`, 5000); @@ -582,7 +582,10 @@ export default class InfioPlugin extends Plugin { if (!this.dbManagerInitPromise) { this.dbManagerInitPromise = (async () => { - this.dbManager = await DBManager.create(this.app) + this.dbManager = await DBManager.create( + this.app, + this.settings.ragOptions.filesystem, + ) return this.dbManager })() } diff --git a/src/pgworker/index.ts b/src/pgworker/index.ts index 8e7d0f3..e53d67c 100644 --- a/src/pgworker/index.ts +++ b/src/pgworker/index.ts @@ -5,7 +5,7 @@ import { PGliteWorker } from '@electric-sql/pglite/worker'; import PGWorker from './pglite.worker'; -export const createAndInitDb = async () => { +export const createAndInitDb = async (filesystem: string) => { const worker = new PGWorker(); const pg = await PGliteWorker.create( @@ -15,7 +15,8 @@ export const createAndInitDb = async () => { live, }, }, + filesystem, ) - console.log('PGlite DB created in opfs-ahp://infio-db') + console.log(`PGlite DB created in ${filesystem}://infio-db`) return pg } diff --git a/src/pgworker/pglite.worker.ts b/src/pgworker/pglite.worker.ts index 8d12aae..cc8a587 100644 --- a/src/pgworker/pglite.worker.ts +++ b/src/pgworker/pglite.worker.ts @@ -42,22 +42,34 @@ const loadPGliteResources = async (): Promise<{ } worker({ - async init(options: PGliteWorkerOptions, ) { + async init(options: PGliteWorkerOptions, filesystem: string) { let db: PGlite; try { const { fsBundle, wasmModule, vectorExtensionBundlePath } = await loadPGliteResources() - - db = await PGlite.create('opfs-ahp://infio-db', { - relaxedDurability: true, - fsBundle: fsBundle, - wasmModule: wasmModule, - ...options, - extensions: { - ...options.extensions, - vector: vectorExtensionBundlePath, - }, - }) + if (filesystem === 'idb') { + db = await PGlite.create('idb://infio-db', { + relaxedDurability: true, + fsBundle: fsBundle, + wasmModule: wasmModule, + ...options, + extensions: { + ...options.extensions, + vector: vectorExtensionBundlePath, + }, + }) + } else { + db = await PGlite.create('opfs-ahp://infio-db', { + relaxedDurability: true, + fsBundle: fsBundle, + wasmModule: wasmModule, + ...options, + extensions: { + ...options.extensions, + vector: vectorExtensionBundlePath, + }, + }) + } } catch (error) { console.error('Error creating PGlite instance:', error) throw error diff --git a/src/settings/SettingTab.tsx b/src/settings/SettingTab.tsx index 194096f..b32ece2 100644 --- a/src/settings/SettingTab.tsx +++ b/src/settings/SettingTab.tsx @@ -375,6 +375,25 @@ export class InfioSettingTab extends PluginSettingTab { titleEl.style.fontWeight = "600"; // 以下是原有的设置内容,移动到内容容器中 + new Setting(contentContainer) + .setName(t('settings.RAG.filesystem')) + .setDesc(t('settings.RAG.filesystemDescription')) + .addDropdown((dropdown) => + dropdown + .addOption('idb', t('settings.RAG.idb')) + .addOption('opfs', t('settings.RAG.opfs')) + .setValue(this.plugin.settings.ragOptions.filesystem) + .onChange(async (value) => { + await this.plugin.setSettings({ + ...this.plugin.settings, + ragOptions: { + ...this.plugin.settings.ragOptions, + filesystem: value as 'idb' | 'opfs', + }, + }); + }), + ); + new Setting(contentContainer) .setName(t('settings.RAG.includePatterns')) .setDesc( diff --git a/src/types/settings.test.ts b/src/types/settings.test.ts index 413624e..28afc1a 100644 --- a/src/types/settings.test.ts +++ b/src/types/settings.test.ts @@ -110,6 +110,7 @@ describe('parseSmartCopilotSettings', () => { }, systemPrompt: '', ragOptions: { + filesystem: 'opfs', batchSize: 32, chunkSize: 500, thresholdTokens: 8192, @@ -238,6 +239,7 @@ describe('settings migration', () => { embeddingModel: 'text-embedding-3-small', systemPrompt: 'system prompt', ragOptions: { + filesystem: 'opfs', batchSize: 32, chunkSize: 500, thresholdTokens: 8192, @@ -350,6 +352,7 @@ describe('settings migration', () => { }, systemPrompt: 'system prompt', ragOptions: { + filesystem: 'opfs', batchSize: 32, chunkSize: 500, thresholdTokens: 8192, diff --git a/src/types/settings.ts b/src/types/settings.ts index b96e142..e9f19fe 100644 --- a/src/types/settings.ts +++ b/src/types/settings.ts @@ -210,6 +210,7 @@ const openAICompatibleModelSchema = z.object({ }) const ragOptionsSchema = z.object({ + filesystem: z.enum(['idb', 'opfs']).catch('opfs'), chunkSize: z.number().catch(500), batchSize: z.number().catch(32), thresholdTokens: z.number().catch(8192), @@ -391,6 +392,7 @@ export const InfioSettingsSchema = z.object({ // RAG Options ragOptions: ragOptionsSchema.catch({ + filesystem: 'opfs', batchSize: 32, chunkSize: 500, thresholdTokens: 8192,