From 32061c81031f6e2873a8add1f6dd33d0ecd66103 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Wed, 18 Jun 2025 15:46:36 +0800 Subject: [PATCH 001/109] (WIP) feat: add Builtin Knowledge Server and settings integration --- package.json | 2 + .../configPresenter/mcpConfHelper.ts | 18 ++ .../mcpPresenter/inMemoryServers/builder.ts | 10 + .../inMemoryServers/builtinKnowledgeServer.ts | 126 +++++++++++ .../settings/BuiltinKnowledgeSettings.vue | 211 ++++++++++++++++++ .../settings/KnowledgeBaseSettings.vue | 27 ++- src/renderer/src/i18n/zh-CN/mcp.json | 4 + src/renderer/src/i18n/zh-CN/settings.json | 6 +- 8 files changed, 400 insertions(+), 4 deletions(-) create mode 100644 src/main/presenter/mcpPresenter/inMemoryServers/builtinKnowledgeServer.ts create mode 100644 src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue diff --git a/package.json b/package.json index cf79238e3..5ecaa4dfa 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,8 @@ "@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/utils": "^4.0.0", "@google/genai": "^1.5.1", + "@llm-tools/embedjs": "^0.1.29", + "@llm-tools/embedjs-libsql": "^0.1.29", "@modelcontextprotocol/sdk": "^1.12.3", "axios": "^1.7.9", "better-sqlite3-multiple-ciphers": "11.10.0", diff --git a/src/main/presenter/configPresenter/mcpConfHelper.ts b/src/main/presenter/configPresenter/mcpConfHelper.ts index e589d506a..b4a85b8e1 100644 --- a/src/main/presenter/configPresenter/mcpConfHelper.ts +++ b/src/main/presenter/configPresenter/mcpConfHelper.ts @@ -4,6 +4,7 @@ import { MCP_EVENTS } from '@/events' import ElectronStore from 'electron-store' import { app } from 'electron' import { compare } from 'compare-versions' +import { BuiltinKnowledgeServer } from '../mcpPresenter/inMemoryServers/builtinKnowledgeServer' // MCP设置的接口 interface IMcpSettings { @@ -139,6 +140,23 @@ const DEFAULT_INMEMORY_SERVERS: Record = { }, disable: false }, + builtinKnowledge: { + args: [], + descriptions: 'DeepChat内置知识库检索服务', + icons: '📚', + autoApprove: ['all'], + type: 'inmemory' as MCPServerType, + command: 'builtinKnowledge', + env: { + configs: [ + { + description: '这是一个内置知识库的描述', + enabled: true + } + ] + }, + disable: false + }, 'deepchat-inmemory/deep-research-server': { args: [], descriptions: diff --git a/src/main/presenter/mcpPresenter/inMemoryServers/builder.ts b/src/main/presenter/mcpPresenter/inMemoryServers/builder.ts index c3caa2368..15ad9008d 100644 --- a/src/main/presenter/mcpPresenter/inMemoryServers/builder.ts +++ b/src/main/presenter/mcpPresenter/inMemoryServers/builder.ts @@ -11,6 +11,7 @@ import { CustomPromptsServer } from './customPromptsServer' import { DeepResearchServer } from './deepResearchServer' import { AutoPromptingServer } from './autoPromptingServer' import { ConversationSearchServer } from './conversationSearchServer' +import { BuiltinKnowledgeServer } from './builtinKnowledgeServer' export function getInMemoryServer( serverName: string, @@ -68,6 +69,15 @@ export function getInMemoryServer( }[] } ) + case 'builtinKnowledge': + return new BuiltinKnowledgeServer( + env as { + configs: { + description: string + enabled: boolean + }[] + } + ) case 'deepchat-inmemory/custom-prompts-server': return new CustomPromptsServer() case 'deepchat-inmemory/deep-research-server': diff --git a/src/main/presenter/mcpPresenter/inMemoryServers/builtinKnowledgeServer.ts b/src/main/presenter/mcpPresenter/inMemoryServers/builtinKnowledgeServer.ts new file mode 100644 index 000000000..96e65d223 --- /dev/null +++ b/src/main/presenter/mcpPresenter/inMemoryServers/builtinKnowledgeServer.ts @@ -0,0 +1,126 @@ +import { Server } from '@modelcontextprotocol/sdk/server/index.js' +import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js' +import { z } from 'zod' +import { zodToJsonSchema } from 'zod-to-json-schema' +import { Transport } from '@modelcontextprotocol/sdk/shared/transport' +import { MCPTextContent } from '@shared/presenter' + +// Schema definitions +const BuiltinKnowledgeSearchArgsSchema = z.object({ + query: z.string().describe('搜索查询内容 (必填)'), + topK: z.number().optional().default(5).describe('返回结果数量 (默认5条)') +}) + +export class BuiltinKnowledgeServer { + private server: Server + private configs: Array<{ + description: string + enabled: boolean + }> = [] + + constructor(env?: { + configs: { + description: string + enabled: boolean + }[] + }) { + if (!env) { + throw new Error('需要提供Builtin知识库配置') + } + const envs = env.configs + if (!Array.isArray(envs) || envs.length === 0) { + throw new Error('需要提供至少一个Builtin知识库配置') + } + for (const env of envs) { + if (!env.description) { + throw new Error('需要提供对这个知识库的描述,以方便ai决定是否检索此知识库') + } + this.configs.push({ + description: env.description, + enabled: env.enabled + }) + } + this.server = new Server( + { + name: 'deepchat-inmemory/builtin-knowledge-server', + version: '0.1.0' + }, + { + capabilities: { + tools: {} + } + } + ) + this.setupRequestHandlers() + } + + public startServer(transport: Transport): void { + this.server.connect(transport) + } + + private setupRequestHandlers(): void { + this.server.setRequestHandler(ListToolsRequestSchema, async () => { + const tools = this.configs + .filter((conf) => conf.enabled) + .map((config, index) => { + const suffix = this.configs.length > 1 ? `_${index + 1}` : '' + return { + name: `builtin_knowledge_search${suffix}`, + description: config.description, + inputSchema: zodToJsonSchema(BuiltinKnowledgeSearchArgsSchema) + } + }) + return { tools } + }) + this.server.setRequestHandler(CallToolRequestSchema, async (request) => { + const { name, arguments: parameters } = request.params + if (name.startsWith('builtin_knowledge_search')) { + try { + const enabledConfigs = this.configs.filter((config) => config.enabled) + let configIndex = 0 + const match = name.match(/_([0-9]+)$/) + if (match) { + configIndex = parseInt(match[1], 10) - 1 + } + if (configIndex < 0 || configIndex >= enabledConfigs.length) { + throw new Error(`无效的知识库索引: ${configIndex}`) + } + // 搜索逻辑留空 + return await this.performBuiltinKnowledgeSearch(parameters, configIndex) + } catch (error) { + return { + content: [ + { + type: 'text', + text: `搜索失败: ${error instanceof Error ? error.message : String(error)}` + } + ] + } + } + } + return { + content: [ + { + type: 'text', + text: `未知工具: ${name}` + } + ] + } + }) + } + + private async performBuiltinKnowledgeSearch( + parameters: Record | undefined, + configIndex: number = 0 + ): Promise<{ content: MCPTextContent[] }> { + // 搜索逻辑留空 + return { + content: [ + { + type: 'text', + text: '(内置知识库搜索逻辑未实现)' + } + ] + } + } +} diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue new file mode 100644 index 000000000..156eeed6b --- /dev/null +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -0,0 +1,211 @@ + + + diff --git a/src/renderer/src/components/settings/KnowledgeBaseSettings.vue b/src/renderer/src/components/settings/KnowledgeBaseSettings.vue index 218e72602..ac9516122 100644 --- a/src/renderer/src/components/settings/KnowledgeBaseSettings.vue +++ b/src/renderer/src/components/settings/KnowledgeBaseSettings.vue @@ -28,6 +28,8 @@ + +
-

Dify知识库

+

{{ t('settings.knowledgeBase.dify') }}

{{ t('settings.knowledgeBase.difyDescription') }}

@@ -64,7 +66,7 @@ >
-

RAGFlow

+

{{ t('settings.knowledgeBase.ragflowTitle') }}

{{ t('settings.knowledgeBase.ragflowDescription') }}

@@ -76,12 +78,24 @@ >
-

FastGPT

+

{{ t('settings.knowledgeBase.fastgptTitle') }}

{{ t('settings.knowledgeBase.fastgptDescription') }}

+
+ +
+

{{ t('settings.knowledgeBase.builtInKnowledgeTitle') }}

+

+ {{ t('settings.knowledgeBase.builtInKnowledgeDescription') }} +

+
+
- - +
+ + + + + + + + + +
- - - - - - +
+
+ + +
+
+ + + + + + + + + +
+
+ + +
+
+ +
- - +
diff --git a/src/renderer/src/i18n/en-US/mcp.json b/src/renderer/src/i18n/en-US/mcp.json index 4ff4a11e1..d75348228 100644 --- a/src/renderer/src/i18n/en-US/mcp.json +++ b/src/renderer/src/i18n/en-US/mcp.json @@ -191,6 +191,9 @@ "deepchat-inmemory/conversation-search-server": { "name": "Conversation History Search", "desc": "DeepChat built-in conversation history search service, can search historical conversation records and message contents" + }, + "builtinKnowledge": { + "desc": "DeepChat built-in knowledge base search service, which can search the content of DeepChat built-in knowledge base" } }, "prompts": { diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index 80abeb856..5adcb9921 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -292,7 +292,12 @@ "builtInKnowledgeDescription": "The built-in knowledge base provides some simple implementations that enable some basic functions in an offline environment.", "builtInKnowledgeTitle": "Built-in knowledge base", "addBuiltinKnowledgeConfig": "Add built-in knowledge base configuration", - "editBuiltinKnowledgeConfig": "Edit the built-in knowledge base configuration" + "editBuiltinKnowledgeConfig": "Edit the built-in knowledge base configuration", + "chunkSize": "Block size", + "chunkSizeHelper": "Cut the document into segments, the size of each segment cannot exceed the model context limit", + "chunkOverlap": "Overlapping size", + "chunkOverlapHelper": "The amount of content repeated between adjacent text blocks ensures that there is still a contextual connection between segmented text blocks, improving the overall effect of the model processing of long texts", + "selectEmbeddingModel": "Select an embed model" }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 6883b4817..98208fe56 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -292,7 +292,12 @@ "builtInKnowledgeDescription": "پایگاه دانش داخلی برخی از پیاده سازی های ساده را ارائه می دهد که برخی از کارکردهای اساسی را در یک محیط آفلاین امکان پذیر می کند.", "builtInKnowledgeTitle": "پایگاه دانش داخلی", "addBuiltinKnowledgeConfig": "پیکربندی پایه دانش داخلی را اضافه کنید", - "editBuiltinKnowledgeConfig": "پیکربندی پایه دانش داخلی را ویرایش کنید" + "editBuiltinKnowledgeConfig": "پیکربندی پایه دانش داخلی را ویرایش کنید", + "chunkSize": "اندازه بلوک", + "chunkSizeHelper": "سند را به بخش ها برش دهید ، اندازه هر بخش نمی تواند از حد زمینه مدل فراتر رود", + "chunkOverlap": "اندازه همپوشانی", + "chunkOverlapHelper": "میزان محتوای تکرار شده بین بلوک های متنی مجاور ، تضمین می کند که هنوز یک ارتباط متنی بین بلوک های متنی تقسیم شده وجود دارد ، و تأثیر کلی پردازش مدل متون طولانی را بهبود می بخشد", + "selectEmbeddingModel": "یک مدل تعبیه شده را انتخاب کنید" }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 4af921671..044957b5a 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -292,7 +292,12 @@ "builtInKnowledgeDescription": "La base de connaissances intégrée fournit des implémentations simples qui permettent certaines fonctions de base dans un environnement hors ligne.", "builtInKnowledgeTitle": "Base de connaissances intégrée", "addBuiltinKnowledgeConfig": "Ajouter une configuration de base de connaissances intégrée", - "editBuiltinKnowledgeConfig": "Modifier la configuration de base de connaissances intégrée" + "editBuiltinKnowledgeConfig": "Modifier la configuration de base de connaissances intégrée", + "chunkSize": "Taille de blocage", + "chunkSizeHelper": "Coupez le document en segments, la taille de chaque segment ne peut pas dépasser la limite de contexte du modèle", + "chunkOverlap": "Taille de chevauchement", + "chunkOverlapHelper": "La quantité de contenu répété entre les blocs de texte adjacents garantit qu'il existe toujours une connexion contextuelle entre les blocs de texte segmentés, améliorant l'effet global du traitement du modèle de textes longs", + "selectEmbeddingModel": "Sélectionnez un modèle intégré" }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index 08b59985b..29cc1b6be 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -292,7 +292,12 @@ "builtInKnowledgeDescription": "組み込みのナレッジベースは、オフライン環境でいくつかの基本機能を可能にするいくつかの簡単な実装を提供します。", "builtInKnowledgeTitle": "組み込みの知識ベース", "addBuiltinKnowledgeConfig": "組み込みのナレッジベースの構成を追加します", - "editBuiltinKnowledgeConfig": "組み込みのナレッジベースの構成を編集します" + "editBuiltinKnowledgeConfig": "組み込みのナレッジベースの構成を編集します", + "chunkSize": "ブロックサイズ", + "chunkSizeHelper": "ドキュメントをセグメントにカットすると、各セグメントのサイズがモデルコンテキスト制限を超えることはできません", + "chunkOverlap": "重複するサイズ", + "chunkOverlapHelper": "隣接するテキストブロック間で繰り返されるコンテンツの量により、セグメント化されたテキストブロック間にコンテキスト接続がまだあることが保証され、長いテキストのモデル処理の全体的な効果が改善されます。", + "selectEmbeddingModel": "埋め込みモデルを選択します" }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index 5f352ef8e..f9ed85f18 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -292,7 +292,12 @@ "builtInKnowledgeDescription": "내장 지식 기반은 오프라인 환경에서 몇 가지 기본 기능을 가능하게하는 간단한 구현을 제공합니다.", "builtInKnowledgeTitle": "내장 지식 기반", "addBuiltinKnowledgeConfig": "내장 된 지식 기반 구성을 추가하십시오", - "editBuiltinKnowledgeConfig": "내장 된 지식 기반 구성을 편집하십시오" + "editBuiltinKnowledgeConfig": "내장 된 지식 기반 구성을 편집하십시오", + "chunkSize": "블록 크기", + "chunkSizeHelper": "문서를 세그먼트로 자르면 각 세그먼트의 크기는 모델 컨텍스트 한계를 초과 할 수 없습니다.", + "chunkOverlap": "겹치는 크기", + "chunkOverlapHelper": "인접한 텍스트 블록 사이에 반복되는 콘텐츠의 양은 세그먼트 된 텍스트 블록 사이에 여전히 상황에 맞는 연결이 있음을 보장하여 긴 텍스트의 모델 처리의 전반적인 효과를 향상시킵니다.", + "selectEmbeddingModel": "임베드 모델을 선택하십시오" }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index e09617d7e..7712840d6 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -292,7 +292,12 @@ "builtInKnowledgeDescription": "Встроенная база знаний предоставляет некоторые простые реализации, которые позволяют некоторые основные функции в автономной среде.", "builtInKnowledgeTitle": "Встроенная база знаний", "addBuiltinKnowledgeConfig": "Добавить встроенную конфигурацию базы знаний", - "editBuiltinKnowledgeConfig": "Редактировать встроенную конфигурацию базы знаний" + "editBuiltinKnowledgeConfig": "Редактировать встроенную конфигурацию базы знаний", + "chunkSize": "Размер блока", + "chunkSizeHelper": "Разрежьте документ на сегменты, размер каждого сегмента не может превышать предел контекста модели", + "chunkOverlap": "Перекрывающийся размер", + "chunkOverlapHelper": "Количество повторного содержания между соседними текстовыми блоками гарантирует, что между сегментированными текстовыми блоками все еще существует контекстуальная связь, улучшая общий эффект обработки модели длинных текстов", + "selectEmbeddingModel": "Выберите модель встраивания" }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index d70845578..5ae350065 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -293,7 +293,11 @@ "builtInKnowledgeDescription": "内置知识库提供了一些简单实现,能够在离线环境下实现部分基础功能。", "addBuiltinKnowledgeConfig": "添加内置知识库配置", "editBuiltinKnowledgeConfig": "编辑内置知识库配置", - "selectEmbeddingModel": "选择嵌入模型" + "selectEmbeddingModel": "选择嵌入模型", + "chunkSize": "分块大小", + "chunkOverlap": "重叠大小", + "chunkSizeHelper": "将文档切割分段,每段的大小,不能超过模型上下文限制", + "chunkOverlapHelper": "相邻文本块之间重复的内容量,确保分段后的文本块之间仍然有上下文联系,提升模型处理长文本的整体效果" }, "mcp": { "title": "MCP设置", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 165bf7595..f5492a540 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -292,7 +292,12 @@ "builtInKnowledgeDescription": "內置知識庫提供了一些簡單實現,能夠在離線環境下實現部分基礎功能。", "builtInKnowledgeTitle": "內置知識庫", "addBuiltinKnowledgeConfig": "添加內置知識庫配置", - "editBuiltinKnowledgeConfig": "編輯內置知識庫配置" + "editBuiltinKnowledgeConfig": "編輯內置知識庫配置", + "chunkSize": "分塊大小", + "chunkSizeHelper": "將文檔切割分段,每段的大小,不能超過模型上下文限制", + "chunkOverlap": "重疊大小", + "chunkOverlapHelper": "相鄰文本塊之間重複的內容量,確保分段後的文本塊之間仍然有上下文聯繫,提升模型處理長文本的整體效果", + "selectEmbeddingModel": "選擇嵌入模型" }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index 158fe4530..6e28a6bf5 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -292,7 +292,12 @@ "builtInKnowledgeDescription": "內置知識庫提供了一些簡單實現,能夠在離線環境下實現部分基礎功能。", "builtInKnowledgeTitle": "內置知識庫", "addBuiltinKnowledgeConfig": "添加內置知識庫配置", - "editBuiltinKnowledgeConfig": "編輯內置知識庫配置" + "editBuiltinKnowledgeConfig": "編輯內置知識庫配置", + "chunkSize": "分塊大小", + "chunkSizeHelper": "將文檔切割分段,每段的大小,不能超過模型上下文限制", + "chunkOverlap": "重疊大小", + "chunkOverlapHelper": "相鄰文本塊之間重複的內容量,確保分段後的文本塊之間仍然有上下文聯繫,提升模型處理長文本的整體效果", + "selectEmbeddingModel": "選擇嵌入模型" }, "mcp": { "title": "MCP設定", From bb80a7e69c4b4ab3746d891ba49443e1cda48b56 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:22:13 +0800 Subject: [PATCH 005/109] feat: update knowledge base settings to use 'builtinKnowledge' and enhance BuiltinKnowledgeSettings with URL query parameter handling --- .../mcp-config/components/McpServers.vue | 3 ++- .../settings/BuiltinKnowledgeSettings.vue | 18 ++++++++++++++++-- .../settings/KnowledgeBaseSettings.vue | 4 ++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/renderer/src/components/mcp-config/components/McpServers.vue b/src/renderer/src/components/mcp-config/components/McpServers.vue index f8ef5b9a5..0ac1851d7 100644 --- a/src/renderer/src/components/mcp-config/components/McpServers.vue +++ b/src/renderer/src/components/mcp-config/components/McpServers.vue @@ -181,7 +181,8 @@ const openEditServerDialog = (serverName: string) => { const specialServers = { difyKnowledge: 'dify', ragflowKnowledge: 'ragflow', - fastGptKnowledge: 'fastgpt' + fastGptKnowledge: 'fastgpt', + builtinKnowledge: 'builtinKnowledge' } if (specialServers[serverName]) { diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 80b42d6c8..d3fccda94 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -108,7 +108,7 @@ - -
@@ -174,6 +193,7 @@ import { import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' import ModelSelect from '@/components/ModelSelect.vue' import ModelIcon from '@/components/icons/ModelIcon.vue' import { useMcpStore } from '@/stores/mcp' @@ -182,9 +202,11 @@ import { useThemeStore } from '@/stores/theme' import { RENDERER_MODEL_META } from '@shared/presenter' import { toast } from '../ui/toast' import { useRoute } from 'vue-router' +import { useSettingsStore } from '@/stores/settings' const { t } = useI18n() const mcpStore = useMcpStore() +const settingsStore = useSettingsStore() const themeStore = useThemeStore() // 模型选择相关 @@ -197,21 +219,25 @@ const builtinConfigs = ref>([]) interface BuiltinKnowledgeConfig { description: string providerId: string - model: RENDERER_MODEL_META | null + modelId: string chunkSize?: number // defualt 1000 chunkOverlap?: number // default 0 enabled?: boolean } +// 正在编辑的配置 const editingBuiltinConfig = ref({ description: '', providerId: '', - model: null, + modelId: '', chunkSize: 512, chunkOverlap: 0, enabled: true }) +// 当前选择的嵌入模型 +const selectEmbeddingModel = ref(null) + // 对话框状态 const isBuiltinConfigDialogOpen = ref(false) @@ -221,7 +247,7 @@ function openAddConfig() { editingBuiltinConfig.value = { description: '', providerId: '', - model: null, + modelId: '', chunkSize: 512, chunkOverlap: 0, enabled: true @@ -240,17 +266,46 @@ const isEditingBuiltinConfigValid = computed(() => { return ( editingBuiltinConfig.value.description.trim() !== '' && editingBuiltinConfig.value.providerId.trim() !== '' && - editingBuiltinConfig.value.model !== null && + editingBuiltinConfig.value.modelId.trim() !== '' && editingBuiltinConfig.value.chunkSize !== undefined && editingBuiltinConfig.value.chunkOverlap !== undefined && - editingBuiltinConfig.value.chunkSize > 0 && - editingBuiltinConfig.value.chunkOverlap >= 0 + editingBuiltinConfig.value.chunkSize <= + (selectEmbeddingModel.value?.maxTokens || 1024 * 1024) && + editingBuiltinConfig.value.chunkOverlap >= 0 && + editingBuiltinConfig.value.chunkOverlap < editingBuiltinConfig.value.chunkSize ) }) +// 获取已启用的模型配置 +const getEnableModelConfig = (modelId: string, providerId: string): RENDERER_MODEL_META | null => { + const provider = settingsStore.enabledModels.find((p) => p.providerId === providerId) + if (!provider || !Array.isArray(provider.models)) return null + const model = provider.models.find((m) => m.id === modelId && m.enabled) + return model || null +} + // 打开编辑对话框 -const editBuiltinConfig = (index: number) => { +const editBuiltinConfig = async (index: number) => { + const config = builtinConfigs.value[index] + // 设置当前选择的嵌入模型 + const model = (await getEnableModelConfig( + config.modelId, + config.providerId + )) as RENDERER_MODEL_META + // 如果模型不存在或被禁用 + if (!model || !model.enabled) { + toast({ + title: t('settings.knowledgeBase.modelNotFound', { + provider: t(config.providerId), + model: config.modelId + }), + description: t('settings.knowledgeBase.modelNotFoundDesc'), + variant: 'destructive' + }) + return + } isEditing.value = true + selectEmbeddingModel.value = model editingConfigIndex.value = index editingBuiltinConfig.value = { ...builtinConfigs.value[index] } isBuiltinConfigDialogOpen.value = true @@ -263,7 +318,7 @@ const closeBuiltinConfigDialog = () => { editingBuiltinConfig.value = { description: '', providerId: '', - model: null, + modelId: '', chunkSize: 512, chunkOverlap: 0, enabled: true @@ -273,7 +328,6 @@ const closeBuiltinConfigDialog = () => { // 保存配置 const saveBuiltinConfig = async () => { if (!isEditingBuiltinConfigValid.value) return - if (isEditing.value) { // 更新配置 if (editingConfigIndex.value !== -1) { @@ -307,7 +361,8 @@ const removeBuiltinConfig = async (index: number) => { // 选择嵌入模型 const handleEmbeddingModelSelect = (model: RENDERER_MODEL_META, providerId: string) => { - editingBuiltinConfig.value.model = model + selectEmbeddingModel.value = model + editingBuiltinConfig.value.modelId = model.id editingBuiltinConfig.value.providerId = providerId modelSelectOpen.value = false } diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index 5ae350065..1595d77ae 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -297,7 +297,9 @@ "chunkSize": "分块大小", "chunkOverlap": "重叠大小", "chunkSizeHelper": "将文档切割分段,每段的大小,不能超过模型上下文限制", - "chunkOverlapHelper": "相邻文本块之间重复的内容量,确保分段后的文本块之间仍然有上下文联系,提升模型处理长文本的整体效果" + "chunkOverlapHelper": "相邻文本块之间重复的内容量,确保分段后的文本块之间仍然有上下文联系,提升模型处理长文本的整体效果", + "modelNotFound": "服务商 {provider} 或模型 {model} 未找到", + "modelNotFoundDesc": "请确保已正确配置模型,并且模型处于启用状态。您可以在服务商设置中检查模型配置。" }, "mcp": { "title": "MCP设置", From dd284837449ab5f8f26dbadad8e694426e64d869 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Fri, 20 Jun 2025 15:12:36 +0800 Subject: [PATCH 007/109] feat: add confirmation dialog and error messages for removing built-in knowledge configurations --- .../settings/BuiltinKnowledgeSettings.vue | 43 ++++++++++++++++--- src/renderer/src/i18n/en-US/settings.json | 6 ++- src/renderer/src/i18n/fa-IR/settings.json | 6 ++- src/renderer/src/i18n/fr-FR/settings.json | 6 ++- src/renderer/src/i18n/ja-JP/settings.json | 6 ++- src/renderer/src/i18n/ko-KR/settings.json | 6 ++- src/renderer/src/i18n/ru-RU/settings.json | 6 ++- src/renderer/src/i18n/zh-CN/settings.json | 4 +- src/renderer/src/i18n/zh-HK/settings.json | 6 ++- src/renderer/src/i18n/zh-TW/settings.json | 6 ++- 10 files changed, 79 insertions(+), 16 deletions(-) diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index efa7c6f73..600ed1e90 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -64,13 +64,31 @@ > - + + + + + + + {{ + t('settings.knowledgeBase.removeBuiltinKnowledgeConfirmTitle', { + name: config.description + }) + }} + + {{ t('settings.knowledgeBase.removeBuiltinKnowledgeConfirmDesc') }} + + + + {{ t('common.cancel') }} + {{ + t('common.confirm') + }} + + +
@@ -190,6 +208,17 @@ import { DialogTitle, DialogFooter } from '@/components/ui/dialog' +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger +} from '@/components/ui/alert-dialog' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index 5adcb9921..31e5ef3c8 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -297,7 +297,11 @@ "chunkSizeHelper": "Cut the document into segments, the size of each segment cannot exceed the model context limit", "chunkOverlap": "Overlapping size", "chunkOverlapHelper": "The amount of content repeated between adjacent text blocks ensures that there is still a contextual connection between segmented text blocks, improving the overall effect of the model processing of long texts", - "selectEmbeddingModel": "Select an embed model" + "selectEmbeddingModel": "Select an embed model", + "modelNotFound": "Service Provider {provider} or model {model} not found", + "modelNotFoundDesc": "Make sure the model is configured correctly and that the model is enabled. \nYou can check the model configuration in the service provider settings.", + "removeBuiltinKnowledgeConfirmDesc": "Deleting the built-in knowledge base configuration will delete all relevant data and cannot be restored. Please be cautious.", + "removeBuiltinKnowledgeConfirmTitle": "Confirm to delete the built-in knowledge base {name}?" }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 98208fe56..3edc1a3dd 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -297,7 +297,11 @@ "chunkSizeHelper": "سند را به بخش ها برش دهید ، اندازه هر بخش نمی تواند از حد زمینه مدل فراتر رود", "chunkOverlap": "اندازه همپوشانی", "chunkOverlapHelper": "میزان محتوای تکرار شده بین بلوک های متنی مجاور ، تضمین می کند که هنوز یک ارتباط متنی بین بلوک های متنی تقسیم شده وجود دارد ، و تأثیر کلی پردازش مدل متون طولانی را بهبود می بخشد", - "selectEmbeddingModel": "یک مدل تعبیه شده را انتخاب کنید" + "selectEmbeddingModel": "یک مدل تعبیه شده را انتخاب کنید", + "modelNotFound": "ارائه دهنده خدمات {provider} یا مدل {model} یافت نشد", + "modelNotFoundDesc": "اطمینان حاصل کنید که مدل به درستی پیکربندی شده و مدل فعال شده است. می توانید پیکربندی مدل را در تنظیمات ارائه دهنده خدمات بررسی کنید.", + "removeBuiltinKnowledgeConfirmDesc": "حذف پیکربندی پایه دانش داخلی ، تمام داده های مربوطه را حذف می کند و قابل ترمیم نیست. لطفا محتاط باشید", + "removeBuiltinKnowledgeConfirmTitle": "تایید می‌کنید که پایگاه دانش داخلی {name} حذف شود؟" }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 044957b5a..521da6a62 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -297,7 +297,11 @@ "chunkSizeHelper": "Coupez le document en segments, la taille de chaque segment ne peut pas dépasser la limite de contexte du modèle", "chunkOverlap": "Taille de chevauchement", "chunkOverlapHelper": "La quantité de contenu répété entre les blocs de texte adjacents garantit qu'il existe toujours une connexion contextuelle entre les blocs de texte segmentés, améliorant l'effet global du traitement du modèle de textes longs", - "selectEmbeddingModel": "Sélectionnez un modèle intégré" + "selectEmbeddingModel": "Sélectionnez un modèle intégré", + "modelNotFound": "Fournisseur de services {provider} ou modèle {model} introuvable", + "modelNotFoundDesc": "Assurez-vous que le modèle est configuré correctement et que le modèle est activé. Vous pouvez vérifier la configuration du modèle dans les paramètres du fournisseur de services.", + "removeBuiltinKnowledgeConfirmDesc": "La suppression de la configuration de base de connaissances intégrée supprimera toutes les données pertinentes et ne peut pas être restaurée. Soyez prudent.", + "removeBuiltinKnowledgeConfirmTitle": "Confirmer pour supprimer la base de connaissances intégrée {name}?" }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index 29cc1b6be..eba8f2e6a 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -297,7 +297,11 @@ "chunkSizeHelper": "ドキュメントをセグメントにカットすると、各セグメントのサイズがモデルコンテキスト制限を超えることはできません", "chunkOverlap": "重複するサイズ", "chunkOverlapHelper": "隣接するテキストブロック間で繰り返されるコンテンツの量により、セグメント化されたテキストブロック間にコンテキスト接続がまだあることが保証され、長いテキストのモデル処理の全体的な効果が改善されます。", - "selectEmbeddingModel": "埋め込みモデルを選択します" + "selectEmbeddingModel": "埋め込みモデルを選択します", + "modelNotFound": "サービスプロバイダー {provider} またはモデル {model} が見つかりません", + "modelNotFoundDesc": "モデルが正しく構成されており、モデルが有効になっていることを確認してください。サービスプロバイダーの設定でモデル構成を確認できます。", + "removeBuiltinKnowledgeConfirmDesc": "組み込みのナレッジベース構成を削除すると、関連するすべてのデータが削除され、復元できません。注意してください。", + "removeBuiltinKnowledgeConfirmTitle": "組み込みのナレッジベース{name}を削除することを確認しますか?" }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index f9ed85f18..cfd669c38 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -297,7 +297,11 @@ "chunkSizeHelper": "문서를 세그먼트로 자르면 각 세그먼트의 크기는 모델 컨텍스트 한계를 초과 할 수 없습니다.", "chunkOverlap": "겹치는 크기", "chunkOverlapHelper": "인접한 텍스트 블록 사이에 반복되는 콘텐츠의 양은 세그먼트 된 텍스트 블록 사이에 여전히 상황에 맞는 연결이 있음을 보장하여 긴 텍스트의 모델 처리의 전반적인 효과를 향상시킵니다.", - "selectEmbeddingModel": "임베드 모델을 선택하십시오" + "selectEmbeddingModel": "임베드 모델을 선택하십시오", + "modelNotFound": "서비스 제공자 {provider} 또는 model {model}을 찾을 수 없습니다", + "modelNotFoundDesc": "모델이 올바르게 구성되고 모델이 활성화되어 있는지 확인하십시오. 서비스 제공 업체 설정에서 모델 구성을 확인할 수 있습니다.", + "removeBuiltinKnowledgeConfirmDesc": "내장 지식 기반 구성을 삭제하면 모든 관련 데이터가 삭제되며 복원 할 수 없습니다. 조심하세요.", + "removeBuiltinKnowledgeConfirmTitle": "내장 지식 기반 {name}을 삭제하도록 확인 하시겠습니까?" }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 7712840d6..dd31bb988 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -297,7 +297,11 @@ "chunkSizeHelper": "Разрежьте документ на сегменты, размер каждого сегмента не может превышать предел контекста модели", "chunkOverlap": "Перекрывающийся размер", "chunkOverlapHelper": "Количество повторного содержания между соседними текстовыми блоками гарантирует, что между сегментированными текстовыми блоками все еще существует контекстуальная связь, улучшая общий эффект обработки модели длинных текстов", - "selectEmbeddingModel": "Выберите модель встраивания" + "selectEmbeddingModel": "Выберите модель встраивания", + "modelNotFound": "Поставщик услуг {provider} или модель {model} не найден", + "modelNotFoundDesc": "Убедитесь, что модель настроена правильно, и что модель включена. Вы можете проверить конфигурацию модели в настройках поставщика услуг.", + "removeBuiltinKnowledgeConfirmDesc": "Удаление встроенной конфигурации базы знаний удалит все соответствующие данные и не может быть восстановлено. Пожалуйста, будьте осторожны.", + "removeBuiltinKnowledgeConfirmTitle": "Подтвердите, чтобы удалить встроенную базу знаний {name}?" }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index 1595d77ae..df3b12660 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -299,7 +299,9 @@ "chunkSizeHelper": "将文档切割分段,每段的大小,不能超过模型上下文限制", "chunkOverlapHelper": "相邻文本块之间重复的内容量,确保分段后的文本块之间仍然有上下文联系,提升模型处理长文本的整体效果", "modelNotFound": "服务商 {provider} 或模型 {model} 未找到", - "modelNotFoundDesc": "请确保已正确配置模型,并且模型处于启用状态。您可以在服务商设置中检查模型配置。" + "modelNotFoundDesc": "请确保已正确配置模型,并且模型处于启用状态。您可以在服务商设置中检查模型配置。", + "removeBuiltinKnowledgeConfirmTitle": "确认删除内置知识库 {name} ?", + "removeBuiltinKnowledgeConfirmDesc": "删除内置知识库配置将会删除所有相关数据,且无法恢复,请谨慎操作。" }, "mcp": { "title": "MCP设置", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index f5492a540..e42d3f109 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -297,7 +297,11 @@ "chunkSizeHelper": "將文檔切割分段,每段的大小,不能超過模型上下文限制", "chunkOverlap": "重疊大小", "chunkOverlapHelper": "相鄰文本塊之間重複的內容量,確保分段後的文本塊之間仍然有上下文聯繫,提升模型處理長文本的整體效果", - "selectEmbeddingModel": "選擇嵌入模型" + "selectEmbeddingModel": "選擇嵌入模型", + "modelNotFound": "服務商 {provider} 或模型 {model} 未找到", + "modelNotFoundDesc": "請確保已正確配置模型,並且模型處於啟用狀態。\n您可以在服務商設置中檢查模型配置。", + "removeBuiltinKnowledgeConfirmDesc": "刪除內置知識庫配置將會刪除所有相關數據,且無法恢復,請謹慎操作。", + "removeBuiltinKnowledgeConfirmTitle": "確認刪除內置知識庫 {name} 嗎?" }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index 6e28a6bf5..0f72667f4 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -297,7 +297,11 @@ "chunkSizeHelper": "將文檔切割分段,每段的大小,不能超過模型上下文限制", "chunkOverlap": "重疊大小", "chunkOverlapHelper": "相鄰文本塊之間重複的內容量,確保分段後的文本塊之間仍然有上下文聯繫,提升模型處理長文本的整體效果", - "selectEmbeddingModel": "選擇嵌入模型" + "selectEmbeddingModel": "選擇嵌入模型", + "modelNotFound": "服務商 {provider} 或模型 {model} 未找到", + "modelNotFoundDesc": "請確保已正確配置模型,並且模型處於啟用狀態。\n您可以在服務商設置中檢查模型配置。", + "removeBuiltinKnowledgeConfirmDesc": "刪除內置知識庫配置將會刪除所有相關數據,且無法恢復,請謹慎操作。", + "removeBuiltinKnowledgeConfirmTitle": "確認刪除內置知識庫 {name} 嗎?" }, "mcp": { "title": "MCP設定", From b4e1226a655042444d5af7cf31a51cf684ac9dcb Mon Sep 17 00:00:00 2001 From: ysli Date: Mon, 23 Jun 2025 18:38:35 +0800 Subject: [PATCH 008/109] props --- .../settings/BuiltinKnowledgeSettings.vue | 15 ++- .../settings/KnowledgeBaseSettings.vue | 19 +++- .../src/components/settings/KnowledgeFile.vue | 91 +++++++++++++++++++ 3 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 src/renderer/src/components/settings/KnowledgeFile.vue diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 600ed1e90..3df427c7f 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -57,6 +57,13 @@ size="sm" @update:checked="toggleConfigEnabled(index, $event)" /> +
@@ -174,6 +175,7 @@ :min="0" :max="editingBuiltinConfig.chunkSize" v-model="editingBuiltinConfig.chunkOverlap" + :step="128" >
@@ -232,6 +234,7 @@ import { RENDERER_MODEL_META } from '@shared/presenter' import { toast } from '../ui/toast' import { useRoute } from 'vue-router' import { useSettingsStore } from '@/stores/settings' +import { ChevronDown } from 'lucide-vue-next' const { t } = useI18n() const mcpStore = useMcpStore() @@ -243,7 +246,27 @@ const modelSelectOpen = ref(false) const isBuiltinConfigPanelOpen = ref(false) const isEditing = ref(false) -const builtinConfigs = ref>([]) +const builtinConfigs = computed(() => { + try { + const serverConfig = mcpStore.config.mcpServers['builtinKnowledge'] + if (serverConfig && serverConfig.env) { + // 解析配置 - env可能是JSON字符串 + try { + // 尝试解析JSON字符串 + const envObj = + typeof serverConfig.env === 'string' ? JSON.parse(serverConfig.env) : serverConfig.env + // const envObj = serverConfig.env + if (envObj.configs && Array.isArray(envObj.configs)) { + return envObj.configs + } + } catch (parseError) { + console.error('解析BuiltinKnowledge配置JSON失败:', parseError) + } + } + } catch (error) { + console.error('加载BuiltinKnowledge配置失败:', error) + } +}) /* ref>([]) */ interface BuiltinKnowledgeConfig { description: string @@ -439,10 +462,9 @@ const updateBuiltinConfigToMcp = async () => { } // 从MCP加载内置配置 -const loadBuiltinConfigFromMcp = async () => { +/* const loadBuiltinConfigFromMcp = async () => { try { const serverConfig = mcpStore.config.mcpServers['builtinKnowledge'] - console.log(serverConfig) if (serverConfig && serverConfig.env) { // 解析配置 - env可能是JSON字符串 try { @@ -460,10 +482,10 @@ const loadBuiltinConfigFromMcp = async () => { } catch (error) { console.error('加载BuiltinKnowledge配置失败:', error) } -} +} */ onMounted(async () => { - await loadBuiltinConfigFromMcp() + // await loadBuiltinConfigFromMcp() }) const route = useRoute() diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index c4fa6a0c1..572d0740f 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -1135,3 +1135,26 @@ export interface KeyStatus { /** 已使用额度 */ usage?: string } + +export interface IKnowledgePresenter { + create(base: KnowledgeBaseParams): Promise + reset(params: { base: KnowledgeBaseParams }): Promise + delete(id: string): Promise +} + +export type KnowledgeBaseParams = { + id: string + model: string + provider: string + dimensions?: number + apiKey: string + apiVersion?: string + baseURL: string + chunkSize?: number + chunkOverlap?: number + rerankApiKey?: string + rerankBaseURL?: string + rerankModel?: string + rerankModelProvider?: string + documentCount?: number +} From 638bb7c89f2a04141744103b5ff4a778b0061af2 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Tue, 24 Jun 2025 11:34:49 +0800 Subject: [PATCH 010/109] [WIP] feat: add KnowledgeConfHelper for managing knowledge base configurations --- src/main/presenter/configPresenter/index.ts | 26 ++++++++- .../configPresenter/knowledgeConfHelper.ts | 51 ++++++++++++++++++ .../presenter/knowledgePresenter/index.ts | 53 ++++++++++--------- .../settings/BuiltinKnowledgeSettings.vue | 5 ++ src/shared/presenter.d.ts | 9 ++++ 5 files changed, 118 insertions(+), 26 deletions(-) create mode 100644 src/main/presenter/configPresenter/knowledgeConfHelper.ts diff --git a/src/main/presenter/configPresenter/index.ts b/src/main/presenter/configPresenter/index.ts index c51496804..2d52dd48f 100644 --- a/src/main/presenter/configPresenter/index.ts +++ b/src/main/presenter/configPresenter/index.ts @@ -7,7 +7,8 @@ import { RENDERER_MODEL_META, MCPServerConfig, Prompt, - IModelConfig + IModelConfig, + KnowledgeBaseParams } from '@shared/presenter' import { SearchEngineTemplate } from '@shared/chat' import { ModelType } from '@shared/model' @@ -22,6 +23,7 @@ import { presenter } from '@/presenter' import { compare } from 'compare-versions' import { defaultShortcutKey, ShortcutKeySetting } from './shortcutKeySettings' import { ModelConfigHelper } from './modelConfig' +import { KnowledgeConfHelper } from './knowledgeConfHelper' // 定义应用设置的接口 interface IAppSettings { @@ -78,6 +80,7 @@ export class ConfigPresenter implements IConfigPresenter { private currentAppVersion: string private mcpConfHelper: McpConfHelper // 使用MCP配置助手 private modelConfigHelper: ModelConfigHelper // 模型配置助手 + private knowledgeConfHelper: KnowledgeConfHelper // 知识配置助手 constructor() { this.userDataPath = app.getPath('userData') @@ -122,6 +125,9 @@ export class ConfigPresenter implements IConfigPresenter { // 初始化模型配置助手 this.modelConfigHelper = new ModelConfigHelper() + // 初始化知识配置助手 + this.knowledgeConfHelper = new KnowledgeConfHelper() + // 初始化provider models目录 this.initProviderModelsDir() @@ -1026,6 +1032,24 @@ export class ConfigPresenter implements IConfigPresenter { resetShortcutKeys() { this.setSetting('shortcutKey', { ...defaultShortcutKey }) } + + // 获取知识库配置 + getKnowledgeConfigs(): KnowledgeBaseParams[] { + return this.knowledgeConfHelper.getKnowledgeConfigs() + } + + // 设置知识库配置 + setKnowledgeConfigs(configs: KnowledgeBaseParams[]): void { + this.knowledgeConfHelper.setKnowledgeConfigs(configs) + } + + // 对比知识库配置差异 + diffKnowledgeConfigs(newConfigs: KnowledgeBaseParams[]) { + return KnowledgeConfHelper.diffKnowledgeConfigs( + this.knowledgeConfHelper.getKnowledgeConfigs(), + newConfigs + ) + } } export { defaultShortcutKey } from './shortcutKeySettings' diff --git a/src/main/presenter/configPresenter/knowledgeConfHelper.ts b/src/main/presenter/configPresenter/knowledgeConfHelper.ts new file mode 100644 index 000000000..59d845768 --- /dev/null +++ b/src/main/presenter/configPresenter/knowledgeConfHelper.ts @@ -0,0 +1,51 @@ +import ElectronStore from 'electron-store' +import { KnowledgeBaseParams } from '@shared/presenter' + +export class KnowledgeConfHelper { + private store: ElectronStore<{ knowledgeConfigs: KnowledgeBaseParams[] }> + + constructor() { + this.store = new ElectronStore<{ knowledgeConfigs: KnowledgeBaseParams[] }>({ + name: 'knowledge-configs', + defaults: { + knowledgeConfigs: [] + } + }) + } + + // 获取所有知识库配置 + getKnowledgeConfigs(): KnowledgeBaseParams[] { + return this.store.get('knowledgeConfigs') || [] + } + + // 设置所有知识库配置 + setKnowledgeConfigs(configs: KnowledgeBaseParams[]): void { + this.store.set('knowledgeConfigs', configs) + } + + /** + * diff 新旧配置,返回 { added, updated, deleted } + * @param oldConfigs + * @param newConfigs + * @returns + */ + static diffKnowledgeConfigs( + oldConfigs: KnowledgeBaseParams[], + newConfigs: KnowledgeBaseParams[] + ): { + added: KnowledgeBaseParams[] + deleted: KnowledgeBaseParams[] + updated: KnowledgeBaseParams[] + } { + const oldMap = new Map(oldConfigs.map((cfg) => [cfg.id, cfg])) + const newMap = new Map(newConfigs.map((cfg) => [cfg.id, cfg])) + + const added = newConfigs.filter((cfg) => !oldMap.has(cfg.id)) + const deleted = oldConfigs.filter((cfg) => !newMap.has(cfg.id)) + const updated = newConfigs.filter( + (cfg) => oldMap.has(cfg.id) && JSON.stringify(cfg) !== JSON.stringify(oldMap.get(cfg.id)) + ) + + return { added, deleted, updated } + } +} diff --git a/src/main/presenter/knowledgePresenter/index.ts b/src/main/presenter/knowledgePresenter/index.ts index 1e7baeddf..2d2a99f07 100644 --- a/src/main/presenter/knowledgePresenter/index.ts +++ b/src/main/presenter/knowledgePresenter/index.ts @@ -1,7 +1,12 @@ import * as fs from 'node:fs' import path from 'node:path' -import { IConfigPresenter, IKnowledgePresenter, KnowledgeBaseParams } from '@shared/presenter' +import { + IConfigPresenter, + IKnowledgePresenter, + KnowledgeBaseParams, + MCPServerConfig +} from '@shared/presenter' import Embeddings from './Embeddings' import { RAGApplication, RAGApplicationBuilder } from '@llm-tools/embedjs' import { LibSqlDb } from '@llm-tools/embedjs-libsql' @@ -37,33 +42,31 @@ export class KnowledgePresenter implements IKnowledgePresenter { private setupEventBus = (): void => { // 监听知识库相关事件 eventBus.on(MCP_EVENTS.CONFIG_CHANGED, async (payload) => { - const mcpServers = payload?.mcpServers || {} - const builtinConfig = mcpServers['builtinKnowledge'] - if (builtinConfig) { - console.log('[RAG] Received builtinKnowledge config update:', builtinConfig) - /* // 取出 configs - const newConfigs = builtinConfig.env?.configs || [] - // 读取旧配置(如有缓存可用缓存,否则从磁盘/数据库读取) - const oldConfigs = (await this.configPresenter.getBuiltinKnowledgeConfigs?.()) || [] - - // diff 新旧配置,自动判断新增、更新、删除 - const oldMap = new Map(oldConfigs.map((cfg) => [cfg.id, cfg])) - const newMap = new Map(newConfigs.map((cfg) => [cfg.id, cfg])) + try { + if (!payload || typeof payload !== 'object' || !payload.mcpServers || typeof payload.mcpServers !== 'object') { + console.warn('[RAG] Invalid payload for CONFIG_CHANGED event:', payload) + return + } + const mcpServers = payload.mcpServers + const builtinConfig = mcpServers['builtinKnowledge'] as MCPServerConfig + if (builtinConfig && builtinConfig.env && Array.isArray(builtinConfig.env.configs)) { + const configs = builtinConfig.env.configs as KnowledgeBaseParams[] + console.log('[RAG] Received builtinKnowledge config update:', configs) - // 新增和更新 - for (const cfg of newConfigs) { - if (!oldMap.has(cfg.id)) { - await this.create(cfg) - } else if (JSON.stringify(cfg) !== JSON.stringify(oldMap.get(cfg.id))) { - await this.reset({ base: cfg }) + const diffs = this.configPresenter.diffKnowledgeConfigs(configs) + if (diffs.added.length > 0) { } - } - // 删除 - for (const cfg of oldConfigs) { - if (!newMap.has(cfg.id)) { - await this.delete(cfg.id) + if (diffs.updated.length > 0) { } - } */ + if (diffs.deleted.length > 0) { + } + this.configPresenter.setKnowledgeConfigs(configs) + console.log('[RAG] Updated knowledge configs:', configs) + } else { + console.warn('[RAG] builtinKnowledge config missing or invalid:', builtinConfig) + } + } catch (err) { + console.error('[RAG] Error handling CONFIG_CHANGED event:', err) } }) } diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 70e4f0a44..cf8d70e77 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -235,6 +235,7 @@ import { toast } from '../ui/toast' import { useRoute } from 'vue-router' import { useSettingsStore } from '@/stores/settings' import { ChevronDown } from 'lucide-vue-next' +import { nanoid } from 'nanoid' const { t } = useI18n() const mcpStore = useMcpStore() @@ -269,6 +270,7 @@ const builtinConfigs = computed(() => { }) /* ref>([]) */ interface BuiltinKnowledgeConfig { + id: string description: string providerId: string modelId: string @@ -279,6 +281,7 @@ interface BuiltinKnowledgeConfig { // 正在编辑的配置 const editingBuiltinConfig = ref({ + id: '', description: '', providerId: '', modelId: '', @@ -297,6 +300,7 @@ const isBuiltinConfigDialogOpen = ref(false) function openAddConfig() { isEditing.value = false editingBuiltinConfig.value = { + id: nanoid(), description: '', providerId: '', modelId: '', @@ -368,6 +372,7 @@ const closeBuiltinConfigDialog = () => { isBuiltinConfigDialogOpen.value = false editingConfigIndex.value = -1 editingBuiltinConfig.value = { + id: '', description: '', providerId: '', modelId: '', diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index 572d0740f..7dc7d8967 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -421,6 +421,14 @@ export interface IConfigPresenter { getShortcutKey(): ShortcutKeySetting setShortcutKey(customShortcutKey: ShortcutKeySetting): void resetShortcutKeys(): void + // 知识库设置 + getKnowledgeConfigs(): KnowledgeBaseParams[] + setKnowledgeConfigs(configs: KnowledgeBaseParams[]): void + diffKnowledgeConfigs(configs: KnowledgeBaseParams[]): { + added: KnowledgeBaseParams[] + deleted: KnowledgeBaseParams[] + updated: KnowledgeBaseParams[] + } } export type RENDERER_MODEL_META = { id: string @@ -1144,6 +1152,7 @@ export interface IKnowledgePresenter { export type KnowledgeBaseParams = { id: string + description: string model: string provider: string dimensions?: number From ba9a31fc29d91952a7b71a9f71a74953e5c194ab Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Tue, 24 Jun 2025 11:41:55 +0800 Subject: [PATCH 011/109] [WIP] feat: log new knowledge config additions in KnowledgePresenter --- docs/builtin-knowledge.md | 84 +++++++++++++++++++ .../presenter/knowledgePresenter/index.ts | 4 + 2 files changed, 88 insertions(+) create mode 100644 docs/builtin-knowledge.md diff --git a/docs/builtin-knowledge.md b/docs/builtin-knowledge.md new file mode 100644 index 000000000..3517b399a --- /dev/null +++ b/docs/builtin-knowledge.md @@ -0,0 +1,84 @@ +# BuiltinKnowledge(内置知识库)模块设计与架构文档 + +## 1. 模块定位与作用 + +BuiltinKnowledge(内置知识库)是 DeepChat 系统内置的知识库服务,作为 MCP(Model Context Protocol)生态中的一种特殊服务器类型,主要用于本地知识的存储、管理与检索,支持 RAG(Retrieval-Augmented Generation)等场景。 + +- **本地化**:无需外部依赖,数据全部存储于本地。 +- **高性能**:集成高效的嵌入模型与向量数据库,适合小型/中型知识库场景。 +- **与 MCP 配置联动**:通过 MCP 配置变更事件自动同步知识库配置。 + +## 2. 架构与核心组件 + +### 2.1 主要类与职责 + +- **KnowledgePresenter** + - 负责内置知识库的生命周期管理(初始化、创建、重置、删除等)。 + - 监听 MCP_EVENTS.CONFIG_CHANGED 事件,自动同步配置。 + - 依赖 ConfigPresenter 进行配置存取与差异对比。 + - 封装 RAG 应用实例的创建与管理。 + +- **ConfigPresenter / KnowledgeConfHelper** + - 提供知识库配置的持久化、读取、差异对比等能力。 + - 通过 ElectronStore 存储所有 KnowledgeBaseParams。 + +- **RAGApplication / Embeddings / LibSqlDb** + - RAGApplicationBuilder 负责集成嵌入模型与向量数据库。 + - Embeddings 封装向量化模型。 + - LibSqlDb 作为本地向量数据库。 + +### 2.2 事件驱动同步机制 + +- 监听 `MCP_EVENTS.CONFIG_CHANGED`,自动同步 MCP 配置中的 builtinKnowledge。 +- 对比新旧配置,支持增量处理(新增、更新、删除)。 +- 通过 ConfigPresenter.setKnowledgeConfigs() 持久化最新配置。 + +## 3. 数据流与调用链 + +### 3.1 配置变更同步 + +```mermaid +sequenceDiagram + participant MCPConfHelper + participant eventBus + participant KnowledgePresenter + participant ConfigPresenter + + MCPConfHelper->>eventBus: send(MCP_EVENTS.CONFIG_CHANGED, { mcpServers, ... }) + eventBus->>KnowledgePresenter: on(MCP_EVENTS.CONFIG_CHANGED, payload) + KnowledgePresenter->>ConfigPresenter: diffKnowledgeConfigs(configs) + KnowledgePresenter->>ConfigPresenter: setKnowledgeConfigs(configs) +``` + +### 3.2 知识库操作 + +- **创建**:KnowledgePresenter.create(base) → getRagApplication(base) +- **重置**:KnowledgePresenter.reset({ base }) +- **删除**:KnowledgePresenter.delete(id) + +## 4. 事件与健壮性 + +- 事件消费方(KnowledgePresenter)需对 payload 结构进行校验,防止脏数据导致异常。 +- 建议在事件回调中增加 try-catch,提升健壮性。 + +## 5. 配置结构 + +- MCP 配置中的 builtinKnowledge 结构: + - `env.configs: KnowledgeBaseParams[]`,每个元素描述一个知识库实例。 +- 本地持久化:ElectronStore(knowledge-configs) + +## 6. 扩展与最佳实践 + +- 支持多知识库并行管理。 +- 可扩展为多种嵌入模型和向量数据库。 +- 推荐与 MCP 生态其他知识库(如 dify、ragflow)统一管理和 UI 入口。 + +## 7. 典型场景 + +- 本地知识问答、FAQ、文档检索。 +- 结合 LLM 进行 RAG 增强。 +- 离线场景下的知识管理。 + +--- + +如需详细 API 或配置字段说明,请参考 `KnowledgePresenter`、`KnowledgeBaseParams` 相关源码与类型定义。 diff --git a/src/main/presenter/knowledgePresenter/index.ts b/src/main/presenter/knowledgePresenter/index.ts index 2d2a99f07..5470c4e89 100644 --- a/src/main/presenter/knowledgePresenter/index.ts +++ b/src/main/presenter/knowledgePresenter/index.ts @@ -55,6 +55,10 @@ export class KnowledgePresenter implements IKnowledgePresenter { const diffs = this.configPresenter.diffKnowledgeConfigs(configs) if (diffs.added.length > 0) { + diffs.added.forEach((config) => { + console.log(`[RAG] New knowledge config added: ${config.id}`) + this.create(config) + }) } if (diffs.updated.length > 0) { } From a46611d109e77d256fbb11ce3238e5423bdb095d Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Tue, 24 Jun 2025 17:51:33 +0800 Subject: [PATCH 012/109] [WIP] feat: enhance knowledge base settings and descriptions across components --- TODO.md | 5 +- package.json | 4 +- .../settings/BuiltinKnowledgeSettings.vue | 253 ++++++++++++------ .../settings/DifyKnowledgeSettings.vue | 8 +- .../settings/FastGptKnowledgeSettings.vue | 8 +- .../settings/RagflowKnowledgeSettings.vue | 8 +- src/renderer/src/i18n/en-US/settings.json | 3 +- src/renderer/src/i18n/fa-IR/settings.json | 3 +- src/renderer/src/i18n/fr-FR/settings.json | 3 +- src/renderer/src/i18n/ja-JP/settings.json | 3 +- src/renderer/src/i18n/ko-KR/settings.json | 3 +- src/renderer/src/i18n/ru-RU/settings.json | 3 +- src/renderer/src/i18n/zh-CN/settings.json | 11 +- src/renderer/src/i18n/zh-HK/settings.json | 3 +- src/renderer/src/i18n/zh-TW/settings.json | 3 +- 15 files changed, 225 insertions(+), 96 deletions(-) diff --git a/TODO.md b/TODO.md index 6af3a6f1e..c71808e80 100644 --- a/TODO.md +++ b/TODO.md @@ -1,2 +1,3 @@ -- [ ] 创建和更新知识库配置时,触发 knowledgePresenter 事件 -- [ ] builtinKnowledgeService performBuiltinKnowledgeSearch 触发 knowledgePresenter 事件 \ No newline at end of file +- [ ] saveBuiltinConfig, dimensions 为空,则通过 LLM 尝试获取。 +- [X] knowledgeProvider 实现数据监听,通过对比获取配置变更 +- [ ] BuiltinKnowledgeSettings 页面和逻辑优化 \ No newline at end of file diff --git a/package.json b/package.json index 4257c5680..2a50b4e54 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "node": ">=20.12.2", "pnpm": ">=10.11.0" }, - "packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac", + "packageManager": "pnpm@10.12.2", "scripts": { "preinstall": "npx only-allow pnpm", "test": "vitest", @@ -131,7 +131,7 @@ "electron-builder": "26.0.12", "electron-vite": "^3.1.0", "jsdom": "^26.1.0", - "lucide-vue-next": "^0.511.0", + "lucide-vue-next": "^0.522.0", "mermaid": "^11.6.0", "minimatch": "^10.0.1", "monaco-editor": "^0.52.2", diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index cf8d70e77..72476992c 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -120,77 +120,174 @@ ? t('settings.knowledgeBase.editBuiltinKnowledgeConfig') : t('settings.knowledgeBase.addBuiltinKnowledgeConfig') }} + + {{ t('settings.knowledgeBase.builtInKnowledgeDescription') }} + -
-
- - -
-
- - - - - - - +
+
+
+ + - - -
-
- - -
-
- - +
+
+ + + + + + + + + +
+
+
+ + + + + + + + + +

{{ t('settings.knowledgeBase.autoDetectHelper') }}

+
+
+
+
+ + +
+
+
+ + + + + + + + + +

{{ t('settings.knowledgeBase.chunkSizeHelper') }}

+
+
+
+
+ +
+
+
+ + + + + + + + + +

{{ t('settings.knowledgeBase.chunkOverlapHelper') }}

+
+
+
+
+ +
+
- - - - -
+ + + + +
@@ -208,7 +305,8 @@ import { DialogContent, DialogHeader, DialogTitle, - DialogFooter + DialogFooter, + DialogDescription } from '@/components/ui/dialog' import { AlertDialog, @@ -227,6 +325,7 @@ import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' import ModelSelect from '@/components/ModelSelect.vue' import ModelIcon from '@/components/icons/ModelIcon.vue' +import { ScrollArea } from '@/components/ui/scroll-area' import { useMcpStore } from '@/stores/mcp' import { ModelType } from '@shared/model' import { useThemeStore } from '@/stores/theme' @@ -234,8 +333,9 @@ import { RENDERER_MODEL_META } from '@shared/presenter' import { toast } from '../ui/toast' import { useRoute } from 'vue-router' import { useSettingsStore } from '@/stores/settings' -import { ChevronDown } from 'lucide-vue-next' +import { ChevronDown, CircleQuestionMark } from 'lucide-vue-next' import { nanoid } from 'nanoid' +import Placeholder from '@tiptap/extension-placeholder' const { t } = useI18n() const mcpStore = useMcpStore() @@ -247,6 +347,9 @@ const modelSelectOpen = ref(false) const isBuiltinConfigPanelOpen = ref(false) const isEditing = ref(false) +// 自动检测维度开关 +const autoDetectDimensionsSwitch = ref(true) + const builtinConfigs = computed(() => { try { const serverConfig = mcpStore.config.mcpServers['builtinKnowledge'] @@ -276,6 +379,7 @@ interface BuiltinKnowledgeConfig { modelId: string chunkSize?: number // defualt 1000 chunkOverlap?: number // default 0 + dimensions?: number enabled?: boolean } @@ -285,8 +389,6 @@ const editingBuiltinConfig = ref({ description: '', providerId: '', modelId: '', - chunkSize: 512, - chunkOverlap: 0, enabled: true }) @@ -304,8 +406,6 @@ function openAddConfig() { description: '', providerId: '', modelId: '', - chunkSize: 512, - chunkOverlap: 0, enabled: true } isBuiltinConfigDialogOpen.value = true @@ -376,8 +476,6 @@ const closeBuiltinConfigDialog = () => { description: '', providerId: '', modelId: '', - chunkSize: 512, - chunkOverlap: 0, enabled: true } } @@ -395,6 +493,9 @@ const saveBuiltinConfig = async () => { description: t('settings.knowledgeBase.configUpdatedDesc') }) } else { + if (autoDetectDimensionsSwitch.value) { + // 自动获取dimensions + } // 添加配置 builtinConfigs.value.push({ ...editingBuiltinConfig.value }) toast({ diff --git a/src/renderer/src/components/settings/DifyKnowledgeSettings.vue b/src/renderer/src/components/settings/DifyKnowledgeSettings.vue index dce651461..db317bb58 100644 --- a/src/renderer/src/components/settings/DifyKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/DifyKnowledgeSettings.vue @@ -122,11 +122,14 @@ ? t('settings.knowledgeBase.editDifyConfig') : t('settings.knowledgeBase.addDifyConfig') }} + + {{ t('settings.knowledgeBase.difyDescription') }} +
+ + {{ t('settings.knowledgeBase.fastgptDescription') }} +
+ + {{ t('settings.knowledgeBase.ragflowDescription') }} +
Date: Tue, 24 Jun 2025 18:32:45 +0800 Subject: [PATCH 013/109] [WIP] feat: enhance Built-in Knowledge settings and descriptions, add advanced options and tooltips --- .../settings/BuiltinKnowledgeSettings.vue | 271 +++++++++++------- src/renderer/src/i18n/en-US/mcp.json | 3 +- src/renderer/src/i18n/en-US/settings.json | 10 +- src/renderer/src/i18n/fa-IR/mcp.json | 4 + src/renderer/src/i18n/fa-IR/settings.json | 10 +- src/renderer/src/i18n/fr-FR/mcp.json | 4 + src/renderer/src/i18n/fr-FR/settings.json | 10 +- src/renderer/src/i18n/ja-JP/mcp.json | 4 + src/renderer/src/i18n/ja-JP/settings.json | 10 +- src/renderer/src/i18n/ko-KR/mcp.json | 4 + src/renderer/src/i18n/ko-KR/settings.json | 10 +- src/renderer/src/i18n/ru-RU/mcp.json | 4 + src/renderer/src/i18n/ru-RU/settings.json | 10 +- src/renderer/src/i18n/zh-CN/settings.json | 4 +- src/renderer/src/i18n/zh-HK/mcp.json | 4 + src/renderer/src/i18n/zh-HK/settings.json | 10 +- src/renderer/src/i18n/zh-TW/mcp.json | 4 + src/renderer/src/i18n/zh-TW/settings.json | 10 +- 18 files changed, 275 insertions(+), 111 deletions(-) diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 72476992c..bf2fd9258 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -141,9 +141,28 @@ />
- +
+ + + + + + + + + +

{{ t('settings.knowledgeBase.selectEmbeddingModelHelper') }}

+
+
+
+
-
-
- - - - - - - - - -

{{ t('settings.knowledgeBase.autoDetectHelper') }}

-
-
-
+
+
+
+ + + + + + + + + +

{{ t('settings.knowledgeBase.autoDetectHelper') }}

+
+
+
+
+
+
+
+
+ + + + + + + + + +

{{ t('settings.knowledgeBase.autoDetectHelper') }}

+
+
+
+
+
-
-
- - - - - - - - - -

{{ t('settings.knowledgeBase.chunkSizeHelper') }}

-
-
-
-
- -
-
-
- - - - - - - - - -

{{ t('settings.knowledgeBase.chunkOverlapHelper') }}

-
-
-
-
- -
+ + + +

{{ t('settings.knowledgeBase.advanced') }}

+
+ +
+
+ + + + + + + + + +

{{ t('settings.knowledgeBase.chunkSizeHelper') }}

+
+
+
+
+ +
+
+
+ + + + + + + + + +

+ {{ t('settings.knowledgeBase.chunkOverlapHelper') }} +

+
+
+
+
+ +
+
+
+
@@ -323,6 +392,12 @@ import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger +} from '@/components/ui/accordion' import ModelSelect from '@/components/ModelSelect.vue' import ModelIcon from '@/components/icons/ModelIcon.vue' import { ScrollArea } from '@/components/ui/scroll-area' @@ -335,7 +410,6 @@ import { useRoute } from 'vue-router' import { useSettingsStore } from '@/stores/settings' import { ChevronDown, CircleQuestionMark } from 'lucide-vue-next' import { nanoid } from 'nanoid' -import Placeholder from '@tiptap/extension-placeholder' const { t } = useI18n() const mcpStore = useMcpStore() @@ -423,12 +497,7 @@ const isEditingBuiltinConfigValid = computed(() => { editingBuiltinConfig.value.description.trim() !== '' && editingBuiltinConfig.value.providerId.trim() !== '' && editingBuiltinConfig.value.modelId.trim() !== '' && - editingBuiltinConfig.value.chunkSize !== undefined && - editingBuiltinConfig.value.chunkOverlap !== undefined && - editingBuiltinConfig.value.chunkSize <= - (selectEmbeddingModel.value?.maxTokens || 1024 * 1024) && - editingBuiltinConfig.value.chunkOverlap >= 0 && - editingBuiltinConfig.value.chunkOverlap < editingBuiltinConfig.value.chunkSize + (autoDetectDimensionsSwitch.value || editingBuiltinConfig.value.dimensions) ) }) diff --git a/src/renderer/src/i18n/en-US/mcp.json b/src/renderer/src/i18n/en-US/mcp.json index 67355f2d6..684593d71 100644 --- a/src/renderer/src/i18n/en-US/mcp.json +++ b/src/renderer/src/i18n/en-US/mcp.json @@ -193,7 +193,8 @@ "desc": "DeepChat built-in conversation history search service, can search historical conversation records and message contents" }, "builtinKnowledge": { - "desc": "DeepChat built-in knowledge base search service, which can search the content of DeepChat built-in knowledge base" + "desc": "DeepChat built-in knowledge base search service, which can search the content of DeepChat built-in knowledge base", + "name": "Built-in knowledge base search" }, "deepchat-inmemory/meeting-server": { "name": "Multi-Agent Meeting", diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index bd7c0247d..ea0944269 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -302,7 +302,15 @@ "modelNotFoundDesc": "Make sure the model is configured correctly and that the model is enabled. \nYou can check the model configuration in the service provider settings.", "removeBuiltinKnowledgeConfirmDesc": "Deleting the built-in knowledge base configuration will delete all relevant data and cannot be restored. Please be cautious.", "removeBuiltinKnowledgeConfirmTitle": "Confirm to delete the built-in knowledge base {name}?", - "descriptionDesc": "Description of the knowledge base so that the AI ​​decides whether to retrieve this knowledge base" + "descriptionDesc": "Description of the knowledge base so that the AI ​​decides whether to retrieve this knowledge base", + "advanced": "Advanced Options", + "autoDetectDimensions": "Automatically detect embedded dimensions", + "autoDetectHelper": "Automatically detect embedded dimensions, consumes a small amount of Tokens", + "chunkOverlapPlaceholder": "Default value, no modification is recommended", + "chunkSizePlaceholder": "Default value, no modification is recommended", + "dimensions": "Embed dimensions", + "dimensionsPlaceholder": "Embed dimension size, such as 1024", + "selectEmbeddingModelHelper": "Embedding models are prohibited after creation of knowledge base" }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/mcp.json b/src/renderer/src/i18n/fa-IR/mcp.json index 6764cc1e6..2ef27ead0 100644 --- a/src/renderer/src/i18n/fa-IR/mcp.json +++ b/src/renderer/src/i18n/fa-IR/mcp.json @@ -195,6 +195,10 @@ "deepchat-inmemory/meeting-server": { "name": "جلسه چند-عامل", "desc": "سرویس جلسه داخلی DeepChat امکان میزبانی و مدیریت بحث‌های چند-عامله را فراهم می‌کند." + }, + "builtinKnowledge": { + "desc": "خدمات جستجوی پایه دانش داخلی Deepchat ، که می تواند محتوای پایگاه دانش داخلی Deepchat را جستجو کند", + "name": "جستجوی پایگاه دانش داخلی" } }, "prompts": { diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index a6af8e80e..6a90e5f5d 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -302,7 +302,15 @@ "modelNotFoundDesc": "اطمینان حاصل کنید که مدل به درستی پیکربندی شده و مدل فعال شده است. می توانید پیکربندی مدل را در تنظیمات ارائه دهنده خدمات بررسی کنید.", "removeBuiltinKnowledgeConfirmDesc": "حذف پیکربندی پایه دانش داخلی ، تمام داده های مربوطه را حذف می کند و قابل ترمیم نیست. لطفا محتاط باشید", "removeBuiltinKnowledgeConfirmTitle": "تایید می‌کنید که پایگاه دانش داخلی {name} حذف شود؟", - "descriptionDesc": "شرح پایگاه دانش به گونه ای که هوش مصنوعی تصمیم بگیرد که آیا این پایگاه دانش را بازیابی کند" + "descriptionDesc": "شرح پایگاه دانش به گونه ای که هوش مصنوعی تصمیم بگیرد که آیا این پایگاه دانش را بازیابی کند", + "advanced": "گزینه های پیشرفته", + "autoDetectDimensions": "به طور خودکار ابعاد تعبیه شده را تشخیص دهید", + "autoDetectHelper": "به طور خودکار ابعاد تعبیه شده را تشخیص دهید ، مقدار کمی از نشانه ها را مصرف می کند", + "chunkOverlapPlaceholder": "مقدار پیش فرض ، هیچ اصلاح توصیه نمی شود", + "chunkSizePlaceholder": "مقدار پیش فرض ، هیچ اصلاح توصیه نمی شود", + "dimensions": "ابعاد جاسازی شده", + "dimensionsPlaceholder": "اندازه ابعاد تعبیه شده ، مانند 1024", + "selectEmbeddingModelHelper": "مدل های تعبیه شده پس از ایجاد پایگاه دانش ممنوع است" }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/mcp.json b/src/renderer/src/i18n/fr-FR/mcp.json index a7d095f5d..b80894f11 100644 --- a/src/renderer/src/i18n/fr-FR/mcp.json +++ b/src/renderer/src/i18n/fr-FR/mcp.json @@ -195,6 +195,10 @@ "deepchat-inmemory/meeting-server": { "name": "Réunion Multi-Agent", "desc": "Le service de réunion intégré de DeepChat permet d’organiser et d’animer des discussions multi-agents." + }, + "builtinKnowledge": { + "desc": "Service de recherche de base de connaissances intégré Deepchat, qui peut rechercher le contenu de la base de connaissances intégrée Deepchat", + "name": "Recherche de base de connaissances intégrée" } }, "prompts": { diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 555f958ac..3021d6919 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -302,7 +302,15 @@ "modelNotFoundDesc": "Assurez-vous que le modèle est configuré correctement et que le modèle est activé. Vous pouvez vérifier la configuration du modèle dans les paramètres du fournisseur de services.", "removeBuiltinKnowledgeConfirmDesc": "La suppression de la configuration de base de connaissances intégrée supprimera toutes les données pertinentes et ne peut pas être restaurée. Soyez prudent.", "removeBuiltinKnowledgeConfirmTitle": "Confirmer pour supprimer la base de connaissances intégrée {name}?", - "descriptionDesc": "Description de la base de connaissances afin que l'IA décide de récupérer cette base de connaissances" + "descriptionDesc": "Description de la base de connaissances afin que l'IA décide de récupérer cette base de connaissances", + "advanced": "Options avancées", + "autoDetectDimensions": "Détecter automatiquement les dimensions intégrées", + "autoDetectHelper": "Détecter automatiquement les dimensions intégrées, consomme une petite quantité de jetons", + "chunkOverlapPlaceholder": "Valeur par défaut, aucune modification n'est recommandée", + "chunkSizePlaceholder": "Valeur par défaut, aucune modification n'est recommandée", + "dimensions": "Dimensions de l'incorporation", + "dimensionsPlaceholder": "Taille de dimension intégrée, comme 1024", + "selectEmbeddingModelHelper": "Les modèles d'intégration sont interdits après la création d'une base de connaissances" }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/mcp.json b/src/renderer/src/i18n/ja-JP/mcp.json index 450ac28f6..d0a6311f2 100644 --- a/src/renderer/src/i18n/ja-JP/mcp.json +++ b/src/renderer/src/i18n/ja-JP/mcp.json @@ -195,6 +195,10 @@ "deepchat-inmemory/meeting-server": { "name": "マルチエージェント会議", "desc": "DeepChatの内蔵会議サービスは、マルチエージェントによる討論の開催と進行を可能にします。" + }, + "builtinKnowledge": { + "desc": "deepchatビルトインナレッジベース検索サービス。これは、deepchatビルトインナレッジベースのコンテンツを検索できる", + "name": "組み込みのナレッジベース検索" } }, "prompts": { diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index a25e1a46d..042577376 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -302,7 +302,15 @@ "modelNotFoundDesc": "モデルが正しく構成されており、モデルが有効になっていることを確認してください。サービスプロバイダーの設定でモデル構成を確認できます。", "removeBuiltinKnowledgeConfirmDesc": "組み込みのナレッジベース構成を削除すると、関連するすべてのデータが削除され、復元できません。注意してください。", "removeBuiltinKnowledgeConfirmTitle": "組み込みのナレッジベース{name}を削除することを確認しますか?", - "descriptionDesc": "AIがこの知識ベースを取得するかどうかを決定するように、知識ベースの説明" + "descriptionDesc": "AIがこの知識ベースを取得するかどうかを決定するように、知識ベースの説明", + "advanced": "高度なオプション", + "autoDetectDimensions": "埋め込み寸法を自動的に検出します", + "autoDetectHelper": "埋め込み寸法を自動的に検出し、少量のトークンを消費します", + "chunkOverlapPlaceholder": "デフォルト値、変更は推奨されません", + "chunkSizePlaceholder": "デフォルト値、変更は推奨されません", + "dimensions": "埋め込まれた寸法", + "dimensionsPlaceholder": "1024などの寸法サイズを埋め込みます", + "selectEmbeddingModelHelper": "埋め込みモデルは、知識ベースの作成後に禁止されています" }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/mcp.json b/src/renderer/src/i18n/ko-KR/mcp.json index 11f429a1b..e28a0d955 100644 --- a/src/renderer/src/i18n/ko-KR/mcp.json +++ b/src/renderer/src/i18n/ko-KR/mcp.json @@ -195,6 +195,10 @@ "deepchat-inmemory/meeting-server": { "name": "멀티 에이전트 회의", "desc": "DeepChat의 내장 회의 서비스는 다중 에이전트 토론의 주최와 진행을 지원합니다." + }, + "builtinKnowledge": { + "desc": "Deepchat 내장 지식 기반 검색 서비스, Deepchat 내장 지식 기반의 내용을 검색 할 수있는 Deepchat 내장 지식 기반 검색 서비스", + "name": "내장 된 지식 기반 검색" } }, "prompts": { diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index 723ee4f21..5fa283fc8 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -302,7 +302,15 @@ "modelNotFoundDesc": "모델이 올바르게 구성되고 모델이 활성화되어 있는지 확인하십시오. 서비스 제공 업체 설정에서 모델 구성을 확인할 수 있습니다.", "removeBuiltinKnowledgeConfirmDesc": "내장 지식 기반 구성을 삭제하면 모든 관련 데이터가 삭제되며 복원 할 수 없습니다. 조심하세요.", "removeBuiltinKnowledgeConfirmTitle": "내장 지식 기반 {name}을 삭제하도록 확인 하시겠습니까?", - "descriptionDesc": "AI 가이 지식 기반을 검색할지 여부를 결정하도록 지식 기반에 대한 설명" + "descriptionDesc": "AI 가이 지식 기반을 검색할지 여부를 결정하도록 지식 기반에 대한 설명", + "advanced": "고급 옵션", + "autoDetectDimensions": "내장 치수를 자동으로 감지합니다", + "autoDetectHelper": "내장 치수를 자동으로 감지하고 소량의 토큰을 소비합니다.", + "chunkOverlapPlaceholder": "기본값, 수정은 권장되지 않습니다", + "chunkSizePlaceholder": "기본값, 수정은 권장되지 않습니다", + "dimensions": "치수를 포함시킵니다", + "dimensionsPlaceholder": "1024와 같은 치수 크기를 포함시킵니다", + "selectEmbeddingModelHelper": "임베딩 모델은 지식 기반을 창출 한 후 금지됩니다" }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/mcp.json b/src/renderer/src/i18n/ru-RU/mcp.json index b0b1eb3ef..213880fef 100644 --- a/src/renderer/src/i18n/ru-RU/mcp.json +++ b/src/renderer/src/i18n/ru-RU/mcp.json @@ -195,6 +195,10 @@ "deepchat-inmemory/meeting-server": { "name": "Мультиагентная встреча", "desc": "Встроенный сервис встреч DeepChat позволяет организовывать и проводить обсуждения между несколькими агентами." + }, + "builtinKnowledge": { + "desc": "Встроенная служба поиска базы знаний DeepChat, которая может искать содержание встроенной базы знаний DeepChat", + "name": "Встроенный поиск базы знаний" } }, "prompts": { diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 66cea34bb..208d140cd 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -302,7 +302,15 @@ "modelNotFoundDesc": "Убедитесь, что модель настроена правильно, и что модель включена. Вы можете проверить конфигурацию модели в настройках поставщика услуг.", "removeBuiltinKnowledgeConfirmDesc": "Удаление встроенной конфигурации базы знаний удалит все соответствующие данные и не может быть восстановлено. Пожалуйста, будьте осторожны.", "removeBuiltinKnowledgeConfirmTitle": "Подтвердите, чтобы удалить встроенную базу знаний {name}?", - "descriptionDesc": "Описание базы знаний, чтобы ИИ решал, получить ли эта база знаний" + "descriptionDesc": "Описание базы знаний, чтобы ИИ решал, получить ли эта база знаний", + "advanced": "Расширенные варианты", + "autoDetectDimensions": "Автоматически обнаруживает встроенные размеры", + "autoDetectHelper": "Автоматически обнаруживает встроенные размеры, потребляет небольшое количество токенов", + "chunkOverlapPlaceholder": "Значение по умолчанию, изменение не рекомендуется", + "chunkSizePlaceholder": "Значение по умолчанию, изменение не рекомендуется", + "dimensions": "Встроенные размеры", + "dimensionsPlaceholder": "Встроенный размер измерения, такой как 1024", + "selectEmbeddingModelHelper": "Встроенные модели запрещены после создания базы знаний" }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index 65854851b..fb02b8a51 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -295,6 +295,7 @@ "editBuiltinKnowledgeConfig": "编辑内置知识库配置", "descriptionDesc": "知识库的描述,以便 AI 决定是否检索此知识库", "selectEmbeddingModel": "选择嵌入模型", + "selectEmbeddingModelHelper": "嵌入模型在知识库创建后禁止修改", "chunkSize": "分块大小", "chunkOverlap": "重叠大小", "chunkSizeHelper": "将文档切割分段,每段的大小,不能超过模型上下文限制", @@ -303,9 +304,10 @@ "modelNotFoundDesc": "请确保已正确配置模型,并且模型处于启用状态。您可以在服务商设置中检查模型配置。", "removeBuiltinKnowledgeConfirmTitle": "确认删除内置知识库 {name} ?", "removeBuiltinKnowledgeConfirmDesc": "删除内置知识库配置将会删除所有相关数据,且无法恢复,请谨慎操作。", + "advanced": "高级选项", "dimensions": "嵌入维度", "dimensionsPlaceholder": "嵌入维度大小,如 1024", - "autoDetect": "自动检测", + "autoDetectDimensions": "自动检测嵌入维度", "autoDetectHelper": "自动检测嵌入维度,会消耗少量 Tokens", "chunkSizePlaceholder": "默认值,不建议修改", "chunkOverlapPlaceholder": "默认值,不建议修改" diff --git a/src/renderer/src/i18n/zh-HK/mcp.json b/src/renderer/src/i18n/zh-HK/mcp.json index 0cb5c0ae2..5c30985d3 100644 --- a/src/renderer/src/i18n/zh-HK/mcp.json +++ b/src/renderer/src/i18n/zh-HK/mcp.json @@ -195,6 +195,10 @@ "deepchat-inmemory/meeting-server": { "name": "多智能體會議", "desc": "DeepChat 內置的會議功能支援舉辦和主持多智能體討論。" + }, + "builtinKnowledge": { + "desc": "DeepChat內置知識庫檢索服務,可以對DeepChat內置知識庫內容進行檢索", + "name": "內置知識庫檢索" } }, "prompts": { diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 4f650010b..48ba0001f 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -302,7 +302,15 @@ "modelNotFoundDesc": "請確保已正確配置模型,並且模型處於啟用狀態。\n您可以在服務商設置中檢查模型配置。", "removeBuiltinKnowledgeConfirmDesc": "刪除內置知識庫配置將會刪除所有相關數據,且無法恢復,請謹慎操作。", "removeBuiltinKnowledgeConfirmTitle": "確認刪除內置知識庫 {name} 嗎?", - "descriptionDesc": "知識庫的描述,以便 AI 決定是否檢索此知識庫" + "descriptionDesc": "知識庫的描述,以便 AI 決定是否檢索此知識庫", + "advanced": "高級選項", + "autoDetectDimensions": "自動檢測嵌入維度", + "autoDetectHelper": "自動檢測嵌入維度,會消耗少量 Tokens", + "chunkOverlapPlaceholder": "默認值,不建議修改", + "chunkSizePlaceholder": "默認值,不建議修改", + "dimensions": "嵌入維度", + "dimensionsPlaceholder": "嵌入維度大小,如 1024", + "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改" }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/mcp.json b/src/renderer/src/i18n/zh-TW/mcp.json index 03be55a95..4710eb240 100644 --- a/src/renderer/src/i18n/zh-TW/mcp.json +++ b/src/renderer/src/i18n/zh-TW/mcp.json @@ -215,6 +215,10 @@ "deepchat-inmemory/meeting-server": { "name": "多智能體會議", "desc": "DeepChat 內建的會議服務可用於發起與主持多智能體討論。" + }, + "builtinKnowledge": { + "desc": "DeepChat內置知識庫檢索服務,可以對DeepChat內置知識庫內容進行檢索", + "name": "內置知識庫檢索" } }, "prompts": { diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index 9a8bccbb5..064905f7b 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -302,7 +302,15 @@ "modelNotFoundDesc": "請確保已正確配置模型,並且模型處於啟用狀態。\n您可以在服務商設置中檢查模型配置。", "removeBuiltinKnowledgeConfirmDesc": "刪除內置知識庫配置將會刪除所有相關數據,且無法恢復,請謹慎操作。", "removeBuiltinKnowledgeConfirmTitle": "確認刪除內置知識庫 {name} 嗎?", - "descriptionDesc": "知識庫的描述,以便 AI 決定是否檢索此知識庫" + "descriptionDesc": "知識庫的描述,以便 AI 決定是否檢索此知識庫", + "advanced": "高級選項", + "autoDetectDimensions": "自動檢測嵌入維度", + "autoDetectHelper": "自動檢測嵌入維度,會消耗少量 Tokens", + "chunkOverlapPlaceholder": "默認值,不建議修改", + "chunkSizePlaceholder": "默認值,不建議修改", + "dimensions": "嵌入維度", + "dimensionsPlaceholder": "嵌入維度大小,如 1024", + "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改" }, "mcp": { "title": "MCP設定", From 54610c1ba8f8b739e8da453256929319ec6cd811 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Wed, 25 Jun 2025 09:01:02 +0800 Subject: [PATCH 014/109] [WIP] feat: add dimensionsHelper to settings for better user guidance on embedding dimensions --- .../src/components/settings/BuiltinKnowledgeSettings.vue | 5 +++-- src/renderer/src/i18n/en-US/settings.json | 3 ++- src/renderer/src/i18n/fa-IR/settings.json | 3 ++- src/renderer/src/i18n/fr-FR/settings.json | 3 ++- src/renderer/src/i18n/ja-JP/settings.json | 3 ++- src/renderer/src/i18n/ko-KR/settings.json | 3 ++- src/renderer/src/i18n/ru-RU/settings.json | 3 ++- src/renderer/src/i18n/zh-CN/settings.json | 1 + src/renderer/src/i18n/zh-HK/settings.json | 3 ++- src/renderer/src/i18n/zh-TW/settings.json | 3 ++- 10 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index f42f85bac..2ddfbf50b 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -256,7 +256,7 @@ -

{{ t('settings.knowledgeBase.autoDetectHelper') }}

+

⚠️ {{ t('settings.knowledgeBase.dimensionsHelper') }}

@@ -576,7 +576,8 @@ const saveBuiltinConfig = async () => { }) } else { if (autoDetectDimensionsSwitch.value) { - // 自动获取dimensions + // TODO 自动获取dimensions + } // 添加配置 builtinConfigs.value.push({ ...editingBuiltinConfig.value }) diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index ea0944269..ae2461b39 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -310,7 +310,8 @@ "chunkSizePlaceholder": "Default value, no modification is recommended", "dimensions": "Embed dimensions", "dimensionsPlaceholder": "Embed dimension size, such as 1024", - "selectEmbeddingModelHelper": "Embedding models are prohibited after creation of knowledge base" + "selectEmbeddingModelHelper": "Embedding models are prohibited after creation of knowledge base", + "dimensionsHelper": "Make sure the model supports the set embed dimension size" }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 6a90e5f5d..b62c92cda 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -310,7 +310,8 @@ "chunkSizePlaceholder": "مقدار پیش فرض ، هیچ اصلاح توصیه نمی شود", "dimensions": "ابعاد جاسازی شده", "dimensionsPlaceholder": "اندازه ابعاد تعبیه شده ، مانند 1024", - "selectEmbeddingModelHelper": "مدل های تعبیه شده پس از ایجاد پایگاه دانش ممنوع است" + "selectEmbeddingModelHelper": "مدل های تعبیه شده پس از ایجاد پایگاه دانش ممنوع است", + "dimensionsHelper": "اطمینان حاصل کنید که مدل از اندازه ابعاد تعبیه شده پشتیبانی می کند" }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 3021d6919..16fd5686e 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -310,7 +310,8 @@ "chunkSizePlaceholder": "Valeur par défaut, aucune modification n'est recommandée", "dimensions": "Dimensions de l'incorporation", "dimensionsPlaceholder": "Taille de dimension intégrée, comme 1024", - "selectEmbeddingModelHelper": "Les modèles d'intégration sont interdits après la création d'une base de connaissances" + "selectEmbeddingModelHelper": "Les modèles d'intégration sont interdits après la création d'une base de connaissances", + "dimensionsHelper": "Assurez-vous que le modèle prend en charge la taille de la dimension intégrée de l'ensemble" }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index 042577376..c6a076134 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -310,7 +310,8 @@ "chunkSizePlaceholder": "デフォルト値、変更は推奨されません", "dimensions": "埋め込まれた寸法", "dimensionsPlaceholder": "1024などの寸法サイズを埋め込みます", - "selectEmbeddingModelHelper": "埋め込みモデルは、知識ベースの作成後に禁止されています" + "selectEmbeddingModelHelper": "埋め込みモデルは、知識ベースの作成後に禁止されています", + "dimensionsHelper": "モデルが設定された埋め込み寸法サイズをサポートしていることを確認してください" }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index 5fa283fc8..5a077b850 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -310,7 +310,8 @@ "chunkSizePlaceholder": "기본값, 수정은 권장되지 않습니다", "dimensions": "치수를 포함시킵니다", "dimensionsPlaceholder": "1024와 같은 치수 크기를 포함시킵니다", - "selectEmbeddingModelHelper": "임베딩 모델은 지식 기반을 창출 한 후 금지됩니다" + "selectEmbeddingModelHelper": "임베딩 모델은 지식 기반을 창출 한 후 금지됩니다", + "dimensionsHelper": "모델이 세트 임베드 치수 크기를 지원하는지 확인하십시오." }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 208d140cd..43ce03216 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -310,7 +310,8 @@ "chunkSizePlaceholder": "Значение по умолчанию, изменение не рекомендуется", "dimensions": "Встроенные размеры", "dimensionsPlaceholder": "Встроенный размер измерения, такой как 1024", - "selectEmbeddingModelHelper": "Встроенные модели запрещены после создания базы знаний" + "selectEmbeddingModelHelper": "Встроенные модели запрещены после создания базы знаний", + "dimensionsHelper": "Убедитесь, что модель поддерживает размер встроенного размера" }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index fb02b8a51..71e05af1a 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -309,6 +309,7 @@ "dimensionsPlaceholder": "嵌入维度大小,如 1024", "autoDetectDimensions": "自动检测嵌入维度", "autoDetectHelper": "自动检测嵌入维度,会消耗少量 Tokens", + "dimensionsHelper": "请确保模型支持所设置的嵌入维度大小", "chunkSizePlaceholder": "默认值,不建议修改", "chunkOverlapPlaceholder": "默认值,不建议修改" }, diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 48ba0001f..a481c0787 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -310,7 +310,8 @@ "chunkSizePlaceholder": "默認值,不建議修改", "dimensions": "嵌入維度", "dimensionsPlaceholder": "嵌入維度大小,如 1024", - "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改" + "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改", + "dimensionsHelper": "請確保模型支持所設置的嵌入維度大小" }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index 064905f7b..398240492 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -310,7 +310,8 @@ "chunkSizePlaceholder": "默認值,不建議修改", "dimensions": "嵌入維度", "dimensionsPlaceholder": "嵌入維度大小,如 1024", - "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改" + "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改", + "dimensionsHelper": "請確保模型支持所設置的嵌入維度大小" }, "mcp": { "title": "MCP設定", From 16c5e443e9403779a1f0e15483d77652912e7f25 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Wed, 25 Jun 2025 14:17:06 +0800 Subject: [PATCH 015/109] [WIP] feat: add getDimensions method and update embedding handling across providers --- .../configPresenter/modelDefaultSettings.ts | 12 ++++ .../configPresenter/providerModelSettings.ts | 2 +- .../llmProviderPresenter/baseProvider.ts | 15 ++++- .../presenter/llmProviderPresenter/index.ts | 18 +++++- .../providers/ollamaProvider.ts | 10 +++ .../providers/openAICompatibleProvider.ts | 18 ------ src/renderer/src/components/ModelSelect.vue | 2 +- .../settings/BuiltinKnowledgeSettings.vue | 9 ++- .../settings/OllamaProviderSettingsDetail.vue | 62 ++++++++++--------- src/shared/presenter.d.ts | 2 + 10 files changed, 93 insertions(+), 57 deletions(-) diff --git a/src/main/presenter/configPresenter/modelDefaultSettings.ts b/src/main/presenter/configPresenter/modelDefaultSettings.ts index fe627aaac..a2f243924 100644 --- a/src/main/presenter/configPresenter/modelDefaultSettings.ts +++ b/src/main/presenter/configPresenter/modelDefaultSettings.ts @@ -1670,6 +1670,18 @@ export const defaultModelsSettings: DefaultModelSetting[] = [ reasoning: false, type: ModelType.Embedding }, + { + id: 'all-minilm', + name: 'all-minilm', + temperature: 0.0, + maxTokens: 8192, + contextLength: 8192, + match: ['all-minilm'], + vision: false, + functionCall: false, + reasoning: false, + type: ModelType.Embedding + }, { id: 'embedding', name: 'embedding', diff --git a/src/main/presenter/configPresenter/providerModelSettings.ts b/src/main/presenter/configPresenter/providerModelSettings.ts index 190d78db7..f20253886 100644 --- a/src/main/presenter/configPresenter/providerModelSettings.ts +++ b/src/main/presenter/configPresenter/providerModelSettings.ts @@ -257,7 +257,7 @@ export const providerModelSettings: Record { + throw new Error('embedding is not supported by this provider') + } + /** * 获取嵌入向量对象 - * @param _params 知识库参数 + * @param _model 知识库参数 * @returns embedjs/Embeddings 对象 */ public getEmbedding(_model: string): BaseEmbeddings { diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index 04b463103..87d947c44 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -1117,15 +1117,29 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { /** * 获取文本的 embedding 表示 * @param providerId 提供商ID - * @param texts 文本数组 * @param modelId 模型ID + * @param texts 文本数组 * @returns embedding 数组 */ - async getEmbeddings(providerId: string, texts: string[], modelId: string): Promise { + getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise { const provider = this.getProviderInstance(providerId) if (!provider.getEmbeddings) { throw new Error('当前 LLM 提供商未实现 embedding 能力') } return provider.getEmbeddings(texts, modelId) } + + /** + * 获取指定模型的 embedding 维度 + * @param providerId 提供商ID + * @param modelId 模型ID + * @returns 模型的 embedding 维度 + */ + getDimensions(providerId: string, modelId: string): Promise { + const provider = this.getProviderInstance(providerId) + if (!provider.getDimensions) { + throw new Error('当前 LLM 提供商未实现 embedding 能力') + } + return provider.getDimensions(modelId) + } } diff --git a/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts b/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts index 5609194bb..68b5c6844 100644 --- a/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts @@ -1144,4 +1144,14 @@ export class OllamaProvider extends BaseLLMProvider { } return results } + + async getDimensions(modelId: string): Promise { + try { + const res = await this.getEmbeddings(['sample'], modelId) + return res[0].length + } catch (error) { + console.error('获取Ollama模型维度失败:', error) + throw error + } + } } diff --git a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts index 091f55913..8e47145fa 100644 --- a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts @@ -1281,22 +1281,4 @@ export class OpenAICompatibleProvider extends BaseLLMProvider { return [] // Return empty on error } } - - /** - * 获取文本的 embedding 表示 - * @param texts 待编码的文本数组 - * @param modelId 使用的模型ID - * @returns embedding 数组 - */ - async getEmbeddings(texts: string[], modelId: string): Promise { - if (!this.isInitialized) throw new Error('Provider not initialized') - if (!modelId) throw new Error('Model ID is required') - // OpenAI embeddings API - const response = await this.openai.embeddings.create({ - model: modelId, - input: texts - }) - // 兼容 OpenAI 返回格式 - return response.data.map((item) => item.embedding) - } } diff --git a/src/renderer/src/components/ModelSelect.vue b/src/renderer/src/components/ModelSelect.vue index d31f5ae29..2ee2de6a0 100644 --- a/src/renderer/src/components/ModelSelect.vue +++ b/src/renderer/src/components/ModelSelect.vue @@ -68,7 +68,7 @@ const props = defineProps({ }) const filteredProviders = computed(() => { - if (!keyword.value) return providers.value + if (!keyword.value) return providers.value.filter((provider) => provider.models.length > 0) return providers.value .map((provider) => ({ ...provider, diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 2ddfbf50b..2f820612d 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -417,11 +417,13 @@ import { useRoute } from 'vue-router' import { useSettingsStore } from '@/stores/settings' import { ChevronDown, CircleQuestionMark } from 'lucide-vue-next' import { nanoid } from 'nanoid' - +import { usePresenter } from '@/composables/usePresenter' +// 全局对象 const { t } = useI18n() const mcpStore = useMcpStore() const settingsStore = useSettingsStore() const themeStore = useThemeStore() +const llmP = usePresenter('llmproviderPresenter') const emit = defineEmits<{ (e: 'showDetail',value:Object): void }>() @@ -576,8 +578,9 @@ const saveBuiltinConfig = async () => { }) } else { if (autoDetectDimensionsSwitch.value) { - // TODO 自动获取dimensions - + // 自动获取dimensions + const dimensions = await llmP.getDimensions(editingBuiltinConfig.value.providerId, editingBuiltinConfig.value.modelId) + console.log('获取到的维度:', dimensions) } // 添加配置 builtinConfigs.value.push({ ...editingBuiltinConfig.value }) diff --git a/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue b/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue index 72f4f7fca..49ac885ff 100644 --- a/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue +++ b/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue @@ -102,7 +102,7 @@
{{ t('settings.provider.noLocalModels') }} @@ -110,36 +110,38 @@
-
-
- {{ model.name }} - - {{ t('settings.provider.pulling') }} - - - - + +
@@ -245,6 +247,8 @@ import { } from '@/components/ui/dialog' import { useSettingsStore } from '@/stores/settings' import type { LLM_PROVIDER } from '@shared/presenter' +import ModelConfigItem from './ModelConfigItem.vue' +import { ModelType } from '@shared/model' const { t } = useI18n() diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index 7dc7d8967..10498ec06 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -529,6 +529,8 @@ export interface ILlmProviderPresenter { listOllamaRunningModels(): Promise pullOllamaModels(modelName: string): Promise deleteOllamaModel(modelName: string): Promise + getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise + getDimensions(providerId: string, modelId: string): Promise } export type CONVERSATION_SETTINGS = { systemPrompt: string From c18a71be462208809d917232918506e13d425815 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Wed, 25 Jun 2025 16:53:48 +0800 Subject: [PATCH 016/109] [wip] feat: enhance embedding handling by adding error handling and resetting model selection in settings --- .../presenter/llmProviderPresenter/index.ts | 17 +++++----- .../providers/openAICompatibleProvider.ts | 31 +++++++++++++++++++ .../settings/BuiltinKnowledgeSettings.vue | 9 +++++- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index 87d947c44..826a9c01e 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -34,6 +34,7 @@ import { LMStudioProvider } from './providers/lmstudioProvider' import { OpenAIResponsesProvider } from './providers/openAIResponsesProvider' import { OpenRouterProvider } from './providers/openRouterProvider' import { MinimaxProvider } from './providers/minimaxProvider' +import { ca } from 'zod/dist/types/v4/locales' // 流的状态 interface StreamState { isGenerating: boolean @@ -1121,12 +1122,12 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { * @param texts 文本数组 * @returns embedding 数组 */ - getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise { + async getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise { const provider = this.getProviderInstance(providerId) if (!provider.getEmbeddings) { throw new Error('当前 LLM 提供商未实现 embedding 能力') } - return provider.getEmbeddings(texts, modelId) + return await provider.getEmbeddings(texts, modelId) } /** @@ -1135,11 +1136,13 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { * @param modelId 模型ID * @returns 模型的 embedding 维度 */ - getDimensions(providerId: string, modelId: string): Promise { - const provider = this.getProviderInstance(providerId) - if (!provider.getDimensions) { - throw new Error('当前 LLM 提供商未实现 embedding 能力') + async getDimensions(providerId: string, modelId: string): Promise { + try { + const provider = this.getProviderInstance(providerId) + return await provider.getDimensions(modelId) + } catch (error) { + console.error(`获取模型 ${modelId} 的 embedding 维度失败:`, error) + return -1 } - return provider.getDimensions(modelId) } } diff --git a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts index 8e47145fa..a369bd407 100644 --- a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts @@ -1281,4 +1281,35 @@ export class OpenAICompatibleProvider extends BaseLLMProvider { return [] // Return empty on error } } + + async getEmbeddings(texts: string[], modelId: string): Promise { + if (!this.isInitialized) throw new Error('Provider not initialized') + if (!modelId) throw new Error('Model ID is required') + // OpenAI embeddings API + const response = await this.openai.embeddings.create({ + model: modelId, + input: texts, + encoding_format: 'float' + }) + // 兼容 OpenAI 返回格式 + return response.data.map((item) => item.embedding) + } + + async getDimensions(modelId: string): Promise { + try { + switch (modelId) { + case 'text-embedding-3-small': + case 'text-embedding-ada-002': + return 1536 + case 'text-embedding-3-large': + return 3072 + default: + const embeddings = await this.getEmbeddings(['embed'], modelId) + return embeddings[0].length + } + } catch (error) { + console.error('获取维度失败:', error) + throw new Error('获取维度失败') + } + } } diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 2f820612d..c9444b80b 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -494,6 +494,8 @@ function openAddConfig() { modelId: '', enabled: true } + selectEmbeddingModel.value = null + autoDetectDimensionsSwitch.value = true isBuiltinConfigDialogOpen.value = true } @@ -559,11 +561,15 @@ const closeBuiltinConfigDialog = () => { modelId: '', enabled: true } + selectEmbeddingModel.value = null + autoDetectDimensionsSwitch.value = true } + // 进入设置页面 const handleSetting = (config) => { emit('showDetail',config) } + // 保存配置 const saveBuiltinConfig = async () => { if (!isEditingBuiltinConfigValid.value) return @@ -580,7 +586,8 @@ const saveBuiltinConfig = async () => { if (autoDetectDimensionsSwitch.value) { // 自动获取dimensions const dimensions = await llmP.getDimensions(editingBuiltinConfig.value.providerId, editingBuiltinConfig.value.modelId) - console.log('获取到的维度:', dimensions) + console.log('获取到模型维度:', dimensions) + editingBuiltinConfig.value.dimensions = dimensions } // 添加配置 builtinConfigs.value.push({ ...editingBuiltinConfig.value }) From a0561219a18bd33246bd169600d2fe02b8cbaa76 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Wed, 25 Jun 2025 17:39:51 +0800 Subject: [PATCH 017/109] [WIP] feat: refactor embedding handling to use modelId and providerId, enhance KnowledgePresenter integration --- TODO.md | 5 +-- src/main/presenter/index.ts | 6 +++- .../knowledgePresenter/Embeddings.ts | 6 ++-- .../knowledgePresenter/EmbeddingsFactory.ts | 14 ++++---- .../presenter/knowledgePresenter/index.ts | 35 +++++++++++-------- .../llmProviderPresenter/baseProvider.ts | 8 ++--- .../presenter/llmProviderPresenter/index.ts | 24 ++++++++++--- .../providers/openAICompatibleProvider.ts | 12 ++++++- .../src/components/settings/KnowledgeFile.vue | 3 -- .../settings/OllamaProviderSettingsDetail.vue | 19 +++++++--- src/renderer/src/i18n/zh-CN/settings.json | 4 +++ src/shared/presenter.d.ts | 5 +-- 12 files changed, 95 insertions(+), 46 deletions(-) diff --git a/TODO.md b/TODO.md index c71808e80..ebdd76bf6 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,4 @@ -- [ ] saveBuiltinConfig, dimensions 为空,则通过 LLM 尝试获取。 -- [X] knowledgeProvider 实现数据监听,通过对比获取配置变更 +- [X] saveBuiltinConfig, dimensions 为空,则通过 LLM 尝试获取。 +- [X] KnowledgePresenter 实现数据监听,通过对比获取配置变更 +- [ ] KnowledgePresenter 中调用create时,Embeddings 应该通过 LlmProviderPresenter 获取。 - [ ] BuiltinKnowledgeSettings 页面和逻辑优化 \ No newline at end of file diff --git a/src/main/presenter/index.ts b/src/main/presenter/index.ts index 573290ecd..b74ecd056 100644 --- a/src/main/presenter/index.ts +++ b/src/main/presenter/index.ts @@ -81,7 +81,11 @@ export class Presenter implements IPresenter { this.notificationPresenter = new NotificationPresenter() this.oauthPresenter = new OAuthPresenter() this.trayPresenter = new TrayPresenter() - this.KnowledgePresenter = new KnowledgePresenter(this.configPresenter, dbDir) + this.KnowledgePresenter = new KnowledgePresenter( + this.configPresenter, + this.llmproviderPresenter, + dbDir + ) // this.llamaCppPresenter = new LlamaCppPresenter() // 保留原始注释 this.setupEventBus() // 设置事件总线监听 diff --git a/src/main/presenter/knowledgePresenter/Embeddings.ts b/src/main/presenter/knowledgePresenter/Embeddings.ts index 69c1d44d1..4f5112219 100644 --- a/src/main/presenter/knowledgePresenter/Embeddings.ts +++ b/src/main/presenter/knowledgePresenter/Embeddings.ts @@ -5,10 +5,10 @@ import { KnowledgeBaseParams } from '@shared/presenter' export default class Embeddings { private sdk: BaseEmbeddings - constructor({ model, provider, apiKey, apiVersion, baseURL, dimensions }: KnowledgeBaseParams) { + constructor({ modelId, providerId, apiKey, apiVersion, baseURL, dimensions }: KnowledgeBaseParams) { this.sdk = EmbeddingsFactory.create({ - model, - provider, + modelId, + providerId, apiKey, apiVersion, baseURL, diff --git a/src/main/presenter/knowledgePresenter/EmbeddingsFactory.ts b/src/main/presenter/knowledgePresenter/EmbeddingsFactory.ts index fc8c91e76..cfe62e5ad 100644 --- a/src/main/presenter/knowledgePresenter/EmbeddingsFactory.ts +++ b/src/main/presenter/knowledgePresenter/EmbeddingsFactory.ts @@ -6,18 +6,18 @@ import { KnowledgeBaseParams } from '@shared/presenter' export default class EmbeddingsFactory { static create({ - model, - provider, + modelId, + providerId, apiKey, apiVersion, baseURL, dimensions }: KnowledgeBaseParams): BaseEmbeddings { const batchSize = 10 - if (provider === 'ollama') { + if (providerId === 'ollama') { if (baseURL.includes('v1/')) { return new OllamaEmbeddings({ - model: model, + model: modelId, baseUrl: baseURL.replace('v1/', ''), requestOptions: { // @ts-ignore expected @@ -26,7 +26,7 @@ export default class EmbeddingsFactory { }) } return new OllamaEmbeddings({ - model: model, + model: modelId, baseUrl: baseURL, requestOptions: { // @ts-ignore expected @@ -38,14 +38,14 @@ export default class EmbeddingsFactory { return new AzureOpenAiEmbeddings({ azureOpenAIApiKey: apiKey, azureOpenAIApiVersion: apiVersion, - azureOpenAIApiDeploymentName: model, + azureOpenAIApiDeploymentName: modelId, azureOpenAIApiInstanceName: this.getInstanceName(baseURL), dimensions, batchSize }) } return new OpenAiEmbeddings({ - model, + model: modelId, apiKey, dimensions, batchSize, diff --git a/src/main/presenter/knowledgePresenter/index.ts b/src/main/presenter/knowledgePresenter/index.ts index 5470c4e89..2e7cec1a0 100644 --- a/src/main/presenter/knowledgePresenter/index.ts +++ b/src/main/presenter/knowledgePresenter/index.ts @@ -4,6 +4,7 @@ import path from 'node:path' import { IConfigPresenter, IKnowledgePresenter, + ILlmProviderPresenter, KnowledgeBaseParams, MCPServerConfig } from '@shared/presenter' @@ -19,11 +20,14 @@ export class KnowledgePresenter implements IKnowledgePresenter { */ private readonly storageDir - configPresenter: IConfigPresenter + private readonly configP: IConfigPresenter - constructor(configPresenter: IConfigPresenter, dbDir: string) { + private readonly llmP: ILlmProviderPresenter + + constructor(configP: IConfigPresenter, llmP: ILlmProviderPresenter, dbDir: string) { console.log('[RAG] Initializing Built-in Knowledge Presenter') - this.configPresenter = configPresenter + this.configP = configP + this.llmP = llmP this.storageDir = path.join(dbDir, 'KnowledgeBase') this.initStorageDir() @@ -43,7 +47,12 @@ export class KnowledgePresenter implements IKnowledgePresenter { // 监听知识库相关事件 eventBus.on(MCP_EVENTS.CONFIG_CHANGED, async (payload) => { try { - if (!payload || typeof payload !== 'object' || !payload.mcpServers || typeof payload.mcpServers !== 'object') { + if ( + !payload || + typeof payload !== 'object' || + !payload.mcpServers || + typeof payload.mcpServers !== 'object' + ) { console.warn('[RAG] Invalid payload for CONFIG_CHANGED event:', payload) return } @@ -53,7 +62,7 @@ export class KnowledgePresenter implements IKnowledgePresenter { const configs = builtinConfig.env.configs as KnowledgeBaseParams[] console.log('[RAG] Received builtinKnowledge config update:', configs) - const diffs = this.configPresenter.diffKnowledgeConfigs(configs) + const diffs = this.configP.diffKnowledgeConfigs(configs) if (diffs.added.length > 0) { diffs.added.forEach((config) => { console.log(`[RAG] New knowledge config added: ${config.id}`) @@ -64,7 +73,7 @@ export class KnowledgePresenter implements IKnowledgePresenter { } if (diffs.deleted.length > 0) { } - this.configPresenter.setKnowledgeConfigs(configs) + this.configP.setKnowledgeConfigs(configs) console.log('[RAG] Updated knowledge configs:', configs) } else { console.warn('[RAG] builtinKnowledge config missing or invalid:', builtinConfig) @@ -103,21 +112,17 @@ export class KnowledgePresenter implements IKnowledgePresenter { */ private getRagApplication = async ({ id, - model, - provider, - apiKey, - apiVersion, - baseURL, + modelId, + providerId, dimensions }: KnowledgeBaseParams): Promise => { let ragApplication: RAGApplication // 创建 Embeddings 实例 + const { apiKey } = this.llmP.getEmbeddingParams(providerId, modelId) const embeddings = new Embeddings({ - model, - provider, + providerId, + modelId, apiKey, - apiVersion, - baseURL, dimensions } as KnowledgeBaseParams) try { diff --git a/src/main/presenter/llmProviderPresenter/baseProvider.ts b/src/main/presenter/llmProviderPresenter/baseProvider.ts index 14e050e42..37d166e88 100644 --- a/src/main/presenter/llmProviderPresenter/baseProvider.ts +++ b/src/main/presenter/llmProviderPresenter/baseProvider.ts @@ -6,12 +6,12 @@ import { LLMCoreStreamEvent, ModelConfig, ChatMessage, - KeyStatus + KeyStatus, + KnowledgeBaseParams } from '@shared/presenter' import { ConfigPresenter } from '../configPresenter' import { DevicePresenter } from '../devicePresenter' import { jsonrepair } from 'jsonrepair' -import { BaseEmbeddings } from '@llm-tools/embedjs-interfaces' /** * 基础LLM提供商抽象类 @@ -567,11 +567,11 @@ ${this.convertToolsToXml(tools)} } /** - * 获取嵌入向量对象 + * 获取嵌入模型的参数 * @param _model 知识库参数 * @returns embedjs/Embeddings 对象 */ - public getEmbedding(_model: string): BaseEmbeddings { + public getEmbeddingParams(_model: string): KnowledgeBaseParams { throw new Error('embedding is not supported by this provider') } diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index 826a9c01e..712ee7d4b 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -34,7 +34,7 @@ import { LMStudioProvider } from './providers/lmstudioProvider' import { OpenAIResponsesProvider } from './providers/openAIResponsesProvider' import { OpenRouterProvider } from './providers/openRouterProvider' import { MinimaxProvider } from './providers/minimaxProvider' -import { ca } from 'zod/dist/types/v4/locales' + // 流的状态 interface StreamState { isGenerating: boolean @@ -1123,11 +1123,12 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { * @returns embedding 数组 */ async getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise { - const provider = this.getProviderInstance(providerId) - if (!provider.getEmbeddings) { + try { + const provider = this.getProviderInstance(providerId) + return await provider.getEmbeddings(texts, modelId) + } catch (error) { throw new Error('当前 LLM 提供商未实现 embedding 能力') } - return await provider.getEmbeddings(texts, modelId) } /** @@ -1145,4 +1146,19 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { return -1 } } + + /** + * 获取指定模型的 embedding 参数 + * @param providerId 提供商ID + * @param modelId 模型ID + * @returns 获取模型的 embedding 参数 + */ + getEmbeddingParams(providerId: string, modelId: string) { + try { + const provider = this.getProviderInstance(providerId) + return provider.getEmbeddingParams(modelId) + } catch (error) { + throw new Error('当前 LLM 提供商未实现 embedding 能力') + } + } } diff --git a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts index a369bd407..747e7c8e2 100644 --- a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts @@ -5,7 +5,8 @@ import { MCPToolDefinition, LLMCoreStreamEvent, ModelConfig, - ChatMessage + ChatMessage, + KnowledgeBaseParams } from '@shared/presenter' import { BaseLLMProvider } from '../baseProvider' import OpenAI, { AzureOpenAI } from 'openai' @@ -1312,4 +1313,13 @@ export class OpenAICompatibleProvider extends BaseLLMProvider { throw new Error('获取维度失败') } } + + public getEmbeddingParams(model: string): KnowledgeBaseParams { + return { + modelId: model, + providerId: this.provider.id, + apiKey: this.provider.apiKey, + baseURL: this.provider.baseUrl + } as KnowledgeBaseParams + } } diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index 349e207ae..9f0f77bdf 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -57,7 +57,6 @@ import { } from '@/components/ui/accordion' import { ref } from 'vue' -import { useI18n } from 'vue-i18n' import { Icon } from '@iconify/vue' import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' @@ -71,8 +70,6 @@ const emit = defineEmits<{ (e: 'hideKnowledgeFile'): void }>() -const { t } = useI18n() - // 返回知识库页面 const onReturn = () => { emit('hideKnowledgeFile') diff --git a/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue b/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue index 49ac885ff..c908d8478 100644 --- a/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue +++ b/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue @@ -129,16 +129,16 @@
{{ model.name }} - + {{ t('settings.provider.pulling') }}
- {{ formatModelSize(model.size) }} + {{ + formatModelSize(model.size) + }}
@@ -249,8 +249,10 @@ import { useSettingsStore } from '@/stores/settings' import type { LLM_PROVIDER } from '@shared/presenter' import ModelConfigItem from './ModelConfigItem.vue' import { ModelType } from '@shared/model' +import { useToast } from '../ui/toast' const { t } = useI18n() +const { toast } = useToast() const props = defineProps<{ provider: LLM_PROVIDER @@ -438,6 +440,15 @@ const pullModel = async (modelName: string) => { // 显示删除模型确认对话框 const showDeleteModelConfirm = (modelName: string) => { + if (isModelRunning(modelName)) { + toast({ + title: t('settings.provider.toast.modelRunning'), + description: t('settings.provider.toast.modelRunningDesc', { model: modelName }), + variant: 'destructive', + duration: 3000 + }) + return + } modelToDelete.value = modelName showDeleteModelDialog.value = true } diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index 71e05af1a..191ec0ba1 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -179,6 +179,10 @@ "stopModel": "停止模型", "pulling": "拉取中...", "runModel": "运行模型", + "toast": { + "modelRunning": "模型正在运行", + "modelRunningDesc": "请先停止模型 {model},然后再删除。" + }, "dialog": { "disableModel": { "title": "确认禁用模型", diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index 10498ec06..7d437912e 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -531,6 +531,7 @@ export interface ILlmProviderPresenter { deleteOllamaModel(modelName: string): Promise getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise getDimensions(providerId: string, modelId: string): Promise + getEmbeddingParams(providerId: string, modelId: string): KnowledgeBaseParams } export type CONVERSATION_SETTINGS = { systemPrompt: string @@ -1155,8 +1156,8 @@ export interface IKnowledgePresenter { export type KnowledgeBaseParams = { id: string description: string - model: string - provider: string + modelId: string + providerId: string dimensions?: number apiKey: string apiVersion?: string From 4e2b5bbc545060723154b70fc4361a1fcfc4ddb6 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Wed, 25 Jun 2025 17:55:19 +0800 Subject: [PATCH 018/109] [WIP] feat: update KnowledgePresenter and LLMProviderPresenter to improve embedding handling and error logging --- TODO.md | 2 +- .../knowledgePresenter/EmbeddingsFactory.ts | 1 + src/main/presenter/knowledgePresenter/index.ts | 2 +- .../llmProviderPresenter/baseProvider.ts | 12 +----------- src/main/presenter/llmProviderPresenter/index.ts | 16 +--------------- .../providers/openAICompatibleProvider.ts | 10 ---------- .../settings/BuiltinKnowledgeSettings.vue | 9 ++++++--- src/shared/presenter.d.ts | 1 - 8 files changed, 11 insertions(+), 42 deletions(-) diff --git a/TODO.md b/TODO.md index ebdd76bf6..717bd1f3d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,4 @@ - [X] saveBuiltinConfig, dimensions 为空,则通过 LLM 尝试获取。 - [X] KnowledgePresenter 实现数据监听,通过对比获取配置变更 -- [ ] KnowledgePresenter 中调用create时,Embeddings 应该通过 LlmProviderPresenter 获取。 +- [X] KnowledgePresenter 中调用create时,Embeddings 应该通过 LlmProviderPresenter 获取。 - [ ] BuiltinKnowledgeSettings 页面和逻辑优化 \ No newline at end of file diff --git a/src/main/presenter/knowledgePresenter/EmbeddingsFactory.ts b/src/main/presenter/knowledgePresenter/EmbeddingsFactory.ts index cfe62e5ad..ba1fab673 100644 --- a/src/main/presenter/knowledgePresenter/EmbeddingsFactory.ts +++ b/src/main/presenter/knowledgePresenter/EmbeddingsFactory.ts @@ -57,6 +57,7 @@ export default class EmbeddingsFactory { try { return new URL(baseURL).host.split('.')[0] } catch (error) { + console.error('Invalid baseURL:', baseURL, error) return '' } } diff --git a/src/main/presenter/knowledgePresenter/index.ts b/src/main/presenter/knowledgePresenter/index.ts index 2e7cec1a0..7ae611cbe 100644 --- a/src/main/presenter/knowledgePresenter/index.ts +++ b/src/main/presenter/knowledgePresenter/index.ts @@ -118,7 +118,7 @@ export class KnowledgePresenter implements IKnowledgePresenter { }: KnowledgeBaseParams): Promise => { let ragApplication: RAGApplication // 创建 Embeddings 实例 - const { apiKey } = this.llmP.getEmbeddingParams(providerId, modelId) + const { apiKey } = this.llmP.getProviderById(providerId) const embeddings = new Embeddings({ providerId, modelId, diff --git a/src/main/presenter/llmProviderPresenter/baseProvider.ts b/src/main/presenter/llmProviderPresenter/baseProvider.ts index 37d166e88..2b7cc7717 100644 --- a/src/main/presenter/llmProviderPresenter/baseProvider.ts +++ b/src/main/presenter/llmProviderPresenter/baseProvider.ts @@ -6,8 +6,7 @@ import { LLMCoreStreamEvent, ModelConfig, ChatMessage, - KeyStatus, - KnowledgeBaseParams + KeyStatus } from '@shared/presenter' import { ConfigPresenter } from '../configPresenter' import { DevicePresenter } from '../devicePresenter' @@ -566,15 +565,6 @@ ${this.convertToolsToXml(tools)} throw new Error('embedding is not supported by this provider') } - /** - * 获取嵌入模型的参数 - * @param _model 知识库参数 - * @returns embedjs/Embeddings 对象 - */ - public getEmbeddingParams(_model: string): KnowledgeBaseParams { - throw new Error('embedding is not supported by this provider') - } - /** * 获取 API key 状态信息 * @returns API key 状态信息,如果不支持则返回 null diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index 712ee7d4b..d8c5181df 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -1127,6 +1127,7 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { const provider = this.getProviderInstance(providerId) return await provider.getEmbeddings(texts, modelId) } catch (error) { + console.error(`${modelId} embedding 失败:`, error) throw new Error('当前 LLM 提供商未实现 embedding 能力') } } @@ -1146,19 +1147,4 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { return -1 } } - - /** - * 获取指定模型的 embedding 参数 - * @param providerId 提供商ID - * @param modelId 模型ID - * @returns 获取模型的 embedding 参数 - */ - getEmbeddingParams(providerId: string, modelId: string) { - try { - const provider = this.getProviderInstance(providerId) - return provider.getEmbeddingParams(modelId) - } catch (error) { - throw new Error('当前 LLM 提供商未实现 embedding 能力') - } - } } diff --git a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts index 747e7c8e2..be27676c0 100644 --- a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts @@ -6,7 +6,6 @@ import { LLMCoreStreamEvent, ModelConfig, ChatMessage, - KnowledgeBaseParams } from '@shared/presenter' import { BaseLLMProvider } from '../baseProvider' import OpenAI, { AzureOpenAI } from 'openai' @@ -1313,13 +1312,4 @@ export class OpenAICompatibleProvider extends BaseLLMProvider { throw new Error('获取维度失败') } } - - public getEmbeddingParams(model: string): KnowledgeBaseParams { - return { - modelId: model, - providerId: this.provider.id, - apiKey: this.provider.apiKey, - baseURL: this.provider.baseUrl - } as KnowledgeBaseParams - } } diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index c9444b80b..590f5a123 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -425,7 +425,7 @@ const settingsStore = useSettingsStore() const themeStore = useThemeStore() const llmP = usePresenter('llmproviderPresenter') const emit = defineEmits<{ - (e: 'showDetail',value:Object): void + (e: 'showDetail', value: object): void }>() // 模型选择相关 @@ -567,7 +567,7 @@ const closeBuiltinConfigDialog = () => { // 进入设置页面 const handleSetting = (config) => { - emit('showDetail',config) + emit('showDetail', config) } // 保存配置 @@ -585,7 +585,10 @@ const saveBuiltinConfig = async () => { } else { if (autoDetectDimensionsSwitch.value) { // 自动获取dimensions - const dimensions = await llmP.getDimensions(editingBuiltinConfig.value.providerId, editingBuiltinConfig.value.modelId) + const dimensions = await llmP.getDimensions( + editingBuiltinConfig.value.providerId, + editingBuiltinConfig.value.modelId + ) console.log('获取到模型维度:', dimensions) editingBuiltinConfig.value.dimensions = dimensions } diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index 7d437912e..b35082e5e 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -531,7 +531,6 @@ export interface ILlmProviderPresenter { deleteOllamaModel(modelName: string): Promise getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise getDimensions(providerId: string, modelId: string): Promise - getEmbeddingParams(providerId: string, modelId: string): KnowledgeBaseParams } export type CONVERSATION_SETTINGS = { systemPrompt: string From dd0e3cfc909fc08e403fcaa52419d81c0d6ad35c Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Wed, 25 Jun 2025 18:05:58 +0800 Subject: [PATCH 019/109] [WIP] feat: enhance BuiltinKnowledgeSettings with additional parameters and loading logic for better user experience --- TODO.md | 5 +- .../settings/BuiltinKnowledgeSettings.vue | 74 ++++++++----------- 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/TODO.md b/TODO.md index 717bd1f3d..68a839d05 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,7 @@ - [X] saveBuiltinConfig, dimensions 为空,则通过 LLM 尝试获取。 - [X] KnowledgePresenter 实现数据监听,通过对比获取配置变更 - [X] KnowledgePresenter 中调用create时,Embeddings 应该通过 LlmProviderPresenter 获取。 -- [ ] BuiltinKnowledgeSettings 页面和逻辑优化 \ No newline at end of file +- [ ] BuiltinKnowledgeSettings 页面和逻辑优化 + - [ ] 添加匹配阈值参数 + - [ ] 提交保存时的 loading + - [ ] 无法获取模型 dimensions 时的处理逻辑 diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 590f5a123..b80dccfe5 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -155,14 +155,12 @@ - - - +

{{ t('settings.knowledgeBase.selectEmbeddingModelHelper') }}

@@ -211,15 +209,12 @@ - - - +

{{ t('settings.knowledgeBase.autoDetectHelper') }}

@@ -245,15 +240,12 @@ - - - +

⚠️ {{ t('settings.knowledgeBase.dimensionsHelper') }}

@@ -268,6 +260,7 @@ :min="1" v-model="editingBuiltinConfig.dimensions" :placeholder="t('settings.knowledgeBase.dimensionsPlaceholder')" + :disabled="isEditing" >
@@ -287,14 +280,12 @@ - - - +

{{ t('settings.knowledgeBase.chunkSizeHelper') }}

@@ -323,14 +314,12 @@ - - - +

@@ -547,6 +536,7 @@ const editBuiltinConfig = async (index: number) => { selectEmbeddingModel.value = model editingConfigIndex.value = index editingBuiltinConfig.value = { ...builtinConfigs.value[index] } + autoDetectDimensionsSwitch.value = editingBuiltinConfig.value.dimensions === undefined isBuiltinConfigDialogOpen.value = true } From 394b0cf18324a36b311c85ceb676b891daada4c5 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 26 Jun 2025 09:49:17 +0800 Subject: [PATCH 020/109] [WIP] feat: enhance KnowledgePresenter to handle deleted configs and improve reset logic --- TODO.md | 1 + src/main/presenter/knowledgePresenter/index.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 68a839d05..e666be001 100644 --- a/TODO.md +++ b/TODO.md @@ -5,3 +5,4 @@ - [ ] 添加匹配阈值参数 - [ ] 提交保存时的 loading - [ ] 无法获取模型 dimensions 时的处理逻辑 +- [ ] OllamaProvider 需要增加自定义模型参数覆盖逻辑 diff --git a/src/main/presenter/knowledgePresenter/index.ts b/src/main/presenter/knowledgePresenter/index.ts index 7ae611cbe..f3cfcb40b 100644 --- a/src/main/presenter/knowledgePresenter/index.ts +++ b/src/main/presenter/knowledgePresenter/index.ts @@ -72,6 +72,7 @@ export class KnowledgePresenter implements IKnowledgePresenter { if (diffs.updated.length > 0) { } if (diffs.deleted.length > 0) { + diffs.deleted.forEach((config) => this.delete(config.id)) } this.configP.setKnowledgeConfigs(configs) console.log('[RAG] Updated knowledge configs:', configs) @@ -95,14 +96,18 @@ export class KnowledgePresenter implements IKnowledgePresenter { * 重置知识库内容 */ reset = async ({ base }: { base: KnowledgeBaseParams }): Promise => { - console.log(base) + const ragApplication = await this.getRagApplication(base) + await ragApplication.reset() } /** * 删除知识库(移除本地存储) */ delete = async (id: string): Promise => { - console.log(id) + const dbPath = path.join(this.storageDir, id) + if (fs.existsSync(dbPath)) { + fs.rmSync(dbPath, { recursive: true }) + } } /** From 3eaf8652f9e6a14969efeead6fbb4670f482f501 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 26 Jun 2025 09:49:30 +0800 Subject: [PATCH 021/109] [WIP] feat: update LLMProviderPresenter and OllamaProvider to enhance model listing with additional configuration properties --- .../presenter/llmProviderPresenter/index.ts | 7 ++++--- .../providers/ollamaProvider.ts | 21 ++++++++++++++----- .../settings/OllamaProviderSettingsDetail.vue | 3 +-- src/renderer/src/stores/settings.ts | 6 +++--- src/shared/presenter.d.ts | 4 ++-- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index d8c5181df..ccb20cb80 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -7,7 +7,8 @@ import { OllamaModel, ChatMessage, LLMAgentEvent, - KeyStatus + KeyStatus, + ModelConfig } from '@shared/presenter' import { BaseLLMProvider } from './baseProvider' import { OpenAIProvider } from './providers/openAIProvider' @@ -1066,7 +1067,7 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { return null } // ollama api - listOllamaModels(): Promise { + listOllamaModels(): Promise>> { const provider = this.getOllamaProviderInstance() if (!provider) { // console.error('Ollama provider not found') @@ -1081,7 +1082,7 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { } return provider.showModelInfo(modelName) } - listOllamaRunningModels(): Promise { + listOllamaRunningModels(): Promise>> { const provider = this.getOllamaProviderInstance() if (!provider) { // console.error('Ollama provider not found') diff --git a/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts b/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts index 68b5c6844..170fb3037 100644 --- a/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts @@ -290,21 +290,32 @@ export class OllamaProvider extends BaseLLMProvider { } // Ollama 特有的模型管理功能 - public async listModels(): Promise { + public async listModels(): Promise>> { try { const response = await this.ollama.list() - // 返回类型转换,适应我们的 OllamaModel 接口 - return response.models as unknown as OllamaModel[] + const models = response.models as unknown as OllamaModel[] + // 合并自定义属性 + return models.map((model) => { + const customConfig = this.configPresenter.getModelConfig(model.name, this.provider.id) + // 合并costomConfig的属性到model + return { ...model, ...customConfig } + }) } catch (error) { console.error('Failed to list Ollama models:', (error as Error).message) return [] } } - public async listRunningModels(): Promise { + public async listRunningModels(): Promise>> { try { const response = await this.ollama.ps() - return response.models as unknown as OllamaModel[] + const runningModels = response.models as unknown as OllamaModel[] + // 合并自定义属性 + return runningModels.map((model) => { + const customConfig = this.configPresenter.getModelConfig(model.name, this.provider.id) + // 合并costomConfig的属性到model + return { ...model, ...customConfig } + }) } catch (error) { console.error('Failed to list running Ollama models:', (error as Error).message) return [] diff --git a/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue b/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue index c908d8478..573ecffa4 100644 --- a/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue +++ b/src/renderer/src/components/settings/OllamaProviderSettingsDetail.vue @@ -118,7 +118,7 @@ :model-id="model.name" :provider-id="provider.id" :is-custom-model="true" - :type="ModelType.Chat" + :type="model.type" :enabled="true" @configChanged="refreshModels" @deleteModel="showDeleteModelConfirm(model.name)" @@ -248,7 +248,6 @@ import { import { useSettingsStore } from '@/stores/settings' import type { LLM_PROVIDER } from '@shared/presenter' import ModelConfigItem from './ModelConfigItem.vue' -import { ModelType } from '@shared/model' import { useToast } from '../ui/toast' const { t } = useI18n() diff --git a/src/renderer/src/stores/settings.ts b/src/renderer/src/stores/settings.ts index 3c5904cb6..f13d5232e 100644 --- a/src/renderer/src/stores/settings.ts +++ b/src/renderer/src/stores/settings.ts @@ -5,7 +5,7 @@ import { ModelType } from '@shared/model' import { usePresenter } from '@/composables/usePresenter' import { SearchEngineTemplate } from '@shared/chat' import { CONFIG_EVENTS, OLLAMA_EVENTS, DEEPLINK_EVENTS } from '@/events' -import type { OllamaModel } from '@shared/presenter' +import type { ModelConfig, OllamaModel } from '@shared/presenter' import { useRouter } from 'vue-router' import { useMcpStore } from '@/stores/mcp' import { useUpgradeStore } from '@/stores/upgrade' @@ -35,8 +35,8 @@ export const useSettingsStore = defineStore('settings', () => { const isRefreshingModels = ref(false) // 是否正在刷新模型列表 const fontSizeLevel = ref(DEFAULT_FONT_SIZE_LEVEL) // 字体大小级别,默认为 1 // Ollama 相关状态 - const ollamaRunningModels = ref([]) - const ollamaLocalModels = ref([]) + const ollamaRunningModels = ref>>([]) + const ollamaLocalModels = ref>>([]) const ollamaPullingModels = ref>(new Map()) // 模型名 -> 进度 // 搜索助手模型相关 diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index b35082e5e..ff6ec7318 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -524,9 +524,9 @@ export interface ILlmProviderPresenter { providerId: string, modelId: string ): Promise - listOllamaModels(): Promise + listOllamaModels(): Promise>> showOllamaModelInfo(modelName: string): Promise - listOllamaRunningModels(): Promise + listOllamaRunningModels(): Promise>> pullOllamaModels(modelName: string): Promise deleteOllamaModel(modelName: string): Promise getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise From 0b6089b85ad3f2d9221ddf17eb18393a675c8abf Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 26 Jun 2025 11:12:50 +0800 Subject: [PATCH 022/109] [WIP] feat: enhance Ollama model integration by updating local models to include dynamic configuration retrieval --- src/renderer/src/stores/settings.ts | 49 ++++++++++++++++------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/renderer/src/stores/settings.ts b/src/renderer/src/stores/settings.ts index f13d5232e..d1421758d 100644 --- a/src/renderer/src/stores/settings.ts +++ b/src/renderer/src/stores/settings.ts @@ -1020,29 +1020,34 @@ export const useSettingsStore = defineStore('settings', () => { allProviderModels.value.find((item) => item.providerId === 'ollama')?.models || [] // 将 Ollama 本地模型转换为全局模型格式 - const ollamaModelsAsGlobal = ollamaLocalModels.value.map((model) => { - // 检查是否已存在相同ID的模型,如果存在,保留其现有的配置 - const existingModel = existingOllamaModels.find((m) => m.id === model.name) + const ollamaModelsAsGlobal = await Promise.all( + ollamaLocalModels.value.map(async (model) => { + // 检查是否已存在相同ID的模型,如果存在,保留其现有的配置 + const existingModel = existingOllamaModels.find((m) => m.id === model.name) + const config = await configP.getModelConfig(model.name, 'ollama') - return { - id: model.name, - name: model.name, - contextLength: existingModel?.contextLength || 4096, // 使用现有值或默认值 - maxTokens: existingModel?.maxTokens || 2048, // 使用现有值或默认值 - provider: 'ollama', - group: existingModel?.group || 'local', - enabled: true, - isCustom: existingModel?.isCustom || false, - providerId: 'ollama', - vision: existingModel?.vision || false, - functionCall: existingModel?.functionCall || false, - reasoning: existingModel?.reasoning || false, - type: existingModel?.type || ModelType.Chat, - // 保留现有的其他配置,但确保更新 Ollama 特有数据 - ...(existingModel ? { ...existingModel } : {}), - ollamaModel: model - } as RENDERER_MODEL_META & { ollamaModel: OllamaModel } - }) + return { + ...{ + contextLength: 4096, + maxTokens: 2048, + group: 'local', + enabled: true, + isCustom: false, + providerId: 'ollama', + vision: false, + functionCall: false, + reasoning: false, + type: ModelType.Chat + }, + ...(existingModel || {}), + ...(config || {}), + provider: 'ollama', + id: model.name, + name: model.name, + ollamaModel: model + } as RENDERER_MODEL_META & { ollamaModel: OllamaModel } + }) + ) // 更新全局模型列表 const existingIndex = allProviderModels.value.findIndex((item) => item.providerId === 'ollama') From 258f6efa6337d583f8864d60508404d0f7b5b24b Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 26 Jun 2025 11:32:00 +0800 Subject: [PATCH 023/109] [WIP] fix: update getRagApplication to include baseURL in Embeddings instantiation --- src/main/presenter/knowledgePresenter/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/presenter/knowledgePresenter/index.ts b/src/main/presenter/knowledgePresenter/index.ts index f3cfcb40b..b62f8c556 100644 --- a/src/main/presenter/knowledgePresenter/index.ts +++ b/src/main/presenter/knowledgePresenter/index.ts @@ -123,12 +123,13 @@ export class KnowledgePresenter implements IKnowledgePresenter { }: KnowledgeBaseParams): Promise => { let ragApplication: RAGApplication // 创建 Embeddings 实例 - const { apiKey } = this.llmP.getProviderById(providerId) + const { apiKey, baseUrl } = this.llmP.getProviderById(providerId) const embeddings = new Embeddings({ providerId, modelId, apiKey, - dimensions + dimensions, + baseURL: baseUrl } as KnowledgeBaseParams) try { // 构建 RAG 应用,集成嵌入模型与向量数据库 From 3116785a64466bafaeb8568cb6ed932644ccc4ad Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 26 Jun 2025 15:38:36 +0800 Subject: [PATCH 024/109] [WIP] feat: update getDimensions method to return structured response with error handling --- .../presenter/llmProviderPresenter/index.ts | 12 +++- .../providers/ollamaProvider.ts | 9 +-- .../providers/openAICompatibleProvider.ts | 25 ++++---- .../settings/BuiltinKnowledgeSettings.vue | 57 +++++++++---------- src/renderer/src/i18n/en-US/settings.json | 3 +- src/renderer/src/i18n/fa-IR/settings.json | 3 +- src/renderer/src/i18n/fr-FR/settings.json | 3 +- src/renderer/src/i18n/ja-JP/settings.json | 3 +- src/renderer/src/i18n/ko-KR/settings.json | 3 +- src/renderer/src/i18n/ru-RU/settings.json | 3 +- src/renderer/src/i18n/zh-CN/settings.json | 3 +- src/renderer/src/i18n/zh-HK/settings.json | 3 +- src/renderer/src/i18n/zh-TW/settings.json | 3 +- src/shared/presenter.d.ts | 2 +- 14 files changed, 67 insertions(+), 65 deletions(-) diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index ccb20cb80..9c7580d45 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -1139,13 +1139,19 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { * @param modelId 模型ID * @returns 模型的 embedding 维度 */ - async getDimensions(providerId: string, modelId: string): Promise { + async getDimensions( + providerId: string, + modelId: string + ): Promise<{ value: number; errorMsg?: string }> { try { const provider = this.getProviderInstance(providerId) - return await provider.getDimensions(modelId) + return { value: await provider.getDimensions(modelId) } } catch (error) { console.error(`获取模型 ${modelId} 的 embedding 维度失败:`, error) - return -1 + return { + value: 0, + errorMsg: error instanceof Error ? error.message : String(error) + } } } } diff --git a/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts b/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts index 170fb3037..228870637 100644 --- a/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts @@ -1157,12 +1157,7 @@ export class OllamaProvider extends BaseLLMProvider { } async getDimensions(modelId: string): Promise { - try { - const res = await this.getEmbeddings(['sample'], modelId) - return res[0].length - } catch (error) { - console.error('获取Ollama模型维度失败:', error) - throw error - } + const res = await this.getEmbeddings(['sample'], modelId) + return res[0].length } } diff --git a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts index be27676c0..1397ce504 100644 --- a/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts +++ b/src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts @@ -5,7 +5,7 @@ import { MCPToolDefinition, LLMCoreStreamEvent, ModelConfig, - ChatMessage, + ChatMessage } from '@shared/presenter' import { BaseLLMProvider } from '../baseProvider' import OpenAI, { AzureOpenAI } from 'openai' @@ -1296,20 +1296,15 @@ export class OpenAICompatibleProvider extends BaseLLMProvider { } async getDimensions(modelId: string): Promise { - try { - switch (modelId) { - case 'text-embedding-3-small': - case 'text-embedding-ada-002': - return 1536 - case 'text-embedding-3-large': - return 3072 - default: - const embeddings = await this.getEmbeddings(['embed'], modelId) - return embeddings[0].length - } - } catch (error) { - console.error('获取维度失败:', error) - throw new Error('获取维度失败') + switch (modelId) { + case 'text-embedding-3-small': + case 'text-embedding-ada-002': + return 1536 + case 'text-embedding-3-large': + return 3072 + default: + const embeddings = await this.getEmbeddings(['sample'], modelId) + return embeddings[0].length } } } diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index b80dccfe5..a207d8c6a 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -155,11 +155,9 @@ - @@ -186,7 +184,7 @@ selectEmbeddingModel?.name || t('settings.common.selectModel') }}

- + @@ -209,11 +207,9 @@ - @@ -240,11 +236,9 @@ - @@ -280,11 +274,9 @@ - @@ -314,11 +306,9 @@ - @@ -404,7 +394,6 @@ import { RENDERER_MODEL_META } from '@shared/presenter' import { toast } from '../ui/toast' import { useRoute } from 'vue-router' import { useSettingsStore } from '@/stores/settings' -import { ChevronDown, CircleQuestionMark } from 'lucide-vue-next' import { nanoid } from 'nanoid' import { usePresenter } from '@/composables/usePresenter' // 全局对象 @@ -575,12 +564,20 @@ const saveBuiltinConfig = async () => { } else { if (autoDetectDimensionsSwitch.value) { // 自动获取dimensions - const dimensions = await llmP.getDimensions( + const result = await llmP.getDimensions( editingBuiltinConfig.value.providerId, editingBuiltinConfig.value.modelId ) - console.log('获取到模型维度:', dimensions) - editingBuiltinConfig.value.dimensions = dimensions + if (result.errorMsg) { + toast({ + title: t('settings.knowledgeBase.autoDetectDimensionsError'), + description: String(result.errorMsg), + variant: 'destructive' + }) + return + } + console.log('获取到模型维度:', result.value) + editingBuiltinConfig.value.dimensions = result.value } // 添加配置 builtinConfigs.value.push({ ...editingBuiltinConfig.value }) diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index ae2461b39..bcbf4f44a 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -311,7 +311,8 @@ "dimensions": "Embed dimensions", "dimensionsPlaceholder": "Embed dimension size, such as 1024", "selectEmbeddingModelHelper": "Embedding models are prohibited after creation of knowledge base", - "dimensionsHelper": "Make sure the model supports the set embed dimension size" + "dimensionsHelper": "Make sure the model supports the set embed dimension size", + "autoDetectDimensionsError": "Automatically detect embedded dimension failure" }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index b62c92cda..479be7755 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -311,7 +311,8 @@ "dimensions": "ابعاد جاسازی شده", "dimensionsPlaceholder": "اندازه ابعاد تعبیه شده ، مانند 1024", "selectEmbeddingModelHelper": "مدل های تعبیه شده پس از ایجاد پایگاه دانش ممنوع است", - "dimensionsHelper": "اطمینان حاصل کنید که مدل از اندازه ابعاد تعبیه شده پشتیبانی می کند" + "dimensionsHelper": "اطمینان حاصل کنید که مدل از اندازه ابعاد تعبیه شده پشتیبانی می کند", + "autoDetectDimensionsError": "به طور خودکار خرابی بعد تعبیه شده را تشخیص دهید" }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 16fd5686e..d2b0ca04f 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -311,7 +311,8 @@ "dimensions": "Dimensions de l'incorporation", "dimensionsPlaceholder": "Taille de dimension intégrée, comme 1024", "selectEmbeddingModelHelper": "Les modèles d'intégration sont interdits après la création d'une base de connaissances", - "dimensionsHelper": "Assurez-vous que le modèle prend en charge la taille de la dimension intégrée de l'ensemble" + "dimensionsHelper": "Assurez-vous que le modèle prend en charge la taille de la dimension intégrée de l'ensemble", + "autoDetectDimensionsError": "Détecter automatiquement la panne de dimension intégrée" }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index c6a076134..56edd3a6f 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -311,7 +311,8 @@ "dimensions": "埋め込まれた寸法", "dimensionsPlaceholder": "1024などの寸法サイズを埋め込みます", "selectEmbeddingModelHelper": "埋め込みモデルは、知識ベースの作成後に禁止されています", - "dimensionsHelper": "モデルが設定された埋め込み寸法サイズをサポートしていることを確認してください" + "dimensionsHelper": "モデルが設定された埋め込み寸法サイズをサポートしていることを確認してください", + "autoDetectDimensionsError": "埋め込まれた寸法障害を自動的に検出します" }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index 5a077b850..d69fd98cd 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -311,7 +311,8 @@ "dimensions": "치수를 포함시킵니다", "dimensionsPlaceholder": "1024와 같은 치수 크기를 포함시킵니다", "selectEmbeddingModelHelper": "임베딩 모델은 지식 기반을 창출 한 후 금지됩니다", - "dimensionsHelper": "모델이 세트 임베드 치수 크기를 지원하는지 확인하십시오." + "dimensionsHelper": "모델이 세트 임베드 치수 크기를 지원하는지 확인하십시오.", + "autoDetectDimensionsError": "임베디드 치수 고장을 자동으로 감지합니다" }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 43ce03216..ef9963219 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -311,7 +311,8 @@ "dimensions": "Встроенные размеры", "dimensionsPlaceholder": "Встроенный размер измерения, такой как 1024", "selectEmbeddingModelHelper": "Встроенные модели запрещены после создания базы знаний", - "dimensionsHelper": "Убедитесь, что модель поддерживает размер встроенного размера" + "dimensionsHelper": "Убедитесь, что модель поддерживает размер встроенного размера", + "autoDetectDimensionsError": "Автоматически обнаружение встроенного сбоя измерения" }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index 191ec0ba1..d12449f6b 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -315,7 +315,8 @@ "autoDetectHelper": "自动检测嵌入维度,会消耗少量 Tokens", "dimensionsHelper": "请确保模型支持所设置的嵌入维度大小", "chunkSizePlaceholder": "默认值,不建议修改", - "chunkOverlapPlaceholder": "默认值,不建议修改" + "chunkOverlapPlaceholder": "默认值,不建议修改", + "autoDetectDimensionsError": "自动检测嵌入维度失败" }, "mcp": { "title": "MCP设置", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index a481c0787..1785f7ffa 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -311,7 +311,8 @@ "dimensions": "嵌入維度", "dimensionsPlaceholder": "嵌入維度大小,如 1024", "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改", - "dimensionsHelper": "請確保模型支持所設置的嵌入維度大小" + "dimensionsHelper": "請確保模型支持所設置的嵌入維度大小", + "autoDetectDimensionsError": "自動檢測嵌入維度失敗" }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index 398240492..4ed4eb9f7 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -311,7 +311,8 @@ "dimensions": "嵌入維度", "dimensionsPlaceholder": "嵌入維度大小,如 1024", "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改", - "dimensionsHelper": "請確保模型支持所設置的嵌入維度大小" + "dimensionsHelper": "請確保模型支持所設置的嵌入維度大小", + "autoDetectDimensionsError": "自動檢測嵌入維度失敗" }, "mcp": { "title": "MCP設定", diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index ff6ec7318..b832369ec 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -530,7 +530,7 @@ export interface ILlmProviderPresenter { pullOllamaModels(modelName: string): Promise deleteOllamaModel(modelName: string): Promise getEmbeddings(providerId: string, modelId: string, texts: string[]): Promise - getDimensions(providerId: string, modelId: string): Promise + getDimensions(providerId: string, modelId: string): Promise<{ value: number; errorMsg?: string }> } export type CONVERSATION_SETTINGS = { systemPrompt: string From 42c1af37d9b7240b4487db86e935853922c671c0 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:10:58 +0800 Subject: [PATCH 025/109] [WIP] feat: enhance BuiltinKnowledgeSettings with dynamic dimension detection and loading state --- .../settings/BuiltinKnowledgeSettings.vue | 30 ++++++++++++++----- src/renderer/src/i18n/en-US/settings.json | 3 +- src/renderer/src/i18n/fa-IR/settings.json | 3 +- src/renderer/src/i18n/fr-FR/settings.json | 3 +- src/renderer/src/i18n/ja-JP/settings.json | 3 +- src/renderer/src/i18n/ko-KR/settings.json | 3 +- src/renderer/src/i18n/ru-RU/settings.json | 3 +- src/renderer/src/i18n/zh-CN/settings.json | 1 + src/renderer/src/i18n/zh-HK/settings.json | 3 +- src/renderer/src/i18n/zh-TW/settings.json | 3 +- 10 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index a207d8c6a..d040bb2a3 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -202,7 +202,11 @@ class="text-xs text-muted-foreground" for="edit-builtin-config-dimensions" > - {{ t('settings.knowledgeBase.autoDetectDimensions') }} + {{ + isEditing + ? t('settings.knowledgeBase.redetectDimensions') + : t('settings.knowledgeBase.autoDetectDimensions') + }} @@ -218,11 +222,11 @@
+
-
@@ -339,8 +343,14 @@ - @@ -410,6 +420,7 @@ const emit = defineEmits<{ const modelSelectOpen = ref(false) const isBuiltinConfigPanelOpen = ref(false) const isEditing = ref(false) +const submitLoading = ref(false) // 自动检测维度开关 const autoDetectDimensionsSwitch = ref(true) @@ -474,6 +485,7 @@ function openAddConfig() { } selectEmbeddingModel.value = null autoDetectDimensionsSwitch.value = true + submitLoading.value = false isBuiltinConfigDialogOpen.value = true } @@ -526,6 +538,7 @@ const editBuiltinConfig = async (index: number) => { editingConfigIndex.value = index editingBuiltinConfig.value = { ...builtinConfigs.value[index] } autoDetectDimensionsSwitch.value = editingBuiltinConfig.value.dimensions === undefined + submitLoading.value = false isBuiltinConfigDialogOpen.value = true } @@ -542,6 +555,7 @@ const closeBuiltinConfigDialog = () => { } selectEmbeddingModel.value = null autoDetectDimensionsSwitch.value = true + submitLoading.value = false } // 进入设置页面 @@ -552,6 +566,7 @@ const handleSetting = (config) => { // 保存配置 const saveBuiltinConfig = async () => { if (!isEditingBuiltinConfigValid.value) return + submitLoading.value = true if (isEditing.value) { // 更新配置 if (editingConfigIndex.value !== -1) { @@ -574,6 +589,7 @@ const saveBuiltinConfig = async () => { description: String(result.errorMsg), variant: 'destructive' }) + submitLoading.value = false return } console.log('获取到模型维度:', result.value) diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index bcbf4f44a..cfdeb2bfd 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -312,7 +312,8 @@ "dimensionsPlaceholder": "Embed dimension size, such as 1024", "selectEmbeddingModelHelper": "Embedding models are prohibited after creation of knowledge base", "dimensionsHelper": "Make sure the model supports the set embed dimension size", - "autoDetectDimensionsError": "Automatically detect embedded dimension failure" + "autoDetectDimensionsError": "Automatically detect embedded dimension failure", + "redetectDimensions": "Redetect the embedded dimension" }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 479be7755..9507ea341 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -312,7 +312,8 @@ "dimensionsPlaceholder": "اندازه ابعاد تعبیه شده ، مانند 1024", "selectEmbeddingModelHelper": "مدل های تعبیه شده پس از ایجاد پایگاه دانش ممنوع است", "dimensionsHelper": "اطمینان حاصل کنید که مدل از اندازه ابعاد تعبیه شده پشتیبانی می کند", - "autoDetectDimensionsError": "به طور خودکار خرابی بعد تعبیه شده را تشخیص دهید" + "autoDetectDimensionsError": "به طور خودکار خرابی بعد تعبیه شده را تشخیص دهید", + "redetectDimensions": "بعد تعبیه شده را دوباره تعیین کنید" }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index d2b0ca04f..99a7314ae 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -312,7 +312,8 @@ "dimensionsPlaceholder": "Taille de dimension intégrée, comme 1024", "selectEmbeddingModelHelper": "Les modèles d'intégration sont interdits après la création d'une base de connaissances", "dimensionsHelper": "Assurez-vous que le modèle prend en charge la taille de la dimension intégrée de l'ensemble", - "autoDetectDimensionsError": "Détecter automatiquement la panne de dimension intégrée" + "autoDetectDimensionsError": "Détecter automatiquement la panne de dimension intégrée", + "redetectDimensions": "Redecteur la dimension intégrée" }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index 56edd3a6f..5711ef3ef 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -312,7 +312,8 @@ "dimensionsPlaceholder": "1024などの寸法サイズを埋め込みます", "selectEmbeddingModelHelper": "埋め込みモデルは、知識ベースの作成後に禁止されています", "dimensionsHelper": "モデルが設定された埋め込み寸法サイズをサポートしていることを確認してください", - "autoDetectDimensionsError": "埋め込まれた寸法障害を自動的に検出します" + "autoDetectDimensionsError": "埋め込まれた寸法障害を自動的に検出します", + "redetectDimensions": "埋め込み寸法を再検出します" }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index d69fd98cd..9c6f058b1 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -312,7 +312,8 @@ "dimensionsPlaceholder": "1024와 같은 치수 크기를 포함시킵니다", "selectEmbeddingModelHelper": "임베딩 모델은 지식 기반을 창출 한 후 금지됩니다", "dimensionsHelper": "모델이 세트 임베드 치수 크기를 지원하는지 확인하십시오.", - "autoDetectDimensionsError": "임베디드 치수 고장을 자동으로 감지합니다" + "autoDetectDimensionsError": "임베디드 치수 고장을 자동으로 감지합니다", + "redetectDimensions": "임베디드 치수를 다시 설정하십시오" }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index ef9963219..0c72f81bc 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -312,7 +312,8 @@ "dimensionsPlaceholder": "Встроенный размер измерения, такой как 1024", "selectEmbeddingModelHelper": "Встроенные модели запрещены после создания базы знаний", "dimensionsHelper": "Убедитесь, что модель поддерживает размер встроенного размера", - "autoDetectDimensionsError": "Автоматически обнаружение встроенного сбоя измерения" + "autoDetectDimensionsError": "Автоматически обнаружение встроенного сбоя измерения", + "redetectDimensions": "Пересмотреть встроенное измерение" }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index d12449f6b..62e2843ef 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -312,6 +312,7 @@ "dimensions": "嵌入维度", "dimensionsPlaceholder": "嵌入维度大小,如 1024", "autoDetectDimensions": "自动检测嵌入维度", + "redetectDimensions": "重新检测嵌入维度", "autoDetectHelper": "自动检测嵌入维度,会消耗少量 Tokens", "dimensionsHelper": "请确保模型支持所设置的嵌入维度大小", "chunkSizePlaceholder": "默认值,不建议修改", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 1785f7ffa..e0003696d 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -312,7 +312,8 @@ "dimensionsPlaceholder": "嵌入維度大小,如 1024", "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改", "dimensionsHelper": "請確保模型支持所設置的嵌入維度大小", - "autoDetectDimensionsError": "自動檢測嵌入維度失敗" + "autoDetectDimensionsError": "自動檢測嵌入維度失敗", + "redetectDimensions": "重新檢測嵌入維度" }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index 4ed4eb9f7..18f619439 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -312,7 +312,8 @@ "dimensionsPlaceholder": "嵌入維度大小,如 1024", "selectEmbeddingModelHelper": "嵌入模型在知識庫創建後禁止修改", "dimensionsHelper": "請確保模型支持所設置的嵌入維度大小", - "autoDetectDimensionsError": "自動檢測嵌入維度失敗" + "autoDetectDimensionsError": "自動檢測嵌入維度失敗", + "redetectDimensions": "重新檢測嵌入維度" }, "mcp": { "title": "MCP設定", From 02f804789ae09236ca4d9b160434f3cb963eb1e0 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:36:24 +0800 Subject: [PATCH 026/109] feat: add duration to toast notifications for improved user feedback --- .../settings/BuiltinKnowledgeSettings.vue | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index d040bb2a3..50db1a0da 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -529,7 +529,8 @@ const editBuiltinConfig = async (index: number) => { model: config.modelId }), description: t('settings.knowledgeBase.modelNotFoundDesc'), - variant: 'destructive' + variant: 'destructive', + duration: 3000 }) return } @@ -574,7 +575,8 @@ const saveBuiltinConfig = async () => { } toast({ title: t('settings.knowledgeBase.configUpdated'), - description: t('settings.knowledgeBase.configUpdatedDesc') + description: t('settings.knowledgeBase.configUpdatedDesc'), + duration: 3000 }) } else { if (autoDetectDimensionsSwitch.value) { @@ -587,7 +589,8 @@ const saveBuiltinConfig = async () => { toast({ title: t('settings.knowledgeBase.autoDetectDimensionsError'), description: String(result.errorMsg), - variant: 'destructive' + variant: 'destructive', + duration: 3000 }) submitLoading.value = false return @@ -599,7 +602,8 @@ const saveBuiltinConfig = async () => { builtinConfigs.value.push({ ...editingBuiltinConfig.value }) toast({ title: t('settings.knowledgeBase.configAdded'), - description: t('settings.knowledgeBase.configAddedDesc') + description: t('settings.knowledgeBase.configAddedDesc'), + duration: 3000 }) } @@ -660,7 +664,8 @@ const updateBuiltinConfigToMcp = async () => { toast({ title: t('common.error.operationFailed'), description: String(error), - variant: 'destructive' + variant: 'destructive', + duration: 3000 }) return false } From a7c63707f6306aeda76c4162ace33b5a72d9e5bc Mon Sep 17 00:00:00 2001 From: ysli Date: Fri, 27 Jun 2025 10:51:37 +0800 Subject: [PATCH 027/109] feat: add BuiltinKnowledge file upload box --- .../src/components/settings/KnowledgeFile.vue | 185 ++++++++++++++++-- .../components/settings/KnowledgeFileItem.vue | 146 ++++++++++++++ 2 files changed, 311 insertions(+), 20 deletions(-) create mode 100644 src/renderer/src/components/settings/KnowledgeFileItem.vue diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index 349e207ae..af82a4c8b 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -1,40 +1,87 @@ diff --git a/src/renderer/src/lib/utils.ts b/src/renderer/src/lib/utils.ts index d32b0fe65..ef6048fdb 100644 --- a/src/renderer/src/lib/utils.ts +++ b/src/renderer/src/lib/utils.ts @@ -1,6 +1,66 @@ import { type ClassValue, clsx } from 'clsx' import { twMerge } from 'tailwind-merge' +/** + * 合并 Tailwind CSS 类名 + * @param inputs + * @returns + */ export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } + +/** + * 根据 MIME 类型获取文件图标 + * @param mimeType + * @returns + */ +export function getMimeTypeIcon(mimeType: string) { + if ( + mimeType.startsWith('text/plain') || + mimeType.startsWith('application/json') || + mimeType.startsWith('application/javascript') || + mimeType.startsWith('application/typescript') + ) { + return 'vscode-icons:file-type-text' + } else if (mimeType.startsWith('text/csv')) { + return 'vscode-icons:file-type-excel' + } else if ( + mimeType.startsWith('application/vnd.ms-excel') || + mimeType.includes('spreadsheet') || + mimeType.includes('numbers') + ) { + return 'vscode-icons:file-type-excel' + } else if (mimeType.startsWith('text/markdown')) { + return 'vscode-icons:file-type-markdown' + } else if (mimeType.startsWith('application/x-yaml')) { + return 'vscode-icons:file-type-yaml' + } else if ( + mimeType.startsWith('application/xml') || + mimeType.startsWith('application/xhtml+xml') + ) { + return 'vscode-icons:file-type-xml' + } else if (mimeType.startsWith('application/pdf')) { + return 'vscode-icons:file-type-pdf2' + } else if (mimeType.startsWith('image/')) { + return 'vscode-icons:file-type-image' + } else if (mimeType.startsWith('application/msword') || mimeType.includes('wordprocessingml')) { + return 'vscode-icons:file-type-word' + } else if ( + mimeType.startsWith('application/vnd.ms-powerpoint') || + mimeType.includes('presentationml') + ) { + return 'vscode-icons:file-type-powerpoint' + } else if (mimeType.startsWith('text/html')) { + return 'vscode-icons:file-type-html' + } else if (mimeType.startsWith('text/css')) { + return 'vscode-icons:file-type-css' + } else if (mimeType.startsWith('audio/')) { + return 'vscode-icons:file-type-audio' + } else if (mimeType.startsWith('directory')) { + return 'vscode-icons:default-folder-opened' + } else { + // 默认文件图标 + return 'vscode-icons:default-file' + } +} From 5bded538cafd038c9014d48500ccadbcad1673e0 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 3 Jul 2025 16:52:04 +0800 Subject: [PATCH 044/109] refactor: enhance type safety for builtinKnowledgeDetail and improve code readability in KnowledgeBaseSettings and KnowledgeFile components --- .../components/settings/KnowledgeBaseSettings.vue | 8 ++++++-- .../src/components/settings/KnowledgeFile.vue | 12 ++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/components/settings/KnowledgeBaseSettings.vue b/src/renderer/src/components/settings/KnowledgeBaseSettings.vue index 4449dd47c..7115d4698 100644 --- a/src/renderer/src/components/settings/KnowledgeBaseSettings.vue +++ b/src/renderer/src/components/settings/KnowledgeBaseSettings.vue @@ -108,7 +108,10 @@
- +
@@ -132,6 +135,7 @@ import DifyKnowledgeSettings from './DifyKnowledgeSettings.vue' import FastGptKnowledgeSettings from './FastGptKnowledgeSettings.vue' import BuiltinKnowledgeSettings from './BuiltinKnowledgeSettings.vue' import KnowledgeFile from './KnowledgeFile.vue' +import { BuiltinKnowledgeConfig } from '@shared/presenter' const difySettingsRef = ref | null>(null) const ragflowSettingsRef = ref | null>(null) @@ -141,7 +145,7 @@ const builtinSettingsRef = ref | n const { t } = useI18n() // 是否展示内置知识库文件详情 const showBuiltinKnowledgeDetail = ref(false) -const builtinKnowledgeDetail = ref({}) +const builtinKnowledgeDetail = ref(null) const showDetail = (detail) => { showBuiltinKnowledgeDetail.value = true builtinKnowledgeDetail.value = detail diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index b9719a3de..14a3403c1 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -56,7 +56,14 @@ - +
() const emit = defineEmits<{ From 7fb70ae483bc5f6ffba47678119959a20cf43a0b Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 3 Jul 2025 16:57:12 +0800 Subject: [PATCH 045/109] fix: add optional chaining for builtinKnowledgeDetail description to prevent potential runtime errors --- src/renderer/src/components/settings/KnowledgeFile.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index 14a3403c1..0b0556414 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -4,7 +4,7 @@
- {{ builtinKnowledgeDetail.description }} + {{ builtinKnowledgeDetail?.description }} @@ -146,7 +147,7 @@ const { t } = useI18n() // 是否展示内置知识库文件详情 const showBuiltinKnowledgeDetail = ref(false) const builtinKnowledgeDetail = ref(null) -const showDetail = (detail) => { +const showDetail = (detail: BuiltinKnowledgeConfig) => { showBuiltinKnowledgeDetail.value = true builtinKnowledgeDetail.value = detail } diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index 0b0556414..3cb1fc771 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -1,20 +1,20 @@ From b742488ad7763cbbfbac1d76183ccc7650df7b12 Mon Sep 17 00:00:00 2001 From: ysli Date: Tue, 8 Jul 2025 10:35:03 +0800 Subject: [PATCH 060/109] feat: change callback function --- .../src/components/settings/KnowledgeFile.vue | 55 +++---------------- src/renderer/src/i18n/en-US/about.json | 7 ++- src/renderer/src/i18n/en-US/settings.json | 8 +-- src/renderer/src/i18n/fa-IR/about.json | 7 ++- src/renderer/src/i18n/fa-IR/settings.json | 8 +-- src/renderer/src/i18n/fr-FR/about.json | 7 ++- src/renderer/src/i18n/fr-FR/settings.json | 8 +-- src/renderer/src/i18n/ja-JP/about.json | 5 ++ src/renderer/src/i18n/ja-JP/settings.json | 8 +-- src/renderer/src/i18n/ko-KR/about.json | 5 ++ src/renderer/src/i18n/ko-KR/settings.json | 8 +-- src/renderer/src/i18n/ru-RU/about.json | 5 ++ src/renderer/src/i18n/ru-RU/settings.json | 8 +-- src/renderer/src/i18n/zh-CN/about.json | 5 ++ src/renderer/src/i18n/zh-CN/settings.json | 11 ++-- src/renderer/src/i18n/zh-HK/about.json | 5 ++ src/renderer/src/i18n/zh-HK/settings.json | 8 +-- src/renderer/src/i18n/zh-TW/about.json | 5 ++ src/renderer/src/i18n/zh-TW/settings.json | 8 +-- 19 files changed, 76 insertions(+), 105 deletions(-) diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index caf98a99f..3e0d5f321 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -196,22 +196,7 @@ const handleDrop = async (e: DragEvent) => { } try { const path = window.api.getPathForFile(file) - const result = await knowledgePresenter.addFile(props.builtinKnowledgeDetail.id, path) - if (result.success) { - toast({ - title: `"${file.name}"${t('settings.knowledgeBase.uploadSuccess')}`, - variant: 'default', - duration: 3000 - }) - } else { - toast({ - title: `"${file.name}"${t('settings.knowledgeBase.uploadError')}`, - description:`${t('settings.knowledgeBase.reason')}:${result.reason}`, - variant: 'destructive', - duration: 3000 - }) - } - + knowledgePresenter.addFile(props.builtinKnowledgeDetail.id, path) loadList() } catch (error) { console.error('文件准备失败:', error) @@ -223,42 +208,18 @@ const handleDrop = async (e: DragEvent) => { // 刪除文件 const deleteFile = async (fileId: string) => { - const result = await knowledgePresenter.deleteFile(props.builtinKnowledgeDetail.id, fileId) - if (result.success) { - toast({ - title: t('settings.knowledgeBase.deleteSuccess'), - variant: 'default', - duration: 3000 - }) - } else { - toast({ - title: t('settings.knowledgeBase.deleteFailed'), - description: `${t('settings.knowledgeBase.reason')}:${result.reason}`, - variant: 'destructive', - duration: 3000 - }) - } + await knowledgePresenter.deleteFile(props.builtinKnowledgeDetail.id, fileId) + toast({ + title: t('settings.knowledgeBase.deleteSuccess'), + variant: 'default', + duration: 3000 + }) } // 重新上传文件 const reAddFile = async (file: KnowledgeFileMessage) => { file.status = 'processing' // 设置状态为加载中 await nextTick(() => {}) - const result = await knowledgePresenter.reAddFile(props.builtinKnowledgeDetail.id, file.id) - if (result.success) { - toast({ - title: t('settings.knowledgeBase.reAddSuccess'), - variant: 'default', - duration: 3000 - }) - } else { - toast({ - title: t('settings.knowledgeBase.reAddFailed'), - description: `${t('settings.knowledgeBase.reason')}:${result.reason}`, - variant: 'destructive', - duration: 3000 - }) - } - loadList() + knowledgePresenter.reAddFile(props.builtinKnowledgeDetail.id, file.id) } diff --git a/src/renderer/src/i18n/en-US/about.json b/src/renderer/src/i18n/en-US/about.json index fc43a3e9d..c10e6bd70 100644 --- a/src/renderer/src/i18n/en-US/about.json +++ b/src/renderer/src/i18n/en-US/about.json @@ -12,5 +12,10 @@ }, "disclaimerButton": "Disclaimer", "disclaimerTitle": "Terms of Use Statement", - "checkUpdateButton": "Check for Updates" + "checkUpdateButton": "Check for Updates", + "settings": { + "knowledgeBase": { + "deleteSuccess": "Delete successfully" + } + } } diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index 62fec21b5..ece4cae48 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -327,16 +327,12 @@ "noData": "No data yet", "file": "document", "uploadProcessing": "Uploading", - "uploadSuccess": "Upload successfully", "uploadCompleted": "Upload completed", "reAdd": "Re-upload", "uploadError": "Upload failed", "delete": "delete", - "deleteSuccess": "Delete successfully", - "deleteFailed": "Deletion failed", - "reAddSuccess": "Re-uploaded successfully", - "reAddFailed": "Re-upload failed", - "reason": "reason" + "reason": "reason", + "deleteSuccess": "Delete successfully" }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/about.json b/src/renderer/src/i18n/fa-IR/about.json index 1b965e7e2..e6d730e55 100644 --- a/src/renderer/src/i18n/fa-IR/about.json +++ b/src/renderer/src/i18n/fa-IR/about.json @@ -12,5 +12,10 @@ }, "disclaimerButton": "رد مسئولیت", "disclaimerTitle": "بیانیه شرایط استفاده", - "checkUpdateButton": "بررسی به‌روزرسانی" + "checkUpdateButton": "بررسی به‌روزرسانی", + "settings": { + "knowledgeBase": { + "deleteSuccess": "با موفقیت حذف کنید" + } + } } diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 23f6de1df..5070155f5 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -327,16 +327,12 @@ "noData": "هنوز اطلاعاتی وجود ندارد", "file": "مدرک", "uploadProcessing": "بارگذاری", - "uploadSuccess": "با موفقیت بارگذاری کنید", "uploadCompleted": "بارگذاری کامل", "reAdd": "بارگذاری مجدد", "uploadError": "بارگذاری ناموفق بود", "delete": "حذف کردن", - "deleteSuccess": "با موفقیت حذف کنید", - "deleteFailed": "حذف انجام نشد", - "reAddSuccess": "دوباره با موفقیت بارگذاری شد", - "reAddFailed": "بارگذاری مجدد انجام نشد", - "reason": "دلیل" + "reason": "دلیل", + "deleteSuccess": "با موفقیت حذف کنید" }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/about.json b/src/renderer/src/i18n/fr-FR/about.json index 2dd3d3cf4..1fa6ef490 100644 --- a/src/renderer/src/i18n/fr-FR/about.json +++ b/src/renderer/src/i18n/fr-FR/about.json @@ -12,5 +12,10 @@ }, "disclaimerButton": "Avertissement", "disclaimerTitle": "Conditions d'utilisation", - "checkUpdateButton": "Vérifier les mises à jour" + "checkUpdateButton": "Vérifier les mises à jour", + "settings": { + "knowledgeBase": { + "deleteSuccess": "Supprimer avec succès" + } + } } diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 265c57932..a5416e573 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -327,16 +327,12 @@ "noData": "Pas encore de données", "file": "document", "uploadProcessing": "Téléchargement", - "uploadSuccess": "Télécharger avec succès", "uploadCompleted": "Téléchargement terminé", "reAdd": "Télécharger à nouveau", "uploadError": "Le téléchargement a échoué", "delete": "supprimer", - "deleteSuccess": "Supprimer avec succès", - "deleteFailed": "La suppression a échoué", - "reAddSuccess": "Re-téléchargé avec succès", - "reAddFailed": "REPOLORD TÉLÉPLARCHE Échec", - "reason": "raison" + "reason": "raison", + "deleteSuccess": "Supprimer avec succès" }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/about.json b/src/renderer/src/i18n/ja-JP/about.json index 53dfb3b13..bd9bdb882 100644 --- a/src/renderer/src/i18n/ja-JP/about.json +++ b/src/renderer/src/i18n/ja-JP/about.json @@ -12,5 +12,10 @@ "cpuModel": "CPUモデル", "totalMemory": "総メモリ", "osVersion": "システムバージョン" + }, + "settings": { + "knowledgeBase": { + "deleteSuccess": "正常に削除します" + } } } diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index 8ff2e30f6..a402c6e6c 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -327,16 +327,12 @@ "noData": "まだデータはありません", "file": "書類", "uploadProcessing": "アップロード", - "uploadSuccess": "正常にアップロードします", "uploadCompleted": "完了したアップロード", "reAdd": "再アップロード", "uploadError": "アップロードに失敗しました", "delete": "消去", - "deleteSuccess": "正常に削除します", - "deleteFailed": "削除が失敗しました", - "reAddSuccess": "正常に再アップロードされました", - "reAddFailed": "再アップロードが失敗しました", - "reason": "理由" + "reason": "理由", + "deleteSuccess": "正常に削除します" }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/about.json b/src/renderer/src/i18n/ko-KR/about.json index 45901727a..a6e5ac929 100644 --- a/src/renderer/src/i18n/ko-KR/about.json +++ b/src/renderer/src/i18n/ko-KR/about.json @@ -12,5 +12,10 @@ "cpuModel": "CPU 모델", "totalMemory": "총 메모리", "osVersion": "시스템 버전" + }, + "settings": { + "knowledgeBase": { + "deleteSuccess": "성공적으로 삭제하십시오" + } } } diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index 1460cd43a..fececf733 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -327,16 +327,12 @@ "noData": "아직 데이터가 없습니다", "file": "문서", "uploadProcessing": "업로드", - "uploadSuccess": "성공적으로 업로드하십시오", "uploadCompleted": "업로드 완료", "reAdd": "재 포장", "uploadError": "업로드 실패", "delete": "삭제", - "deleteSuccess": "성공적으로 삭제하십시오", - "deleteFailed": "삭제가 실패했습니다", - "reAddSuccess": "성공적으로 다시 업로드했습니다", - "reAddFailed": "다시 업로드가 실패했습니다", - "reason": "이유" + "reason": "이유", + "deleteSuccess": "성공적으로 삭제하십시오" }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/about.json b/src/renderer/src/i18n/ru-RU/about.json index 5f8ba7f34..8af71a85a 100644 --- a/src/renderer/src/i18n/ru-RU/about.json +++ b/src/renderer/src/i18n/ru-RU/about.json @@ -12,5 +12,10 @@ "cpuModel": "Модель процессора", "totalMemory": "Общий объем памяти", "osVersion": "Версия системы" + }, + "settings": { + "knowledgeBase": { + "deleteSuccess": "Удалить успешно" + } } } diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 92aed9f59..ec444c64b 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -327,16 +327,12 @@ "noData": "Нет данных пока", "file": "документ", "uploadProcessing": "Загрузка", - "uploadSuccess": "Загрузить успешно", "uploadCompleted": "Загрузка завершена", "reAdd": "Повторная загрузка", "uploadError": "Загрузка не удалась", "delete": "удалить", - "deleteSuccess": "Удалить успешно", - "deleteFailed": "Удаление не удалось", - "reAddSuccess": "Повторно загружен успешно", - "reAddFailed": "Повторная загрузка не удалась", - "reason": "причина" + "reason": "причина", + "deleteSuccess": "Удалить успешно" }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-CN/about.json b/src/renderer/src/i18n/zh-CN/about.json index 87fc29af3..4404d58fe 100644 --- a/src/renderer/src/i18n/zh-CN/about.json +++ b/src/renderer/src/i18n/zh-CN/about.json @@ -12,5 +12,10 @@ "cpuModel": "CPU型号", "totalMemory": "总内存", "osVersion": "系统版本" + }, + "settings": { + "knowledgeBase": { + "deleteSuccess": "删除成功" + } } } diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index f67721ba9..4d2cc07f0 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -328,18 +328,15 @@ "onlySupport": "仅支持", "searchKnowledge": "搜索知识库", "searchKnowledgePlaceholder": "请输入查询内容", + "noData":"暂无数据", "file": "文件", "uploadProcessing": "上传中", - "uploadSuccess": "上传成功", "uploadCompleted": "上传完成", - "uploadError": "上传失败", "reAdd": "重新上传", + "uploadError": "上传失败", "delete": "删除", - "deleteSuccess": "删除成功", - "deleteFailed": "删除失败", - "reAddSuccess": "重新上传成功", - "reAddFailed": " 重新上传失败", - "reason": "原因" + "reason": "原因", + "deleteSuccess": "删除成功" }, "mcp": { "title": "MCP设置", diff --git a/src/renderer/src/i18n/zh-HK/about.json b/src/renderer/src/i18n/zh-HK/about.json index dad5e39ac..a11a53561 100644 --- a/src/renderer/src/i18n/zh-HK/about.json +++ b/src/renderer/src/i18n/zh-HK/about.json @@ -12,5 +12,10 @@ "cpuModel": "CPU 型號", "totalMemory": "總記憶體", "osVersion": "系統版本" + }, + "settings": { + "knowledgeBase": { + "deleteSuccess": "刪除成功" + } } } diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 00d546fe6..183a29505 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -327,16 +327,12 @@ "noData": "暫無數據", "file": "文件", "uploadProcessing": "上傳中", - "uploadSuccess": "上傳成功", "uploadCompleted": "上傳完成", "reAdd": "重新上傳", "uploadError": "上傳失敗", "delete": "刪除", - "deleteSuccess": "刪除成功", - "deleteFailed": "刪除失敗", - "reAddSuccess": "重新上傳成功", - "reAddFailed": "重新上傳失敗", - "reason": "原因" + "reason": "原因", + "deleteSuccess": "刪除成功" }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/about.json b/src/renderer/src/i18n/zh-TW/about.json index 35551ac32..7f4b6fe37 100644 --- a/src/renderer/src/i18n/zh-TW/about.json +++ b/src/renderer/src/i18n/zh-TW/about.json @@ -12,5 +12,10 @@ "cpuModel": "CPU 型號", "totalMemory": "總記憶體", "osVersion": "系統版本" + }, + "settings": { + "knowledgeBase": { + "deleteSuccess": "刪除成功" + } } } diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index 113d4d14b..b084d85b6 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -327,16 +327,12 @@ "noData": "暫無數據", "file": "文件", "uploadProcessing": "上傳中", - "uploadSuccess": "上傳成功", "uploadCompleted": "上傳完成", "reAdd": "重新上傳", "uploadError": "上傳失敗", "delete": "刪除", - "deleteSuccess": "刪除成功", - "deleteFailed": "刪除失敗", - "reAddSuccess": "重新上傳成功", - "reAddFailed": "重新上傳失敗", - "reason": "原因" + "reason": "原因", + "deleteSuccess": "刪除成功" }, "mcp": { "title": "MCP設定", From 0dd265ae5d3dbe5e4565ac58d9a9cc3a37046727 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:39:32 +0800 Subject: [PATCH 061/109] fix: resolve merge conflicts in localization files --- src/renderer/src/i18n/en-US/settings.json | 10 ---------- src/renderer/src/i18n/fa-IR/settings.json | 10 ---------- src/renderer/src/i18n/fr-FR/settings.json | 10 ---------- src/renderer/src/i18n/ja-JP/settings.json | 10 ---------- src/renderer/src/i18n/ko-KR/settings.json | 10 ---------- src/renderer/src/i18n/ru-RU/settings.json | 10 ---------- src/renderer/src/i18n/zh-HK/settings.json | 10 ---------- src/renderer/src/i18n/zh-TW/settings.json | 10 ---------- 8 files changed, 80 deletions(-) diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index f1d568436..ece4cae48 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -331,18 +331,8 @@ "reAdd": "Re-upload", "uploadError": "Upload failed", "delete": "delete", -<<<<<<< HEAD - "deleteSuccess": "Delete successfully", - "deleteFailed": "Deletion failed", - "reAddSuccess": "Re-uploaded successfully", - "reAddFailed": "Re-upload failed", - "reason": "reason", - "normalized": "L2 Normalization", - "normalizedHelper": "Please confirm that the model supports L2 normalization of output vectors" -======= "reason": "reason", "deleteSuccess": "Delete successfully" ->>>>>>> pre-merge-view-from-file-setting }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 3fcd22f2f..5070155f5 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -331,18 +331,8 @@ "reAdd": "بارگذاری مجدد", "uploadError": "بارگذاری ناموفق بود", "delete": "حذف کردن", -<<<<<<< HEAD - "deleteSuccess": "با موفقیت حذف کنید", - "deleteFailed": "حذف انجام نشد", - "reAddSuccess": "دوباره با موفقیت بارگذاری شد", - "reAddFailed": "بارگذاری مجدد انجام نشد", - "reason": "دلیل", - "normalized": "عادی سازی L2", - "normalizedHelper": "لطفاً تأیید کنید که این مدل از نرمال سازی L2 بردارهای خروجی پشتیبانی می کند" -======= "reason": "دلیل", "deleteSuccess": "با موفقیت حذف کنید" ->>>>>>> pre-merge-view-from-file-setting }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index 1be3840bf..a5416e573 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -331,18 +331,8 @@ "reAdd": "Télécharger à nouveau", "uploadError": "Le téléchargement a échoué", "delete": "supprimer", -<<<<<<< HEAD - "deleteSuccess": "Supprimer avec succès", - "deleteFailed": "La suppression a échoué", - "reAddSuccess": "Re-téléchargé avec succès", - "reAddFailed": "REPOLORD TÉLÉPLARCHE Échec", - "reason": "raison", - "normalized": "Normalisation L2", - "normalizedHelper": "Veuillez confirmer que le modèle prend en charge la normalisation L2 des vecteurs de sortie" -======= "reason": "raison", "deleteSuccess": "Supprimer avec succès" ->>>>>>> pre-merge-view-from-file-setting }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index 854316b68..a402c6e6c 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -331,18 +331,8 @@ "reAdd": "再アップロード", "uploadError": "アップロードに失敗しました", "delete": "消去", -<<<<<<< HEAD - "deleteSuccess": "正常に削除します", - "deleteFailed": "削除が失敗しました", - "reAddSuccess": "正常に再アップロードされました", - "reAddFailed": "再アップロードが失敗しました", - "reason": "理由", - "normalized": "L2正規化", - "normalizedHelper": "モデルが出力ベクトルのL2正規化をサポートしていることを確認してください" -======= "reason": "理由", "deleteSuccess": "正常に削除します" ->>>>>>> pre-merge-view-from-file-setting }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index b7829fd62..fececf733 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -331,18 +331,8 @@ "reAdd": "재 포장", "uploadError": "업로드 실패", "delete": "삭제", -<<<<<<< HEAD - "deleteSuccess": "성공적으로 삭제하십시오", - "deleteFailed": "삭제가 실패했습니다", - "reAddSuccess": "성공적으로 다시 업로드했습니다", - "reAddFailed": "다시 업로드가 실패했습니다", - "reason": "이유", - "normalized": "L2 정규화", - "normalizedHelper": "모델이 출력 벡터의 L2 정규화를 지원하는지 확인하십시오." -======= "reason": "이유", "deleteSuccess": "성공적으로 삭제하십시오" ->>>>>>> pre-merge-view-from-file-setting }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index 5d94e7052..ec444c64b 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -331,18 +331,8 @@ "reAdd": "Повторная загрузка", "uploadError": "Загрузка не удалась", "delete": "удалить", -<<<<<<< HEAD - "deleteSuccess": "Удалить успешно", - "deleteFailed": "Удаление не удалось", - "reAddSuccess": "Повторно загружен успешно", - "reAddFailed": "Повторная загрузка не удалась", - "reason": "причина", - "normalized": "L2 Нормализация", - "normalizedHelper": "Убедитесь, что модель поддерживает нормализацию выходных векторов L2" -======= "reason": "причина", "deleteSuccess": "Удалить успешно" ->>>>>>> pre-merge-view-from-file-setting }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 9b5109333..183a29505 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -331,18 +331,8 @@ "reAdd": "重新上傳", "uploadError": "上傳失敗", "delete": "刪除", -<<<<<<< HEAD - "deleteSuccess": "刪除成功", - "deleteFailed": "刪除失敗", - "reAddSuccess": "重新上傳成功", - "reAddFailed": "重新上傳失敗", - "reason": "原因", - "normalized": "L2 歸一化", - "normalizedHelper": "請確認模型支持對輸出向量進行 L2 歸一化" -======= "reason": "原因", "deleteSuccess": "刪除成功" ->>>>>>> pre-merge-view-from-file-setting }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index e7f0f0593..b084d85b6 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -331,18 +331,8 @@ "reAdd": "重新上傳", "uploadError": "上傳失敗", "delete": "刪除", -<<<<<<< HEAD - "deleteSuccess": "刪除成功", - "deleteFailed": "刪除失敗", - "reAddSuccess": "重新上傳成功", - "reAddFailed": "重新上傳失敗", - "reason": "原因", - "normalized": "L2 歸一化", - "normalizedHelper": "請確認模型支持對輸出向量進行 L2 歸一化" -======= "reason": "原因", "deleteSuccess": "刪除成功" ->>>>>>> pre-merge-view-from-file-setting }, "mcp": { "title": "MCP設定", From e18923e24e272b7fc946e83b8b342f5c75d93362 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:42:24 +0800 Subject: [PATCH 062/109] feat(knowledge): Implement file listing and fix embedding parameters --- .../knowledgePresenter/RagPresenter.ts | 4 +- .../database/duckdbPresenter.ts | 30 ++++++------- .../settings/BuiltinKnowledgeSettings.vue | 45 ++++++++++--------- src/shared/presenter.d.ts | 7 ++- 4 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/main/presenter/knowledgePresenter/RagPresenter.ts b/src/main/presenter/knowledgePresenter/RagPresenter.ts index 3aedd93f2..7f858ae13 100644 --- a/src/main/presenter/knowledgePresenter/RagPresenter.ts +++ b/src/main/presenter/knowledgePresenter/RagPresenter.ts @@ -47,7 +47,7 @@ export class RagPresenter { const vectors = await presenter.llmproviderPresenter.getEmbeddings( this.config.embedding.providerId, - this.config.embedding.providerId, + this.config.embedding.modelId, chunks ) @@ -80,7 +80,7 @@ export class RagPresenter { return await this.vectorP.queryFile(fileId) } async listFiles(): Promise { - throw new Error('Method not implemented.') + return await this.vectorP.listFiles() } async reset() {} diff --git a/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts b/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts index a1bf8222a..351c713ba 100644 --- a/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts +++ b/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts @@ -91,7 +91,8 @@ export class DuckDBPresenter implements IVectorDatabasePresenter { private async installAndLoadVSS(): Promise { if (!this.connection) await this.connect() if (fs.existsSync(extensionPath)) { - await this.safeRun(`LOAD ?;`, [extensionPath]) + const escapedPath = extensionPath.replace(/\\/g, '\\\\') + await this.safeRun(`LOAD '${escapedPath}';`) } else { await this.safeRun(`INSTALL vss;`) await this.safeRun(`LOAD vss;`) @@ -135,16 +136,16 @@ export class DuckDBPresenter implements IVectorDatabasePresenter { const M = opts?.M || 16 const efConstruction = opts?.efConstruction || 200 const sql = `CREATE INDEX IF NOT EXISTS idx_${this.vectorTable}_emb - ON ${this.vectorTable} - USING HNSW (embedding) - WITH ( - metric=?, - M=?, - ef_construction=? - );` - await this.safeRun(sql, [metric, M, efConstruction]) + ON ${this.vectorTable} + USING HNSW (embedding) + WITH ( + metric='${metric}', + M=${M}, + ef_construction=${efConstruction} + );` + await this.safeRun(sql) await this.safeRun( - `CREATE INDEX IF NOT EXISTS idx_${this.vectorTable}_file_id ON ${this.vectorTable} USING HASH (file_id);` + `CREATE INDEX IF NOT EXISTS idx_${this.vectorTable}_file_id ON ${this.vectorTable} (file_id);` ) } @@ -175,9 +176,7 @@ export class DuckDBPresenter implements IVectorDatabasePresenter { await this.safeRun(sql, params) } - async similarityQuery( - params: QueryOptions & { vector: number[] } - ): Promise { + async similarityQuery(params: QueryOptions & { vector: number[] }): Promise { if (!this.connection) await this.connect() const k = params.topK const fn = @@ -255,11 +254,10 @@ export class DuckDBPresenter implements IVectorDatabasePresenter { } } - async listFiles(knowledgeId: string): Promise { + async listFiles(): Promise { if (!this.connection) await this.connect() const reader = await this.connection.runAndReadAll( - `SELECT * FROM ${this.fileTable} WHERE knowledge_id = ? ORDER BY uploaded_at DESC;`, - [knowledgeId] + `SELECT * FROM ${this.fileTable} ORDER BY uploaded_at DESC;` ) const rows = reader.getRowObjectsJson() return rows.map((r: any) => ({ diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 086f047da..b395913d6 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -258,7 +258,6 @@
-
-
+
From e592e11f32d8443729885c7eababd2b3e082ccc9 Mon Sep 17 00:00:00 2001 From: ysli Date: Wed, 9 Jul 2025 18:43:51 +0800 Subject: [PATCH 072/109] fix: fix file status switching bug --- src/renderer/src/components/settings/KnowledgeFile.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index 1a8aa09ca..934ed5856 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -177,7 +177,7 @@ onMounted(() => { window.electron.ipcRenderer.on(RAG_EVENTS.FILE_UPDATED, (_, data) => { console.log('知识库文件更新:', data) // TODO - const file = fileList.value.find((file) => file.id === data.fileId) + const file = fileList.value.find((file) => file.id === data.id) if (!file) { return } From 579e453f3e67e41fe87f1db4888052ff6026afcd Mon Sep 17 00:00:00 2001 From: ysli Date: Wed, 9 Jul 2025 19:47:03 +0800 Subject: [PATCH 073/109] feat: add builtinKnowledge file search --- .../src/components/settings/KnowledgeFile.vue | 237 ++++++++++++------ src/renderer/src/i18n/en-US/settings.json | 5 +- src/renderer/src/i18n/fa-IR/settings.json | 5 +- src/renderer/src/i18n/fr-FR/settings.json | 5 +- src/renderer/src/i18n/ja-JP/settings.json | 5 +- src/renderer/src/i18n/ko-KR/settings.json | 5 +- src/renderer/src/i18n/ru-RU/settings.json | 5 +- src/renderer/src/i18n/zh-CN/settings.json | 7 +- src/renderer/src/i18n/zh-HK/settings.json | 5 +- src/renderer/src/i18n/zh-TW/settings.json | 5 +- 10 files changed, 195 insertions(+), 89 deletions(-) diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index 934ed5856..14b22a51d 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -26,92 +26,149 @@
-
- - -
{{ t('settings.knowledgeBase.file') }}
+
+ {{ t('settings.knowledgeBase.file') }} + + {{ fileList.length }} + +
+
+
diff --git a/src/renderer/src/i18n/en-US/settings.json b/src/renderer/src/i18n/en-US/settings.json index ece4cae48..f8afc340e 100644 --- a/src/renderer/src/i18n/en-US/settings.json +++ b/src/renderer/src/i18n/en-US/settings.json @@ -332,7 +332,10 @@ "uploadError": "Upload failed", "delete": "delete", "reason": "reason", - "deleteSuccess": "Delete successfully" + "deleteSuccess": "Delete successfully", + "copy": "copy", + "copySuccess": "Copy successfully", + "source": "source" }, "mcp": { "title": "MCP Settings", diff --git a/src/renderer/src/i18n/fa-IR/settings.json b/src/renderer/src/i18n/fa-IR/settings.json index 5070155f5..fd181b0cf 100644 --- a/src/renderer/src/i18n/fa-IR/settings.json +++ b/src/renderer/src/i18n/fa-IR/settings.json @@ -332,7 +332,10 @@ "uploadError": "بارگذاری ناموفق بود", "delete": "حذف کردن", "reason": "دلیل", - "deleteSuccess": "با موفقیت حذف کنید" + "deleteSuccess": "با موفقیت حذف کنید", + "copy": "کپی کردن", + "copySuccess": "با موفقیت کپی کنید", + "source": "منبع" }, "mcp": { "title": "تنظیمات MCP", diff --git a/src/renderer/src/i18n/fr-FR/settings.json b/src/renderer/src/i18n/fr-FR/settings.json index a5416e573..680b1915b 100644 --- a/src/renderer/src/i18n/fr-FR/settings.json +++ b/src/renderer/src/i18n/fr-FR/settings.json @@ -332,7 +332,10 @@ "uploadError": "Le téléchargement a échoué", "delete": "supprimer", "reason": "raison", - "deleteSuccess": "Supprimer avec succès" + "deleteSuccess": "Supprimer avec succès", + "copy": "copie", + "copySuccess": "Copier avec succès", + "source": "source" }, "mcp": { "title": "Paramètres MCP", diff --git a/src/renderer/src/i18n/ja-JP/settings.json b/src/renderer/src/i18n/ja-JP/settings.json index a402c6e6c..b13867e0b 100644 --- a/src/renderer/src/i18n/ja-JP/settings.json +++ b/src/renderer/src/i18n/ja-JP/settings.json @@ -332,7 +332,10 @@ "uploadError": "アップロードに失敗しました", "delete": "消去", "reason": "理由", - "deleteSuccess": "正常に削除します" + "deleteSuccess": "正常に削除します", + "copy": "コピー", + "copySuccess": "正常にコピーします", + "source": "ソース" }, "mcp": { "title": "MCP設定", diff --git a/src/renderer/src/i18n/ko-KR/settings.json b/src/renderer/src/i18n/ko-KR/settings.json index fececf733..729e61802 100644 --- a/src/renderer/src/i18n/ko-KR/settings.json +++ b/src/renderer/src/i18n/ko-KR/settings.json @@ -332,7 +332,10 @@ "uploadError": "업로드 실패", "delete": "삭제", "reason": "이유", - "deleteSuccess": "성공적으로 삭제하십시오" + "deleteSuccess": "성공적으로 삭제하십시오", + "copy": "복사", + "copySuccess": "성공적으로 복사하십시오", + "source": "원천" }, "mcp": { "title": "MCP 설정", diff --git a/src/renderer/src/i18n/ru-RU/settings.json b/src/renderer/src/i18n/ru-RU/settings.json index ec444c64b..e6afc64f5 100644 --- a/src/renderer/src/i18n/ru-RU/settings.json +++ b/src/renderer/src/i18n/ru-RU/settings.json @@ -332,7 +332,10 @@ "uploadError": "Загрузка не удалась", "delete": "удалить", "reason": "причина", - "deleteSuccess": "Удалить успешно" + "deleteSuccess": "Удалить успешно", + "copy": "копия", + "copySuccess": "Копировать успешно", + "source": "источник" }, "mcp": { "title": "Настройки MCP", diff --git a/src/renderer/src/i18n/zh-CN/settings.json b/src/renderer/src/i18n/zh-CN/settings.json index 876f14a3b..b19f22200 100644 --- a/src/renderer/src/i18n/zh-CN/settings.json +++ b/src/renderer/src/i18n/zh-CN/settings.json @@ -330,7 +330,7 @@ "onlySupport": "仅支持", "searchKnowledge": "搜索知识库", "searchKnowledgePlaceholder": "请输入查询内容", - "noData":"暂无数据", + "noData": "暂无数据", "file": "文件", "uploadProcessing": "上传中", "uploadCompleted": "上传完成", @@ -338,7 +338,10 @@ "uploadError": "上传失败", "delete": "删除", "reason": "原因", - "deleteSuccess": "删除成功" + "deleteSuccess": "删除成功", + "copy": "复制", + "copySuccess": "复制成功", + "source": "来源" }, "mcp": { "title": "MCP设置", diff --git a/src/renderer/src/i18n/zh-HK/settings.json b/src/renderer/src/i18n/zh-HK/settings.json index 183a29505..2e63c21dc 100644 --- a/src/renderer/src/i18n/zh-HK/settings.json +++ b/src/renderer/src/i18n/zh-HK/settings.json @@ -332,7 +332,10 @@ "uploadError": "上傳失敗", "delete": "刪除", "reason": "原因", - "deleteSuccess": "刪除成功" + "deleteSuccess": "刪除成功", + "copy": "複製", + "copySuccess": "複製成功", + "source": "來源" }, "mcp": { "title": "MCP設置", diff --git a/src/renderer/src/i18n/zh-TW/settings.json b/src/renderer/src/i18n/zh-TW/settings.json index b084d85b6..7b54fe1f1 100644 --- a/src/renderer/src/i18n/zh-TW/settings.json +++ b/src/renderer/src/i18n/zh-TW/settings.json @@ -332,7 +332,10 @@ "uploadError": "上傳失敗", "delete": "刪除", "reason": "原因", - "deleteSuccess": "刪除成功" + "deleteSuccess": "刪除成功", + "copy": "複製", + "copySuccess": "複製成功", + "source": "來源" }, "mcp": { "title": "MCP設定", From c1591ffdab9a5de237f3f9ddaca0d7c8217845b7 Mon Sep 17 00:00:00 2001 From: ysli Date: Wed, 9 Jul 2025 19:53:29 +0800 Subject: [PATCH 074/109] fix: reemove redundant div --- .../src/components/settings/BuiltinKnowledgeSettings.vue | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index 6faf561a3..f02e7e6fd 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -235,7 +235,6 @@ {{ selectRerankModel?.name || t('settings.common.selectModel') }}
-
-
From 1479102a73a48476e55a267888f41b947073a45e Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 10 Jul 2025 11:04:37 +0800 Subject: [PATCH 075/109] feat: enhance file handling process in BuiltinKnowledge design with detailed flow for file insertion and retrieval --- docs/builtin-knowledge-design.md | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/builtin-knowledge-design.md b/docs/builtin-knowledge-design.md index af9d3c933..c18d29dbd 100644 --- a/docs/builtin-knowledge-design.md +++ b/docs/builtin-knowledge-design.md @@ -60,17 +60,34 @@ sequenceDiagram participant User participant KnowledgePresenter participant RagPresenter + participant LLMProvider participant IVectorDatabasePresenter + participant EventBus + %% 文件入库流程 User->>KnowledgePresenter: addFile(id, filePath) KnowledgePresenter->>RagPresenter: addFile(filePath) - RagPresenter->>IVectorDatabasePresenter: insertFile/insertVectors - RagPresenter-->>KnowledgePresenter: 任务完成事件 - KnowledgePresenter-->>User: 文件入库结果 - + RagPresenter->>LLMProvider: getMimeType(filePath) + LLMProvider-->>RagPresenter: mimeType + RagPresenter->>LLMProvider: prepareFileCompletely(filePath, mimeType) + LLMProvider-->>RagPresenter: fileInfo (name, path, content, size) + RagPresenter->>IVectorDatabasePresenter: insertFile(fileMessage) + RagPresenter->>LLMProvider: 分块+嵌入 (splitText+getEmbeddings) + LLMProvider-->>RagPresenter: chunks, vectors + RagPresenter->>IVectorDatabasePresenter: insertVectors(vectors) + RagPresenter->>IVectorDatabasePresenter: updateFile(status=completed) + RagPresenter->>EventBus: RAG_EVENTS.FILE_UPDATED (文件处理完成) + RagPresenter-->>KnowledgePresenter: fileTask Promise resolve + KnowledgePresenter-->>User: 返回文件入库结果 + Note over RagPresenter,IVectorDatabasePresenter: 异常时更新status=error并通知EventBus + + %% 文件检索流程 User->>KnowledgePresenter: similarityQuery(id, key) KnowledgePresenter->>RagPresenter: similarityQuery(key) - RagPresenter->>IVectorDatabasePresenter: similarityQuery + RagPresenter->>LLMProvider: getEmbeddings(key) + LLMProvider-->>RagPresenter: embedding + RagPresenter->>IVectorDatabasePresenter: similarityQuery(embedding) + IVectorDatabasePresenter-->>RagPresenter: 检索结果 RagPresenter-->>KnowledgePresenter: 检索结果 KnowledgePresenter-->>User: 检索结果 ``` From 93794d8f1ddf837ea86ab800e8623c5c2f273e9b Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 10 Jul 2025 11:16:58 +0800 Subject: [PATCH 076/109] feat: update BuiltinKnowledge design document with refined file handling and retrieval processes --- docs/builtin-knowledge-design.md | 46 +++++++++++++++++++------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/docs/builtin-knowledge-design.md b/docs/builtin-knowledge-design.md index c18d29dbd..a28572a83 100644 --- a/docs/builtin-knowledge-design.md +++ b/docs/builtin-knowledge-design.md @@ -53,46 +53,55 @@ - `getKnowledgeConfigs()`, `setKnowledgeConfigs()`, `diffKnowledgeConfigs()` 等。 -## 2. 文件入库与检索流程 +## 2. 文件入库流程 ```mermaid sequenceDiagram participant User participant KnowledgePresenter participant RagPresenter - participant LLMProvider participant IVectorDatabasePresenter + participant LLMProvider participant EventBus - %% 文件入库流程 User->>KnowledgePresenter: addFile(id, filePath) KnowledgePresenter->>RagPresenter: addFile(filePath) - RagPresenter->>LLMProvider: getMimeType(filePath) - LLMProvider-->>RagPresenter: mimeType - RagPresenter->>LLMProvider: prepareFileCompletely(filePath, mimeType) - LLMProvider-->>RagPresenter: fileInfo (name, path, content, size) + RagPresenter->>RagPresenter: 读取文件内容 RagPresenter->>IVectorDatabasePresenter: insertFile(fileMessage) - RagPresenter->>LLMProvider: 分块+嵌入 (splitText+getEmbeddings) - LLMProvider-->>RagPresenter: chunks, vectors + RagPresenter->>RagPresenter: 分块 (splitText) + loop 对每个chunk + RagPresenter->>LLMProvider: getEmbeddings(chunk) + LLMProvider-->>RagPresenter: vector + end RagPresenter->>IVectorDatabasePresenter: insertVectors(vectors) RagPresenter->>IVectorDatabasePresenter: updateFile(status=completed) RagPresenter->>EventBus: RAG_EVENTS.FILE_UPDATED (文件处理完成) RagPresenter-->>KnowledgePresenter: fileTask Promise resolve KnowledgePresenter-->>User: 返回文件入库结果 Note over RagPresenter,IVectorDatabasePresenter: 异常时更新status=error并通知EventBus +``` + +## 3. 检索流程 + +```mermaid +sequenceDiagram + participant User + participant KnowledgePresenter + participant RagPresenter + participant LLMProvider + participant IVectorDatabasePresenter - %% 文件检索流程 User->>KnowledgePresenter: similarityQuery(id, key) KnowledgePresenter->>RagPresenter: similarityQuery(key) - RagPresenter->>LLMProvider: getEmbeddings(key) + RagPresenter->>LLMProvider: getEmbeddings([key]) LLMProvider-->>RagPresenter: embedding RagPresenter->>IVectorDatabasePresenter: similarityQuery(embedding) - IVectorDatabasePresenter-->>RagPresenter: 检索结果 + IVectorDatabasePresenter-->>RagPresenter: 检索结果(相关片段、距离、元数据) RagPresenter-->>KnowledgePresenter: 检索结果 KnowledgePresenter-->>User: 检索结果 ``` -## 3. 事件系统 +## 4. 事件系统 BuiltinKnowledge 通过 eventBus 发出以下事件: @@ -100,9 +109,8 @@ BuiltinKnowledge 通过 eventBus 发出以下事件: | ---------------------------------- | -------------------------------- | ----------------- | ------------------------- | | `MCP_EVENTS.CONFIG_CHANGED` | 配置变更 | eventBus | configs | | `RAG_EVENTS.FILE_UPDATED` | 文件处理完成/状态变更 | KnowledgePresenter | KnowledgeFileMessage | -| ... | ... | ... | ... | -## 4. 配置管理 +## 5. 配置管理 知识库相关配置通过 `ConfigPresenter` 管理,持久化存储。 @@ -126,19 +134,19 @@ type BuiltinKnowledgeConfig = { } ``` -## 5. 扩展指南 +## 6. 扩展指南 -### 5.1 添加新向量数据库 +### 6.1 添加新向量数据库 1. 实现 `IVectorDatabasePresenter` 接口。 2. 在 `KnowledgePresenter` 中根据配置选择不同数据库实现。 -### 5.2 支持新嵌入模型 +### 6.2 支持新嵌入模型 1. 扩展 `ModelProvider` 类型和相关调用逻辑。 2. 在 `RagPresenter` 中适配新模型。 -### 5.3 自定义事件与回调 +### 6.3 自定义事件与回调 1. 在 `KnowledgePresenter`/`RagPresenter` 中增加事件触发点。 2. 在前端 UI 层监听并响应相关事件。 From 93e2dec8b9b0eb6a2ded0b74ee85850ac3fb6b7b Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 10 Jul 2025 13:59:53 +0800 Subject: [PATCH 077/109] feat: refactor BuiltinKnowledge module by replacing RagPresenter with KnowledgeStorePresenter and updating related components --- docs/builtin-knowledge-architecture.md | 24 ++-- docs/builtin-knowledge-design.md | 127 ++++++++++++++---- .../presenter/knowledgePresenter/index.ts | 46 +++---- ...resenter.ts => knowledgeStorePresenter.ts} | 2 +- src/shared/presenter.d.ts | 2 - 5 files changed, 134 insertions(+), 67 deletions(-) rename src/main/presenter/knowledgePresenter/{RagPresenter.ts => knowledgeStorePresenter.ts} (99%) diff --git a/docs/builtin-knowledge-architecture.md b/docs/builtin-knowledge-architecture.md index c7423b8c7..bc14cad6e 100644 --- a/docs/builtin-knowledge-architecture.md +++ b/docs/builtin-knowledge-architecture.md @@ -16,7 +16,7 @@ classDiagram class KnowledgePresenter { -configPresenter: IConfigPresenter -storageDir: string - -ragPresenterCache: Map + -storePresenterCache: Map +create() +reset() +delete() @@ -29,7 +29,7 @@ classDiagram +closeAll() } - class RagPresenter { + class KnowledgeStorePresenter { -vectorP: IVectorDatabasePresenter -config: BuiltinKnowledgeConfig +addFile() @@ -58,8 +58,8 @@ classDiagram +destroy() } - KnowledgePresenter o-- RagPresenter : manages - RagPresenter o-- IVectorDatabasePresenter + KnowledgePresenter o-- KnowledgeStorePresenter : manages + KnowledgeStorePresenter o-- IVectorDatabasePresenter ``` ## 数据流 @@ -84,25 +84,25 @@ sequenceDiagram sequenceDiagram participant User participant KnowledgePresenter - participant RagPresenter + participant KnowledgeStorePresenter participant IVectorDatabasePresenter User->>KnowledgePresenter: addFile(id, filePath) - KnowledgePresenter->>RagPresenter: addFile(filePath) - RagPresenter->>IVectorDatabasePresenter: insertFile/insertVectors - RagPresenter-->>KnowledgePresenter: 任务完成事件 + KnowledgePresenter->>KnowledgeStorePresenter: addFile(filePath) + KnowledgeStorePresenter->>IVectorDatabasePresenter: insertFile/insertVectors + KnowledgeStorePresenter-->>KnowledgePresenter: 任务完成事件 KnowledgePresenter-->>User: 文件入库结果 User->>KnowledgePresenter: similarityQuery(id, key) - KnowledgePresenter->>RagPresenter: similarityQuery(key) - RagPresenter->>IVectorDatabasePresenter: similarityQuery - RagPresenter-->>KnowledgePresenter: 检索结果 + KnowledgePresenter->>KnowledgeStorePresenter: similarityQuery(key) + KnowledgeStorePresenter->>IVectorDatabasePresenter: similarityQuery + KnowledgeStorePresenter-->>KnowledgePresenter: 检索结果 KnowledgePresenter-->>User: 检索结果 ``` ## 关键设计 -1. **分层架构**:接口层(IKnowledgePresenter)、管理层(KnowledgePresenter)、业务层(RagPresenter)、存储层(IVectorDatabasePresenter)、配置层(ConfigPresenter)。 +1. **分层架构**:接口层(IKnowledgePresenter)、管理层(KnowledgePresenter)、业务层(KnowledgeStorePresenter)、存储层(IVectorDatabasePresenter)、配置层(ConfigPresenter)。 2. **事件驱动**:通过 eventBus 监听 MCP 配置变更,自动同步知识库。 3. **高性能本地检索**:集成 DuckDB 向量数据库和本地嵌入模型。 4. **配置驱动与持久化**:所有知识库配置通过 ConfigPresenter 管理和持久化。 diff --git a/docs/builtin-knowledge-design.md b/docs/builtin-knowledge-design.md index a28572a83..a70df1930 100644 --- a/docs/builtin-knowledge-design.md +++ b/docs/builtin-knowledge-design.md @@ -23,9 +23,9 @@ - `similarityQuery(id, key)`: 相似度检索。 - `closeAll()`: 关闭所有 RAG 实例。 -### 1.2 RagPresenter +### 1.2 KnowledgeStorePresenter -`RagPresenter` (`src/main/presenter/knowledgePresenter/RagPresenter.ts`) 负责知识库的核心业务逻辑: +`KnowledgeStorePresenter` (`src/main/presenter/knowledgePresenter/KnowledgeStorePresenter.ts`) 负责知识库的核心业务逻辑: - 文件分块、嵌入生成、向量入库、相似度检索。 - 依赖 `IVectorDatabasePresenter` 进行底层向量存储和检索。 @@ -59,26 +59,26 @@ sequenceDiagram participant User participant KnowledgePresenter - participant RagPresenter + participant KnowledgeStorePresenter participant IVectorDatabasePresenter participant LLMProvider participant EventBus User->>KnowledgePresenter: addFile(id, filePath) - KnowledgePresenter->>RagPresenter: addFile(filePath) - RagPresenter->>RagPresenter: 读取文件内容 - RagPresenter->>IVectorDatabasePresenter: insertFile(fileMessage) - RagPresenter->>RagPresenter: 分块 (splitText) + KnowledgePresenter->>KnowledgeStorePresenter: addFile(filePath) + KnowledgeStorePresenter->>KnowledgeStorePresenter: 读取文件内容 + KnowledgeStorePresenter->>IVectorDatabasePresenter: insertFile(fileMessage) + KnowledgeStorePresenter->>KnowledgeStorePresenter: 分块 (splitText) loop 对每个chunk - RagPresenter->>LLMProvider: getEmbeddings(chunk) - LLMProvider-->>RagPresenter: vector + KnowledgeStorePresenter->>LLMProvider: getEmbeddings(chunk) + LLMProvider-->>KnowledgeStorePresenter: vector end - RagPresenter->>IVectorDatabasePresenter: insertVectors(vectors) - RagPresenter->>IVectorDatabasePresenter: updateFile(status=completed) - RagPresenter->>EventBus: RAG_EVENTS.FILE_UPDATED (文件处理完成) - RagPresenter-->>KnowledgePresenter: fileTask Promise resolve + KnowledgeStorePresenter->>IVectorDatabasePresenter: insertVectors(vectors) + KnowledgeStorePresenter->>IVectorDatabasePresenter: updateFile(status=completed) + KnowledgeStorePresenter->>EventBus: RAG_EVENTS.FILE_UPDATED (文件处理完成) + KnowledgeStorePresenter-->>KnowledgePresenter: fileTask Promise resolve KnowledgePresenter-->>User: 返回文件入库结果 - Note over RagPresenter,IVectorDatabasePresenter: 异常时更新status=error并通知EventBus + Note over KnowledgeStorePresenter,IVectorDatabasePresenter: 异常时更新status=error并通知EventBus ``` ## 3. 检索流程 @@ -87,21 +87,57 @@ sequenceDiagram sequenceDiagram participant User participant KnowledgePresenter - participant RagPresenter + participant KnowledgeStorePresenter participant LLMProvider participant IVectorDatabasePresenter User->>KnowledgePresenter: similarityQuery(id, key) - KnowledgePresenter->>RagPresenter: similarityQuery(key) - RagPresenter->>LLMProvider: getEmbeddings([key]) - LLMProvider-->>RagPresenter: embedding - RagPresenter->>IVectorDatabasePresenter: similarityQuery(embedding) - IVectorDatabasePresenter-->>RagPresenter: 检索结果(相关片段、距离、元数据) - RagPresenter-->>KnowledgePresenter: 检索结果 + KnowledgePresenter->>KnowledgeStorePresenter: similarityQuery(key) + KnowledgeStorePresenter->>LLMProvider: getEmbeddings([key]) + LLMProvider-->>KnowledgeStorePresenter: embedding + KnowledgeStorePresenter->>IVectorDatabasePresenter: similarityQuery(embedding) + IVectorDatabasePresenter-->>KnowledgeStorePresenter: 检索结果(相关片段、距离、元数据) + KnowledgeStorePresenter-->>KnowledgePresenter: 检索结果 KnowledgePresenter-->>User: 检索结果 ``` -## 4. 事件系统 +## 4. 配置变更到知识库创建流程 + +当 MCP 配置变更(如新增/修改 builtinKnowledge 配置)时,系统自动同步并创建/更新本地知识库,流程如下: + +```mermaid +sequenceDiagram + participant MCPConfHelper + participant EventBus + participant KnowledgePresenter + participant ConfigPresenter + participant KnowledgeStorePresenter + participant IVectorDatabasePresenter (DuckDB) + + MCPConfHelper->>EventBus: send(MCP_EVENTS.CONFIG_CHANGED, { mcpServers, ... }) + EventBus->>KnowledgePresenter: MCP_EVENTS.CONFIG_CHANGED + KnowledgePresenter->>ConfigPresenter: diffKnowledgeConfigs(configs) + KnowledgePresenter->>ConfigPresenter: setKnowledgeConfigs(configs) + alt 新增/变更 + KnowledgePresenter->>KnowledgePresenter: create(config) + KnowledgePresenter->>KnowledgeStorePresenter: createKnowledgeStorePresenter(config) + KnowledgePresenter->>IVectorDatabasePresenter (DuckDB): getVectorDatabasePresenter(id, dimensions, normalized) + IVectorDatabasePresenter (DuckDB)-->>KnowledgePresenter: DuckDB 实例 + KnowledgePresenter->>KnowledgeStorePresenter: new KnowledgeStorePresenter(db, config) + end + alt 删除 + KnowledgePresenter->>KnowledgePresenter: delete(id) + KnowledgePresenter->>IVectorDatabasePresenter (DuckDB): 清理本地存储 + end +``` + +**说明:** +- MCPConfHelper 负责监听和发出配置变更事件。 +- KnowledgePresenter 监听事件,调用 ConfigPresenter 进行配置 diff 和持久化。 +- 对于新增/变更,KnowledgePresenter 创建 KnowledgeStorePresenter,并初始化/获取 DuckDB 实例。 +- 对于删除,KnowledgePresenter 清理本地存储和缓存。 + +## 5. 事件系统 BuiltinKnowledge 通过 eventBus 发出以下事件: @@ -110,7 +146,7 @@ BuiltinKnowledge 通过 eventBus 发出以下事件: | `MCP_EVENTS.CONFIG_CHANGED` | 配置变更 | eventBus | configs | | `RAG_EVENTS.FILE_UPDATED` | 文件处理完成/状态变更 | KnowledgePresenter | KnowledgeFileMessage | -## 5. 配置管理 +## 6. 配置管理 知识库相关配置通过 `ConfigPresenter` 管理,持久化存储。 @@ -134,19 +170,52 @@ type BuiltinKnowledgeConfig = { } ``` -## 6. 扩展指南 +## 7. 扩展指南 -### 6.1 添加新向量数据库 +### 7.1 添加新向量数据库 1. 实现 `IVectorDatabasePresenter` 接口。 2. 在 `KnowledgePresenter` 中根据配置选择不同数据库实现。 -### 6.2 支持新嵌入模型 +### 7.2 支持新嵌入模型 1. 扩展 `ModelProvider` 类型和相关调用逻辑。 -2. 在 `RagPresenter` 中适配新模型。 +2. 在 `KnowledgeStorePresenter` 中适配新模型。 -### 6.3 自定义事件与回调 +### 7.3 自定义事件与回调 -1. 在 `KnowledgePresenter`/`RagPresenter` 中增加事件触发点。 +1. 在 `KnowledgePresenter`/`KnowledgeStorePresenter` 中增加事件触发点。 2. 在前端 UI 层监听并响应相关事件。 + +## 8. DuckDBPresenter 主要流程与细节 + +DuckDBPresenter 作为本地向量数据库的实现,负责表结构初始化、向量插入、检索、文件元数据管理等。下图展示其主要方法调用和数据流: + +```mermaid +flowchart TD + A[initialize] --> B[CreateTableAndIndex] + C[open] --> D[OpenDBConnection] + E[insertFile] --> F[InsertFileMetadata] + G[insertVectors] --> H[BatchInsertVectors] + I[updateFile] --> J[UpdateFileStatusOrMetadata] + K[deleteVectorsByFile] --> L[DeleteVectorsForFile] + M[deleteFile] --> N[DeleteFileMetadata] + O[similarityQuery] --> P[VectorANNQuery] + Q[queryFile] --> R[QueryFileMetadata] + S[listFiles] --> T[ListAllFiles] + U[destroyOrClose] --> V[CloseConnectionOrRelease] + + %% Main data flow + G --> P + E --> Q + E --> S + K --> M +``` + +**说明:** +- `initialize` 负责表结构和索引的创建,支持多维度和不同度量方式(如 cosine、ip)。 +- `insertFile`/`insertVectors` 分别管理文件元数据和向量数据,支持批量插入。 +- `similarityQuery` 实现高效 ANN 检索,返回相关片段及距离。 +- `deleteVectorsByFile`、`deleteFile` 支持文件级别的物理删除。 +- `updateFile`、`queryFile`、`listFiles` 支持文件状态和元数据的维护。 +- `destroy`/`close` 负责资源释放和连接关闭。 diff --git a/src/main/presenter/knowledgePresenter/index.ts b/src/main/presenter/knowledgePresenter/index.ts index 37aeaa7b7..d8c047f9e 100644 --- a/src/main/presenter/knowledgePresenter/index.ts +++ b/src/main/presenter/knowledgePresenter/index.ts @@ -13,7 +13,7 @@ import { import { eventBus, SendTarget } from '@/eventbus' import { MCP_EVENTS, RAG_EVENTS } from '@/events' import { DuckDBPresenter } from './database/duckdbPresenter' -import { RagPresenter } from './RagPresenter' +import { KnowledgeStorePresenter } from './knowledgeStorePresenter' export class KnowledgePresenter implements IKnowledgePresenter { /** @@ -87,15 +87,15 @@ export class KnowledgePresenter implements IKnowledgePresenter { * 创建知识库(初始化 RAG 应用) */ create = async (config: BuiltinKnowledgeConfig): Promise => { - this.createRagPresenter(config) + this.createStorePresenter(config) } /** * 删除知识库(移除本地存储) */ delete = async (id: string): Promise => { - if (this.ragPresenterCache.has(id)) { - const rag = this.ragPresenterCache.get(id) as RagPresenter + if (this.storePresenterCache.has(id)) { + const rag = this.storePresenterCache.get(id) as KnowledgeStorePresenter await rag.destory() } else { const dbPath = path.join(this.storageDir, id) @@ -108,27 +108,27 @@ export class KnowledgePresenter implements IKnowledgePresenter { /** * 缓存 RAG 应用实例 */ - private ragPresenterCache: Map = new Map() + private storePresenterCache: Map = new Map() /** * 创建 RAG 应用实例 * @param params BuiltinKnowledgeConfig - * @returns RagPresenter + * @returns KnowledgeStorePresenter */ - private createRagPresenter = async (config: BuiltinKnowledgeConfig): Promise => { - let rag: RagPresenter + private createStorePresenter = async (config: BuiltinKnowledgeConfig): Promise => { + let rag: KnowledgeStorePresenter const db = await this.getVectorDatabasePresenter( config.id, config.dimensions, config.normalized ) try { - rag = new RagPresenter(db, config) + rag = new KnowledgeStorePresenter(db, config) } catch (e) { - throw new Error(`Failed to create RagPresenter: ${e}`) + throw new Error(`Failed to create storePresenter: ${e}`) } - this.ragPresenterCache.set(config.id, rag) + this.storePresenterCache.set(config.id, rag) return rag } @@ -136,10 +136,10 @@ export class KnowledgePresenter implements IKnowledgePresenter { * 获取 RAG 应用实例 * @param id 知识库 ID */ - private getRagPresenter = async (id: string): Promise => { + private getStorePresenter = async (id: string): Promise => { // 缓存命中直接返回 - if (this.ragPresenterCache.has(id)) { - return this.ragPresenterCache.get(id) as RagPresenter + if (this.storePresenterCache.has(id)) { + return this.storePresenterCache.get(id) as KnowledgeStorePresenter } // 获取配置 const configs = this.configP.getKnowledgeConfigs() @@ -150,8 +150,8 @@ export class KnowledgePresenter implements IKnowledgePresenter { // DuckDB 存储 const db = await this.getVectorDatabasePresenter(id, config.dimensions, config.normalized) // 创建 RAG 应用实例 - const rag = new RagPresenter(db, config) - this.ragPresenterCache.set(id, rag) + const rag = new KnowledgeStorePresenter(db, config) + this.storePresenterCache.set(id, rag) return rag } @@ -182,11 +182,11 @@ export class KnowledgePresenter implements IKnowledgePresenter { private async handleFileTask( id: string, - fileHandler: (rag: RagPresenter) => Promise<{ data: KnowledgeFileMessage; task: Promise }>, + fileHandler: (rag: KnowledgeStorePresenter) => Promise<{ data: KnowledgeFileMessage; task: Promise }>, errorMsg: string ): Promise { try { - const rag = await this.getRagPresenter(id) + const rag = await this.getStorePresenter(id) const fileTask = await fileHandler(rag) fileTask.task .then((message) => { @@ -215,7 +215,7 @@ export class KnowledgePresenter implements IKnowledgePresenter { } async deleteFile(id: string, fileId: string): Promise { - const rag = await this.getRagPresenter(id) + const rag = await this.getStorePresenter(id) await rag.deleteFile(fileId) } @@ -228,23 +228,23 @@ export class KnowledgePresenter implements IKnowledgePresenter { } async queryFile(id: string, fileId: string): Promise { - const rag = await this.getRagPresenter(id) + const rag = await this.getStorePresenter(id) return await rag.queryFile(fileId) } async listFiles(id: string): Promise { - const rag = await this.getRagPresenter(id) + const rag = await this.getStorePresenter(id) return await rag.listFiles() } async closeAll(): Promise { - this.ragPresenterCache.forEach((rag) => { + this.storePresenterCache.forEach((rag) => { rag.close() }) } async similarityQuery(id: string, key: string): Promise { - const rag = await this.getRagPresenter(id) + const rag = await this.getStorePresenter(id) return await rag.similarityQuery(key) } } diff --git a/src/main/presenter/knowledgePresenter/RagPresenter.ts b/src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts similarity index 99% rename from src/main/presenter/knowledgePresenter/RagPresenter.ts rename to src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts index 8f3e607dc..56d77915f 100644 --- a/src/main/presenter/knowledgePresenter/RagPresenter.ts +++ b/src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts @@ -11,7 +11,7 @@ import { nanoid } from 'nanoid' import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters' import { sanitizeText } from '@/utils/strings' -export class RagPresenter { +export class KnowledgeStorePresenter { private readonly vectorP: IVectorDatabasePresenter private readonly config: BuiltinKnowledgeConfig diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index 5b68006ee..06acaaabc 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -1371,5 +1371,3 @@ export interface IVectorDatabasePresenter { */ deleteFile(id: string): Promise } - -export interface IRagPresenter {} From 7c41c9cfb2b5acbe0d6bc3ffcf5f767bc88a5190 Mon Sep 17 00:00:00 2001 From: ysli Date: Thu, 10 Jul 2025 14:04:07 +0800 Subject: [PATCH 078/109] feat: add builtinKnowledge file search score --- .../src/components/settings/KnowledgeFile.vue | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index 14b22a51d..d75bf41d3 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -118,22 +118,26 @@ :key="item.id" class="relative px-6 py-4 mt-2 bg-card border border-border rounded-sm bg-secondary" > +
+ score:{{ ((1 - item.distance)*100).toFixed(2) + '%' }} +
- -
{{ t('settings.knowledgeBase.copySuccess') }} <
-
{{ t('settings.knowledgeBase.copy') }}
+
+ {{ t('settings.knowledgeBase.copySuccess') }} < +
+
{{ t('settings.knowledgeBase.copy') }}
@@ -198,6 +202,7 @@ const openSearchDialog = () => { searchKey.value = '' searchResult.value = [] copyId.value = '' + loading.value = false } // 返回知识库页面 @@ -215,11 +220,12 @@ const handleSearch = async () => { if (!searchKey.value) return copyId.value = '' loading.value = true - searchResult.value = await knowledgePresenter.similarityQuery( - props.builtinKnowledgeDetail.id, - searchKey.value - ) - loading.value = false + knowledgePresenter + .similarityQuery(props.builtinKnowledgeDetail.id, searchKey.value) + .then((res: any) => { + searchResult.value = res || [] + loading.value = false + }) } // 复制文本 From 1b1fb0dce4cae2b5238aad4f65b374376963c4e6 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:36:53 +0800 Subject: [PATCH 079/109] feat: enhance error handling in file upload and re-upload processes in KnowledgeFile component --- .../database/duckdbPresenter.ts | 3 +++ .../src/components/settings/KnowledgeFile.vue | 23 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts b/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts index b6fbfa785..b15e24522 100644 --- a/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts +++ b/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts @@ -48,6 +48,9 @@ export class DuckDBPresenter implements IVectorDatabasePresenter { throw new Error('Database does not exist, please initialize first.') } await this.connect() + if (fs.existsSync(this.dbPath + '.wal')) { + await this.connection.run('CHECKPOINT;') + } await this.installAndLoadVSS() } diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index d75bf41d3..32162eefd 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -291,7 +291,18 @@ const handleDrop = async (e: DragEvent) => { try { const path = window.api.getPathForFile(file) const result = await knowledgePresenter.addFile(props.builtinKnowledgeDetail.id, path) - fileList.value.push(result) + if(result.error) { + toast({ + title: `${file.name} ${t('settings.knowledgeBase.uploadError')}`, + description: result.error, + variant: 'destructive', + duration: 3000 + }) + return + } + if (result.data) { + fileList.value.push(result.data) + } } catch (error) { console.error('文件准备失败:', error) return @@ -313,7 +324,15 @@ const deleteFile = async (fileId: string) => { // 重新上传文件 const reAddFile = async (file: KnowledgeFileMessage) => { + const result = await knowledgePresenter.reAddFile(props.builtinKnowledgeDetail.id, file.id) file.status = 'processing' // 设置状态为加载中 - knowledgePresenter.reAddFile(props.builtinKnowledgeDetail.id, file.id) + if(result.error) { + toast({ + title: `${file.name} ${t('settings.knowledgeBase.uploadError')}`, + description: result.error, + variant: 'destructive', + duration: 3000 + }) + } } From 3384fbe532e88aa172f0d08411ad34c86df6ac71 Mon Sep 17 00:00:00 2001 From: ysli Date: Thu, 10 Jul 2025 15:49:03 +0800 Subject: [PATCH 080/109] fix: fix overly long file names --- src/renderer/src/components/settings/KnowledgeFileItem.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/components/settings/KnowledgeFileItem.vue b/src/renderer/src/components/settings/KnowledgeFileItem.vue index 276281ea0..eddaae01d 100644 --- a/src/renderer/src/components/settings/KnowledgeFileItem.vue +++ b/src/renderer/src/components/settings/KnowledgeFileItem.vue @@ -6,8 +6,8 @@ :icon="getFileIcon()" class="w-10 h-10 text-muted-foreground p-1 bg-accent rounded-md border" /> -
-
+
+
{{ file.name }}
Date: Thu, 10 Jul 2025 15:52:18 +0800 Subject: [PATCH 081/109] fix: fix overly long file names --- .../src/components/settings/BuiltinKnowledgeSettings.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue index f02e7e6fd..cee4b4b9d 100644 --- a/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue +++ b/src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue @@ -99,7 +99,7 @@
- {{ config.description }} + {{ config.description }}
From 8bb8d911627e09730c173097f6ccd0b90f21d5d0 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:01:16 +0800 Subject: [PATCH 082/109] refactor: simplify checkpoint logic in DuckDBPresenter open method --- .../presenter/knowledgePresenter/database/duckdbPresenter.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts b/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts index b15e24522..921d238e0 100644 --- a/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts +++ b/src/main/presenter/knowledgePresenter/database/duckdbPresenter.ts @@ -48,9 +48,7 @@ export class DuckDBPresenter implements IVectorDatabasePresenter { throw new Error('Database does not exist, please initialize first.') } await this.connect() - if (fs.existsSync(this.dbPath + '.wal')) { - await this.connection.run('CHECKPOINT;') - } + await this.connection.run('CHECKPOINT;') await this.installAndLoadVSS() } From e5de3813c0bb896ed02f8c1e9307fcfb2a058b91 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:29:07 +0800 Subject: [PATCH 083/109] feat: add @langchain/core dependency to enhance functionality --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 4699bcfd3..d94a2832e 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/utils": "^4.0.0", "@google/genai": "^1.5.1", + "@langchain/core": "^0.3.62", "@langchain/textsplitters": "^0.1.0", "@modelcontextprotocol/sdk": "^1.12.3", "axios": "^1.7.9", From 6a2a48ccffc5a41cdd910850b1a29c93605fdad4 Mon Sep 17 00:00:00 2001 From: hllshiro <40970081+hllshiro@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:35:45 +0800 Subject: [PATCH 084/109] fix: update file extension handling to use correct variable name --- .../src/components/settings/KnowledgeFile.vue | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/renderer/src/components/settings/KnowledgeFile.vue b/src/renderer/src/components/settings/KnowledgeFile.vue index 32162eefd..68c6e2e98 100644 --- a/src/renderer/src/components/settings/KnowledgeFile.vue +++ b/src/renderer/src/components/settings/KnowledgeFile.vue @@ -53,7 +53,7 @@ {{ t('settings.knowledgeBase.onlySupport') }} - {{ allowedExts.join(',') }} + {{ acceptExts.join(',') }}
@@ -65,7 +65,7 @@ type="file" id="upload" @change="handleChange" - :accept="allowedExts.map((ext) => '.' + ext).join(',')" + :accept="acceptExts.map((ext) => '.' + ext).join(',')" />
-
- score:{{ ((1 - item.distance)*100).toFixed(2) + '%' }} +
+ score:{{ ((1 - item.distance) * 100).toFixed(2) + '%' }}
-