mirror of
https://github.com/jie65535/JChatGPT.git
synced 2026-09-15 02:56:10 +08:00
profile: add progressive user profiles
Add cache-expiry profile maintenance and contextual injection, reorganize runtime code by responsibility, remove automatic favorability decay, and prepare version 1.15.0.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
package top.jie65535.mirai.profile
|
||||
|
||||
import net.mamoe.mirai.message.data.MessageSourceKind
|
||||
import java.nio.file.Files
|
||||
import java.sql.DriverManager
|
||||
import kotlin.io.path.absolutePathString
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ProfileHistoryReaderTest {
|
||||
@Test
|
||||
fun keepsEqualTimestampTargetMessagesTogetherAndLoadsGroupContext() {
|
||||
val directory = Files.createTempDirectory("jchatgpt-profile-history-test-")
|
||||
val database = directory.resolve("history.sqlite")
|
||||
try {
|
||||
DriverManager.getConnection("jdbc:sqlite:${database.absolutePathString()}").use { connection ->
|
||||
connection.createStatement().use { statement ->
|
||||
statement.executeUpdate(
|
||||
"""
|
||||
CREATE TABLE message_record(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
bot_id INTEGER NOT NULL,
|
||||
from_id INTEGER NOT NULL,
|
||||
target_id INTEGER NOT NULL,
|
||||
ids TEXT,
|
||||
internal_ids TEXT,
|
||||
time INTEGER NOT NULL,
|
||||
kind INTEGER NOT NULL,
|
||||
code TEXT NOT NULL,
|
||||
recalled INTEGER NOT NULL DEFAULT 0
|
||||
)
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
connection.prepareStatement(
|
||||
"INSERT INTO message_record(" +
|
||||
"bot_id, from_id, target_id, time, kind, code, recalled" +
|
||||
") VALUES (1, ?, ?, ?, ?, ?, 0)"
|
||||
).use { statement ->
|
||||
fun insert(fromId: Long, groupId: Long, time: Int, text: String) {
|
||||
statement.setLong(1, fromId)
|
||||
statement.setLong(2, groupId)
|
||||
statement.setInt(3, time)
|
||||
statement.setInt(4, MessageSourceKind.GROUP.ordinal)
|
||||
statement.setString(5, """[{"type":"PlainText","content":"$text"}]""")
|
||||
statement.executeUpdate()
|
||||
}
|
||||
insert(TARGET, 10, 100, "目标发言一")
|
||||
insert(OTHER, 10, 110, "用于理解语境的回复")
|
||||
insert(TARGET, 10, 130, "目标发言二")
|
||||
insert(TARGET, 20, 130, "同一秒的另一群发言")
|
||||
insert(OTHER, 20, 140, "后续上下文")
|
||||
insert(TARGET, 10, 200, "下一批目标发言")
|
||||
}
|
||||
}
|
||||
|
||||
val reader = ProfileHistoryReader(database.toFile())
|
||||
val bounds = assertNotNull(reader.findUserTimeBounds(TARGET))
|
||||
assertEquals(100, bounds.startTime)
|
||||
assertEquals(201, bounds.endTime)
|
||||
|
||||
val first = assertNotNull(
|
||||
reader.loadNextBatch(
|
||||
userId = TARGET,
|
||||
startTime = bounds.startTime,
|
||||
snapshotEndTime = bounds.endTime,
|
||||
targetMessageLimit = 2,
|
||||
maxEpisodes = 1,
|
||||
episodeGapSeconds = 60,
|
||||
contextBeforeMessages = 2,
|
||||
contextAfterMessages = 2,
|
||||
contextCoreMessages = 20,
|
||||
maxMessageChars = 200,
|
||||
)
|
||||
)
|
||||
assertEquals(131, first.endTime)
|
||||
assertEquals(3, first.evidenceByRef.values.count { it.record.fromId == TARGET })
|
||||
assertTrue(first.messages.any { it.record.fromId == OTHER })
|
||||
assertEquals("TARGET", first.aliases[TARGET])
|
||||
|
||||
val second = assertNotNull(
|
||||
reader.loadNextBatch(
|
||||
userId = TARGET,
|
||||
startTime = first.endTime,
|
||||
snapshotEndTime = bounds.endTime,
|
||||
targetMessageLimit = 2,
|
||||
maxEpisodes = 10,
|
||||
episodeGapSeconds = 60,
|
||||
contextBeforeMessages = 2,
|
||||
contextAfterMessages = 2,
|
||||
contextCoreMessages = 20,
|
||||
maxMessageChars = 200,
|
||||
)
|
||||
)
|
||||
assertEquals(201, second.endTime)
|
||||
assertEquals(1, second.evidenceByRef.values.count { it.record.fromId == TARGET })
|
||||
|
||||
val conversation = assertNotNull(
|
||||
reader.loadConversationBatch(
|
||||
botId = 1,
|
||||
groupId = 10,
|
||||
startTime = 90,
|
||||
endTime = 150,
|
||||
messageLimit = 10,
|
||||
maxMessageChars = 200,
|
||||
)
|
||||
)
|
||||
assertTrue(conversation.authoredTextCharsByUser.getValue(TARGET) > 0)
|
||||
assertTrue(conversation.messages.all { it.record.targetId == 10L })
|
||||
assertTrue(conversation.messages.all { it.record.time in 90 until 150 })
|
||||
} finally {
|
||||
directory.toFile().deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TARGET = 100L
|
||||
private const val OTHER = 200L
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user