From 5d8c19deab60f816a14f52222285f7fa3df1a073 Mon Sep 17 00:00:00 2001 From: AiKrai Date: Mon, 17 Mar 2025 17:52:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(vertx-demo):=20=E6=B7=BB=E5=8A=A0=20MCP=20?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vertx-demo/build.gradle.kts | 17 +---- .../kotlin/app/controller/ChatController.kt | 19 ++++- .../src/main/kotlin/app/port/mcp/AiClient.kt | 75 +++++++++++++++++++ vertx-fw/build.gradle.kts | 12 +-- 4 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 vertx-demo/src/main/kotlin/app/port/mcp/AiClient.kt diff --git a/vertx-demo/build.gradle.kts b/vertx-demo/build.gradle.kts index 07d201f..75c6992 100644 --- a/vertx-demo/build.gradle.kts +++ b/vertx-demo/build.gradle.kts @@ -41,16 +41,8 @@ tasks.test { } } -tasks.compileKotlin { - kotlinOptions { - jvmTarget = "17" - } -} - -tasks.compileTestKotlin { - kotlinOptions { - jvmTarget = "17" - } +kotlin { + jvmToolchain(17) } spotless { @@ -88,10 +80,9 @@ 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("dev.langchain4j:langchain4j-open-ai:1.0.0-beta1") + implementation("dev.langchain4j:langchain4j-mcp:1.0.0-beta1") implementation("com.google.inject:guice:5.1.0") implementation("org.reflections:reflections:0.10.2") diff --git a/vertx-demo/src/main/kotlin/app/controller/ChatController.kt b/vertx-demo/src/main/kotlin/app/controller/ChatController.kt index 6ea0eb5..7ea1862 100644 --- a/vertx-demo/src/main/kotlin/app/controller/ChatController.kt +++ b/vertx-demo/src/main/kotlin/app/controller/ChatController.kt @@ -1,12 +1,12 @@ package app.controller +import app.port.mcp.AiClient 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 @@ -109,4 +109,21 @@ class ChatController @Inject constructor( return null } + + + @AllowAnonymous + @D("MCP测试", "详细说明......") + suspend fun chatWithMcp( + @D("message", "提问") message: String, + ): String { + val aiService = AiClient.getAiAssistant() + + return withContext(Dispatchers.IO) { + + val response = aiService.chat(message) + println(response) + + return@withContext response + } + } } \ No newline at end of file diff --git a/vertx-demo/src/main/kotlin/app/port/mcp/AiClient.kt b/vertx-demo/src/main/kotlin/app/port/mcp/AiClient.kt new file mode 100644 index 0000000..6d3168b --- /dev/null +++ b/vertx-demo/src/main/kotlin/app/port/mcp/AiClient.kt @@ -0,0 +1,75 @@ +package app.port.mcp + +import dev.langchain4j.mcp.McpToolProvider +import dev.langchain4j.mcp.client.DefaultMcpClient +import dev.langchain4j.mcp.client.McpClient +import dev.langchain4j.mcp.client.transport.stdio.StdioMcpTransport +import dev.langchain4j.memory.chat.MessageWindowChatMemory +import dev.langchain4j.model.chat.ChatLanguageModel +import dev.langchain4j.model.chat.request.ChatRequestParameters +import dev.langchain4j.model.openai.OpenAiChatModel +import dev.langchain4j.service.AiServices +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import mu.KotlinLogging +import org.aikrai.vertx.config.Config + +interface AiAssistant { + fun chat(message: String): String +} + +object AiClient { + 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() + + + private suspend fun createMcpClient(): McpClient { + val apiKey = Config.getKey("weather.api.api-key").toString() + return withContext(Dispatchers.IO) { + DefaultMcpClient.Builder() + .transport( +// HttpMcpTransport.Builder() +// .sseUrl("http://127.0.0.1:17080/sse") +// .build() + StdioMcpTransport.Builder() + .command( + listOf( + "java", + "-Dspring.ai.mcp.server.stdio=true", + "-jar", + "vertx-demo/src/main/resources/mcp-demo-0.0.1-SNAPSHOT.jar", + "--weather.api.api-key=${apiKey}" + ) + ) + .logEvents(true) + .build() + ) + .build() + } + } + + private fun createChatClient(): ChatLanguageModel { + return OpenAiChatModel.builder() + .baseUrl(baseUrl) + .apiKey(apiKey) + .defaultRequestParameters( + ChatRequestParameters.builder() + .modelName(modelName) + .build() + ) + .build() + } + + suspend fun getAiAssistant(): AiAssistant { + val toolProvider = McpToolProvider.builder() + .mcpClients(listOf(createMcpClient())) + .build() + return AiServices.builder(AiAssistant::class.java) + .chatLanguageModel(createChatClient()) + .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) + .toolProvider(toolProvider) + .build() + } +} \ No newline at end of file diff --git a/vertx-fw/build.gradle.kts b/vertx-fw/build.gradle.kts index f212056..03fc706 100644 --- a/vertx-fw/build.gradle.kts +++ b/vertx-fw/build.gradle.kts @@ -27,16 +27,8 @@ tasks.test { } } -tasks.compileKotlin { - kotlinOptions { - jvmTarget = "17" - } -} - -tasks.compileTestKotlin { - kotlinOptions { - jvmTarget = "17" - } +kotlin { + jvmToolchain(17) } spotless {