diff --git a/src/components/ConversationView.vue b/src/components/ConversationView.vue index 7f16e88..1d6f5e2 100644 --- a/src/components/ConversationView.vue +++ b/src/components/ConversationView.vue @@ -245,11 +245,17 @@ const evaluateMessage = async (messageId: string, force = false) => { const historyLimit = 10; const recentMessages = activeSession.value.messages.filter(m => m.id !== messageId).slice(-historyLimit); + // 净化历史:只提供原文流 const historyBlock = recentMessages.map(m => { const senderName = m.sender === 'me' ? activeSession.value!.me.name : activeSession.value!.partner.name; - return `${senderName}: [Original] ${m.original} -> [Translated] ${m.translated}`; + return `${senderName}: ${m.original}`; }).join('\n'); + // 动态确定语言方向 + const fromLang = msg.sender === 'me' ? activeSession.value.me.language : activeSession.value.partner.language; + const toLang = msg.sender === 'me' ? activeSession.value.partner.language : activeSession.value.me.language; + const senderName = msg.sender === 'me' ? activeSession.value.me.name : activeSession.value.partner.name; + // 动态确定目标语气约束 const targetTone = msg.sender === 'me' ? (TONE_REGISTER_OPTIONS.find(o => o.value === activeSession.value!.me.tone)?.label || '随和') @@ -263,7 +269,12 @@ const evaluateMessage = async (messageId: string, force = false) => { .replace(/{PART_GENDER}/g, activeSession.value.partner.gender) .replace(/{PART_LANG}/g, activeSession.value.partner.language.englishName) .replace(/{HISTORY_BLOCK}/g, historyBlock || 'None') - .replace(/{TARGET_TONE}/g, targetTone); + .replace(/{TARGET_TONE}/g, targetTone) + .replace(/{SENDER_NAME}/g, senderName) + .replace(/{FROM_LANG}/g, fromLang.englishName) + .replace(/{TO_LANG}/g, toLang.englishName) + .replace(/{ORIGINAL_TEXT}/g, msg.original) + .replace(/{CURRENT_TRANSLATION}/g, msg.translated); const userPrompt = `[Source Text]\n${msg.original}\n\n[Current Translation]\n${msg.translated}`; @@ -337,15 +348,20 @@ const refineMessage = async (messageId: string) => { const historyLimit = 10; const recentMessages = activeSession.value.messages.filter(m => m.id !== messageId).slice(-historyLimit); + // 净化历史:只提供原文流 const historyBlock = recentMessages.map(m => { const senderName = m.sender === 'me' ? activeSession.value!.me.name : activeSession.value!.partner.name; - return `${senderName}: [Original] ${m.original} -> [Translated] ${m.translated}`; + return `${senderName}: ${m.original}`; }).join('\n'); const myToneLabel = TONE_REGISTER_OPTIONS.find(o => o.value === activeSession.value!.me.tone)?.label || '随和'; // 确定目标语气 const targetTone = msg.sender === 'me' ? myToneLabel : '自动识别 (保持原作者原始语气和情绪)'; + + // 动态确定语言方向 + const fromLang = msg.sender === 'me' ? activeSession.value.me.language : activeSession.value.partner.language; + const toLang = msg.sender === 'me' ? activeSession.value.partner.language : activeSession.value.me.language; const systemPrompt = settings.chatRefinementPromptTemplate .replace(/{ME_NAME}/g, activeSession.value.me.name) @@ -358,7 +374,9 @@ const refineMessage = async (messageId: string) => { .replace(/{ORIGINAL_TEXT}/g, msg.original) .replace(/{CURRENT_TRANSLATION}/g, msg.translated) .replace(/{SUGGESTIONS}/g, suggestionsText) - .replace(/{TARGET_TONE}/g, targetTone); + .replace(/{TARGET_TONE}/g, targetTone) + .replace(/{FROM_LANG}/g, fromLang.englishName) + .replace(/{TO_LANG}/g, toLang.englishName); const requestBody = { model: settings.modelName, diff --git a/src/components/SettingsView.vue b/src/components/SettingsView.vue index 372ae32..b4edc34 100644 --- a/src/components/SettingsView.vue +++ b/src/components/SettingsView.vue @@ -558,7 +558,7 @@ onUnmounted(() => window.removeEventListener('click', handleGlobalClick)); >
- {{ tag }} + {{ tag }}
diff --git a/src/stores/settings.ts b/src/stores/settings.ts index 5fac1fd..0c2986e 100644 --- a/src/stores/settings.ts +++ b/src/stores/settings.ts @@ -174,31 +174,26 @@ Translate the incoming text from {FROM_LANG} to {TO_LANG}. 4. Strictly avoid over-translation: Do not add extra information not present in the source text. 5. Output ONLY the translated text, no explanations.`; -export const CONVERSATION_EVALUATION_PROMPT_TEMPLATE = `# Role -You are an expert Conversation Auditor. Your task is to evaluate if the [Current Translation] accurately reflects the [Source Text] within the specific flow of the [Conversation History]. +export const CONVERSATION_EVALUATION_PROMPT_TEMPLATE = `# Role: Expert Conversation Auditor # Context Info -- Me: {ME_NAME} ({ME_GENDER}, {ME_LANG}) -- Partner: {PART_NAME} ({PART_GENDER}, {PART_LANG}) +- Role A (Me): {ME_NAME} ({ME_GENDER}, Native {ME_LANG}) +- Role B (Partner): {PART_NAME} ({PART_GENDER}, Native {PART_LANG}) - Target Tone: {TARGET_TONE} -[Conversation History] +# Recent Conversation Flow (Original Messages Only): {HISTORY_BLOCK} -# Audit Priorities -1. **Contextual Accuracy**: Do pronouns (it, that, etc.) correctly point to objects/topics mentioned in the [Conversation History]? -2. **Relational Tone**: Does the translation match the [Target Tone]? (e.g., if set to 'Polite', is it too casual?) -3. **Consistency**: Are names, terms, or previously established facts handled consistently? -4. **Naturalness**: Is it concise and fit for an IM (Instant Messaging) environment? +# Current Turn to Audit: +- Speaker: {SENDER_NAME} +- Direction: {FROM_LANG} -> {TO_LANG} +- Source Text ({FROM_LANG}): {ORIGINAL_TEXT} +- Translation ({TO_LANG}): {CURRENT_TRANSLATION} -# Instructions -1. Analyze the [Source Text] and [Current Translation] against the history. -2. Scoring: 0-100. -3. Suggestions: Provide actionable improvements. -4. **Severity Level**: For each suggestion, assign an "importance" score (0-100). - - **80-100 (Critical)**: Misunderstanding meaning, wrong pronoun reference, or offensive tone. - - **40-79 (Moderate)**: Unnatural phrasing, minor tone mismatch. - - **0-39 (Minor)**: Polishing, stylistic preferences. +# Audit Priorities +1. **Contextual Accuracy**: Does the translation correctly reflect the meaning based on the [Recent Conversation Flow]? +2. **Relational Tone**: Does it match the [Target Tone]? +3. **Naturalness**: Is it concise and fit for an IM (Instant Messaging) environment? # Output Format Respond ONLY in JSON. "analysis" and "text" MUST be in Simplified Chinese: @@ -210,32 +205,28 @@ Respond ONLY in JSON. "analysis" and "text" MUST be in Simplified Chinese: ] }`; -export const CONVERSATION_REFINEMENT_PROMPT_TEMPLATE = `You are a professional conversation editor. Refine the [Current Translation] based on the [Original Source Text], [Audit Suggestions], and [Conversation History]. +export const CONVERSATION_REFINEMENT_PROMPT_TEMPLATE = `# Role: Professional Conversation Editor -# Context Info -- Role A (Me): {ME_NAME}, Gender: {ME_GENDER}, Language: {ME_LANG}. -- Role B (Partner): {PART_NAME}, Gender: {PART_GENDER}, Language: {PART_LANG}. +# Context: +- Role A: {ME_NAME} ({ME_GENDER}, Native {ME_LANG}) +- Role B: {PART_NAME} ({PART_GENDER}, Native {PART_LANG}) - Target Tone: {TARGET_TONE} -[Conversation History] +# Recent Conversation Flow (Original Messages Only): {HISTORY_BLOCK} -[Original Source Text] -{ORIGINAL_TEXT} +# Task: Refine the following translation +- Direction: {FROM_LANG} -> {TO_LANG} +- Source Text ({FROM_LANG}): {ORIGINAL_TEXT} +- Current Draft ({TO_LANG}): {CURRENT_TRANSLATION} -[Current Translation] -{CURRENT_TRANSLATION} - -[Audit Suggestions] +# Suggestions to Apply: {SUGGESTIONS} -# Task -Produce a new, refined version of the translation that addresses the suggestions while staying true to the original meaning and natural conversation flow. - -# Constraints -1. Maintain semantic identity with the [Original Source Text]. -2. Strictly follow the Target Tone. -3. Output ONLY the refined translation text. No explanations.`; +# Instructions: +1. Produce a new version of the translation that addresses the [Suggestions] while ensuring it fits naturally into the [Recent Conversation Flow]. +2. Strictly maintain the {TARGET_TONE}. +3. Output ONLY the refined {TO_LANG} text. No preamble, no commentary.`; export const useSettingsStore = defineStore('settings', () => { const isDark = useLocalStorage('is-dark', false);