翻译改直译模式(用户拍板):去掉同轮上下文(≤600字)——触发点不再拼装、两级引擎签名去掉 context、transCtxBlock 删除、重试丢上下文环节随之废除;原先疑虑的'长上下文诱发漂移'变量一并消除;指代/省略句质量代价已知情

This commit is contained in:
liwenhao2 2026-09-16 11:44:06 +08:00
parent 5dc9fdaf74
commit f77f90e1e9
1 changed files with 14 additions and 29 deletions

View File

@ -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<Pair<String, String>>, temp: Float = 0f,
context: String = "",
): Map<String, String>? {
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,
)