update default settings

This commit is contained in:
duanfuxiang 2025-07-05 15:47:59 +08:00
parent 4b7efe8d29
commit bbd89fbfa4
8 changed files with 73 additions and 27 deletions

View File

@ -88,6 +88,7 @@ export class RAGEngine {
this.embeddingModel, this.embeddingModel,
{ {
chunkSize: this.settings.ragOptions.chunkSize, chunkSize: this.settings.ragOptions.chunkSize,
batchSize: this.settings.ragOptions.batchSize,
excludePatterns: this.settings.ragOptions.excludePatterns, excludePatterns: this.settings.ragOptions.excludePatterns,
includePatterns: this.settings.ragOptions.includePatterns, includePatterns: this.settings.ragOptions.includePatterns,
reindexAll: options.reindexAll, reindexAll: options.reindexAll,
@ -112,6 +113,7 @@ export class RAGEngine {
await this.vectorManager.UpdateFileVectorIndex( await this.vectorManager.UpdateFileVectorIndex(
this.embeddingModel, this.embeddingModel,
this.settings.ragOptions.chunkSize, this.settings.ragOptions.chunkSize,
this.settings.ragOptions.batchSize,
file, file,
) )
} }

View File

@ -27,7 +27,7 @@ export class VectorManager {
constructor(app: App, dbManager: DBManager) { constructor(app: App, dbManager: DBManager) {
this.app = app this.app = app
this.dbManager = dbManager this.dbManager = dbManager
this.repository = new VectorRepository(app, dbManager.getPgClient() as any) this.repository = new VectorRepository(app, dbManager.getPgClient())
} }
async performSimilaritySearch( async performSimilaritySearch(
@ -59,7 +59,7 @@ export class VectorManager {
if (typeof global !== 'undefined' && global.gc) { if (typeof global !== 'undefined' && global.gc) {
global.gc() global.gc()
} else if (typeof window !== 'undefined' && (window as any).gc) { } else if (typeof window !== 'undefined' && (window as any).gc) {
(window as any).gc() ((window as any).gc as () => void)();
} }
} catch (e) { } catch (e) {
// 忽略垃圾回收错误 // 忽略垃圾回收错误
@ -80,6 +80,7 @@ export class VectorManager {
embeddingModel: EmbeddingModel, embeddingModel: EmbeddingModel,
options: { options: {
chunkSize: number chunkSize: number
batchSize: number
excludePatterns: string[] excludePatterns: string[]
includePatterns: string[] includePatterns: string[]
reindexAll?: boolean reindexAll?: boolean
@ -194,17 +195,15 @@ export class VectorManager {
const embeddingProgress = { completed: 0 } const embeddingProgress = { completed: 0 }
// 减少批量大小以降低内存压力 // 减少批量大小以降低内存压力
const insertBatchSize = 32 const batchSize = options.batchSize
let batchCount = 0 let batchCount = 0
try { try {
if (embeddingModel.supportsBatch) { if (embeddingModel.supportsBatch) {
// 支持批量处理的提供商:使用流式处理逻辑 // 支持批量处理的提供商:使用流式处理逻辑
const embeddingBatchSize = 32 for (let i = 0; i < contentChunks.length; i += batchSize) {
for (let i = 0; i < contentChunks.length; i += embeddingBatchSize) {
batchCount++ batchCount++
const batchChunks = contentChunks.slice(i, Math.min(i + embeddingBatchSize, contentChunks.length)) const batchChunks = contentChunks.slice(i, Math.min(i + batchSize, contentChunks.length))
const embeddedBatch: InsertVector[] = [] const embeddedBatch: InsertVector[] = []
@ -267,13 +266,13 @@ export class VectorManager {
const abortController = new AbortController() const abortController = new AbortController()
// 流式处理:分批处理并立即插入 // 流式处理:分批处理并立即插入
for (let i = 0; i < contentChunks.length; i += insertBatchSize) { for (let i = 0; i < contentChunks.length; i += batchSize) {
if (abortController.signal.aborted) { if (abortController.signal.aborted) {
throw new Error('Operation was aborted') throw new Error('Operation was aborted')
} }
batchCount++ batchCount++
const batchChunks = contentChunks.slice(i, Math.min(i + insertBatchSize, contentChunks.length)) const batchChunks = contentChunks.slice(i, Math.min(i + batchSize, contentChunks.length))
const embeddedBatch: InsertVector[] = [] const embeddedBatch: InsertVector[] = []
const tasks = batchChunks.map((chunk) => const tasks = batchChunks.map((chunk) =>
@ -357,6 +356,7 @@ export class VectorManager {
async UpdateFileVectorIndex( async UpdateFileVectorIndex(
embeddingModel: EmbeddingModel, embeddingModel: EmbeddingModel,
chunkSize: number, chunkSize: number,
batchSize: number,
file: TFile file: TFile
) { ) {
try { try {
@ -412,19 +412,15 @@ export class VectorManager {
}) })
.filter((chunk): chunk is InsertVector => chunk !== null) .filter((chunk): chunk is InsertVector => chunk !== null)
// 减少批量大小以降低内存压力
const insertBatchSize = 16 // 从64降低到16
let batchCount = 0 let batchCount = 0
try { try {
if (embeddingModel.supportsBatch) { if (embeddingModel.supportsBatch) {
// 支持批量处理的提供商:使用流式处理逻辑 // 支持批量处理的提供商:使用流式处理逻辑
const embeddingBatchSize = 16 // 从64降低到16 for (let i = 0; i < contentChunks.length; i += batchSize) {
for (let i = 0; i < contentChunks.length; i += embeddingBatchSize) {
batchCount++ batchCount++
console.log(`Embedding batch ${batchCount} of ${Math.ceil(contentChunks.length / embeddingBatchSize)}`) console.log(`Embedding batch ${batchCount} of ${Math.ceil(contentChunks.length / batchSize)}`)
const batchChunks = contentChunks.slice(i, Math.min(i + embeddingBatchSize, contentChunks.length)) const batchChunks = contentChunks.slice(i, Math.min(i + batchSize, contentChunks.length))
const embeddedBatch: InsertVector[] = [] const embeddedBatch: InsertVector[] = []
@ -480,13 +476,13 @@ export class VectorManager {
const abortController = new AbortController() const abortController = new AbortController()
// 流式处理:分批处理并立即插入 // 流式处理:分批处理并立即插入
for (let i = 0; i < contentChunks.length; i += insertBatchSize) { for (let i = 0; i < contentChunks.length; i += batchSize) {
if (abortController.signal.aborted) { if (abortController.signal.aborted) {
throw new Error('Operation was aborted') throw new Error('Operation was aborted')
} }
batchCount++ batchCount++
const batchChunks = contentChunks.slice(i, Math.min(i + insertBatchSize, contentChunks.length)) const batchChunks = contentChunks.slice(i, Math.min(i + batchSize, contentChunks.length))
const embeddedBatch: InsertVector[] = [] const embeddedBatch: InsertVector[] = []
const tasks = batchChunks.map((chunk) => const tasks = batchChunks.map((chunk) =>

View File

@ -358,6 +358,8 @@ export default {
excludePatternsDescription: 'Files matching ANY of these patterns will be excluded from indexing. One pattern per line. Uses glob patterns (e.g., "private/*", "*.tmp"). Leave empty to exclude nothing. After changing this, use the command "Rebuild entire vault index" to apply changes.', excludePatternsDescription: 'Files matching ANY of these patterns will be excluded from indexing. One pattern per line. Uses glob patterns (e.g., "private/*", "*.tmp"). Leave empty to exclude nothing. After changing this, use the command "Rebuild entire vault index" to apply changes.',
chunkSize: 'Chunk size', chunkSize: 'Chunk size',
chunkSizeDescription: 'Set the chunk size for text splitting. After changing this, please re-index the vault using the "Rebuild entire vault index" command.', chunkSizeDescription: 'Set the chunk size for text splitting. After changing this, please re-index the vault using the "Rebuild entire vault index" command.',
batchSize: 'Batch size',
batchSizeDescription: 'Set the batch size for embedding. A smaller value may reduce memory usage. After changing this, please re-index the vault using the "Rebuild entire vault index" command.',
thresholdTokens: 'Threshold tokens', thresholdTokens: 'Threshold tokens',
thresholdTokensDescription: 'Maximum number of tokens before switching to RAG. If the total tokens from mentioned files exceed this, RAG will be used instead of including all file contents.', thresholdTokensDescription: 'Maximum number of tokens before switching to RAG. If the total tokens from mentioned files exceed this, RAG will be used instead of including all file contents.',
minSimilarity: 'Minimum similarity', minSimilarity: 'Minimum similarity',

View File

@ -360,6 +360,8 @@ export default {
excludePatternsDescription: '匹配任何这些模式的文件将从索引中排除。每行一个模式。使用 glob 模式(例如,"private/*", "*.tmp")。留空以不排除任何内容。更改后,请使用命令 "重建整个 Vault 索引" 来应用更改。', excludePatternsDescription: '匹配任何这些模式的文件将从索引中排除。每行一个模式。使用 glob 模式(例如,"private/*", "*.tmp")。留空以不排除任何内容。更改后,请使用命令 "重建整个 Vault 索引" 来应用更改。',
chunkSize: '分块大小', chunkSize: '分块大小',
chunkSizeDescription: '设置文本分割的分块大小。更改后,请使用 "重建整个 Vault 索引" 命令重新索引 Vault。', chunkSizeDescription: '设置文本分割的分块大小。更改后,请使用 "重建整个 Vault 索引" 命令重新索引 Vault。',
batchSize: '批处理大小',
batchSizeDescription: '设置嵌入的批处理大小。较小的值可以减少内存使用。更改后,请使用 "重建整个 Vault 索引" 命令重新索引 Vault。',
thresholdTokens: '阈值 Tokens', thresholdTokens: '阈值 Tokens',
thresholdTokensDescription: '切换到 RAG 之前的最大 Tokens 数。如果提及文件的总 Tokens 超过此值,将使用 RAG 而不是包含所有文件内容。', thresholdTokensDescription: '切换到 RAG 之前的最大 Tokens 数。如果提及文件的总 Tokens 超过此值,将使用 RAG 而不是包含所有文件内容。',
minSimilarity: '最小相似度', minSimilarity: '最小相似度',

View File

@ -468,6 +468,29 @@ export class InfioSettingTab extends PluginSettingTab {
}), }),
) )
new Setting(contentContainer)
.setName(t('settings.RAG.batchSize'))
.setDesc(
t('settings.RAG.batchSizeDescription'),
)
.addText((text) =>
text
.setPlaceholder('32')
.setValue(String(this.plugin.settings.ragOptions.batchSize))
.onChange(async (value) => {
const batchSize = parseInt(value, 10)
if (!isNaN(batchSize)) {
await this.plugin.setSettings({
...this.plugin.settings,
ragOptions: {
...this.plugin.settings.ragOptions,
batchSize,
},
})
}
}),
)
new Setting(contentContainer) new Setting(contentContainer)
.setName(t('settings.RAG.thresholdTokens')) .setName(t('settings.RAG.thresholdTokens'))
.setDesc( .setDesc(

View File

@ -4,7 +4,7 @@ export const MIN_DELAY = 0;
export const MAX_DELAY = 2000; export const MAX_DELAY = 2000;
export const MIN_MAX_CHAR_LIMIT = 100; export const MIN_MAX_CHAR_LIMIT = 100;
export const MAX_MAX_CHAR_LIMIT = 10000; export const MAX_MAX_CHAR_LIMIT = 10000;
export const MIN_MAX_TOKENS = 128; export const MIN_MAX_TOKENS = 4096;
export const MAX_MAX_TOKENS = 8192; export const MAX_MAX_TOKENS = 8192;
export const MIN_TEMPERATURE = 0.0; export const MIN_TEMPERATURE = 0.0;
export const MAX_TEMPERATURE = 1.0; export const MAX_TEMPERATURE = 1.0;

View File

@ -16,7 +16,7 @@ describe('parseSmartCopilotSettings', () => {
top_p: 0.1, top_p: 0.1,
frequency_penalty: 0.25, frequency_penalty: 0.25,
presence_penalty: 0, presence_penalty: 0,
max_tokens: 800, max_tokens: 4096,
}, },
systemMessage: DEFAULT_SETTINGS.systemMessage, systemMessage: DEFAULT_SETTINGS.systemMessage,
fewShotExamples: DEFAULT_SETTINGS.fewShotExamples, fewShotExamples: DEFAULT_SETTINGS.fewShotExamples,
@ -34,6 +34,7 @@ describe('parseSmartCopilotSettings', () => {
}) })
expect(result).toEqual({ expect(result).toEqual({
version: 0.4, version: 0.4,
workspace: '',
activeModels: DEFAULT_MODELS, activeModels: DEFAULT_MODELS,
activeProviderTab: 'Infio', activeProviderTab: 'Infio',
infioApiKey: '', infioApiKey: '',
@ -66,6 +67,13 @@ describe('parseSmartCopilotSettings', () => {
useCustomUrl: false, useCustomUrl: false,
models: [], models: [],
}, },
localproviderProvider: {
name: 'LocalProvider',
apiKey: '',
baseUrl: '',
useCustomUrl: false,
models: [],
},
anthropicProvider: { anthropicProvider: {
name: 'Anthropic', name: 'Anthropic',
apiKey: '', apiKey: '',
@ -97,7 +105,8 @@ describe('parseSmartCopilotSettings', () => {
}, },
systemPrompt: '', systemPrompt: '',
ragOptions: { ragOptions: {
chunkSize: 1000, batchSize: 32,
chunkSize: 500,
thresholdTokens: 8192, thresholdTokens: 8192,
minSimilarity: 0.0, minSimilarity: 0.0,
limit: 10, limit: 10,
@ -118,7 +127,7 @@ describe('parseSmartCopilotSettings', () => {
top_p: 0.1, top_p: 0.1,
frequency_penalty: 0.25, frequency_penalty: 0.25,
presence_penalty: 0, presence_penalty: 0,
max_tokens: 800, max_tokens: 4096,
}, },
systemMessage: DEFAULT_SETTINGS.systemMessage, systemMessage: DEFAULT_SETTINGS.systemMessage,
fewShotExamples: DEFAULT_SETTINGS.fewShotExamples, fewShotExamples: DEFAULT_SETTINGS.fewShotExamples,
@ -224,7 +233,8 @@ describe('settings migration', () => {
embeddingModel: 'text-embedding-3-small', embeddingModel: 'text-embedding-3-small',
systemPrompt: 'system prompt', systemPrompt: 'system prompt',
ragOptions: { ragOptions: {
chunkSize: 1000, batchSize: 32,
chunkSize: 500,
thresholdTokens: 8192, thresholdTokens: 8192,
minSimilarity: 0.0, minSimilarity: 0.0,
limit: 10, limit: 10,
@ -239,7 +249,7 @@ describe('settings migration', () => {
top_p: 0.1, top_p: 0.1,
frequency_penalty: 0.25, frequency_penalty: 0.25,
presence_penalty: 0, presence_penalty: 0,
max_tokens: 800, max_tokens: 4096,
}, },
systemMessage: DEFAULT_SETTINGS.systemMessage, systemMessage: DEFAULT_SETTINGS.systemMessage,
fewShotExamples: DEFAULT_SETTINGS.fewShotExamples, fewShotExamples: DEFAULT_SETTINGS.fewShotExamples,
@ -259,6 +269,7 @@ describe('settings migration', () => {
const result = parseInfioSettings(oldSettings) const result = parseInfioSettings(oldSettings)
expect(result).toEqual({ expect(result).toEqual({
version: 0.4, version: 0.4,
workspace: '',
activeModels: DEFAULT_MODELS, activeModels: DEFAULT_MODELS,
activeProviderTab: 'Infio', activeProviderTab: 'Infio',
infioApiKey: '', infioApiKey: '',
@ -291,6 +302,13 @@ describe('settings migration', () => {
useCustomUrl: false, useCustomUrl: false,
models: [], models: [],
}, },
localproviderProvider: {
name: 'LocalProvider',
apiKey: '',
baseUrl: '',
useCustomUrl: false,
models: [],
},
anthropicProvider: { anthropicProvider: {
name: 'Anthropic', name: 'Anthropic',
apiKey: '', apiKey: '',
@ -322,7 +340,8 @@ describe('settings migration', () => {
}, },
systemPrompt: 'system prompt', systemPrompt: 'system prompt',
ragOptions: { ragOptions: {
chunkSize: 1000, batchSize: 32,
chunkSize: 500,
thresholdTokens: 8192, thresholdTokens: 8192,
minSimilarity: 0.0, minSimilarity: 0.0,
limit: 10, limit: 10,
@ -343,7 +362,7 @@ describe('settings migration', () => {
top_p: 0.1, top_p: 0.1,
frequency_penalty: 0.25, frequency_penalty: 0.25,
presence_penalty: 0, presence_penalty: 0,
max_tokens: 800, max_tokens: 4096,
}, },
systemMessage: DEFAULT_SETTINGS.systemMessage, systemMessage: DEFAULT_SETTINGS.systemMessage,
fewShotExamples: DEFAULT_SETTINGS.fewShotExamples, fewShotExamples: DEFAULT_SETTINGS.fewShotExamples,

View File

@ -210,6 +210,7 @@ const openAICompatibleModelSchema = z.object({
const ragOptionsSchema = z.object({ const ragOptionsSchema = z.object({
chunkSize: z.number().catch(1000), chunkSize: z.number().catch(1000),
batchSize: z.number().catch(32),
thresholdTokens: z.number().catch(8192), thresholdTokens: z.number().catch(8192),
minSimilarity: z.number().catch(0.0), minSimilarity: z.number().catch(0.0),
limit: z.number().catch(10), limit: z.number().catch(10),
@ -367,7 +368,8 @@ export const InfioSettingsSchema = z.object({
// RAG Options // RAG Options
ragOptions: ragOptionsSchema.catch({ ragOptions: ragOptionsSchema.catch({
chunkSize: 1000, batchSize: 32,
chunkSize: 500,
thresholdTokens: 8192, thresholdTokens: 8192,
minSimilarity: 0.0, minSimilarity: 0.0,
limit: 10, limit: 10,