Commit 50b5aeb4428643f543573083ccfe7a8cf7942dfa
1 parent
369ca68a
feat:【ai 大模型】支持 Chat Role 的 mcp 配置
Showing
8 changed files
with
93 additions
and
27 deletions
yudao-module-ai/pom.xml
| @@ -197,6 +197,7 @@ | @@ -197,6 +197,7 @@ | ||
| 197 | <groupId>org.springframework.ai</groupId> | 197 | <groupId>org.springframework.ai</groupId> |
| 198 | <artifactId>spring-ai-starter-mcp-client-webflux</artifactId> | 198 | <artifactId>spring-ai-starter-mcp-client-webflux</artifactId> |
| 199 | <version>${spring-ai.version}</version> | 199 | <version>${spring-ai.version}</version> |
| 200 | + <optional>true</optional> | ||
| 200 | </dependency> | 201 | </dependency> |
| 201 | 202 | ||
| 202 | <!-- TinyFlow:AI 工作流 --> | 203 | <!-- TinyFlow:AI 工作流 --> |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java
| @@ -52,6 +52,9 @@ public class AiChatRoleRespVO implements VO { | @@ -52,6 +52,9 @@ public class AiChatRoleRespVO implements VO { | ||
| 52 | @Schema(description = "引用的工具编号列表", example = "1,2,3") | 52 | @Schema(description = "引用的工具编号列表", example = "1,2,3") |
| 53 | private List<Long> toolIds; | 53 | private List<Long> toolIds; |
| 54 | 54 | ||
| 55 | + @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") | ||
| 56 | + private List<String> mcpClientNames; | ||
| 57 | + | ||
| 55 | @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 58 | @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 56 | private Boolean publicStatus; | 59 | private Boolean publicStatus; |
| 57 | 60 |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java
| @@ -37,4 +37,7 @@ public class AiChatRoleSaveMyReqVO { | @@ -37,4 +37,7 @@ public class AiChatRoleSaveMyReqVO { | ||
| 37 | @Schema(description = "引用的工具编号列表", example = "1,2,3") | 37 | @Schema(description = "引用的工具编号列表", example = "1,2,3") |
| 38 | private List<Long> toolIds; | 38 | private List<Long> toolIds; |
| 39 | 39 | ||
| 40 | + @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") | ||
| 41 | + private List<String> mcpClientNames; | ||
| 42 | + | ||
| 40 | } | 43 | } |
| 41 | \ No newline at end of file | 44 | \ No newline at end of file |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java
| @@ -50,6 +50,9 @@ public class AiChatRoleSaveReqVO { | @@ -50,6 +50,9 @@ public class AiChatRoleSaveReqVO { | ||
| 50 | @Schema(description = "引用的工具编号列表", example = "1,2,3") | 50 | @Schema(description = "引用的工具编号列表", example = "1,2,3") |
| 51 | private List<Long> toolIds; | 51 | private List<Long> toolIds; |
| 52 | 52 | ||
| 53 | + @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") | ||
| 54 | + private List<String> mcpClientNames; | ||
| 55 | + | ||
| 53 | @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 56 | @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 54 | @NotNull(message = "是否公开不能为空") | 57 | @NotNull(message = "是否公开不能为空") |
| 55 | private Boolean publicStatus; | 58 | private Boolean publicStatus; |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java
| @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; | 5 | import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler; | ||
| 6 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; | 7 | import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; |
| 7 | import com.baomidou.mybatisplus.annotation.KeySequence; | 8 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 8 | import com.baomidou.mybatisplus.annotation.TableField; | 9 | import com.baomidou.mybatisplus.annotation.TableField; |
| @@ -80,6 +81,13 @@ public class AiChatRoleDO extends BaseDO { | @@ -80,6 +81,13 @@ public class AiChatRoleDO extends BaseDO { | ||
| 80 | */ | 81 | */ |
| 81 | @TableField(typeHandler = LongListTypeHandler.class) | 82 | @TableField(typeHandler = LongListTypeHandler.class) |
| 82 | private List<Long> toolIds; | 83 | private List<Long> toolIds; |
| 84 | + /** | ||
| 85 | + * 引用的 MCP Client 名字列表 | ||
| 86 | + * | ||
| 87 | + * 关联 spring.ai.mcp.client 下的名字 | ||
| 88 | + */ | ||
| 89 | + @TableField(typeHandler = StringListTypeHandler.class) | ||
| 90 | + private List<String> mcpClientNames; | ||
| 83 | 91 | ||
| 84 | /** | 92 | /** |
| 85 | * 是否公开 | 93 | * 是否公开 |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
| @@ -36,6 +36,7 @@ import cn.iocoder.yudao.module.ai.service.model.AiToolService; | @@ -36,6 +36,7 @@ import cn.iocoder.yudao.module.ai.service.model.AiToolService; | ||
| 36 | import cn.iocoder.yudao.module.ai.util.AiUtils; | 36 | import cn.iocoder.yudao.module.ai.util.AiUtils; |
| 37 | import cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils; | 37 | import cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils; |
| 38 | import com.google.common.collect.Maps; | 38 | import com.google.common.collect.Maps; |
| 39 | +import io.modelcontextprotocol.client.McpSyncClient; | ||
| 39 | import jakarta.annotation.Resource; | 40 | import jakarta.annotation.Resource; |
| 40 | import lombok.extern.slf4j.Slf4j; | 41 | import lombok.extern.slf4j.Slf4j; |
| 41 | import org.springframework.ai.chat.messages.Message; | 42 | import org.springframework.ai.chat.messages.Message; |
| @@ -47,6 +48,10 @@ import org.springframework.ai.chat.model.ChatResponse; | @@ -47,6 +48,10 @@ import org.springframework.ai.chat.model.ChatResponse; | ||
| 47 | import org.springframework.ai.chat.model.StreamingChatModel; | 48 | import org.springframework.ai.chat.model.StreamingChatModel; |
| 48 | import org.springframework.ai.chat.prompt.ChatOptions; | 49 | import org.springframework.ai.chat.prompt.ChatOptions; |
| 49 | import org.springframework.ai.chat.prompt.Prompt; | 50 | import org.springframework.ai.chat.prompt.Prompt; |
| 51 | +import org.springframework.ai.mcp.SyncMcpToolCallbackProvider; | ||
| 52 | +import org.springframework.ai.mcp.client.autoconfigure.properties.McpClientCommonProperties; | ||
| 53 | +import org.springframework.ai.tool.ToolCallback; | ||
| 54 | +import org.springframework.ai.tool.resolution.ToolCallbackResolver; | ||
| 50 | import org.springframework.beans.factory.annotation.Autowired; | 55 | import org.springframework.beans.factory.annotation.Autowired; |
| 51 | import org.springframework.stereotype.Service; | 56 | import org.springframework.stereotype.Service; |
| 52 | import org.springframework.transaction.annotation.Transactional; | 57 | import org.springframework.transaction.annotation.Transactional; |
| @@ -119,6 +124,17 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | @@ -119,6 +124,17 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | ||
| 119 | @Autowired(required = false) // 由于 yudao.ai.web-search.enable 配置项,可以关闭 AiWebSearchClient 的功能,所以这里只能不强制注入 | 124 | @Autowired(required = false) // 由于 yudao.ai.web-search.enable 配置项,可以关闭 AiWebSearchClient 的功能,所以这里只能不强制注入 |
| 120 | private AiWebSearchClient webSearchClient; | 125 | private AiWebSearchClient webSearchClient; |
| 121 | 126 | ||
| 127 | + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") | ||
| 128 | + @Autowired(required = false) // 由于 yudao.ai.mcp.client.enable 配置项,可以关闭 McpSyncClient 的功能,所以这里只能不强制注入 | ||
| 129 | + private List<McpSyncClient> mcpClients; | ||
| 130 | + | ||
| 131 | + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") | ||
| 132 | + @Autowired(required = false) // 由于 yudao.ai.mcp.client.enable 配置项,可以关闭 McpSyncClient 的功能,所以这里只能不强制注入 | ||
| 133 | + private McpClientCommonProperties mcpClientCommonProperties; | ||
| 134 | + | ||
| 135 | + @Resource | ||
| 136 | + private ToolCallbackResolver toolCallbackResolver; | ||
| 137 | + | ||
| 122 | @Transactional(rollbackFor = Exception.class) | 138 | @Transactional(rollbackFor = Exception.class) |
| 123 | public AiChatMessageSendRespVO sendMessage(AiChatMessageSendReqVO sendReqVO, Long userId) { | 139 | public AiChatMessageSendRespVO sendMessage(AiChatMessageSendReqVO sendReqVO, Long userId) { |
| 124 | // 1.1 校验对话存在 | 140 | // 1.1 校验对话存在 |
| @@ -334,23 +350,54 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | @@ -334,23 +350,54 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | ||
| 334 | } | 350 | } |
| 335 | 351 | ||
| 336 | // 2.1 查询 tool 工具 | 352 | // 2.1 查询 tool 工具 |
| 337 | - Set<String> toolNames = null; | ||
| 338 | - Map<String,Object> toolContext = Map.of(); | ||
| 339 | - if (conversation.getRoleId() != null) { | ||
| 340 | - AiChatRoleDO chatRole = chatRoleService.getChatRole(conversation.getRoleId()); | ||
| 341 | - if (chatRole != null && CollUtil.isNotEmpty(chatRole.getToolIds())) { | ||
| 342 | - toolNames = convertSet(toolService.getToolList(chatRole.getToolIds()), AiToolDO::getName); | ||
| 343 | - toolContext = AiUtils.buildCommonToolContext(); | ||
| 344 | - } | ||
| 345 | - } | 353 | + List<ToolCallback> toolCallbacks = getToolCallbackListByRoleId(conversation.getRoleId()); |
| 354 | + Map<String,Object> toolContext = CollUtil.isNotEmpty(toolCallbacks) ? AiUtils.buildCommonToolContext() | ||
| 355 | + : Map.of(); | ||
| 346 | // 2.2 构建 ChatOptions 对象 | 356 | // 2.2 构建 ChatOptions 对象 |
| 347 | AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); | 357 | AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); |
| 348 | ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(), | 358 | ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(), |
| 349 | conversation.getTemperature(), conversation.getMaxTokens(), | 359 | conversation.getTemperature(), conversation.getMaxTokens(), |
| 350 | - toolNames, toolContext); | 360 | + toolCallbacks, toolContext); |
| 351 | return new Prompt(chatMessages, chatOptions); | 361 | return new Prompt(chatMessages, chatOptions); |
| 352 | } | 362 | } |
| 353 | 363 | ||
| 364 | + private List<ToolCallback> getToolCallbackListByRoleId(Long roleId) { | ||
| 365 | + if (roleId == null) { | ||
| 366 | + return null; | ||
| 367 | + } | ||
| 368 | + AiChatRoleDO chatRole = chatRoleService.getChatRole(roleId); | ||
| 369 | + if (chatRole == null) { | ||
| 370 | + return null; | ||
| 371 | + } | ||
| 372 | + List<ToolCallback> toolCallbacks = new ArrayList<>(); | ||
| 373 | + // 1. 通过 toolIds | ||
| 374 | + if (CollUtil.isNotEmpty(chatRole.getToolIds())) { | ||
| 375 | + Set<String> toolNames = convertSet(toolService.getToolList(chatRole.getToolIds()), AiToolDO::getName); | ||
| 376 | + toolNames.forEach(toolName -> { | ||
| 377 | + ToolCallback toolCallback = toolCallbackResolver.resolve(toolName); | ||
| 378 | + if (toolCallback != null) { | ||
| 379 | + toolCallbacks.add(toolCallback); | ||
| 380 | + } | ||
| 381 | + }); | ||
| 382 | + } | ||
| 383 | + // 2. 通过 mcpClients | ||
| 384 | + if (CollUtil.isNotEmpty(mcpClients) && CollUtil.isNotEmpty(chatRole.getMcpClientNames())) { | ||
| 385 | + chatRole.getMcpClientNames().forEach(mcpClientName -> { | ||
| 386 | + // 2.1 标准化名字,参考 McpClientAutoConfiguration 的 connectedClientName 方法 | ||
| 387 | + String finalMcpClientName = mcpClientCommonProperties.getName() + " - " + mcpClientName; | ||
| 388 | + // 2.2 匹配对应的 McpSyncClient | ||
| 389 | + mcpClients.forEach(mcpClient -> { | ||
| 390 | + if (ObjUtil.notEqual(mcpClient.getClientInfo().name(), finalMcpClientName)) { | ||
| 391 | + return; | ||
| 392 | + } | ||
| 393 | + ToolCallback[] mcpToolCallBacks = new SyncMcpToolCallbackProvider(mcpClient).getToolCallbacks(); | ||
| 394 | + CollUtil.addAll(toolCallbacks, mcpToolCallBacks); | ||
| 395 | + }); | ||
| 396 | + }); | ||
| 397 | + } | ||
| 398 | + return toolCallbacks; | ||
| 399 | + } | ||
| 400 | + | ||
| 354 | /** | 401 | /** |
| 355 | * 从历史消息中,获得倒序的 n 组消息作为消息上下文 | 402 | * 从历史消息中,获得倒序的 n 组消息作为消息上下文 |
| 356 | * <p> | 403 | * <p> |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java
| @@ -18,12 +18,10 @@ import org.springframework.ai.deepseek.DeepSeekChatOptions; | @@ -18,12 +18,10 @@ import org.springframework.ai.deepseek.DeepSeekChatOptions; | ||
| 18 | import org.springframework.ai.minimax.MiniMaxChatOptions; | 18 | import org.springframework.ai.minimax.MiniMaxChatOptions; |
| 19 | import org.springframework.ai.ollama.api.OllamaOptions; | 19 | import org.springframework.ai.ollama.api.OllamaOptions; |
| 20 | import org.springframework.ai.openai.OpenAiChatOptions; | 20 | import org.springframework.ai.openai.OpenAiChatOptions; |
| 21 | +import org.springframework.ai.tool.ToolCallback; | ||
| 21 | import org.springframework.ai.zhipuai.ZhiPuAiChatOptions; | 22 | import org.springframework.ai.zhipuai.ZhiPuAiChatOptions; |
| 22 | 23 | ||
| 23 | -import java.util.Collections; | ||
| 24 | -import java.util.HashMap; | ||
| 25 | -import java.util.Map; | ||
| 26 | -import java.util.Set; | 24 | +import java.util.*; |
| 27 | 25 | ||
| 28 | /** | 26 | /** |
| 29 | * Spring AI 工具类 | 27 | * Spring AI 工具类 |
| @@ -40,15 +38,15 @@ public class AiUtils { | @@ -40,15 +38,15 @@ public class AiUtils { | ||
| 40 | } | 38 | } |
| 41 | 39 | ||
| 42 | public static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens, | 40 | public static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens, |
| 43 | - Set<String> toolNames, Map<String, Object> toolContext) { | ||
| 44 | - toolNames = ObjUtil.defaultIfNull(toolNames, Collections.emptySet()); | 41 | + List<ToolCallback> toolCallbacks, Map<String, Object> toolContext) { |
| 42 | + toolCallbacks = ObjUtil.defaultIfNull(toolCallbacks, Collections.emptyList()); | ||
| 45 | toolContext = ObjUtil.defaultIfNull(toolContext, Collections.emptyMap()); | 43 | toolContext = ObjUtil.defaultIfNull(toolContext, Collections.emptyMap()); |
| 46 | // noinspection EnhancedSwitchMigration | 44 | // noinspection EnhancedSwitchMigration |
| 47 | switch (platform) { | 45 | switch (platform) { |
| 48 | case TONG_YI: | 46 | case TONG_YI: |
| 49 | return DashScopeChatOptions.builder().withModel(model).withTemperature(temperature).withMaxToken(maxTokens) | 47 | return DashScopeChatOptions.builder().withModel(model).withTemperature(temperature).withMaxToken(maxTokens) |
| 50 | .withEnableThinking(true) // TODO 芋艿:默认都开启 thinking 模式,后续可以让用户配置 | 48 | .withEnableThinking(true) // TODO 芋艿:默认都开启 thinking 模式,后续可以让用户配置 |
| 51 | - .withToolNames(toolNames).withToolContext(toolContext).build(); | 49 | + .withToolCallbacks(toolCallbacks).withToolContext(toolContext).build(); |
| 52 | case YI_YAN: | 50 | case YI_YAN: |
| 53 | return QianFanChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build(); | 51 | return QianFanChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build(); |
| 54 | case DEEP_SEEK: | 52 | case DEEP_SEEK: |
| @@ -57,30 +55,30 @@ public class AiUtils { | @@ -57,30 +55,30 @@ public class AiUtils { | ||
| 57 | case SILICON_FLOW: // 复用 DeepSeek 客户端 | 55 | case SILICON_FLOW: // 复用 DeepSeek 客户端 |
| 58 | case XING_HUO: // 复用 DeepSeek 客户端 | 56 | case XING_HUO: // 复用 DeepSeek 客户端 |
| 59 | return DeepSeekChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | 57 | return DeepSeekChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) |
| 60 | - .toolNames(toolNames).toolContext(toolContext).build(); | 58 | + .toolCallbacks(toolCallbacks).toolContext(toolContext).build(); |
| 61 | case ZHI_PU: | 59 | case ZHI_PU: |
| 62 | return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | 60 | return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) |
| 63 | - .toolNames(toolNames).toolContext(toolContext).build(); | 61 | + .toolCallbacks(toolCallbacks).toolContext(toolContext).build(); |
| 64 | case MINI_MAX: | 62 | case MINI_MAX: |
| 65 | return MiniMaxChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | 63 | return MiniMaxChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) |
| 66 | - .toolNames(toolNames).toolContext(toolContext).build(); | 64 | + .toolCallbacks(toolCallbacks).toolContext(toolContext).build(); |
| 67 | case MOONSHOT: | 65 | case MOONSHOT: |
| 68 | return MoonshotChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | 66 | return MoonshotChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) |
| 69 | - .toolNames(toolNames).toolContext(toolContext).build(); | 67 | + .toolCallbacks(toolCallbacks).toolContext(toolContext).build(); |
| 70 | case OPENAI: | 68 | case OPENAI: |
| 71 | case GEMINI: // 复用 OpenAI 客户端 | 69 | case GEMINI: // 复用 OpenAI 客户端 |
| 72 | case BAI_CHUAN: // 复用 OpenAI 客户端 | 70 | case BAI_CHUAN: // 复用 OpenAI 客户端 |
| 73 | return OpenAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | 71 | return OpenAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) |
| 74 | - .toolNames(toolNames).toolContext(toolContext).build(); | 72 | + .toolCallbacks(toolCallbacks).toolContext(toolContext).build(); |
| 75 | case AZURE_OPENAI: | 73 | case AZURE_OPENAI: |
| 76 | return AzureOpenAiChatOptions.builder().deploymentName(model).temperature(temperature).maxTokens(maxTokens) | 74 | return AzureOpenAiChatOptions.builder().deploymentName(model).temperature(temperature).maxTokens(maxTokens) |
| 77 | - .toolNames(toolNames).toolContext(toolContext).build(); | 75 | + .toolCallbacks(toolCallbacks).toolContext(toolContext).build(); |
| 78 | case ANTHROPIC: | 76 | case ANTHROPIC: |
| 79 | return AnthropicChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | 77 | return AnthropicChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) |
| 80 | - .toolNames(toolNames).toolContext(toolContext).build(); | 78 | + .toolCallbacks(toolCallbacks).toolContext(toolContext).build(); |
| 81 | case OLLAMA: | 79 | case OLLAMA: |
| 82 | return OllamaOptions.builder().model(model).temperature(temperature).numPredict(maxTokens) | 80 | return OllamaOptions.builder().model(model).temperature(temperature).numPredict(maxTokens) |
| 83 | - .toolNames(toolNames).toolContext(toolContext).build(); | 81 | + .toolCallbacks(toolCallbacks).toolContext(toolContext).build(); |
| 84 | default: | 82 | default: |
| 85 | throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); | 83 | throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); |
| 86 | } | 84 | } |
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/mcp/DouBaoMcpTests.java
| @@ -36,44 +36,47 @@ public class DouBaoMcpTests { | @@ -36,44 +36,47 @@ public class DouBaoMcpTests { | ||
| 36 | 36 | ||
| 37 | @Test | 37 | @Test |
| 38 | public void testMcpGetUserInfo() { | 38 | public void testMcpGetUserInfo() { |
| 39 | - | ||
| 40 | // 打印结果 | 39 | // 打印结果 |
| 41 | System.out.println(chatClient.prompt() | 40 | System.out.println(chatClient.prompt() |
| 42 | .user("目前有哪些工具可以使用") | 41 | .user("目前有哪些工具可以使用") |
| 43 | .call() | 42 | .call() |
| 44 | .content()); | 43 | .content()); |
| 45 | System.out.println("===================================="); | 44 | System.out.println("===================================="); |
| 45 | + | ||
| 46 | // 打印结果 | 46 | // 打印结果 |
| 47 | System.out.println(chatClient.prompt() | 47 | System.out.println(chatClient.prompt() |
| 48 | .user("小新的年龄是多少") | 48 | .user("小新的年龄是多少") |
| 49 | .call() | 49 | .call() |
| 50 | .content()); | 50 | .content()); |
| 51 | System.out.println("===================================="); | 51 | System.out.println("===================================="); |
| 52 | + | ||
| 52 | // 打印结果 | 53 | // 打印结果 |
| 53 | System.out.println(chatClient.prompt() | 54 | System.out.println(chatClient.prompt() |
| 54 | .user("获取小新的基本信息") | 55 | .user("获取小新的基本信息") |
| 55 | .call() | 56 | .call() |
| 56 | .content()); | 57 | .content()); |
| 57 | System.out.println("===================================="); | 58 | System.out.println("===================================="); |
| 59 | + | ||
| 58 | // 打印结果 | 60 | // 打印结果 |
| 59 | System.out.println(chatClient.prompt() | 61 | System.out.println(chatClient.prompt() |
| 60 | .user("小新是什么职业的") | 62 | .user("小新是什么职业的") |
| 61 | .call() | 63 | .call() |
| 62 | .content()); | 64 | .content()); |
| 63 | System.out.println("===================================="); | 65 | System.out.println("===================================="); |
| 66 | + | ||
| 64 | // 打印结果 | 67 | // 打印结果 |
| 65 | System.out.println(chatClient.prompt() | 68 | System.out.println(chatClient.prompt() |
| 66 | .user("小新的教育背景") | 69 | .user("小新的教育背景") |
| 67 | .call() | 70 | .call() |
| 68 | .content()); | 71 | .content()); |
| 69 | System.out.println("===================================="); | 72 | System.out.println("===================================="); |
| 73 | + | ||
| 70 | // 打印结果 | 74 | // 打印结果 |
| 71 | System.out.println(chatClient.prompt() | 75 | System.out.println(chatClient.prompt() |
| 72 | .user("小新的兴趣爱好是什么") | 76 | .user("小新的兴趣爱好是什么") |
| 73 | .call() | 77 | .call() |
| 74 | .content()); | 78 | .content()); |
| 75 | System.out.println("===================================="); | 79 | System.out.println("===================================="); |
| 76 | - | ||
| 77 | } | 80 | } |
| 78 | 81 | ||
| 79 | 82 |