批次跳号与拉丁混入治理: 编号批缺失段逐一直出兜底(每段全新引擎)、拼回整句要求段段齐全(有洞宁缺不残,MISS seg-hole)、targetLangOk对日/中目标加拉丁占比>33%拒绝(拦manque类欧洲语言漂移)
This commit is contained in:
parent
679b88bec3
commit
635a06e1c5
|
|
@ -2141,11 +2141,37 @@ class MainActivity : AppCompatActivity() {
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
Log.w(TAG, "TRANSLATE batch failed: " + t.message); null
|
Log.w(TAG, "TRANSLATE batch failed: " + t.message); null
|
||||||
}
|
}
|
||||||
val byIdx = extractNumberedPairs(out) ?: return null
|
val byIdx = extractNumberedPairs(out)
|
||||||
segKeys.forEachIndexed { i, st ->
|
segKeys.forEachIndexed { i, st ->
|
||||||
byIdx[(i + 1).toString()]?.takeIf { it.isNotBlank() }
|
byIdx?.get((i + 1).toString())?.takeIf { it.isNotBlank() }
|
||||||
?.let { got[st.first] = it }
|
?.let { got[st.first] = it }
|
||||||
}
|
}
|
||||||
|
// 模型对编号批会"犯懒跳号"(只写最后一段等)→ 缺失段逐一直出
|
||||||
|
// 兜底;每段重建引擎(nativeGenerate 不清 KV,复用必复读)
|
||||||
|
val missSegs = segKeys.filter { !got.containsKey(it.first) }
|
||||||
|
if (missSegs.isNotEmpty()) {
|
||||||
|
Log.i(TAG, "BATCH incomplete " + got.size + "/" +
|
||||||
|
segKeys.size + " -> per-seg fallback")
|
||||||
|
for (st in missSegs) {
|
||||||
|
translateEngine?.let { runCatching { it.release() } }
|
||||||
|
translateEngine = null
|
||||||
|
val e2 = ensureTranslateEngine() ?: break
|
||||||
|
val one = try {
|
||||||
|
e2.generate(
|
||||||
|
systemPrompt = "你是专业翻译。把给出的文本翻译成" +
|
||||||
|
targetName + "。只输出译文本身,不要解释。" +
|
||||||
|
langHint + "。",
|
||||||
|
userPrompt = st.second,
|
||||||
|
maxNewTokens = (st.second.length * 2 + 96)
|
||||||
|
.coerceAtMost(1200),
|
||||||
|
temperature = 0f,
|
||||||
|
)
|
||||||
|
} catch (t: Throwable) { null }
|
||||||
|
one?.trim()?.lines()?.firstOrNull { it.isNotBlank() }
|
||||||
|
?.trim()?.takeIf { it.isNotEmpty() }
|
||||||
|
?.let { got[st.first] = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
if (got.isEmpty()) return null
|
if (got.isEmpty()) return null
|
||||||
}
|
}
|
||||||
val res = HashMap<String, String>()
|
val res = HashMap<String, String>()
|
||||||
|
|
@ -2154,10 +2180,14 @@ class MainActivity : AppCompatActivity() {
|
||||||
if (n == null) got[key]?.let { res[key] = it }
|
if (n == null) got[key]?.let { res[key] = it }
|
||||||
else {
|
else {
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
|
var full = true
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
got[key + "#s" + i]?.let { sb.append(it) }
|
val g = got[key + "#s" + i]
|
||||||
|
if (g == null) { full = false; break }
|
||||||
|
sb.append(g)
|
||||||
}
|
}
|
||||||
if (sb.isNotEmpty()) res[key] = sb.toString()
|
if (full) res[key] = sb.toString()
|
||||||
|
else Log.i(TAG, "MISS key=" + key + " reason=seg-hole")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return if (res.isEmpty()) null else res
|
return if (res.isEmpty()) null else res
|
||||||
|
|
@ -2214,9 +2244,17 @@ class MainActivity : AppCompatActivity() {
|
||||||
private fun targetLangOk(tr: String): Boolean {
|
private fun targetLangOk(tr: String): Boolean {
|
||||||
if (tr.length < 12) return true
|
if (tr.length < 12) return true
|
||||||
return when (uiLanguage()) {
|
return when (uiLanguage()) {
|
||||||
"ja" -> tr.count { it.code in 0x3040..0x30FF } * 25 >= tr.length
|
"ja" -> {
|
||||||
"zh" -> tr.none { it.code in 0x3040..0x30FF } &&
|
val latin = tr.count { it in 'a'..'z' || it in 'A'..'Z' }
|
||||||
tr.count { c -> tradOnlyChars.contains(c) } <= 1
|
tr.count { it.code in 0x3040..0x30FF } * 25 >= tr.length &&
|
||||||
|
latin * 3 <= tr.length
|
||||||
|
}
|
||||||
|
"zh" -> {
|
||||||
|
val latin = tr.count { it in 'a'..'z' || it in 'A'..'Z' }
|
||||||
|
tr.none { it.code in 0x3040..0x30FF } &&
|
||||||
|
tr.count { c -> tradOnlyChars.contains(c) } <= 1 &&
|
||||||
|
latin * 3 <= tr.length
|
||||||
|
}
|
||||||
else -> tr.none { it.code >= 0x2E80 }
|
else -> tr.none { it.code >= 0x2E80 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue