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 5438739..639a1b7 100644 --- a/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt +++ b/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt @@ -2141,11 +2141,37 @@ class MainActivity : AppCompatActivity() { } catch (t: Throwable) { Log.w(TAG, "TRANSLATE batch failed: " + t.message); null } - val byIdx = extractNumberedPairs(out) ?: return null + val byIdx = extractNumberedPairs(out) segKeys.forEachIndexed { i, st -> - byIdx[(i + 1).toString()]?.takeIf { it.isNotBlank() } + byIdx?.get((i + 1).toString())?.takeIf { it.isNotBlank() } ?.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 } val res = HashMap() @@ -2154,10 +2180,14 @@ class MainActivity : AppCompatActivity() { if (n == null) got[key]?.let { res[key] = it } else { val sb = StringBuilder() + var full = true 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 @@ -2214,9 +2244,17 @@ class MainActivity : AppCompatActivity() { private fun targetLangOk(tr: String): Boolean { if (tr.length < 12) return true return when (uiLanguage()) { - "ja" -> tr.count { it.code in 0x3040..0x30FF } * 25 >= tr.length - "zh" -> tr.none { it.code in 0x3040..0x30FF } && - tr.count { c -> tradOnlyChars.contains(c) } <= 1 + "ja" -> { + val latin = tr.count { it in 'a'..'z' || it in 'A'..'Z' } + 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 } } }