LLM大模型开发使用MCP+Skill 模式(LLM大模型智能调用工具执行业务返回结果)
·
-
用户输入自然语言
我上周买的手机为什么还没发货? -
LLM 自动决策
- 识别意图:订单问题
- 自动匹配 Skill:
订单查询技能
-
LLM 自动生成 MCP 调用
- 调用
query_order - 调用
query_logistics
- 调用
-
执行 MCP 工具去后端 / 数据库 / 接口查数据
-
LLM 整理结果 → 返回自然语言回答
-
AiConfig 注册工具
LlmTools
-
@Bean public DecisionAgent decisionAgent(ChatModel chatLanguageModel, ChatMemoryStore chatMemoryStore, com.example.ai.tools.LlmTools llmTools) { ChatMemory chatMemory = MessageWindowChatMemory.builder() .maxMessages(20) .chatMemoryStore(chatMemoryStore) .build(); return AiServices.builder(DecisionAgent.class) .chatModel(chatLanguageModel) .chatMemory(chatMemory) .tools(llmTools) .build(); }在LlmTools 工具中定义要实现的业务内容,由LLm大模型识别用户意图,然后自行调用
-
LlmTools
package com.example.ai.tools; import dev.langchain4j.agent.tool.Tool; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @Slf4j @Component public class LlmTools { @Tool("对文本进行摘要总结,提取核心要点,保持简洁") public String summarize(String text) { log.info("LlmTools - summarize called with text length: {}", text.length()); String prompt = """ 请对以下文本进行摘要总结: {{text}} 要求: 1. 提取核心要点 2. 保持简洁,不超过200字 3. 使用中文 """.replace("{{text}}", text); return prompt; } @Tool("翻译文本到指定语言,如中文、English、日语等") public String translate(String text, String targetLanguage) { log.info("LlmTools - translate called with text length: {}, targetLanguage: {}", text.length(), targetLanguage); String prompt = """ 请将以下文本翻译成{{targetLanguage}}: {{text}} 要求: 1. 翻译准确完整 2. 保持原文风格 """.replace("{{text}}", text) .replace("{{targetLanguage}}", targetLanguage); return prompt; } @Tool("分析文本的情感倾向,判断是正面、中性还是负面") public String analyzeSentiment(String text) { log.info("LlmTools - analyzeSentiment called with text length: {}", text.length()); String prompt = """ 请分析以下文本的情感倾向: {{text}} 要求: 1. 判断情感类型:正面、中性、负面 2. 给出简短理由 3. 使用中文回答 """.replace("{{text}}", text); return prompt; } @Tool("搜索知识库获取相关信息") public String searchKnowledge(String query) { log.info("LlmTools - searchKnowledge called with query: {}", query); return "搜索知识库: " + query; } @Tool("获取当前时间") public String getCurrentTime() { String currentTime = java.time.LocalDateTime.now() .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); log.info("LlmTools - getCurrentTime called, returning: {}", currentTime); return currentTime; } }由LLM大模型 识别意图自主使用Skill来调用哪个mcp工具
-
Skill
package com.example.ai.skill; import com.example.ai.config.AiConfig.DecisionAgent; import com.example.ai.mcp.LlmMcpServer; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import java.util.Map; @Slf4j @Component public class LlmSkill { private final LlmMcpServer llmMcpServer; private final DecisionAgent decisionAgent; public LlmSkill(LlmMcpServer llmMcpServer, DecisionAgent decisionAgent) { this.llmMcpServer = llmMcpServer; this.decisionAgent = decisionAgent; } public Map<String, Object> chat(Map<String, Object> params) { String sessionId = (String) params.get("sessionId"); String message = (String) params.get("message"); String systemPrompt = (String) params.getOrDefault("systemPrompt", null); log.info("LlmSkill - chat called with sessionId: {}, message: {}", sessionId, message != null ? message.substring(0, Math.min(50, message.length())) : "null"); String response; if (systemPrompt != null && !systemPrompt.isEmpty()) { response = llmMcpServer.chat(sessionId, message, systemPrompt); } else { response = llmMcpServer.chat(sessionId, message); } return Map.of( "response", response, "sessionId", sessionId ); } public Map<String, Object> autoDecisionChat(Map<String, Object> params) { String sessionId = (String) params.get("sessionId"); String message = (String) params.get("message"); log.info("LlmSkill - autoDecisionChat called with sessionId: {}, message: {}", sessionId, message != null ? message.substring(0, Math.min(50, message.length())) : "null"); String response = decisionAgent.chat(message); log.info("LlmSkill - autoDecisionChat response: {}", response.substring(0, Math.min(100, response.length()))); return Map.of( "response", response, "sessionId", sessionId, "usedTool", true ); } public Map<String, Object> streamChat(Map<String, Object> params) { String sessionId = (String) params.get("sessionId"); String message = (String) params.get("message"); String systemPrompt = (String) params.getOrDefault("systemPrompt", null); log.info("LlmSkill - streamChat called with sessionId: {}, message: {}", sessionId, message != null ? message.substring(0, Math.min(50, message.length())) : "null"); Flux<String> stream; if (systemPrompt != null && !systemPrompt.isEmpty()) { stream = llmMcpServer.streamChat(sessionId, message, systemPrompt); } else { stream = llmMcpServer.streamChat(sessionId, message); } return Map.of( "stream", stream, "streamId", sessionId + "_" + System.currentTimeMillis(), "sessionId", sessionId ); } public Map<String, Object> summarize(Map<String, Object> params) { String text = (String) params.get("text"); log.info("LlmSkill - summarize called with text length: {}", text != null ? text.length() : 0); String summary = llmMcpServer.summarize(text); return Map.of("summary", summary); } public Map<String, Object> translate(Map<String, Object> params) { String text = (String) params.get("text"); String targetLanguage = (String) params.get("targetLanguage"); log.info("LlmSkill - translate called with text length: {}, targetLanguage: {}", text != null ? text.length() : 0, targetLanguage); String translation = llmMcpServer.translate(text, targetLanguage); return Map.of( "translation", translation, "targetLanguage", targetLanguage ); } public Map<String, Object> analyzeSentiment(Map<String, Object> params) { String text = (String) params.get("text"); log.info("LlmSkill - analyzeSentiment called with text length: {}", text != null ? text.length() : 0); String result = llmMcpServer.analyzeSentiment(text); String sentiment = extractSentiment(result); String reason = extractReason(result); return Map.of( "sentiment", sentiment, "reason", reason ); } public Map<String, Object> clearSession(Map<String, Object> params) { String sessionId = (String) params.get("sessionId"); log.info("LlmSkill - clearSession called with sessionId: {}", sessionId); llmMcpServer.clearSession(sessionId); return Map.of( "success", true, "sessionId", sessionId ); } private String extractSentiment(String result) { if (result.contains("正面")) { return "正面"; } else if (result.contains("负面")) { return "负面"; } else if (result.contains("中性")) { return "中性"; } return "中性"; } private String extractReason(String result) { int reasonIndex = result.indexOf("理由"); if (reasonIndex != -1) { return result.substring(reasonIndex + 2).trim(); } return result; } }Mcp执行工具
-
package com.example.ai.mcp; import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.chat.ChatModel; import dev.langchain4j.model.ollama.OllamaStreamingChatModel; import dev.langchain4j.service.AiServices; import dev.langchain4j.service.SystemMessage; import dev.langchain4j.service.UserMessage; import dev.langchain4j.store.memory.chat.ChatMemoryStore; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Slf4j @Component public class LlmMcpServer { private final ChatModel chatModel; private final OllamaStreamingChatModel streamingChatModel; private final ChatMemoryStore chatMemoryStore; @Value("${ai.llm.system-prompt:你是一位专业的AI助手,请友好、专业地回答用户问题。}") private String systemPrompt; private final Map<String, LlmAgent> agentCache = new ConcurrentHashMap<>(); public interface LlmAgent { @SystemMessage(""" {{system_prompt}} 当前时间:{{current_time}} """) String chat(@UserMessage String userMessage, @dev.langchain4j.service.V("system_prompt") String systemPrompt, @dev.langchain4j.service.V("current_time") String currentTime); @SystemMessage("{{system_prompt}}") Flux<String> streamChat(@UserMessage String userMessage, @dev.langchain4j.service.V("system_prompt") String systemPrompt); } public LlmMcpServer(ChatModel chatModel, OllamaStreamingChatModel streamingChatModel, ChatMemoryStore chatMemoryStore) { this.chatModel = chatModel; this.streamingChatModel = streamingChatModel; this.chatMemoryStore = chatMemoryStore; } public String chat(String sessionId, String message) { return chat(sessionId, message, systemPrompt); } public String chat(String sessionId, String message, String customSystemPrompt) { LlmAgent agent = agentCache.computeIfAbsent(sessionId, sid -> { ChatMemory chatMemory = MessageWindowChatMemory.builder() .id(sid) .maxMessages(20) .chatMemoryStore(chatMemoryStore) .build(); return AiServices.builder(LlmAgent.class) .chatModel(chatModel) .chatMemory(chatMemory) .build(); }); String currentTime = LocalDateTime.now() .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); String response = agent.chat(message, customSystemPrompt, currentTime); log.info("LLM MCP - Session[{}] User: {} | Response: {}", sessionId, message.substring(0, Math.min(50, message.length())), response.substring(0, Math.min(100, response.length()))); return response; } public Flux<String> streamChat(String sessionId, String message) { return streamChat(sessionId, message, systemPrompt); } public Flux<String> streamChat(String sessionId, String message, String customSystemPrompt) { LlmAgent agent = agentCache.computeIfAbsent(sessionId, sid -> { ChatMemory chatMemory = MessageWindowChatMemory.builder() .id(sid) .maxMessages(20) .chatMemoryStore(chatMemoryStore) .build(); return AiServices.builder(LlmAgent.class) .streamingChatModel(streamingChatModel) .chatMemory(chatMemory) .build(); }); log.info("LLM MCP - Streaming Session[{}] User: {}", sessionId, message.substring(0, Math.min(50, message.length()))); return agent.streamChat(message, customSystemPrompt); } public void clearSession(String sessionId) { agentCache.remove(sessionId); chatMemoryStore.deleteMessages(sessionId); log.info("LLM MCP - Session[{}] cleared", sessionId); } public String summarize(String text) { String prompt = """ 请对以下文本进行摘要总结: {{text}} 要求: 1. 提取核心要点 2. 保持简洁,不超过200字 3. 使用中文 """; prompt = prompt.replace("{{text}}", text); LlmAgent summarizer = AiServices.builder(LlmAgent.class) .chatModel(chatModel) .build(); return summarizer.chat(prompt, "你是一位专业的文本摘要助手。", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); } public String translate(String text, String targetLanguage) { String prompt = """ 请将以下文本翻译成{{target_language}}: {{text}} 要求: 1. 翻译准确完整 2. 保持原文风格 """; prompt = prompt.replace("{{text}}", text) .replace("{{target_language}}", targetLanguage); LlmAgent translator = AiServices.builder(LlmAgent.class) .chatModel(chatModel) .build(); return translator.chat(prompt, "你是一位专业的翻译助手,精通多种语言。", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); } public String analyzeSentiment(String text) { String prompt = """ 请分析以下文本的情感倾向: {{text}} 要求: 1. 判断情感类型:正面、中性、负面 2. 给出简短理由 3. 使用中文回答 """; prompt = prompt.replace("{{text}}", text); LlmAgent analyzer = AiServices.builder(LlmAgent.class) .chatModel(chatModel) .build(); return analyzer.chat(prompt, "你是一位专业的情感分析助手。", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); } }
接收用户请求的controller
package com.example.ai.controller;
import com.example.ai.skill.LlmSkill;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.UUID;
@Slf4j
@RestController
@RequestMapping("/api/llm")
@RequiredArgsConstructor
public class LlmController {
private final LlmSkill llmSkill;
@PostMapping("/auto-decision")
public ResponseEntity<Map<String, Object>> autoDecisionChat(@RequestBody AutoDecisionRequest request) {
log.info("收到自动决策请求 - sessionId: {}, message: {}",
request.sessionId,
request.message != null ? request.message.substring(0, Math.min(50, request.message.length())) : "null");
String sessionId = request.sessionId != null ? request.sessionId : UUID.randomUUID().toString();
Map<String, Object> result = llmSkill.autoDecisionChat(Map.of(
"sessionId", sessionId,
"message", request.message
));
return ResponseEntity.ok(result);
}
@PostMapping("/chat")
public ResponseEntity<Map<String, Object>> chat(@RequestBody ChatRequest request) {
log.info("收到普通聊天请求 - sessionId: {}, message: {}",
request.sessionId,
request.message != null ? request.message.substring(0, Math.min(50, request.message.length())) : "null");
String sessionId = request.sessionId != null ? request.sessionId : UUID.randomUUID().toString();
Map<String, Object> params = Map.of(
"sessionId", sessionId,
"message", request.message
);
if (request.systemPrompt != null && !request.systemPrompt.isEmpty()) {
params = Map.of(
"sessionId", sessionId,
"message", request.message,
"systemPrompt", request.systemPrompt
);
}
Map<String, Object> result = llmSkill.chat(params);
return ResponseEntity.ok(result);
}
@PostMapping("/summarize")
public ResponseEntity<Map<String, Object>> summarize(@RequestBody SummarizeRequest request) {
log.info("收到摘要请求 - text length: {}", request.text != null ? request.text.length() : 0);
Map<String, Object> result = llmSkill.summarize(Map.of("text", request.text));
return ResponseEntity.ok(result);
}
@PostMapping("/translate")
public ResponseEntity<Map<String, Object>> translate(@RequestBody TranslateRequest request) {
log.info("收到翻译请求 - text length: {}, targetLanguage: {}",
request.text != null ? request.text.length() : 0,
request.targetLanguage);
Map<String, Object> result = llmSkill.translate(Map.of(
"text", request.text,
"targetLanguage", request.targetLanguage
));
return ResponseEntity.ok(result);
}
@PostMapping("/sentiment")
public ResponseEntity<Map<String, Object>> analyzeSentiment(@RequestBody SentimentRequest request) {
log.info("收到情感分析请求 - text length: {}", request.text != null ? request.text.length() : 0);
Map<String, Object> result = llmSkill.analyzeSentiment(Map.of("text", request.text));
return ResponseEntity.ok(result);
}
@DeleteMapping("/session/{sessionId}")
public ResponseEntity<Map<String, Object>> clearSession(@PathVariable String sessionId) {
log.info("收到清除会话请求 - sessionId: {}", sessionId);
Map<String, Object> result = llmSkill.clearSession(Map.of("sessionId", sessionId));
return ResponseEntity.ok(result);
}
public record AutoDecisionRequest(String sessionId, String message) {}
public record ChatRequest(String sessionId, String message, String systemPrompt) {}
public record SummarizeRequest(String text) {}
public record TranslateRequest(String text, String targetLanguage) {}
public record SentimentRequest(String text) {}
}
完成代码可以参考
https://gitee.com/bluethky/ai-service-1.4.git
欢迎各位同学互相交流
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)