mirror of
https://github.com/jie65535/JChatGPT.git
synced 2025-12-08 18:31:36 +08:00
Compare commits
3 Commits
099625c2f2
...
0f482407d4
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f482407d4 | |||
| 8ac0197fc4 | |||
| 68a45a9657 |
34
README.md
34
README.md
@@ -7,6 +7,7 @@ JChatGPT 是一个基于 Kotlin 的 Mirai Console 插件,它将大型语言模
|
|||||||
- **多模型支持**:支持聊天模型、推理模型和视觉模型
|
- **多模型支持**:支持聊天模型、推理模型和视觉模型
|
||||||
- **丰富的工具系统**:包括网络搜索、代码执行、图像识别、群管理等
|
- **丰富的工具系统**:包括网络搜索、代码执行、图像识别、群管理等
|
||||||
- **上下文记忆**:支持持久化记忆存储
|
- **上下文记忆**:支持持久化记忆存储
|
||||||
|
- **好感度系统**:基于用户行为的好感度管理机制
|
||||||
- **LaTeX 渲染**:自动将数学表达式渲染为图片
|
- **LaTeX 渲染**:自动将数学表达式渲染为图片
|
||||||
- **灵活的触发方式**:@机器人、关键字触发、回复消息等
|
- **灵活的触发方式**:@机器人、关键字触发、回复消息等
|
||||||
- **权限控制**:细粒度的权限管理系统
|
- **权限控制**:细粒度的权限管理系统
|
||||||
@@ -40,6 +41,8 @@ AI 可以自动调用多种工具来完成复杂任务:
|
|||||||
- `/jgpt enable <contact>` - 启用目标对话权限
|
- `/jgpt enable <contact>` - 启用目标对话权限
|
||||||
- `/jgpt disable <contact>` - 禁用目标对话权限
|
- `/jgpt disable <contact>` - 禁用目标对话权限
|
||||||
- `/jgpt reload` - 重载配置文件
|
- `/jgpt reload` - 重载配置文件
|
||||||
|
- `/jgpt favorability <userId> <value>` - 设置指定用户的好感度值(-100~100)
|
||||||
|
- `/jgpt resetFavorability` - 重置所有用户的好感度
|
||||||
|
|
||||||
## 配置文件
|
## 配置文件
|
||||||
|
|
||||||
@@ -108,6 +111,10 @@ callKeyword: '[小筱][林淋月玥]'
|
|||||||
showToolCallingMessage: true
|
showToolCallingMessage: true
|
||||||
# 是否启用记忆编辑功能,记忆存在data目录,提示词中需要加上{memory}来填充记忆,每个群都有独立记忆
|
# 是否启用记忆编辑功能,记忆存在data目录,提示词中需要加上{memory}来填充记忆,每个群都有独立记忆
|
||||||
memoryEnabled: true
|
memoryEnabled: true
|
||||||
|
# 是否启用好感度系统
|
||||||
|
enableFavorabilitySystem: true
|
||||||
|
# 好感度每日基础偏移速度(点/天)
|
||||||
|
favorabilityBaseShiftSpeed: 2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## 系统提示词
|
## 系统提示词
|
||||||
@@ -250,6 +257,33 @@ JChatGPT 默认配置为使用阿里云百炼平台的通义千问系列模型
|
|||||||
9. **ImageEdit** - 图像编辑
|
9. **ImageEdit** - 图像编辑
|
||||||
10. **WeatherService** - 天气查询
|
10. **WeatherService** - 天气查询
|
||||||
|
|
||||||
|
## 好感度系统
|
||||||
|
|
||||||
|
JChatGPT 插件包含一个可选的好感度系统,用于根据用户行为调整机器人对用户的好感度。该系统有以下特性:
|
||||||
|
|
||||||
|
### 核心机制
|
||||||
|
- 好感度值范围:-100(完全不理会)到 100(非常好的朋友)
|
||||||
|
- 负好感度用户有一定概率不会收到回复,概率为好感度绝对值的百分比
|
||||||
|
- 好感度会随时间向0偏移,偏移速度与当前好感度绝对值相关
|
||||||
|
|
||||||
|
### 好感度调整规则
|
||||||
|
- 问正经问题:+好感度
|
||||||
|
- 问无聊问题:-好感度
|
||||||
|
- 骂人:直接降至-100
|
||||||
|
|
||||||
|
### 时间偏移机制
|
||||||
|
好感度会随时间自然向0回归:
|
||||||
|
- 偏移公式:偏移量 = sign(好感度) * (1 - (|好感度| / 100)^2) * 基础偏移速度
|
||||||
|
- 极端值变化缓慢,-100可能需要好几天才消气,100可能好多天都不会降低
|
||||||
|
|
||||||
|
### 管理命令
|
||||||
|
- `/jgpt favorability <userId> <value>` - 设置指定用户的好感度值(-100~100)
|
||||||
|
- `/jgpt resetFavorability` - 重置所有用户的好感度
|
||||||
|
|
||||||
|
### 配置选项
|
||||||
|
- `enableFavorabilitySystem` - 是否启用好感度系统(默认:true)
|
||||||
|
- `favorabilityBaseShiftSpeed` - 好感度每日基础偏移速度(点/天,默认:2.0)
|
||||||
|
|
||||||
## 部署要求
|
## 部署要求
|
||||||
|
|
||||||
- Java 11 或更高版本
|
- Java 11 或更高版本
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "top.jie65535.mirai"
|
group = "top.jie65535.mirai"
|
||||||
version = "1.8.0"
|
version = "1.9.0"
|
||||||
|
|
||||||
mirai {
|
mirai {
|
||||||
jvmTarget = JavaVersion.VERSION_11
|
jvmTarget = JavaVersion.VERSION_11
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import net.mamoe.mirai.event.events.GroupMessageEvent
|
|||||||
import net.mamoe.mirai.event.events.MessageEvent
|
import net.mamoe.mirai.event.events.MessageEvent
|
||||||
import net.mamoe.mirai.message.data.*
|
import net.mamoe.mirai.message.data.*
|
||||||
import net.mamoe.mirai.message.data.Image.Key.queryUrl
|
import net.mamoe.mirai.message.data.Image.Key.queryUrl
|
||||||
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
|
||||||
import net.mamoe.mirai.utils.info
|
import net.mamoe.mirai.utils.info
|
||||||
import top.jie65535.mirai.tools.*
|
import top.jie65535.mirai.tools.*
|
||||||
import xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder
|
import xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder
|
||||||
@@ -40,13 +39,16 @@ import java.time.ZoneOffset
|
|||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import kotlin.collections.*
|
import kotlin.collections.*
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
import kotlin.math.pow
|
||||||
|
import kotlin.math.sign
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
import kotlin.time.Duration.Companion.hours
|
||||||
|
|
||||||
object JChatGPT : KotlinPlugin(
|
object JChatGPT : KotlinPlugin(
|
||||||
JvmPluginDescription(
|
JvmPluginDescription(
|
||||||
id = "top.jie65535.mirai.JChatGPT",
|
id = "top.jie65535.mirai.JChatGPT",
|
||||||
name = "J ChatGPT",
|
name = "J ChatGPT",
|
||||||
version = "1.8.0",
|
version = "1.9.0",
|
||||||
) {
|
) {
|
||||||
author("jie65535")
|
author("jie65535")
|
||||||
// dependsOn("xyz.cssxsh.mirai.plugin.mirai-hibernate-plugin", true)
|
// dependsOn("xyz.cssxsh.mirai.plugin.mirai-hibernate-plugin", true)
|
||||||
@@ -94,6 +96,16 @@ object JChatGPT : KotlinPlugin(
|
|||||||
GlobalEventChannel.parentScope(this)
|
GlobalEventChannel.parentScope(this)
|
||||||
.subscribeAlways<MessageEvent> { event -> onMessage(event) }
|
.subscribeAlways<MessageEvent> { event -> onMessage(event) }
|
||||||
|
|
||||||
|
// 启动定时任务处理好感度时间偏移
|
||||||
|
if (PluginConfig.enableFavorabilitySystem) {
|
||||||
|
launch {
|
||||||
|
while (true) {
|
||||||
|
delay(24.hours) // 每24小时执行一次
|
||||||
|
shiftFavorabilityOverTime()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.info { "Plugin loaded" }
|
logger.info { "Plugin loaded" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +144,24 @@ object JChatGPT : KotlinPlugin(
|
|||||||
&& event.message[QuoteReply]?.source?.fromId != event.bot.id)
|
&& event.message[QuoteReply]?.source?.fromId != event.bot.id)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
// 好感度系统检查
|
||||||
|
if (PluginConfig.enableFavorabilitySystem) {
|
||||||
|
val userId = event.sender.id
|
||||||
|
PluginData.userFavorability[userId]?.let { favorabilityInfo ->
|
||||||
|
val favorability = favorabilityInfo.value
|
||||||
|
if (favorability < 0) {
|
||||||
|
// 负好感度有一定概率不回复
|
||||||
|
val probability = kotlin.math.abs(favorability).toDouble() / 100.0
|
||||||
|
if (kotlin.random.Random.nextDouble() < probability) {
|
||||||
|
// 不回复此消息
|
||||||
|
logger.info("根据好感度系统,用户 ${event.senderName}($userId) (好感度: $favorability) 的消息被忽略,忽略概率: ${probability * 100}%")
|
||||||
|
event.subject.sendMessage("[实验功能] 因好感度低,此消息已被忽略(${probability * 100}%)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
startChat(event)
|
startChat(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,12 +242,38 @@ object JChatGPT : KotlinPlugin(
|
|||||||
val historyText = StringBuilder()
|
val historyText = StringBuilder()
|
||||||
var lastId = 0L
|
var lastId = 0L
|
||||||
if (event is GroupMessageEvent) {
|
if (event is GroupMessageEvent) {
|
||||||
|
if (PluginConfig.enableFavorabilitySystem) {
|
||||||
|
val favorabilityInfos = history.map { it.fromId }
|
||||||
|
.filter { it != event.bot.id }
|
||||||
|
.distinct()
|
||||||
|
.mapNotNull { PluginData.userFavorability[it] }
|
||||||
|
if (favorabilityInfos.isNotEmpty()) {
|
||||||
|
historyText.appendLine("## 相关成员的好感信息")
|
||||||
|
for (info in favorabilityInfos) {
|
||||||
|
historyText.append(getNameCard(event.group, info.userId)).append('\t')
|
||||||
|
.appendLine(info).appendLine()
|
||||||
|
}
|
||||||
|
historyText.appendLine("---").appendLine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
historyText.appendLine("## 近期群消息(更早已隐藏)")
|
||||||
for (record in history) {
|
for (record in history) {
|
||||||
// 同一人发言不要反复出现这人的名字,减少上下文
|
// 同一人发言不要反复出现这人的名字,减少上下文
|
||||||
appendGroupMessageRecord(historyText, record, event, lastId != record.fromId)
|
appendGroupMessageRecord(historyText, record, event, lastId != record.fromId)
|
||||||
lastId = record.fromId
|
lastId = record.fromId
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (PluginConfig.enableFavorabilitySystem) {
|
||||||
|
val favorabilityInfo = PluginData.userFavorability[event.sender.id]
|
||||||
|
if (favorabilityInfo != null) {
|
||||||
|
historyText.append("你对\"").append(event.senderName).append("\"的好感信息如下: ")
|
||||||
|
.appendLine(favorabilityInfo).appendLine()
|
||||||
|
historyText.appendLine("---").appendLine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
historyText.appendLine("## 近期对话(更早已隐藏)")
|
||||||
for (record in history) {
|
for (record in history) {
|
||||||
// 同一人发言不要反复出现这人的名字,减少上下文
|
// 同一人发言不要反复出现这人的名字,减少上下文
|
||||||
appendMessageRecord(historyText, record, event, lastId != record.fromId)
|
appendMessageRecord(historyText, record, event, lastId != record.fromId)
|
||||||
@@ -241,6 +297,9 @@ object JChatGPT : KotlinPlugin(
|
|||||||
showSender: Boolean,
|
showSender: Boolean,
|
||||||
) {
|
) {
|
||||||
if (showSender) {
|
if (showSender) {
|
||||||
|
// 名字前空行
|
||||||
|
historyText.appendLine()
|
||||||
|
// 名称显示
|
||||||
if (event.bot.id == record.fromId) {
|
if (event.bot.id == record.fromId) {
|
||||||
historyText.append("**你** " + getNameCard(event.subject.botAsMember))
|
historyText.append("**你** " + getNameCard(event.subject.botAsMember))
|
||||||
} else {
|
} else {
|
||||||
@@ -476,14 +535,15 @@ object JChatGPT : KotlinPlugin(
|
|||||||
if (!done) {
|
if (!done) {
|
||||||
history.add(ChatMessage.User(
|
history.add(ChatMessage.User(
|
||||||
buildString {
|
buildString {
|
||||||
appendLine("系统提示:本次运行最多还剩${retry-1}轮。")
|
appendLine("## 系统提示")
|
||||||
|
append("本次运行最多还剩").append(retry-1).appendLine("轮。")
|
||||||
appendLine("如果要多次发言,可以一次性调用多次发言工具。")
|
appendLine("如果要多次发言,可以一次性调用多次发言工具。")
|
||||||
appendLine("如果没有什么要做的,可以提前结束。")
|
appendLine("如果没有什么要做的,可以提前结束。")
|
||||||
appendLine("当前时间:" + dateTimeFormatter.format(OffsetDateTime.now()))
|
appendLine("当前时间:" + dateTimeFormatter.format(OffsetDateTime.now()))
|
||||||
|
|
||||||
val newMessages = getAfterHistory(startedAt, event)
|
val newMessages = getAfterHistory(startedAt, event)
|
||||||
if (newMessages.isNotEmpty()) {
|
if (newMessages.isNotEmpty()) {
|
||||||
append("以下是上次运行至今的新消息\n\n$newMessages")
|
append("## 以下是上次运行至今的新消息\n\n$newMessages")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
@@ -494,7 +554,7 @@ object JChatGPT : KotlinPlugin(
|
|||||||
} else {
|
} else {
|
||||||
done = false
|
done = false
|
||||||
logger.warning("调用llm时发生异常,重试中", e)
|
logger.warning("调用llm时发生异常,重试中", e)
|
||||||
event.subject.sendMessage("出错了...正在重试...")
|
// event.subject.sendMessage("出错了...正在重试...")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (!done && 0 < --retry)
|
} while (!done && 0 < --retry)
|
||||||
@@ -611,6 +671,9 @@ object JChatGPT : KotlinPlugin(
|
|||||||
// 天气服务
|
// 天气服务
|
||||||
WeatherService(),
|
WeatherService(),
|
||||||
|
|
||||||
|
// 好感度调整
|
||||||
|
AdjustUserFavorabilityAgent(),
|
||||||
|
|
||||||
// Epic 免费游戏
|
// Epic 免费游戏
|
||||||
// EpicFreeGame(),
|
// EpicFreeGame(),
|
||||||
|
|
||||||
@@ -678,7 +741,7 @@ object JChatGPT : KotlinPlugin(
|
|||||||
logger.warning("获取群头衔失败", e)
|
logger.warning("获取群头衔失败", e)
|
||||||
}
|
}
|
||||||
// 群名片
|
// 群名片
|
||||||
nameCard.append("】 ").append(member.nameCardOrNick).append("(").append(member.id).append(")")
|
nameCard.append("】\t\"").append(member.nameCardOrNick).append("\"\t(qq=").append(member.id).append(")")
|
||||||
return nameCard.toString()
|
return nameCard.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,4 +782,41 @@ object JChatGPT : KotlinPlugin(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 好感度时间偏移处理函数
|
||||||
|
* 使好感度逐渐向0回归,偏移速度与当前好感度绝对值相关
|
||||||
|
*/
|
||||||
|
private fun shiftFavorabilityOverTime() {
|
||||||
|
logger.info("开始执行好感度时间偏移处理")
|
||||||
|
|
||||||
|
val iterator = PluginData.userFavorability.iterator()
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val entry = iterator.next()
|
||||||
|
val userId = entry.key
|
||||||
|
val favorabilityInfo = entry.value
|
||||||
|
val currentFavorability = favorabilityInfo.value
|
||||||
|
|
||||||
|
// 计算偏移量
|
||||||
|
// 偏移公式:偏移量 = sign(好感度) * (1 - (|好感度| / 100)^2) * 基础偏移速度
|
||||||
|
val sign = sign(currentFavorability.toFloat()).toInt()
|
||||||
|
val absFavorability = kotlin.math.abs(currentFavorability)
|
||||||
|
val shiftAmount = sign * (1 - (absFavorability / 100.0).pow(2)) * PluginConfig.favorabilityBaseShiftSpeed
|
||||||
|
|
||||||
|
// 更新好感度
|
||||||
|
val newFavorability = (currentFavorability - shiftAmount).toInt().coerceIn(-100, 100)
|
||||||
|
|
||||||
|
// 如果新的好感度为0,则移除该条目以节省空间
|
||||||
|
if (newFavorability == 0) {
|
||||||
|
iterator.remove()
|
||||||
|
logger.info("用户 $userId 的好感度已回归0,移除记录")
|
||||||
|
} else {
|
||||||
|
// 创建新的好感度信息,保持原因和印象不变
|
||||||
|
val newInfo = favorabilityInfo.copy(value = newFavorability)
|
||||||
|
PluginData.userFavorability[userId] = newInfo
|
||||||
|
logger.info("用户 $userId 的好感度 ($currentFavorability -> $newFavorability)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("好感度时间偏移处理完成")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package top.jie65535.mirai
|
|||||||
|
|
||||||
import net.mamoe.mirai.console.command.CommandSender
|
import net.mamoe.mirai.console.command.CommandSender
|
||||||
import net.mamoe.mirai.console.command.CompositeCommand
|
import net.mamoe.mirai.console.command.CompositeCommand
|
||||||
|
import net.mamoe.mirai.console.permission.PermissionService.Companion.cancel
|
||||||
import net.mamoe.mirai.console.permission.PermissionService.Companion.permit
|
import net.mamoe.mirai.console.permission.PermissionService.Companion.permit
|
||||||
import net.mamoe.mirai.console.permission.PermitteeId.Companion.permitteeId
|
import net.mamoe.mirai.console.permission.PermitteeId.Companion.permitteeId
|
||||||
import net.mamoe.mirai.contact.Contact
|
import net.mamoe.mirai.contact.Contact
|
||||||
@@ -9,15 +10,15 @@ import net.mamoe.mirai.contact.Group
|
|||||||
import net.mamoe.mirai.contact.Member
|
import net.mamoe.mirai.contact.Member
|
||||||
import net.mamoe.mirai.contact.User
|
import net.mamoe.mirai.contact.User
|
||||||
import top.jie65535.mirai.JChatGPT.reload
|
import top.jie65535.mirai.JChatGPT.reload
|
||||||
import top.jie65535.mirai.JChatGPT.save
|
|
||||||
|
|
||||||
object PluginCommands : CompositeCommand(
|
object PluginCommands : CompositeCommand(
|
||||||
JChatGPT, "jgpt", description = "J OpenAI ChatGPT"
|
JChatGPT, "jgpt", description = "J OpenAI ChatGPT"
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@SubCommand
|
@SubCommand
|
||||||
suspend fun CommandSender.setToken(token: String) {
|
suspend fun CommandSender.reload() {
|
||||||
PluginConfig.openAiToken = token
|
PluginConfig.reload()
|
||||||
PluginConfig.save()
|
PluginData.reload()
|
||||||
LargeLanguageModels.reload()
|
LargeLanguageModels.reload()
|
||||||
sendMessage("OK")
|
sendMessage("OK")
|
||||||
}
|
}
|
||||||
@@ -35,18 +36,34 @@ object PluginCommands : CompositeCommand(
|
|||||||
@SubCommand
|
@SubCommand
|
||||||
suspend fun CommandSender.disable(contact: Contact) {
|
suspend fun CommandSender.disable(contact: Contact) {
|
||||||
when (contact) {
|
when (contact) {
|
||||||
is Member -> contact.permitteeId.permit(JChatGPT.chatPermission)
|
is Member -> contact.permitteeId.cancel(JChatGPT.chatPermission, false)
|
||||||
is User -> contact.permitteeId.permit(JChatGPT.chatPermission)
|
is User -> contact.permitteeId.cancel(JChatGPT.chatPermission, false)
|
||||||
is Group -> contact.permitteeId.permit(JChatGPT.chatPermission)
|
is Group -> contact.permitteeId.cancel(JChatGPT.chatPermission, false)
|
||||||
}
|
}
|
||||||
sendMessage("OK")
|
sendMessage("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubCommand
|
@SubCommand
|
||||||
suspend fun CommandSender.reload() {
|
suspend fun CommandSender.clearMemory() {
|
||||||
PluginConfig.reload()
|
PluginData.contactMemory.clear()
|
||||||
PluginData.reload()
|
sendMessage("OK")
|
||||||
LargeLanguageModels.reload()
|
}
|
||||||
|
|
||||||
|
@SubCommand
|
||||||
|
suspend fun CommandSender.setFavor(user: User, value: Int) {
|
||||||
|
// 限制好感度值在-100到100之间
|
||||||
|
val clampedValue = value.coerceIn(-100, 100)
|
||||||
|
// 获取当前的好感度信息
|
||||||
|
val currentInfo = PluginData.userFavorability[user.id] ?: FavorabilityInfo(user.id)
|
||||||
|
// 创建新的好感度信息,保持原因和印象不变
|
||||||
|
val newInfo = currentInfo.copy(value = clampedValue)
|
||||||
|
PluginData.userFavorability[user.id] = newInfo
|
||||||
|
sendMessage("OK")
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubCommand
|
||||||
|
suspend fun CommandSender.clearFavor() {
|
||||||
|
PluginData.userFavorability.clear()
|
||||||
sendMessage("OK")
|
sendMessage("OK")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,4 +98,10 @@ object PluginConfig : AutoSavePluginConfig("Config") {
|
|||||||
|
|
||||||
@ValueDescription("是否启用记忆编辑功能,记忆存在data目录,提示词中需要加上{memory}来填充记忆,每个群都有独立记忆")
|
@ValueDescription("是否启用记忆编辑功能,记忆存在data目录,提示词中需要加上{memory}来填充记忆,每个群都有独立记忆")
|
||||||
val memoryEnabled by value(true)
|
val memoryEnabled by value(true)
|
||||||
|
|
||||||
|
@ValueDescription("是否启用好感度系统")
|
||||||
|
val enableFavorabilitySystem by value(true)
|
||||||
|
|
||||||
|
@ValueDescription("好感度每日基础偏移速度(点/天)")
|
||||||
|
val favorabilityBaseShiftSpeed by value(2.0)
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,52 @@
|
|||||||
package top.jie65535.mirai
|
package top.jie65535.mirai
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import net.mamoe.mirai.console.data.AutoSavePluginData
|
import net.mamoe.mirai.console.data.AutoSavePluginData
|
||||||
import net.mamoe.mirai.console.data.value
|
import net.mamoe.mirai.console.data.value
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 好感度信息数据类
|
||||||
|
* @param userId QQ
|
||||||
|
* @param value 好感度值 (-100 ~ 100)
|
||||||
|
* @param reasons 调整原因列表,用于溯源
|
||||||
|
* @param impression 对用户的印象/画像
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class FavorabilityInfo(
|
||||||
|
val userId: Long,
|
||||||
|
val value: Int = 0,
|
||||||
|
val reasons: List<String> = emptyList(),
|
||||||
|
val impression: String = ""
|
||||||
|
) {
|
||||||
|
override fun toString(): String {
|
||||||
|
return buildString {
|
||||||
|
append("好感度:$value")
|
||||||
|
if (impression.isNotEmpty()) {
|
||||||
|
append("\t印象:$impression")
|
||||||
|
}
|
||||||
|
if (reasons.isNotEmpty()) {
|
||||||
|
appendLine("\t调整原因:")
|
||||||
|
reasons.forEach { reason ->
|
||||||
|
appendLine("* $reason")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object PluginData : AutoSavePluginData("data") {
|
object PluginData : AutoSavePluginData("data") {
|
||||||
/**
|
/**
|
||||||
* 联系人记忆
|
* 联系人记忆
|
||||||
*/
|
*/
|
||||||
val contactMemory by value(mutableMapOf<Long, String>())
|
val contactMemory by value(mutableMapOf<Long, String>())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户好感度数据
|
||||||
|
* Key: 用户QQ号
|
||||||
|
* Value: 好感度信息
|
||||||
|
*/
|
||||||
|
val userFavorability by value(mutableMapOf<Long, FavorabilityInfo>())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加对话记忆
|
* 添加对话记忆
|
||||||
*/
|
*/
|
||||||
|
|||||||
103
src/main/kotlin/tools/AdjustUserFavorabilityAgent.kt
Normal file
103
src/main/kotlin/tools/AdjustUserFavorabilityAgent.kt
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package top.jie65535.mirai.tools
|
||||||
|
|
||||||
|
import com.aallam.openai.api.chat.Tool
|
||||||
|
import com.aallam.openai.api.core.Parameters
|
||||||
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
import kotlinx.serialization.json.add
|
||||||
|
import kotlinx.serialization.json.buildJsonObject
|
||||||
|
import kotlinx.serialization.json.contentOrNull
|
||||||
|
import kotlinx.serialization.json.intOrNull
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
import kotlinx.serialization.json.longOrNull
|
||||||
|
import kotlinx.serialization.json.put
|
||||||
|
import kotlinx.serialization.json.putJsonArray
|
||||||
|
import net.mamoe.mirai.event.events.MessageEvent
|
||||||
|
import top.jie65535.mirai.JChatGPT
|
||||||
|
import top.jie65535.mirai.PluginData
|
||||||
|
import top.jie65535.mirai.FavorabilityInfo
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
class AdjustUserFavorabilityAgent : BaseAgent(
|
||||||
|
tool = Tool.function(
|
||||||
|
name = "adjustUserFavorability",
|
||||||
|
description = "可根据网友行为调整对其好感度,范围从-100到100。" +
|
||||||
|
"默认为0表示陌生人,100表示非常好的朋友,-100表示已拉黑。" +
|
||||||
|
"当好感度低于0时,有一定概率忽略该用户的消息,-100则100%忽略其消息。",
|
||||||
|
parameters = Parameters.buildJsonObject {
|
||||||
|
put("type", "object")
|
||||||
|
put("properties", buildJsonObject {
|
||||||
|
put("userId", buildJsonObject {
|
||||||
|
put("type", "integer")
|
||||||
|
put("description", "用户QQ号")
|
||||||
|
})
|
||||||
|
put("change", buildJsonObject {
|
||||||
|
put("type", "integer")
|
||||||
|
put("description", "好感度变化值(可正可负)")
|
||||||
|
})
|
||||||
|
put("reason", buildJsonObject {
|
||||||
|
put("type", "string")
|
||||||
|
put("description", "调整原因(供日志记录和溯源)")
|
||||||
|
})
|
||||||
|
put("impression", buildJsonObject {
|
||||||
|
put("type", "string")
|
||||||
|
put("description", "对用户的印象或称呼(可选)")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
putJsonArray("required") {
|
||||||
|
add("userId")
|
||||||
|
add("change")
|
||||||
|
add("reason")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override suspend fun execute(args: JsonObject?, event: MessageEvent): String {
|
||||||
|
requireNotNull(args)
|
||||||
|
|
||||||
|
val userId = args["userId"]?.jsonPrimitive?.longOrNull
|
||||||
|
val change = args["change"]?.jsonPrimitive?.intOrNull
|
||||||
|
val reason = args["reason"]?.jsonPrimitive?.contentOrNull
|
||||||
|
val impression = args["impression"]?.jsonPrimitive?.contentOrNull
|
||||||
|
|
||||||
|
if (userId == null || change == null || reason == null) {
|
||||||
|
return "错误:userId、change和reason参数不能为空"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前好感度信息
|
||||||
|
val currentInfo = PluginData.userFavorability[userId] ?: FavorabilityInfo(userId)
|
||||||
|
val currentValue = currentInfo.value
|
||||||
|
|
||||||
|
// 计算新的好感度值,限制在-100~100范围内
|
||||||
|
val newValue = (currentValue + change).coerceIn(-100, 100)
|
||||||
|
|
||||||
|
// 更新原因列表
|
||||||
|
val timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
|
||||||
|
val newReason = "${timeFormatter.format(OffsetDateTime.now())}: $reason"
|
||||||
|
val newReasons = if (currentInfo.reasons.size >= 10) {
|
||||||
|
// 保留最近的10条原因记录
|
||||||
|
(currentInfo.reasons.drop(1) + newReason)
|
||||||
|
} else {
|
||||||
|
(currentInfo.reasons + newReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新印象/画像
|
||||||
|
val newImpression = impression ?: currentInfo.impression
|
||||||
|
|
||||||
|
// 创建新的好感度信息
|
||||||
|
val newInfo = FavorabilityInfo(
|
||||||
|
userId = userId,
|
||||||
|
value = newValue,
|
||||||
|
reasons = newReasons,
|
||||||
|
impression = newImpression
|
||||||
|
)
|
||||||
|
|
||||||
|
// 更新好感度
|
||||||
|
PluginData.userFavorability[userId] = newInfo
|
||||||
|
|
||||||
|
// 记录日志
|
||||||
|
JChatGPT.logger.info("用户 $userId 的好感度 ($currentValue -> $newValue),原因:$reason")
|
||||||
|
|
||||||
|
return "用户 $userId 的好感度已更新为 $newValue"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
|||||||
class SendLaTeXExpression : BaseAgent(
|
class SendLaTeXExpression : BaseAgent(
|
||||||
tool = Tool.function(
|
tool = Tool.function(
|
||||||
name = "sendLaTeXExpression",
|
name = "sendLaTeXExpression",
|
||||||
description = "发送LaTeX数学表达式,将其渲染为图片并发送",
|
description = "发送LaTeX数学表达式,将其渲染为图片并发送。(暂不支持中文)",
|
||||||
parameters = Parameters.buildJsonObject {
|
parameters = Parameters.buildJsonObject {
|
||||||
put("type", "object")
|
put("type", "object")
|
||||||
putJsonObject("properties") {
|
putJsonObject("properties") {
|
||||||
@@ -38,7 +38,7 @@ class SendLaTeXExpression : BaseAgent(
|
|||||||
// 发送图片消息
|
// 发送图片消息
|
||||||
event.subject.sendMessage(image)
|
event.subject.sendMessage(image)
|
||||||
|
|
||||||
return "成功发送LaTeX表达式"
|
return "已成功将LaTeX表达式转为图片发送"
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
return "处理LaTeX表达式时发生异常: ${ex.message}"
|
return "处理LaTeX表达式时发生异常: ${ex.message}"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user