feat(demo): 添加聊天模型功能并优化用户账户
- 在 vertx-demo 项目中添加了 ChatController,实现与 OpenAI聊天模型交互 - 在 Account 模型中添加了唯一索引 TableIndex - 更新了项目依赖,增加了 langchain4j相关库
This commit is contained in:
parent
5eccf7ceed
commit
dbd2246a09
@ -88,6 +88,10 @@ dependencies {
|
||||
implementation("io.vertx:vertx-auth-jwt:$vertxVersion")
|
||||
implementation("io.vertx:vertx-redis-client:$vertxVersion")
|
||||
|
||||
implementation("dev.langchain4j:langchain4j-open-ai:1.0.0-beta1")
|
||||
implementation("dev.langchain4j:langchain4j:1.0.0-beta1")
|
||||
|
||||
|
||||
|
||||
implementation("com.google.inject:guice:5.1.0")
|
||||
implementation("org.reflections:reflections:0.10.2")
|
||||
|
||||
112
vertx-demo/src/main/kotlin/app/controller/ChatController.kt
Normal file
112
vertx-demo/src/main/kotlin/app/controller/ChatController.kt
Normal file
@ -0,0 +1,112 @@
|
||||
package app.controller
|
||||
|
||||
import com.google.inject.Inject
|
||||
import dev.langchain4j.model.chat.request.ChatRequestParameters
|
||||
import dev.langchain4j.model.chat.response.ChatResponse
|
||||
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler
|
||||
import dev.langchain4j.model.openai.OpenAiChatModel
|
||||
import dev.langchain4j.model.openai.OpenAiStreamingChatModel
|
||||
import io.vertx.core.http.HttpServerResponse
|
||||
import io.vertx.ext.web.RoutingContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import mu.KotlinLogging
|
||||
import org.aikrai.vertx.auth.AllowAnonymous
|
||||
import org.aikrai.vertx.config.Config
|
||||
import org.aikrai.vertx.context.Controller
|
||||
import org.aikrai.vertx.context.CustomizeResponse
|
||||
import org.aikrai.vertx.context.D
|
||||
|
||||
|
||||
@AllowAnonymous
|
||||
@D("对话")
|
||||
@Controller("/chat")
|
||||
class ChatController @Inject constructor(
|
||||
private val coroutineScope: CoroutineScope
|
||||
) {
|
||||
private val logger = KotlinLogging.logger { }
|
||||
val baseUrl = Config.getKey("langchain4j.open-ai.chat-model.base-url").toString()
|
||||
val apiKey = Config.getKey("langchain4j.open-ai.chat-model.api-key").toString()
|
||||
val modelName = Config.getKey("langchain4j.open-ai.chat-model.model-name").toString()
|
||||
|
||||
@AllowAnonymous
|
||||
@D("对话测试", "详细说明......")
|
||||
suspend fun chat(
|
||||
@D("message", "提问") message: String,
|
||||
): String {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val chatModel = OpenAiChatModel.builder()
|
||||
.baseUrl(baseUrl)
|
||||
.apiKey(apiKey)
|
||||
.defaultRequestParameters(
|
||||
ChatRequestParameters.builder()
|
||||
.modelName(modelName)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
val response = chatModel.chat(message)
|
||||
println(response)
|
||||
|
||||
return@withContext response.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@CustomizeResponse
|
||||
@AllowAnonymous
|
||||
@D("对话流式响应测试", "详细说明......")
|
||||
suspend fun stream(
|
||||
ctx: RoutingContext,
|
||||
@D("message", "提问") message: String,
|
||||
): Void? {
|
||||
val response = ctx.response()
|
||||
// 设置响应头,表明这是一个流式响应
|
||||
response.setChunked(true)
|
||||
response.putHeader("Content-Type", "text/event-stream")
|
||||
response.putHeader("Cache-Control", "no-cache")
|
||||
response.putHeader("Connection", "keep-alive")
|
||||
|
||||
var isResponseEnded = false // 响应结束标志
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
val chatModel = OpenAiStreamingChatModel.builder()
|
||||
.baseUrl(baseUrl)
|
||||
.apiKey(apiKey)
|
||||
.defaultRequestParameters(
|
||||
ChatRequestParameters.builder()
|
||||
.modelName(modelName)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
|
||||
chatModel.chat(message, object : StreamingChatResponseHandler {
|
||||
override fun onPartialResponse(partialResponse: String) {
|
||||
if (!isResponseEnded) {
|
||||
response.write("data: $partialResponse\n\n")
|
||||
logger.debug { "发送部分响应: $partialResponse" }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCompleteResponse(completeResponse: ChatResponse) {
|
||||
if (!isResponseEnded) {
|
||||
response.write("data: [DONE]\n\n")
|
||||
response.end() // 结束响应
|
||||
isResponseEnded = true // 设置结束标志
|
||||
logger.debug { "响应完成: $completeResponse" }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(error: Throwable) {
|
||||
if (!isResponseEnded) {
|
||||
response.write("data: {\"error\": \"${error.message}\"}\n\n")
|
||||
response.end() // 结束响应
|
||||
isResponseEnded = true // 设置结束标志
|
||||
logger.error(error) { "流式响应出错" }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ import org.aikrai.vertx.utlis.BaseEntity
|
||||
import java.sql.Timestamp
|
||||
|
||||
@TableName("sys_user")
|
||||
@TableIndex(name = "idx_phone", unique = true, columnNames=["phone"])
|
||||
class Account : BaseEntity() {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
|
||||
@ -1,8 +1,19 @@
|
||||
package org.aikrai.vertx.db.annotation
|
||||
|
||||
import java.lang.annotation.Documented
|
||||
import java.lang.annotation.ElementType
|
||||
import java.lang.annotation.RetentionPolicy
|
||||
|
||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.FIELD)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Repeatable
|
||||
annotation class TableIndex(
|
||||
val name: String = "",
|
||||
val unique: Boolean = false,
|
||||
val concurrent: Boolean = false,
|
||||
val columnNames: Array<String> = emptyArray(),
|
||||
// val platforms: Array<Platform> = emptyArray(),
|
||||
val definition: String = ""
|
||||
)
|
||||
|
||||
|
||||
|
||||
@MustBeDocumented
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user