From cd6c0a1f668c227660dc58cdfe6b789bad46be48 Mon Sep 17 00:00:00 2001 From: Hao He <57698783+Harris-H@users.noreply.github.com> Date: Thu, 20 Mar 2025 21:12:04 +0800 Subject: [PATCH 01/17] fix: update file extensions for Fortran source files (#3683) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Enhance update error logging and fix duplicate type import - Improve error logging in AppUpdater with more detailed error information and timestamps - Remove duplicate MCPServer type import in Inputbar component * feat(constants): 添加 Fortran 源文件扩展名支持 --- packages/shared/config/constant.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/shared/config/constant.ts b/packages/shared/config/constant.ts index a5fca5afc..34f7d1658 100644 --- a/packages/shared/config/constant.ts +++ b/packages/shared/config/constant.ts @@ -103,7 +103,10 @@ export const textExts = [ '.cxx', // C++ 源文件 '.cppm', // C++20 模块接口文件 '.ipp', // 模板实现文件 - '.ixx' // C++20 模块实现文件 + '.ixx', // C++20 模块实现文件 + '.f90', // Fortran 90 源文件 + '.f', // Fortran 固定格式源代码文件 + '.f03' // Fortran 2003+ 源代码文件 ] export const ZOOM_SHORTCUTS = [ From 6fd5ff991d5c893591b4cce5c2f1343a58954db4 Mon Sep 17 00:00:00 2001 From: FischLu Date: Thu, 20 Mar 2025 14:31:13 +0100 Subject: [PATCH 02/17] =?UTF-8?q?fix(translate):=20=E5=8E=BB=E9=99=A4?= =?UTF-8?q?=E7=BF=BB=E8=AF=91=E9=A1=B5=E9=9D=A2=E4=B8=AD=E7=94=9F=E6=88=90?= =?UTF-8?q?=E7=9A=84=E7=BF=BB=E8=AF=91=E5=86=85=E5=AE=B9=E5=BC=80=E5=A7=8B?= =?UTF-8?q?=E7=9A=84=E7=A9=BA=E7=99=BD=E8=A1=8C=20(#3684)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(translate): trim whitespace from translated text before setting result --- src/renderer/src/pages/translate/TranslatePage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/pages/translate/TranslatePage.tsx b/src/renderer/src/pages/translate/TranslatePage.tsx index c6afe9768..c5f35e4a9 100644 --- a/src/renderer/src/pages/translate/TranslatePage.tsx +++ b/src/renderer/src/pages/translate/TranslatePage.tsx @@ -112,8 +112,8 @@ const TranslatePage: FC = () => { message, assistant, onResponse: (text) => { - translatedText = text - setResult(text) + translatedText = text.replace(/^\s*\n+/g, '') + setResult(translatedText) } }) } catch (error) { From ea990e78a5d42dfe33c8f2f895aaffb6f4b150ed Mon Sep 17 00:00:00 2001 From: Chen Tao <70054568+eeee0717@users.noreply.github.com> Date: Thu, 20 Mar 2025 22:32:54 +0800 Subject: [PATCH 03/17] feat: support jina reranker (#3658) --- src/main/reranker/JinaReranker.ts | 48 ++++++++++++++++ src/main/reranker/RerankerFactory.ts | 3 + src/main/reranker/SiliconFlowReranker.ts | 55 ++++++++++--------- .../components/KnowledgeSettingsPopup.tsx | 2 +- 4 files changed, 80 insertions(+), 28 deletions(-) create mode 100644 src/main/reranker/JinaReranker.ts diff --git a/src/main/reranker/JinaReranker.ts b/src/main/reranker/JinaReranker.ts new file mode 100644 index 000000000..dbee063cc --- /dev/null +++ b/src/main/reranker/JinaReranker.ts @@ -0,0 +1,48 @@ +import { ExtractChunkData } from '@llm-tools/embedjs-interfaces' +import { KnowledgeBaseParams } from '@types' +import axios from 'axios' + +import BaseReranker from './BaseReranker' + +export default class JinaReranker extends BaseReranker { + constructor(base: KnowledgeBaseParams) { + super(base) + } + + public rerank = async (query: string, searchResults: ExtractChunkData[]): Promise => { + const baseURL = this.base?.rerankBaseURL?.endsWith('/') + ? this.base.rerankBaseURL.slice(0, -1) + : this.base.rerankBaseURL + const url = `${baseURL}/rerank` + + const requestBody = { + model: this.base.rerankModel, + query, + documents: searchResults.map((doc) => doc.pageContent), + top_n: this.base.topN + } + + try { + const { data } = await axios.post(url, requestBody, { headers: this.defaultHeaders() }) + + const rerankResults = data.results + console.log(rerankResults) + const resultMap = new Map(rerankResults.map((result: any) => [result.index, result.relevance_score || 0])) + return searchResults + .map((doc: ExtractChunkData, index: number) => { + const score = resultMap.get(index) + if (score === undefined) return undefined + + return { + ...doc, + score + } + }) + .filter((doc): doc is ExtractChunkData => doc !== undefined) + .sort((a, b) => b.score - a.score) + } catch (error) { + console.error('Jina Reranker API 错误:', error) + throw error + } + } +} diff --git a/src/main/reranker/RerankerFactory.ts b/src/main/reranker/RerankerFactory.ts index 2c15fe6cc..0c2e8d7dd 100644 --- a/src/main/reranker/RerankerFactory.ts +++ b/src/main/reranker/RerankerFactory.ts @@ -2,12 +2,15 @@ import { KnowledgeBaseParams } from '@types' import BaseReranker from './BaseReranker' import DefaultReranker from './DefaultReranker' +import JinaReranker from './JinaReranker' import SiliconFlowReranker from './SiliconFlowReranker' export default class RerankerFactory { static create(base: KnowledgeBaseParams): BaseReranker { if (base.rerankModelProvider === 'silicon') { return new SiliconFlowReranker(base) + } else if (base.rerankModelProvider === 'jina') { + return new JinaReranker(base) } return new DefaultReranker(base) } diff --git a/src/main/reranker/SiliconFlowReranker.ts b/src/main/reranker/SiliconFlowReranker.ts index 1730efdae..ee82362e2 100644 --- a/src/main/reranker/SiliconFlowReranker.ts +++ b/src/main/reranker/SiliconFlowReranker.ts @@ -15,35 +15,36 @@ export default class SiliconFlowReranker extends BaseReranker { : this.base.rerankBaseURL const url = `${baseURL}/rerank` - const { data } = await axios.post( - url, - { - model: this.base.rerankModel, - query, - documents: searchResults.map((doc) => doc.pageContent), - top_n: this.base.topN, - max_chunks_per_doc: this.base.chunkSize, - overlap_tokens: this.base.chunkOverlap - }, - { - headers: this.defaultHeaders() - } - ) + const requestBody = { + model: this.base.rerankModel, + query, + documents: searchResults.map((doc) => doc.pageContent), + top_n: this.base.topN, + max_chunks_per_doc: this.base.chunkSize, + overlap_tokens: this.base.chunkOverlap + } - const rerankResults = data.results - const resultMap = new Map(rerankResults.map((result: any) => [result.index, result.relevance_score || 0])) + try { + const { data } = await axios.post(url, requestBody, { headers: this.defaultHeaders() }) - return searchResults - .map((doc: ExtractChunkData, index: number) => { - const score = resultMap.get(index) - if (score === undefined) return undefined + const rerankResults = data.results + const resultMap = new Map(rerankResults.map((result: any) => [result.index, result.relevance_score || 0])) - return { - ...doc, - score - } - }) - .filter((doc): doc is ExtractChunkData => doc !== undefined) - .sort((a, b) => b.score - a.score) + return searchResults + .map((doc: ExtractChunkData, index: number) => { + const score = resultMap.get(index) + if (score === undefined) return undefined + + return { + ...doc, + score + } + }) + .filter((doc): doc is ExtractChunkData => doc !== undefined) + .sort((a, b) => b.score - a.score) + } catch (error) { + console.error('SiliconFlow Reranker API 错误:', error) + throw error + } } } diff --git a/src/renderer/src/pages/knowledge/components/KnowledgeSettingsPopup.tsx b/src/renderer/src/pages/knowledge/components/KnowledgeSettingsPopup.tsx index e1c1e8c18..56c00b66f 100644 --- a/src/renderer/src/pages/knowledge/components/KnowledgeSettingsPopup.tsx +++ b/src/renderer/src/pages/knowledge/components/KnowledgeSettingsPopup.tsx @@ -142,10 +142,10 @@ const PopupContainer: React.FC = ({ base: _base, resolve }) => { name="rerankModel" label={t('models.rerank_model')} tooltip={{ title: t('models.rerank_model_tooltip'), placement: 'right' }} + initialValue={getModelUniqId(base.rerankModel) || undefined} rules={[{ required: false, message: t('message.error.enter.model') }]}> setCustomFileName(e.target.value)} + placeholder={t('settings.data.webdav.backup.modal.filename.placeholder')} + /> + + + setIsRestoreModalVisible(false)} + okButtonProps={{ loading: restoring }} + width={600}> +
+ setCustomFileName(e.target.value)} - placeholder={t('settings.data.webdav.backup.modal.filename.placeholder')} - /> - - - setIsRestoreModalVisible(false)} - okButtonProps={{ loading: restoring }} - width={600}> -
- setCustomFileName(e.target.value)} + placeholder={t('settings.data.webdav.backup.modal.filename.placeholder')} /> - {loadingFiles && ( -
- -
- )} -
-
- + + + setIsRestoreModalVisible(false)} + okButtonProps={{ loading: restoring }} + width={600}> +
+