diff --git a/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt b/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt index 2f7de2e..b39d6f5 100644 --- a/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt +++ b/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt @@ -2136,15 +2136,8 @@ class MainActivity : AppCompatActivity() { Toast.LENGTH_LONG).show() return } - // 同轮上下文:本行中该句之前的句子(最近 ≤600 字),仅帮助模型消解 - // 指代/省略,不进入译文 - val ctx = StringBuilder() - for (prev in s.line?.sentences.orEmpty()) { - if (prev === s) break - if (prev.text.isNotBlank()) ctx.append(prev.text.trim()).append(' ') - } - var context = ctx.toString().trim() - if (context.length > 600) context = context.takeLast(600) + // 直译模式(2026-09-16 用户拍板):不带同轮上下文,逐句独立翻译。 + // 原先 600 字上下文曾被怀疑是漂移诱因;指代/省略句的质量代价已知情 s.transPending = true s.line?.let { notifyLine(it) } transBusy = true @@ -2154,7 +2147,7 @@ class MainActivity : AppCompatActivity() { // 让核:翻译线程永远低于录音/ASR 线程优先级(工程惯例同定稿线程) Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND) translateHandler.removeCallbacks(unloadRunnable) - val tr = translateOne(srcId, srcText, context) + val tr = translateOne(srcId, srcText) transBusy = false uiHandler.post { s.transPending = false @@ -2281,24 +2274,23 @@ class MainActivity : AppCompatActivity() { // 点击翻译总入口:1B 主链失败 → 升档兜底(摘要引擎,多语言能力强得多)。 // 歌词体/文言中文("最贪富贵的潦倒一生…")超 1B 边界,温度重试无用, // 唯一解是换更大的模型再试一次。 - private fun translateOne(sid: Long, src: String, context: String): String? { + private fun translateOne(sid: Long, src: String): String? { // 时间预算:录音中 45s、空闲 95s。超预算宁可失败(toast 可重试), // 也不让重试链长时间抢 ASR 的核(饥饿会引发第一遍字幕复读)。 val deadline = SystemClock.elapsedRealtime() + if (isRecording) 45_000L else 95_000L - translateOne1B(sid, src, context, deadline)?.let { return it } - return translateFallback(sid, src, context, deadline) + translateOne1B(sid, src, deadline)?.let { return it } + return translateFallback(sid, src, deadline) } private fun translateOne1B( - sid: Long, src: String, context: String, deadline: Long, + sid: Long, src: String, deadline: Long, ): String? { var temp = 0f var genRetry = 0 // 重试预算:录音中只允许 1 次(两次尝试≈30s),给兜底留出时间窗—— // 现场:三次尝试 15s×3 吃满 45s 预算,兜底被 skipped=budget 拒之门外 val maxGenRetry = if (isRecording) 1 else 2 - var ctx = context var lastRej = "" while (true) { if (SystemClock.elapsedRealtime() > deadline) { @@ -2306,7 +2298,7 @@ class MainActivity : AppCompatActivity() { return null } val map = translateNumbered( - listOf(Pair(sid.toString(), src)), temp, ctx) + listOf(Pair(sid.toString(), src)), temp) val raw = map?.get(sid.toString())?.trim() val srcTag = " src=" + SummarizePipeline.detectLanguage(src) + ":" + src.take(20).replace("\n", " ") @@ -2334,7 +2326,6 @@ class MainActivity : AppCompatActivity() { " temp=$temp" + srcTag) if (genRetry >= maxGenRetry) return null genRetry++; temp = if (temp == 0f) 0.3f else 0.7f - if (genRetry >= 2) ctx = "" } isEcho(src, tr, echoJaccardTh(src)) -> { val es = tr.replace("\n", " ") @@ -2343,7 +2334,6 @@ class MainActivity : AppCompatActivity() { lastRej = es if (genRetry >= maxGenRetry) return null genRetry++; temp = if (temp == 0f) 0.3f else 0.7f - if (genRetry >= 2) ctx = "" } !targetLangOk(tr) -> { val sample = tr.replace("\n", " ") @@ -2369,7 +2359,7 @@ class MainActivity : AppCompatActivity() { // 目录)低温再译一次。临时引擎用完即 release(KV 污染协议);预算将尽 // (剩不到 8s)不启用。产物过同样的 echo/drift 质检,宁缺毋滥。 private fun translateFallback( - sid: Long, src: String, context: String, deadline: Long, + sid: Long, src: String, deadline: Long, ): String? { if (SystemClock.elapsedRealtime() > deadline - 8_000) { Log.i(TAG, "TAP-FALLBACK sid=$sid skipped=budget") @@ -2399,7 +2389,7 @@ class MainActivity : AppCompatActivity() { "禁止道歉或说明无法完成,翻不了就输出空字符串。" + "文学性表达按原文风格意译,保留重复与排比。" + transLangHint() + "。", - userPrompt = transCtxBlock(context) + src, + userPrompt = src, maxNewTokens = (src.length * 2 + 96).coerceAtMost(1200), temperature = 0.2f, repeatPenalty = 1.1f, ) @@ -2432,9 +2422,6 @@ class MainActivity : AppCompatActivity() { "zh" -> "译文必须是简体中文(不得用繁体字,不要输出日语或英语)" else -> "The translation must be English only (no CJK characters)" } - private fun transCtxBlock(context: String): String = - if (context.isBlank()) "" else - "【参考上下文(不要翻译)】\n" + context + "\n\n【需要翻译的句子】\n" // 容错提取 "编号":"译文" 对:顺序扫描,不要求 JSON 完整闭合—— // 生成被 maxNewTokens 截断时,已完成的条目仍能救出 @@ -2489,16 +2476,14 @@ class MainActivity : AppCompatActivity() { } // 一批 = 一个全新引擎(nativeGenerate 不清 KV 的 workaround)。 - // items: key(通常是 sid 字符串) × 原文;context: 可选的同轮参考上下文 - // (只帮助消解指代,不进译文);返回 key × 译文,失败 null。 + // items: key(通常是 sid 字符串) × 原文;返回 key × 译文,失败 null。 + // 直译模式(2026-09-16):不再携带同轮上下文 private fun translateNumbered( items: List>, temp: Float = 0f, - context: String = "", ): Map? { if (items.isEmpty()) return emptyMap() val targetName = transTargetName() val langHint = transLangHint() - val ctxBlock = transCtxBlock(context) translateEngine?.let { runCatching { it.release() } } translateEngine = null val engine = ensureTranslateEngine() ?: return null @@ -2524,7 +2509,7 @@ class MainActivity : AppCompatActivity() { "禁止道歉或说明无法完成,翻不了就输出空字符串。" + "你只在中文、日本語、English 三种语言之间翻译;" + "输入不属于这三种语言时输出空字符串。" + langHint + "。" - val usr1 = ctxBlock + segKeys[0].second + val usr1 = segKeys[0].second // 白卷事故诊断(2026-09-16):空 raw= 的现场缺"模型看到了什么" // 这一环;转储两段长度与首尾,排除提示词层脏数据 Log.i(TAG, "TRANSLATE prompt sys.len=" + sys1.length + @@ -2564,7 +2549,7 @@ class MainActivity : AppCompatActivity() { "你只在中文、日本語、English 三种语言之间翻译;" + "段不属于这三种语言时其值输出空字符串。" + langHint + "。", - userPrompt = ctxBlock + "【文本】\n" + numbered, + userPrompt = "【文本】\n" + numbered, maxNewTokens = budget, temperature = temp, repeatPenalty = 1.1f, )