Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Done :D, you can now custom the prompt for concluding
  • Loading branch information
tuxKOH committed Jun 15, 2026
commit baadb3666bce4340727c573777023069f3be5d78
Original file line number Diff line number Diff line change
Expand Up @@ -2496,17 +2496,19 @@ class EnhancedAIService private constructor(private val context: Context) {
*/
suspend fun generateSummary(
messages: List<Pair<String, String>>,
previousSummary: String?
previousSummary: String?,
customRules: String? = null
): String {
return generateSummaryFromPromptTurns(messages.toPromptTurns(), previousSummary)
return generateSummaryFromPromptTurns(messages.toPromptTurns(), previousSummary, customRules)
}

suspend fun generateSummaryFromPromptTurns(
messages: List<PromptTurn>,
previousSummary: String?
previousSummary: String?,
customRules: String? = null
): String {
// 调用ConversationService中的方法
return conversationService.generateSummaryFromPromptTurns(messages, previousSummary, multiServiceManager)
return conversationService.generateSummaryFromPromptTurns(messages, previousSummary, multiServiceManager, customRules)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,17 @@ class ConversationService(
suspend fun generateSummaryFromPromptTurns(
messages: List<PromptTurn>,
previousSummary: String?,
multiServiceManager: MultiServiceManager
multiServiceManager: MultiServiceManager,
customRules: String? = null
): String {
try {
val useEnglish = LocaleUtils.getCurrentLanguage(context).lowercase().startsWith("en")
val activePromptMetadata = buildActivePromptHookMetadata(context)
var systemPrompt = FunctionalPrompts.buildSummarySystemPrompt(previousSummary, useEnglish)
// 注入自定义总结规则
if (!customRules.isNullOrBlank()) {
systemPrompt += "\n\n${customRules.trim()}"
}
val sanitizedMessages = ChatUtils.stripGeminiThoughtSignatureMetaTurns(messages)

// Get all model parameters from preferences (with enabled state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,8 @@ object AIMessageManager {
enhancedAiService: EnhancedAIService,
messages: List<ChatMessage>,
autoContinue: Boolean = false,
isGroupChat: Boolean = false
isGroupChat: Boolean = false,
summaryCustomRules: String? = null
): ChatMessage? {
val lastSummaryIndex = messages.indexOfLast { it.sender == "summary" }
val previousSummary = if (lastSummaryIndex != -1) messages[lastSummaryIndex].content.trim() else null
Expand Down Expand Up @@ -1011,7 +1012,7 @@ object AIMessageManager {

return try {
AppLogger.d(TAG, "开始使用AI生成对话总结:总结 ${messagesToSummarize.size} 条消息")
val summary = enhancedAiService.generateSummary(conversationToSummarize, previousSummary)
val summary = enhancedAiService.generateSummary(conversationToSummarize, previousSummary, summaryCustomRules)
AppLogger.d(TAG, "AI生成总结完成: ${summary.take(50)}...")

if (summary.isBlank()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ data class ModelConfigData(
ModelConfigDefaults.DEFAULT_ENABLE_SUMMARY_BY_MESSAGE_COUNT,
val summaryMessageCountThreshold: Int =
ModelConfigDefaults.DEFAULT_SUMMARY_MESSAGE_COUNT_THRESHOLD,
// 自定义总结规则
val summaryCustomRules: String = "",

// MNN特定配置
// 注意:MNN模型路径会根据modelName自动构建,不需要单独存储
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,14 +539,16 @@ class ModelConfigManager(private val context: Context) {
enableSummary: Boolean,
summaryTokenThreshold: Float,
enableSummaryByMessageCount: Boolean,
summaryMessageCountThreshold: Int
summaryMessageCountThreshold: Int,
summaryCustomRules: String = ""
): ModelConfigData {
return updateConfigInternal(configId) {
it.copy(
enableSummary = enableSummary,
summaryTokenThreshold = summaryTokenThreshold,
enableSummaryByMessageCount = enableSummaryByMessageCount,
summaryMessageCountThreshold = summaryMessageCountThreshold
summaryMessageCountThreshold = summaryMessageCountThreshold,
summaryCustomRules = summaryCustomRules
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import com.ai.assistance.operit.data.preferences.CharacterGroupCardManager
import com.ai.assistance.operit.data.preferences.ActivePromptManager
import com.ai.assistance.operit.data.preferences.DisplayPreferencesManager
import com.ai.assistance.operit.data.preferences.preferencesManager
import com.ai.assistance.operit.data.preferences.ModelConfigManager
import com.ai.assistance.operit.data.preferences.FunctionalConfigManager
import com.ai.assistance.operit.data.preferences.FunctionConfigMapping
import com.ai.assistance.operit.services.ChatServiceUiBridge
import com.ai.assistance.operit.util.ChatMarkupRegex
import com.ai.assistance.operit.util.ChatUtils
Expand Down Expand Up @@ -1703,11 +1706,13 @@ class MessageCoordinationDelegate(
val currentChat = chatHistoryDelegate.chatHistories.value.firstOrNull { it.id == originalChatId }
val isGroupChat = currentChat?.characterGroupId != null

val summaryCustomRules = readSummaryCustomRules()
val summaryMessage = AIMessageManager.summarizeMemory(
enhancedAiService = service,
messages = snapshotMessages,
autoContinue = false,
isGroupChat = isGroupChat
isGroupChat = isGroupChat,
summaryCustomRules = summaryCustomRules
) ?: return@launch

val currentChatId = chatHistoryDelegate.currentChatId.value
Expand Down Expand Up @@ -1827,8 +1832,9 @@ class MessageCoordinationDelegate(
summaryInsertReferenceMessages.getOrNull(insertPosition - 1)?.timestamp
val afterTimestamp =
summaryInsertReferenceMessages.getOrNull(insertPosition)?.timestamp
val summaryCustomRules = readSummaryCustomRules()
val summaryMessage =
AIMessageManager.summarizeMemory(service, currentMessages, autoContinue, effectiveIsGroupChat)
AIMessageManager.summarizeMemory(service, currentMessages, autoContinue, effectiveIsGroupChat, summaryCustomRules)

if (summaryMessage != null) {
chatHistoryDelegate.addSummaryMessage(
Expand Down Expand Up @@ -1936,4 +1942,25 @@ class MessageCoordinationDelegate(
fun setUiBridge(uiBridge: ChatServiceUiBridge) {
this.uiBridge = uiBridge
}

/** 从当前聊天绑定的模型配置中读取自定义总结规则 */
private suspend fun readSummaryCustomRules(): String? {
return try {
val functionalConfigManager = FunctionalConfigManager(context)
val modelConfigManager = ModelConfigManager(context)
functionalConfigManager.initializeIfNeeded()
modelConfigManager.initializeIfNeeded()
val functionMappings = functionalConfigManager.functionConfigMappingWithIndexFlow.first()
val chatMapping = functionMappings[FunctionType.CHAT] ?: FunctionConfigMapping()
if (chatMapping.configId.isNotBlank()) {
val config = modelConfigManager.getModelConfigFlow(chatMapping.configId).first()
config.summaryCustomRules.takeIf { it.isNotBlank() }
} else {
null
}
} catch (e: Exception) {
AppLogger.w(TAG, "读取自定义总结规则失败", e)
null
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,21 @@ import com.ai.assistance.operit.data.model.ChatMessage
import com.ai.assistance.operit.data.model.ActivePrompt

import com.ai.assistance.operit.data.preferences.UserPreferencesManager
import com.ai.assistance.operit.data.preferences.ModelConfigManager
import com.ai.assistance.operit.ui.features.chat.viewmodel.ChatViewModel
import com.ai.assistance.operit.ui.features.chat.viewmodel.ChatHistoryDisplayMode
import com.ai.assistance.operit.ui.features.chat.components.style.bubble.BubbleImageStyleConfig
import com.ai.assistance.operit.data.model.ModelConfigData
import com.ai.assistance.operit.data.preferences.FunctionalConfigManager
import com.ai.assistance.operit.ui.components.CustomScaffold
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.ui.platform.LocalFocusManager
import com.ai.assistance.operit.ui.features.chat.webview.workspace.WorkspaceBackupManager
import java.io.File
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.first
import androidx.compose.material.icons.filled.Cancel
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Close
Expand Down Expand Up @@ -747,6 +755,65 @@ fun ChatScreenContent(
)
}

// 插入总结自定义规则对话框
val insertSummaryDialogVisible by actualViewModel.showInsertSummaryDialog.collectAsState()
val pendingMessage by actualViewModel.pendingInsertSummaryMessage.collectAsState()
if (insertSummaryDialogVisible && pendingMessage != null) {
val context = LocalContext.current
val functionalConfigManager = remember { FunctionalConfigManager(context) }
val modelConfigManager = remember { ModelConfigManager(context) }
var savedCustomRules by remember { mutableStateOf("") }
var customRulesInput by remember { mutableStateOf("") }

LaunchedEffect(Unit) {
functionalConfigManager.initializeIfNeeded()
modelConfigManager.initializeIfNeeded()
val functionMappings = functionalConfigManager.functionConfigMappingWithIndexFlow.first()
val chatMapping = functionMappings[com.ai.assistance.operit.data.model.FunctionType.CHAT] ?: com.ai.assistance.operit.data.preferences.FunctionConfigMapping()
if (chatMapping.configId.isNotBlank()) {
modelConfigManager.getModelConfigFlow(chatMapping.configId).first().let { config ->
savedCustomRules = config.summaryCustomRules
customRulesInput = config.summaryCustomRules
}
}
}

AlertDialog(
onDismissRequest = { actualViewModel.cancelInsertSummary() },
title = { Text(stringResource(R.string.settings_summary_custom_rules)) },
text = {
Column {
Text(
text = stringResource(R.string.settings_summary_custom_rules_desc),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = customRulesInput,
onValueChange = { customRulesInput = it },
modifier = Modifier.fillMaxWidth().heightIn(min = 100.dp),
placeholder = { Text(stringResource(R.string.settings_summary_custom_rules_desc)) },
textStyle = MaterialTheme.typography.bodySmall,
keyboardOptions = KeyboardOptions.Default
)
}
},
confirmButton = {
TextButton(onClick = {
actualViewModel.confirmInsertSummary(customRulesInput)
}) {
Text(stringResource(android.R.string.ok))
}
},
dismissButton = {
TextButton(onClick = { actualViewModel.cancelInsertSummary() }) {
Text(stringResource(R.string.common_cancel))
}
}
)
}

if (showSharePreviewDialog) {
LaunchedEffect(
showSharePreviewDialog,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,12 @@ class ChatViewModel(private val context: Context) : ViewModel() {
val webViewRefreshCounter: StateFlow<Int> = _webViewRefreshCounter

// 控制 @ mention 建议面板的可见性
// 插入总结对话框状态
private val _showInsertSummaryDialog = MutableStateFlow(false)
val showInsertSummaryDialog: StateFlow<Boolean> = _showInsertSummaryDialog.asStateFlow()
private val _pendingInsertSummaryMessage = MutableStateFlow<ChatMessage?>(null)
val pendingInsertSummaryMessage: StateFlow<ChatMessage?> = _pendingInsertSummaryMessage.asStateFlow()

private val _showMentionSuggestionPanel = MutableStateFlow(false)
val showMentionSuggestionPanel: StateFlow<Boolean> = _showMentionSuggestionPanel.asStateFlow()

Expand Down Expand Up @@ -808,8 +814,27 @@ class ChatViewModel(private val context: Context) : ViewModel() {
uiStateDelegate.showToast(context.getString(R.string.chat_branch_created))
}

/** 插入总结 */
/** 弹出自定义总结规则对话框,确认后再执行插入总结 */
fun insertSummary(message: ChatMessage) {
_pendingInsertSummaryMessage.value = message
_showInsertSummaryDialog.value = true
}

/** 取消插入总结对话框 */
fun cancelInsertSummary() {
_showInsertSummaryDialog.value = false
_pendingInsertSummaryMessage.value = null
}

/** 确认插入总结(携带自定义规则) */
fun confirmInsertSummary(customRules: String?) {
val message = _pendingInsertSummaryMessage.value ?: return
_showInsertSummaryDialog.value = false
_pendingInsertSummaryMessage.value = null
performInsertSummary(message, customRules)
}

private fun performInsertSummary(message: ChatMessage, customRules: String?) {
viewModelScope.launch {
try {
// 获取当前会话ID并绑定
Expand Down Expand Up @@ -863,7 +888,8 @@ class ChatViewModel(private val context: Context) : ViewModel() {
enhancedAiService!!,
messagesToSummarize,
autoContinue = false,
isGroupChat = isGroupChat
isGroupChat = isGroupChat,
summaryCustomRules = customRules?.takeIf { it.isNotBlank() }
)

if (summaryMessage != null) {
Expand Down
Loading