diff --git a/src/views/SearchView.vue b/src/views/SearchView.vue index 2998bf8..b3ef850 100644 --- a/src/views/SearchView.vue +++ b/src/views/SearchView.vue @@ -1178,18 +1178,22 @@ async function sendMessage() { const frameNumber = s.frame_number ?? Math.round(ts * fps) const windowSec = 5 - // Build bilingual description + // Build bilingual description: localized language first, then English let vlmDesc = s.vlm_description || '' let textContent = vlmDesc if (bilingual && s.vlm_description_en && s.vlm_description_lang) { - // Show both English and preferred language - textContent = `【English】\n${s.vlm_description_en}\n\n【${outputLang.toUpperCase()}】\n${s.vlm_description_lang}` - vlmDesc = textContent + // Show localized language first, then English + textContent = `【${outputLang.toUpperCase()}】\n${s.vlm_description_lang}\n\n【English】\n${s.vlm_description_en}` + vlmDesc = s.vlm_description_lang + } else if (bilingual && s.vlm_description_lang) { + // Only localized language available + textContent = `【${outputLang.toUpperCase()}】\n${s.vlm_description_lang}` + vlmDesc = s.vlm_description_lang } else if (bilingual && s.vlm_description_en) { // Only English available textContent = `【English】\n${s.vlm_description_en}` - vlmDesc = textContent + vlmDesc = s.vlm_description_en } return { @@ -1217,16 +1221,22 @@ async function sendMessage() { const ts = t.start_time ?? t.timestamp_sec ?? (frame / fps) const windowSec = 5 - // Build bilingual description + // Build bilingual description: localized language first, then English let vlmDesc = t.vlm_description || '' let textContent = vlmDesc if (bilingual && t.vlm_description_en && t.vlm_description_lang) { - textContent = `【English】\n${t.vlm_description_en}\n\n【${outputLang.toUpperCase()}】\n${t.vlm_description_lang}` - vlmDesc = textContent + // Show localized language first, then English + textContent = `【${outputLang.toUpperCase()}】\n${t.vlm_description_lang}\n\n【English】\n${t.vlm_description_en}` + vlmDesc = t.vlm_description_lang + } else if (bilingual && t.vlm_description_lang) { + // Only localized language available + textContent = `【${outputLang.toUpperCase()}】\n${t.vlm_description_lang}` + vlmDesc = t.vlm_description_lang } else if (bilingual && t.vlm_description_en) { + // Only English available textContent = `【English】\n${t.vlm_description_en}` - vlmDesc = textContent + vlmDesc = t.vlm_description_en } return { @@ -1323,6 +1333,7 @@ async function loadMore() { const base = getApiBase() const maxResults = 10 const outputLang = searchConfig.value.vlm_output_language || 'en' + const bilingual = outputLang !== 'en' // Use offset-based pagination instead of page const offset = nextOffset.value @@ -1339,33 +1350,72 @@ async function loadMore() { }).then(r => r.json()).catch(() => ({})) ]) - const sceneResults = (scenesRes.scenes || []).map((s: any) => ({ - file_uuid: s.file_uuid, - file_name: s.file_name || '', - summary: `[SCENE] ${s.vlm_description || ''}`, - similarity: s.score ?? null, - start_frame: s.frame_number ?? Math.round((s.timestamp_sec || 0) * 30), - end_frame: (s.frame_number ?? Math.round((s.timestamp_sec || 0) * 30)) + 30, - start_time: s.timestamp_sec, - end_time: (s.timestamp_sec || 0) + 1, - source_type: 'scene', - thumbnail_url: s.thumbnail_url, - vlm_tags: s.vlm_tags || [], - search_query: q - })) + const sceneResults = (scenesRes.scenes || []).map((s: any) => { + let vlmDesc = s.vlm_description || '' + let textContent = vlmDesc + + if (bilingual && s.vlm_description_en && s.vlm_description_lang) { + textContent = `【${outputLang.toUpperCase()}】\n${s.vlm_description_lang}\n\n【English】\n${s.vlm_description_en}` + vlmDesc = s.vlm_description_lang + } else if (bilingual && s.vlm_description_lang) { + textContent = `【${outputLang.toUpperCase()}】\n${s.vlm_description_lang}` + vlmDesc = s.vlm_description_lang + } else if (bilingual && s.vlm_description_en) { + textContent = `【English】\n${s.vlm_description_en}` + vlmDesc = s.vlm_description_en + } + + return { + file_uuid: s.file_uuid, + file_name: s.file_name || '', + summary: vlmDesc ? `[SCENE] ${vlmDesc}` : `[SCENE] ${s.vlm_description || ''}`, + text_content: textContent, + similarity: s.score ?? null, + start_frame: s.frame_number ?? Math.round((s.timestamp_sec || 0) * 30), + end_frame: (s.frame_number ?? Math.round((s.timestamp_sec || 0) * 30)) + 30, + start_time: s.timestamp_sec, + end_time: (s.timestamp_sec || 0) + 1, + source_type: 'scene', + thumbnail_url: s.thumbnail_url, + vlm_tags: s.vlm_tags || [], + bilingual, + vlm_description_en: s.vlm_description_en, + vlm_description_lang: s.vlm_description_lang, + search_query: q + } + }) - const traceResults = (tracesRes.traces || []).map((t: any) => ({ - file_uuid: t.file_uuid, - file_name: t.file_name || '', - summary: `[TRACE] ${t.vlm_description || ''}`, - similarity: t.score ?? null, - start_frame: t.start_frame, - end_frame: t.end_frame, - source_type: 'trace', - trace_id: t.trace_id, - vlm_description: t.vlm_description, - search_query: q - })) + const traceResults = (tracesRes.traces || []).map((t: any) => { + let vlmDesc = t.vlm_description || '' + let textContent = vlmDesc + + if (bilingual && t.vlm_description_en && t.vlm_description_lang) { + textContent = `【${outputLang.toUpperCase()}】\n${t.vlm_description_lang}\n\n【English】\n${t.vlm_description_en}` + vlmDesc = t.vlm_description_lang + } else if (bilingual && t.vlm_description_lang) { + textContent = `【${outputLang.toUpperCase()}】\n${t.vlm_description_lang}` + vlmDesc = t.vlm_description_lang + } else if (bilingual && t.vlm_description_en) { + textContent = `【English】\n${t.vlm_description_en}` + vlmDesc = t.vlm_description_en + } + + return { + file_uuid: t.file_uuid, + file_name: t.file_name || '', + summary: vlmDesc || t.text_content || t.vlm_description || 'Person appearance', + text_content: textContent, + similarity: t.score ?? null, + start_frame: t.start_frame, + end_frame: t.end_frame, + source_type: 'trace', + trace_id: t.trace_id, + bilingual, + vlm_description_en: t.vlm_description_en, + vlm_description_lang: t.vlm_description_lang, + search_query: q + } + }) newResults = [...sceneResults, ...traceResults].slice(0, maxResults) } else if (currentMode === 'people') {