fix: 翻译功能的一些小优化和修复 (#1225)

1. llm温度是可调的,对于ds而言,翻译1.3最佳,默认值调整成该值
2. 翻译字典,最多允许从50增加到80,取头尾各一半,因为小说出场最早和最近的人最重要

Co-authored-by: duanhl <duanhl7749@gmail.com>
This commit is contained in:
Duanhl
2026-05-30 03:50:34 +08:00
committed by GitHub
co-authored by duanhl
parent f8f19f7379
commit 978d6d2840
9 changed files with 49 additions and 6 deletions
@@ -331,6 +331,7 @@ object PreferKey {
const val llmMaxCharsPerChunk = "llmMaxCharsPerChunk"
const val llmConcurrentChunks = "llmConcurrentChunks"
const val llmRetryCount = "llmRetryCount"
const val llmTemperature = "llmTemperature"
const val llmPrompt = "llmPrompt"
const val homepageModuleOrder = "homepageModuleOrder"
@@ -31,6 +31,7 @@ class LlmTranslateRepositoryImpl : LlmGateway {
apiKey: String,
model: String,
prompt: String,
temperature: Float,
dictionaries: List<DictPair>,
onUpdate: ((List<DictPair>) -> Unit)?,
retryReason: RetryReason?
@@ -55,6 +56,7 @@ class LlmTranslateRepositoryImpl : LlmGateway {
apiKey,
model,
prompt,
temperature,
dictionaries,
onUpdate,
retryReason
@@ -131,6 +133,7 @@ class LlmTranslateRepositoryImpl : LlmGateway {
apiKey: String,
model: String,
prompt: String,
temperature: Float,
dictionaries: List<DictPair>,
onUpdate: ((List<DictPair>) -> Unit)?,
retryReason: RetryReason?
@@ -150,7 +153,10 @@ class LlmTranslateRepositoryImpl : LlmGateway {
mapOf("role" to "system", "content" to systemPrompt),
mapOf("role" to "user", "content" to "Translate the following text:\n\n$text")
),
"temperature" to 0.8
"temperature" to temperature.coerceIn(
TranslationConstants.MIN_TEMPERATURE,
TranslationConstants.MAX_TEMPERATURE
)
)
val jsonBody = GSON.toJson(requestBody)
val fullUrl = baseUrl.trimEnd('/') + "/v1/chat/completions"
@@ -2,6 +2,7 @@ package io.legado.app.domain.gateway
import io.legado.app.domain.model.DictPair
import io.legado.app.domain.model.RetryReason
import io.legado.app.domain.model.TranslationConstants
interface LlmGateway {
suspend fun translate(
@@ -12,6 +13,7 @@ interface LlmGateway {
apiKey: String,
model: String,
prompt: String,
temperature: Float = TranslationConstants.DEFAULT_TEMPERATURE,
dictionaries: List<DictPair> = emptyList(),
onUpdate: ((List<DictPair>) -> Unit)? = null,
retryReason: RetryReason? = null
@@ -4,6 +4,9 @@ object TranslationConstants {
const val PROVIDER_OPENAI = "openai"
const val PROVIDER_GOOGLE = "google"
const val MIN_TEMPERATURE = 0f
const val MAX_TEMPERATURE = 2f
const val DEFAULT_TEMPERATURE = 1.3f
val providerDisplayNames = listOf("Google Translate", "OpenAI适配接口")
val providerValues = listOf(PROVIDER_GOOGLE, PROVIDER_OPENAI)
@@ -34,7 +34,7 @@ class TranslateChapterUseCase(
)
companion object {
private const val MAX_DICTIONARY_PAIRS = 50
private const val MAX_DICTIONARY_PAIRS = 80
}
private val dictionaryLock = Any()
@@ -198,9 +198,11 @@ class TranslateChapterUseCase(
}
}
// Keep only the most recent MAX_DICTIONARY_PAIRS
// Keep early important names and the most recently discovered terms.
if (existing.size > MAX_DICTIONARY_PAIRS) {
val trimmed = existing.takeLast(MAX_DICTIONARY_PAIRS)
val headCount = MAX_DICTIONARY_PAIRS / 2
val tailCount = MAX_DICTIONARY_PAIRS - headCount
val trimmed = existing.take(headCount) + existing.takeLast(tailCount)
existing.clear()
existing.addAll(trimmed)
changed = true
@@ -261,6 +263,7 @@ class TranslateChapterUseCase(
apiKey = TranslationConfig.llmApiKey,
model = TranslationConfig.llmModel,
prompt = TranslationConfig.llmPrompt,
temperature = TranslationConfig.llmTemperature,
dictionaries = dictSnapshot,
onUpdate = onDictionaryUpdate,
retryReason = lastRetryReason
@@ -285,4 +288,4 @@ class TranslateChapterUseCase(
else -> null
}
}
}
}
@@ -51,6 +51,17 @@ object TranslationConfig {
2
)
private var storedLlmTemperature by prefDelegate(
PreferKey.llmTemperature,
TranslationConstants.DEFAULT_TEMPERATURE
)
var llmTemperature: Float
get() = storedLlmTemperature.coerceIn(MIN_TEMPERATURE, MAX_TEMPERATURE)
set(value) {
storedLlmTemperature = value.coerceIn(MIN_TEMPERATURE, MAX_TEMPERATURE)
}
var llmPrompt by prefDelegate(
PreferKey.llmPrompt,
TranslationConstants.DEFAULT_PROMPT
@@ -62,6 +73,9 @@ object TranslationConfig {
val providerDisplayNames get() = TranslationConstants.providerDisplayNames
val providerValues get() = TranslationConstants.providerValues
val targetLanguages get() = TranslationConstants.targetLanguages
const val MIN_TEMPERATURE = TranslationConstants.MIN_TEMPERATURE
const val MAX_TEMPERATURE = TranslationConstants.MAX_TEMPERATURE
const val DEFAULT_TEMPERATURE = TranslationConstants.DEFAULT_TEMPERATURE
const val DEFAULT_PROMPT = TranslationConstants.DEFAULT_PROMPT
const val OUTPUT_FORMAT = TranslationConstants.OUTPUT_FORMAT
}
@@ -109,6 +109,16 @@ fun TranslationConfigScreen(
onConfirm = { TranslationConfig.llmModel = it }
)
SliderSettingItem(
title = stringResource(R.string.llm_temperature),
value = TranslationConfig.llmTemperature,
defaultValue = TranslationConfig.DEFAULT_TEMPERATURE,
valueRange = TranslationConfig.MIN_TEMPERATURE..TranslationConfig.MAX_TEMPERATURE,
steps = 19,
description = stringResource(R.string.llm_temperature_description),
onValueChange = { TranslationConfig.llmTemperature = it }
)
InputSettingItem(
title = stringResource(R.string.llm_prompt),
value = tempPrompt,
@@ -122,4 +132,4 @@ fun TranslationConfigScreen(
}
}
}
}
}