From 388c548e4a12330cedf7eacf82d42678f74cec81 Mon Sep 17 00:00:00 2001 From: Momentry Studio Date: Tue, 27 Oct 2026 01:18:19 +0800 Subject: [PATCH] feat: multi-language support for agent search and admin pipeline config - search_agents now accepts output_language parameter (en/zh-TW/ja) - Admin Settings: added Pipeline Configuration section (enabled, max_concurrent_stages, default_timeout_secs) - Admin Settings: search config now includes vlm_output_language dropdown - Added translations for pipeline config in en/zh-TW/ja locales - Agent search uses searchConfig.vlm_output_language for output language --- data/users/demo.sqlite-shm | Bin 32768 -> 32768 bytes src/api/index.ts | 1 + src/locales/en.json | 21 +++++++++++++++ src/locales/ja.json | 20 +++++++++++++++ src/locales/zh-TW.json | 20 +++++++++++++++ src/views/AdminView.vue | 51 ++++++++++++++++++++++++++++++++++++- src/views/SearchView.vue | 1 + 7 files changed, 113 insertions(+), 1 deletion(-) diff --git a/data/users/demo.sqlite-shm b/data/users/demo.sqlite-shm index f5df5c8b3e1ee9d1cb659488e30f8897a5e2ec3e..056709c6e255224615a3baf05673d550ab96ffc5 100644 GIT binary patch literal 32768 zcmeI5b#xU+7{%|0yGzjE9^BpC36S8yU4py2x5a{cajSc&)0PS?ZK=>wSL#BA-T}6x z?~vwuBzv~+F>}r@XWz`-JKx;dm;c^u$b~SNmX`>SX&V1*O#(!Wj+`Fd=H$gQ8%7LV z88hYFh4Yuro;n>K9pb0{iaGxn-^;O@(;s#1g2PBkl96=eI6F>|7}jF?%x81$t6Rl}Qy+l~g0uNexny)FQP>9a5LnBlSrG(vaN9+k6MskhNqTSx+{Q7_yOU zBAdw;vXyKj+sO{Hlk6h9$sV$oICD7P&35c-Pdbo}q!S4zokHUXP}O~58#6R-)`1Z)B} z0h@qLz$Rc5unE`%Yyvg`n}AKgCSVh=3D^W|0yY7gfK9+AU=y$j*aU0>HUXP}O~58# z6R-)`1Z)B}0h@qLz$Rc5unE`%Yyvic|6Kwvsw;}bBDK~H;SlqKSP$DK_1te<`K`2C zp6J3K6W!52!vku0W)c2=IXln3D2x&)hpMQ9hG>TN=#0J?gxOe)owy$_<8vgH0#ZWC zOLeI)&7`&TlmRj=z@M2jPaO+shEK|xDC5-2>0Ouyo6Wq8Injc$ts~z zP>M@QDJK=An$(bb(m`Qq`h>IP7*F%q^m?qH|Zh0Bue^9e;Fu4Ww@9VO#Ep* zu+$%U&}p}-S9DITbVvA$JGN@q!)j$VNs3fFvn301B0q|t6e^%P>Y*`Opd-4XKZale zCSw|AVlHmSZaj!r@dc7gAt@ylrKU8L7SdKaN@t0X?$TTO$sifw=aa1|wcG5=%%V_&uQfKd< z@JY4&L$%T+VZb~Cd8HMGVNAf(>(YKHY*Trh(Nl^VuSz~rD{pmSK532Ni1ut}zY3TQ zNbOlhS0j2_oz%x_WpE1DsF!sw+F%6V^i);Gda}D;t1IzDCdeG<=j zun(_QFEGEf#Yl|vY-hhwSL(Get!EisUHP->06tYKgHyQ9k7bR*cn|mWq92udD^2HN zN@nHHdAs}onti<=wT{LF5BK$3KPvTBn%={d%*s!xmp}i?J22Jqpc8KJV?|>y(ZhZH z&W}pnklv{_&ER25rpV{jl`c>#gHsrzUe@b~#v~8-^?P-t?g;m(Z8Lh9k}2{9b)^f{ o%HR}kR4?l+a-kr?P#Lu__R8C%)wd>!@P|Zkxp|ZQ>RU6(-wb{%od5s; delta 309 zcmZo@U}|V!s+V}A%K!p=K+MR%Am9(A=QA-dY(AtRt1tah`tr=&wEkIDxAu7-a5^3) zu!>amAhSULWUd|%|AzvQ7!Uw$+SusKxVf3_x8>#uZ1(Jv|2c_mZerWPI{A!;)Z`{M z5n(0<9tJT6Sq4o80|s*jI|gS4kIjv2ubCv788{et8H5!UMI|oB!eP@E`te!HIS>w2mppmQVIY7 diff --git a/src/api/index.ts b/src/api/index.ts index 6bac23c..a91c5e7 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -301,6 +301,7 @@ case 'search_keyword': { case 'search_agents': { const body: any = { query: a.query } if (a.conversationId) body.conversation_id = a.conversationId + if (a.outputLanguage) body.output_language = a.outputLanguage return { url: '/api/v1/agents/search', method: 'POST', body, timeout: 180000 } } diff --git a/src/locales/en.json b/src/locales/en.json index 981103d..c036a84 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -413,6 +413,7 @@ "processorConfig": "Processor Configuration", "filterConfig": "Filter Configuration", "searchConfig": "Search Configuration", + "pipelineConfig": "Pipeline Configuration", "systemConfig": "System Configuration", "uploadPath": "Upload Path", "serviceUrls": "Service URLs" @@ -448,6 +449,26 @@ "stat": { "users": "Users", "shares": "Shares" + }, + "vlm": { + "minScore": "VLM Min Score", + "maxResults": "VLM Max Results", + "outputLanguage": "Output Language", + "hint": { + "minScore": "Minimum similarity score for VLM search", + "maxResults": "Maximum number of VLM search results", + "outputLanguage": "Language for VLM descriptions" + } + }, + "pipeline": { + "enabled": "Enabled", + "maxConcurrentStages": "Max Concurrent Stages", + "defaultTimeoutSecs": "Default Timeout (seconds)", + "hint": { + "enabled": "Enable pipeline processing", + "maxConcurrentStages": "Maximum number of stages to run concurrently", + "defaultTimeoutSecs": "Default timeout for pipeline execution" + } } }, "app": { diff --git a/src/locales/ja.json b/src/locales/ja.json index c5aaef7..fc260c1 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -445,6 +445,26 @@ "stat": { "users": "ユーザー", "shares": "共有" + }, + "vlm": { + "minScore": "VLM 最小スコア", + "maxResults": "VLM 最大結果数", + "outputLanguage": "出力言語", + "hint": { + "minScore": "VLM検索の最小類似度スコア", + "maxResults": "VLM検索の最大結果数", + "outputLanguage": "VLM説明の言語" + } + }, + "pipeline": { + "enabled": "有効", + "maxConcurrentStages": "最大並列ステージ数", + "defaultTimeoutSecs": "デフォルトタイムアウト(秒)", + "hint": { + "enabled": "パイプライン処理を有効化", + "maxConcurrentStages": "同時に実行する最大ステージ数", + "defaultTimeoutSecs": "パイプライン実行のデフォルトタイムアウト" + } } }, "app": { diff --git a/src/locales/zh-TW.json b/src/locales/zh-TW.json index 28b1b31..41fb143 100644 --- a/src/locales/zh-TW.json +++ b/src/locales/zh-TW.json @@ -448,6 +448,26 @@ "stat": { "users": "用戶", "shares": "共享" + }, + "vlm": { + "minScore": "VLM 最低分數", + "maxResults": "VLM 最大結果數", + "outputLanguage": "輸出語言", + "hint": { + "minScore": "VLM 搜尋的最低相似度分數", + "maxResults": "VLM 搜尋的最大結果數量", + "outputLanguage": "VLM 描述的語言" + } + }, + "pipeline": { + "enabled": "啟用", + "maxConcurrentStages": "最大並行階段數", + "defaultTimeoutSecs": "預設超時(秒)", + "hint": { + "enabled": "啟用管線處理", + "maxConcurrentStages": "同時執行的最大階段數", + "defaultTimeoutSecs": "管線執行的預設超時時間" + } } }, "app": { diff --git a/src/views/AdminView.vue b/src/views/AdminView.vue index a387e38..ebe9ee5 100644 --- a/src/views/AdminView.vue +++ b/src/views/AdminView.vue @@ -408,6 +408,44 @@ + +
+

+ {{ expandedSections.pipeline ? '▼' : '▶' }} + {{ t('admin.section.pipelineConfig') }} +

+
+
+ + + {{ t('admin.pipeline.hint.enabled') }} +
+
+ + + {{ t('admin.pipeline.hint.maxConcurrentStages') }} +
+
+ + + {{ t('admin.pipeline.hint.defaultTimeoutSecs') }} +
+
+
+

@@ -1130,7 +1168,7 @@ const configSaving = ref(false) const configError = ref('') const configSaveMsg = ref('') const configSaveOk = ref(false) -const expandedSections = ref({ vlm: true, llm: true, proc: true, filter: true, search: true, sys: false, lang: false }) +const expandedSections = ref({ vlm: true, llm: true, proc: true, filter: true, search: true, pipeline: false, sys: false, lang: false }) const vlmPrompts = ref>({}) const llmConfig = ref>({}) @@ -1142,6 +1180,11 @@ const searchConfig = ref>({ vlm_max_results: 5, vlm_output_language: 'en' }) +const pipelineConfig = ref>({ + enabled: false, + max_concurrent_stages: 3, + default_timeout_secs: 3600 +}) function toggleSection(section: string) { expandedSections.value[section] = !expandedSections.value[section] @@ -1188,6 +1231,7 @@ async function loadConfig() { filterConfig.value = data.filter_config || {} systemConfig.value = data.system_config || {} searchConfig.value = data.search || { vlm_min_score: 0.0, vlm_max_results: 5, vlm_output_language: 'en' } + pipelineConfig.value = data.pipeline || { enabled: false, max_concurrent_stages: 3, default_timeout_secs: 3600 } } catch (e: any) { configError.value = 'Failed to load config: ' + (e.message || e) } finally { @@ -1215,6 +1259,11 @@ async function saveConfig() { vlm_max_results: searchConfig.value.vlm_max_results || 5, vlm_output_language: searchConfig.value.vlm_output_language || 'en' }, + pipeline: { + enabled: pipelineConfig.value.enabled ?? false, + max_concurrent_stages: pipelineConfig.value.max_concurrent_stages || 3, + default_timeout_secs: pipelineConfig.value.default_timeout_secs || 3600 + }, } const saveRes = await fetch('/api/v1/admin/config', { method: 'POST', diff --git a/src/views/SearchView.vue b/src/views/SearchView.vue index e78746f..dc30c4f 100644 --- a/src/views/SearchView.vue +++ b/src/views/SearchView.vue @@ -815,6 +815,7 @@ async function sendMessage() { const res: any = await apiCall('search_agents', { query: q, conversationId: conversationId.value || null, + outputLanguage: searchConfig.value.vlm_output_language || 'en', }) if (searchSeq !== seq) return if (res?.conversation_id) conversationId.value = res.conversation_id