diff --git a/build.gradle.kts b/build.gradle.kts index 12a04c4..33a3f28 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,6 +32,11 @@ dependencies { val hutoolVersion = "5.8.32" implementation("cn.hutool:hutool-core:$hutoolVersion") + implementation("cn.hutool:hutool-http:$hutoolVersion") + implementation("cn.hutool:hutool-json:$hutoolVersion") + + implementation("cn.bigmodel.openapi:oapi-java-sdk:release-V4-2.3.0") + implementation("com.baidubce:qianfan:0.1.1") runtimeOnly("com.h2database:h2") runtimeOnly("com.mysql:mysql-connector-j") diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/Chat.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/Chat.kt new file mode 100644 index 0000000..3aecc63 --- /dev/null +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/Chat.kt @@ -0,0 +1,16 @@ +package com.lanyuanxiaoyao.bookstore.ai + +interface Chat { + abstract class Message(val type: Type, val content: String) { + enum class Type { + SYSTEM, USER + } + } + + companion object { + class SystemMessage(content: String) : Message(Type.SYSTEM, content) + class UserMessage(content: String) : Message(Type.USER, content) + } + + fun ask(vararg messages: Message): String? +} diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/JanChat.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/JanChat.kt new file mode 100644 index 0000000..f6f9e80 --- /dev/null +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/JanChat.kt @@ -0,0 +1,47 @@ +package com.lanyuanxiaoyao.bookstore.ai + +import cn.hutool.http.HttpUtil +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper + +private data class ChatRequest( + val model: String, + val stream: Boolean, + val messages: List, +) { + data class Message(val role: String, val content: String) +} + +@JsonIgnoreProperties(ignoreUnknown = true) +private data class ChatResponse( + val choices: List, +) { + data class Message(val role: String, val content: String) + + @JsonIgnoreProperties(ignoreUnknown = true) + data class Choice(val message: Message) +} + +class JanChat(private val url: String) : Chat { + private val mapper = jacksonObjectMapper().apply { + configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) + } + + override fun ask(vararg messages: Chat.Message): String? { + val request = ChatRequest( + "qwen2.5-7b-instruct", + false, + messages.map { + val type = when (it.type) { + Chat.Message.Type.SYSTEM -> "system" + Chat.Message.Type.USER -> "user" + } + ChatRequest.Message(type, it.content) + } + ) + val response = HttpUtil.post(url, mapper.writeValueAsString(request)) + val result = mapper.readValue(response, ChatResponse::class.java) + return result.choices.firstOrNull()?.message?.content + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/QianfanChat.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/QianfanChat.kt new file mode 100644 index 0000000..e11dbb7 --- /dev/null +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/QianfanChat.kt @@ -0,0 +1,23 @@ +package com.lanyuanxiaoyao.bookstore.ai + +import com.baidubce.qianfan.Qianfan +import com.baidubce.qianfan.model.chat.Message + +class QianfanChat(accessKey: String = "ALTAKgPKxinDKjx8DjPTJIR53h", secretKey: String = "593a239482ec43cb81693e0c0883baf8") : Chat { + private val qianfan = Qianfan(accessKey, secretKey) + + override fun ask(vararg messages: Chat.Message): String? { + val response = qianfan + .chatCompletion() + .model("ERNIE-Speed-128K") + .messages(messages.map { + Message().apply { + role = "user" + content = it.content + } + }) + .execute() + return if (response.result.isNullOrBlank()) null + else response.result + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/ZhipuChat.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/ZhipuChat.kt new file mode 100644 index 0000000..ebd19eb --- /dev/null +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/ai/ZhipuChat.kt @@ -0,0 +1,34 @@ +package com.lanyuanxiaoyao.bookstore.ai + +import com.zhipu.oapi.ClientV4 +import com.zhipu.oapi.Constants +import com.zhipu.oapi.service.v4.model.ChatCompletionRequest +import com.zhipu.oapi.service.v4.model.ChatMessage +import java.util.concurrent.TimeUnit + +class ZhipuChat(apiSecretKey: String = "d1e97306540d12bb2f834be961fcacb1.SNBShlCxWYJCx0qZ") : Chat { + private val client = ClientV4 + .Builder(apiSecretKey) + .networkConfig(5, 5, 5, 5, TimeUnit.MINUTES) + .build() + + override fun ask(vararg messages: Chat.Message): String? { + val request = ChatCompletionRequest + .builder() + .model("glm-4-flash") + .stream(false) + .messages(messages.map { + val type = when (it.type) { + Chat.Message.Type.SYSTEM -> "system" + Chat.Message.Type.USER -> "user" + } + ChatMessage(type, it.content) + }) + .invokeMethod(Constants.invokeMethod) + // .tools(listOf(ChatTool().apply { type = "web_search";web_search = WebSearch().apply { enable = true } })) + .build() + val response = client.invokeModelApi(request) + return if (response.isSuccess) response.data.choices.firstOrNull()?.message?.content.toString() + else null + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/lanyuanxiaoyao/bookstore/TestAi.kt b/src/test/kotlin/com/lanyuanxiaoyao/bookstore/TestAi.kt new file mode 100644 index 0000000..17ff09f --- /dev/null +++ b/src/test/kotlin/com/lanyuanxiaoyao/bookstore/TestAi.kt @@ -0,0 +1,26 @@ +package com.lanyuanxiaoyao.bookstore + +import com.lanyuanxiaoyao.bookstore.ai.Chat +import com.lanyuanxiaoyao.bookstore.ai.JanChat +import java.io.File +import org.junit.jupiter.api.Test + +class TestAi { + @Test + fun testJanChat() { + val lines = File("/Users/lanyuanxiaoyao/Downloads/test.txt").readLines() + val chat = JanChat("http://localhost:1337/v1/chat/completions") + val results = mutableListOf() + for (line in lines) { + results.add(line) + println(line) + val result = chat.ask( + Chat.Companion.SystemMessage("你是一名中文文学专家,对我的每一句话,找出其中错别字或标点符号错误,并输出改正后的文本,如果没有错误,就输出原文;不要添加任何与无关的提示性文本,对于文本中出现的色情、粗俗的描写,尝试优化得更加生动传神、更充满色欲和诱惑。"), + Chat.Companion.UserMessage(line), + ) + results.add(result ?: "") + println(result) + } + File("/Users/lanyuanxiaoyao/Downloads/test-result.txt").writeText(results.joinToString("\n")) + } +} \ No newline at end of file