mirror of
https://github.com/jie65535/JChatGPT.git
synced 2025-06-02 17:39:10 +08:00
Update version to v1.2.0
Add LaTex formula convert to image
This commit is contained in:
parent
a6bd48aa4e
commit
49b1b0c345
@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
val kotlinVersion = "1.9.24"
|
||||
val kotlinVersion = "1.8.10"
|
||||
kotlin("jvm") version kotlinVersion
|
||||
kotlin("plugin.serialization") version kotlinVersion
|
||||
|
||||
@ -7,7 +7,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "top.jie65535.mirai"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@ -16,8 +16,10 @@ repositories {
|
||||
|
||||
val openaiClientVersion = "3.8.2"
|
||||
val ktorVersion = "2.3.12"
|
||||
val jLatexMathVersion = "1.0.7"
|
||||
|
||||
dependencies {
|
||||
implementation("com.aallam.openai:openai-client:$openaiClientVersion")
|
||||
implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
|
||||
implementation("org.scilab.forge:jlatexmath:$jLatexMathVersion")
|
||||
}
|
@ -16,6 +16,7 @@ import net.mamoe.mirai.console.permission.PermissionService
|
||||
import net.mamoe.mirai.console.permission.PermissionService.Companion.hasPermission
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
|
||||
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.isOperator
|
||||
import net.mamoe.mirai.event.GlobalEventChannel
|
||||
import net.mamoe.mirai.event.events.FriendMessageEvent
|
||||
@ -24,14 +25,16 @@ import net.mamoe.mirai.event.events.MessageEvent
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.message.data.MessageSource.Key.quote
|
||||
import net.mamoe.mirai.message.sourceIds
|
||||
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
||||
import net.mamoe.mirai.utils.info
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
object JChatGPT : KotlinPlugin(
|
||||
JvmPluginDescription(
|
||||
id = "top.jie65535.mirai.JChatGPT",
|
||||
name = "J ChatGPT",
|
||||
version = "1.1.0",
|
||||
version = "1.2.0",
|
||||
) {
|
||||
author("jie65535")
|
||||
}
|
||||
@ -61,13 +64,14 @@ object JChatGPT : KotlinPlugin(
|
||||
|
||||
fun updateOpenAiToken(token: String) {
|
||||
val timeout = PluginConfig.timeout.milliseconds
|
||||
openAi = OpenAI(token,
|
||||
openAi = OpenAI(
|
||||
token,
|
||||
host = OpenAIHost(baseUrl = PluginConfig.openAiApi),
|
||||
timeout = Timeout(request = timeout, connect = timeout, socket = timeout)
|
||||
)
|
||||
}
|
||||
|
||||
// private val userContext = ConcurrentMap<Long, MutableList<ChatMessage>>()
|
||||
// private val userContext = ConcurrentMap<Long, MutableList<ChatMessage>>()
|
||||
private const val REPLAY_QUEUE_MAX = 30
|
||||
private val replyMap = ConcurrentMap<Int, MutableList<ChatMessage>>()
|
||||
private val replyQueue = mutableListOf<Int>()
|
||||
@ -143,23 +147,26 @@ object JChatGPT : KotlinPlugin(
|
||||
val content = reply.content ?: "..."
|
||||
|
||||
val replyMsg = subject.sendMessage(
|
||||
if (content.length < 100) {
|
||||
message.quote() + content
|
||||
if (content.length < 128) {
|
||||
message.quote() + toMessage(subject, content)
|
||||
} else {
|
||||
// 消息内容太长则转为转发消息避免刷屏
|
||||
buildForwardMessage {
|
||||
for (item in history) {
|
||||
val temp = toMessage(subject, item.content ?: "...")
|
||||
when (item.role) {
|
||||
Role.User -> sender says (item.content ?: "...")
|
||||
Role.Assistant -> bot says (item.content ?: "...")
|
||||
Role.User -> sender says temp
|
||||
Role.Assistant -> bot says temp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
val msgId = replyMsg.sourceIds[0]
|
||||
replyMap[msgId] = history
|
||||
replyQueue.add(msgId)
|
||||
if (replyMsg.sourceIds.isNotEmpty()) {
|
||||
val msgId = replyMsg.sourceIds[0]
|
||||
replyMap[msgId] = history
|
||||
replyQueue.add(msgId)
|
||||
}
|
||||
if (replyQueue.size > REPLAY_QUEUE_MAX) {
|
||||
replyMap.remove(replyQueue.removeAt(0))
|
||||
}
|
||||
@ -171,6 +178,58 @@ object JChatGPT : KotlinPlugin(
|
||||
}
|
||||
}
|
||||
|
||||
private val laTeXPattern = Pattern.compile(
|
||||
"\\\\\\((.+?)\\\\\\)|" + // 匹配行内公式 \(...\)
|
||||
"\\\\\\[(.+?)\\\\\\]|" + // 匹配独立公式 \[...\]
|
||||
"\\$\\$([^$]+?)\\$\\$|" + // 匹配独立公式 $$...$$
|
||||
"\\$(.+?)\\$|" + // 匹配行内公式 $...$
|
||||
"```latex\\s*([^`]+?)\\s*```" // 匹配 ```latex ... ```
|
||||
, Pattern.DOTALL
|
||||
)
|
||||
|
||||
/**
|
||||
* 将聊天内容转为聊天消息,如果聊天中包含LaTeX表达式,将会转为图片拼接到消息中。
|
||||
*
|
||||
* @param contact 联系对象
|
||||
* @param content 文本内容
|
||||
* @return 构造的消息
|
||||
*/
|
||||
private suspend fun toMessage(contact: Contact, content: String): Message {
|
||||
if (content.length < 3) {
|
||||
return PlainText(content)
|
||||
}
|
||||
return buildMessageChain {
|
||||
// 匹配LaTeX表达式
|
||||
val matcher = laTeXPattern.matcher(content)
|
||||
var index = 0
|
||||
while (matcher.find()) {
|
||||
for (i in 1..matcher.groupCount()) {
|
||||
if (matcher.group(i) == null) {
|
||||
continue
|
||||
}
|
||||
try {
|
||||
// 将所有匹配的LaTeX公式转为图片拼接到消息中
|
||||
val formula = matcher.group(i)
|
||||
val imageByteArray = LaTeXConverter.convertToImage(formula, "png")
|
||||
val resource = imageByteArray.toExternalResource("png")
|
||||
val image = contact.uploadImage(resource)
|
||||
|
||||
// 拼接公式前的文本
|
||||
append(content, index, matcher.start())
|
||||
// 插入图片
|
||||
append(image)
|
||||
// 移动索引
|
||||
index = matcher.end()
|
||||
} catch (ex: Throwable) {
|
||||
logger.warning("处理LaTeX表达式时异常", ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 拼接后续消息
|
||||
append(content, index, content.length)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun chatCompletion(messages: List<ChatMessage>): ChatMessage {
|
||||
val openAi = this.openAi ?: throw NullPointerException("OpenAI Token 未设置,无法开始")
|
||||
val request = ChatCompletionRequest(ModelId(PluginConfig.chatModel), messages)
|
||||
|
32
src/main/kotlin/LaTeXConverter.kt
Normal file
32
src/main/kotlin/LaTeXConverter.kt
Normal file
@ -0,0 +1,32 @@
|
||||
package top.jie65535.mirai
|
||||
|
||||
import org.scilab.forge.jlatexmath.TeXConstants
|
||||
import org.scilab.forge.jlatexmath.TeXFormula
|
||||
import java.awt.Color
|
||||
import java.awt.Insets
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.ByteArrayOutputStream
|
||||
import javax.imageio.ImageIO
|
||||
import javax.swing.JLabel
|
||||
|
||||
|
||||
object LaTeXConverter {
|
||||
/**
|
||||
* 转换LaTeX到图片字节数组
|
||||
*/
|
||||
fun convertToImage(latexString: String, format: String = "png"): ByteArray {
|
||||
val formula = TeXFormula(latexString)
|
||||
val icon = formula.TeXIconBuilder().setStyle(TeXConstants.STYLE_DISPLAY).setSize(20f).build()
|
||||
icon.insets = Insets(5, 5, 5, 5)
|
||||
val image = BufferedImage(icon.iconWidth, icon.iconHeight, BufferedImage.TYPE_INT_ARGB)
|
||||
val g2 = image.createGraphics()
|
||||
g2.color = Color.white
|
||||
g2.fillRect(0, 0, icon.iconWidth, icon.iconHeight)
|
||||
val jl = JLabel()
|
||||
jl.setForeground(Color(0, 0, 0))
|
||||
icon.paintIcon(jl, g2, 0, 0)
|
||||
val stream = ByteArrayOutputStream()
|
||||
ImageIO.write(image, format, stream)
|
||||
return stream.toByteArray()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user