mirror of
https://github.com/jie65535/JChatGPT.git
synced 2026-09-15 02:56:10 +08:00
profile: require pending messages for bulk runs
This commit is contained in:
@@ -90,20 +90,30 @@ object PluginCommands : CompositeCommand(
|
||||
suspend fun CommandSender.profileAnalyzeGroup(groupIds: String = "", batches: Int = 1) {
|
||||
require(batches > 0) { "batches 必须是正数" }
|
||||
val analyzeAllGroups = groupIds.isBlank()
|
||||
val minimumMessages = PluginConfig.profileBulkGroupMinPendingMessages.coerceAtLeast(1)
|
||||
val parsedGroupIds = if (analyzeAllGroups) {
|
||||
UserProfileAnalysisService.listPendingHistoryGroupIds()
|
||||
UserProfileAnalysisService.listPendingHistoryGroupIds(minimumMessages)
|
||||
} else {
|
||||
parseProfileGroupIds(groupIds)
|
||||
}
|
||||
if (parsedGroupIds.isEmpty()) {
|
||||
sendMessage("没有待推进的群画像:历史库中无有效群消息,或所有群均已追平当前快照。")
|
||||
sendMessage(
|
||||
if (analyzeAllGroups) {
|
||||
"没有达到启动条件的群画像:历史库中无有效群消息、群已追平," +
|
||||
"或尚未处理的消息少于 $minimumMessages 条。"
|
||||
} else {
|
||||
"没有可推进的指定群画像。"
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
val runToken = UserProfileAnalysisService.newRunToken()
|
||||
sendMessage(
|
||||
"已启动 ${parsedGroupIds.size} 个群的画像分析,每群最多推进 $batches 个批次。" +
|
||||
if (analyzeAllGroups) {
|
||||
" 画像请求并发上限 ${normalizeMaxConcurrentRequests(PluginConfig.profileMaxConcurrentRequests)}。"
|
||||
" 全量启动门槛 $minimumMessages 条待处理消息," +
|
||||
"画像请求并发上限 " +
|
||||
"${normalizeMaxConcurrentRequests(PluginConfig.profileMaxConcurrentRequests)}。"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
@@ -96,6 +96,9 @@ object PluginConfig : AutoSavePluginConfig("Config") {
|
||||
@ValueDescription("每个画像分析批次最多读取目标用户多少条消息")
|
||||
val profileBatchTargetMessages: Int by value(120)
|
||||
|
||||
@ValueDescription("全量推进群画像时,群内至少有多少条尚未处理的消息才启动;显式指定群号不受限制")
|
||||
val profileBulkGroupMinPendingMessages: Int by value(20)
|
||||
|
||||
@ValueDescription("每个画像分析批次最多包含多少个离散对话片段;同一秒的消息仍会一起处理")
|
||||
val profileBatchMaxEpisodes: Int by value(16)
|
||||
|
||||
|
||||
@@ -32,17 +32,21 @@ object UserProfileAnalysisService {
|
||||
return report
|
||||
}
|
||||
|
||||
suspend fun listPendingHistoryGroupIds(): List<Long> {
|
||||
suspend fun listPendingHistoryGroupIds(
|
||||
minimumMessages: Int = PluginConfig.profileBulkGroupMinPendingMessages,
|
||||
): List<Long> {
|
||||
check(PluginConfig.profileEnabled) { "历史用户画像分析未启用" }
|
||||
check(UserProfileStore.isAvailable) { "用户画像数据库不可用" }
|
||||
return withContext(Dispatchers.IO) {
|
||||
val historyBounds = ProfileHistoryReader(resolveHistoryFile()).listGroupTimeBounds()
|
||||
val reader = ProfileHistoryReader(resolveHistoryFile())
|
||||
val historyBounds = reader.listGroupTimeBounds()
|
||||
val cursors = UserProfileStore.loadGroupCursors()
|
||||
.associateBy { cursor -> cursor.botId to cursor.groupId }
|
||||
historyBounds.asSequence()
|
||||
.filter { bounds ->
|
||||
isGroupAnalysisPending(bounds, cursors[bounds.botId to bounds.groupId])
|
||||
}
|
||||
val pendingRanges = historyBounds.mapNotNull { bounds ->
|
||||
pendingGroupAnalysisRange(bounds, cursors[bounds.botId to bounds.groupId])
|
||||
}
|
||||
reader.filterGroupRangesByMinimumMessageCount(pendingRanges, minimumMessages)
|
||||
.asSequence()
|
||||
.map(ProfileHistoryReader.GroupTimeBounds::groupId)
|
||||
.toList()
|
||||
}
|
||||
@@ -758,4 +762,14 @@ object UserProfileAnalysisService {
|
||||
internal fun isGroupAnalysisPending(
|
||||
bounds: ProfileHistoryReader.GroupTimeBounds,
|
||||
cursor: GroupProfileCursor?,
|
||||
): Boolean = cursor == null || cursor.cursorTime < maxOf(cursor.snapshotEndTime, bounds.endTime)
|
||||
): Boolean = pendingGroupAnalysisRange(bounds, cursor) != null
|
||||
|
||||
internal fun pendingGroupAnalysisRange(
|
||||
bounds: ProfileHistoryReader.GroupTimeBounds,
|
||||
cursor: GroupProfileCursor?,
|
||||
): ProfileHistoryReader.GroupTimeBounds? {
|
||||
val startTime = cursor?.cursorTime ?: bounds.startTime
|
||||
val endTime = maxOf(cursor?.snapshotEndTime ?: bounds.endTime, bounds.endTime)
|
||||
return bounds.copy(startTime = startTime, endTime = endTime)
|
||||
.takeIf { startTime < endTime }
|
||||
}
|
||||
|
||||
@@ -47,6 +47,28 @@ class UserProfileAnalysisServiceTest {
|
||||
GroupProfileCursor(BOT, GROUP, cursorTime = 500, snapshotEndTime = 500),
|
||||
)
|
||||
)
|
||||
|
||||
assertEquals(bounds, pendingGroupAnalysisRange(bounds, null))
|
||||
assertEquals(
|
||||
bounds.copy(startTime = 300),
|
||||
pendingGroupAnalysisRange(
|
||||
bounds,
|
||||
GroupProfileCursor(BOT, GROUP, cursorTime = 300, snapshotEndTime = 500),
|
||||
)
|
||||
)
|
||||
assertEquals(
|
||||
bounds.copy(startTime = 400, endTime = 600),
|
||||
pendingGroupAnalysisRange(
|
||||
bounds,
|
||||
GroupProfileCursor(BOT, GROUP, cursorTime = 400, snapshotEndTime = 600),
|
||||
)
|
||||
)
|
||||
assertNull(
|
||||
pendingGroupAnalysisRange(
|
||||
bounds,
|
||||
GroupProfileCursor(BOT, GROUP, cursorTime = 500, snapshotEndTime = 500),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user