接上节继续今天来学习Skill的使用要说明的是目前langchain4j关于SKILL的API尚在试验阶段未来可能会有较大变化生产环境使用时请大家谨慎。先添加pom依赖View Code以下是使用步骤一、编写SKILL.md说明这里我们以订单处理为示例写1个process-order的skill---name: process-orderdescription: 处理客户订单---处理订单的步骤1. 调用 validateOrder(orderId) 检查订单是否有效。2. 调用 reserveInventory(orderId) 预留所需库存。3. 仅当预留成功时调用 chargePayment(orderId) 进行扣款。4. 最后调用 sendConfirmationEmail(orderId) 发送确认邮件。如果任何步骤失败在报告错误之前调用 rollbackOrder(orderId) 回滚订单。skill有多种存储方式本例直接存放于文件src/main/resources/skills/process-order/SKILL.md二、定义Toolsprocess-order的skill中会用到一系列Tool这里给出mock实现1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162packagecom.cnblogs.yjmyzz.langchain4j.study.tools;importdev.langchain4j.agent.tool.Tool;importorg.springframework.stereotype.Component;/*** 一组用于处理客户订单的工具。* 当 process-order SKILL激活时LLM 将调用这些方法。*/ComponentpublicclassOrderTools {Tool(验证订单ID是否有效)publicString validateOrder(String orderId) {System.out.println(工具正在验证订单 orderId);// 模拟验证逻辑if(orderId !null orderId.startsWith(ORD)) {System.out.println(订单 orderId 有效。);return订单 orderId 有效。;}else{System.out.println(订单 orderId 无效。);return订单 orderId 无效。;}}Tool(为指定订单ID预留库存。返回成功或失败信息。)publicString reserveInventory(String orderId) {System.out.println(工具正在为订单预留库存 orderId);// 模拟库存预留if(ORD001.equals(orderId)) {// 模拟成功示例System.out.println(订单 orderId 的库存已预留。);return订单 orderId 的库存已预留。;}elseif(ORD002.equals(orderId)) {// 模拟失败示例System.out.println(为订单 orderId 预留库存失败。库存不足。);return为订单 orderId 预留库存失败。库存不足。;}else{System.out.println(订单 orderId 的库存预留状态未知。);return订单 orderId 的库存预留状态未知。;}}Tool(为指定订单ID扣款。返回支付状态。)publicString chargePayment(String orderId) {System.out.println(工具正在为订单扣款 orderId);// 模拟支付处理return订单 orderId 扣款成功。;}Tool(向客户发送指定订单ID的确认邮件。返回确认状态。)publicString sendConfirmationEmail(String orderId) {System.out.println(工具正在为订单发送确认邮件 orderId);// 模拟邮件发送return订单 orderId 的确认邮件已发送。;}Tool(因处理出错回滚订单。返回回滚状态。)publicString rollbackOrder(String orderId) {System.out.println(工具因失败正在回滚订单 orderId);// 模拟回滚return订单 orderId 已成功回滚。;}}三、定义AIService123456789packagecom.cnblogs.yjmyzz.langchain4j.study.service;importdev.langchain4j.service.UserMessage;publicinterfaceOrderProcessingAiService {// 系统消息由 Spring 配置中的 AiServices.builder(...).systemMessage(...) 提供String chat(UserMessageString userMessage);}四、添加配置(注入skill)12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576packagecom.cnblogs.yjmyzz.langchain4j.study.config;importcom.cnblogs.yjmyzz.langchain4j.study.service.OrderProcessingAiService;importcom.cnblogs.yjmyzz.langchain4j.study.tools.OrderTools;importdev.langchain4j.memory.chat.MessageWindowChatMemory;importdev.langchain4j.model.chat.ChatModel;importdev.langchain4j.service.AiServices;importdev.langchain4j.service.tool.ToolProvider;importdev.langchain4j.skills.ClassPathSkillLoader;importdev.langchain4j.skills.FileSystemSkill;importdev.langchain4j.skills.Skill;importdev.langchain4j.skills.Skills;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjava.util.List;importjava.util.stream.Collectors;ConfigurationpublicclassLangChain4jConfig {privatefinalOrderTools orderTools;// 自动注入 OrderTools// 注入 OrderTools用于技能作用域的工具publicLangChain4jConfig(OrderTools orderTools) {this.orderTools orderTools;}BeanpublicSkills skills() {// 从类路径下的 skills 目录加载所有技能// 假设你的 SKILL.md 文件位于 src/main/resources/skills/ 下ListFileSystemSkill loadedSkills ClassPathSkillLoader.loadSkills(skills);// 为 process-order 技能附加 OrderTools 作为技能作用域的工具// 这意味着 OrderTools 中的方法只有在显式激活 process-order 技能后// 才会对 LLM 可见ListSkill configuredSkills loadedSkills.stream().map(fsSkill - {if(process-order.equals(fsSkill.name())) {returnSkill.builder().name(fsSkill.name()).description(fsSkill.description()).content(fsSkill.content()).resources(fsSkill.resources()).tools(orderTools)// 附加 OrderTools 作为技能作用域的工具.build();}returnfsSkill;}).collect(Collectors.toList());returnSkills.from(configuredSkills);}BeanpublicToolProvider skillsToolProvider(Skills skills) {// 该 ToolProvider 将处理 activate_skill、read_skill_resource// 并在技能激活时动态暴露技能作用域的工具例如 OrderTools 中的工具returnskills.toolProvider();}BeanpublicOrderProcessingAiService orderProcessingAiService(ChatModel chatModel, Skills skills, ToolProvider skillsToolProvider) {// 构建 AI 服务整合聊天模型、聊天记忆以及技能 ToolProviderreturnAiServices.builder(OrderProcessingAiService.class).chatModel(chatModel).chatMemory(MessageWindowChatMemory.withMaxMessages(100))// 保留对话历史.toolProvider(skillsToolProvider)// 注册技能工具提供者// 将技能目录注入到系统消息中以便 LLM 知道它可以激活哪些技能.systemMessage(你是一个订单处理助手。你可以使用以下技能\n skills.formatAvailableSkills()// 将技能格式化为 XML 提供给 LLM\n当用户请求与这些技能之一相关时请先使用 activate_skill 工具激活该技能然后再继续处理。).build();}}五、使用Skill123456789101112131415161718192021222324252627282930313233packagecom.cnblogs.yjmyzz.langchain4j.study.controller;importcom.cnblogs.yjmyzz.langchain4j.study.service.OrderProcessingAiService;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;/*** 与使用技能的 LangChain4j AI 服务进行交互的 REST 控制器。*/RestControllerpublicclassOrderController {privatefinalOrderProcessingAiService orderProcessingAiService;// 自动注入 AI 服务publicOrderController(OrderProcessingAiService orderProcessingAiService) {this.orderProcessingAiService orderProcessingAiService;}/*** 与订单处理 AI 助手进行聊天的端点。* 示例http://localhost:8080/chat/order?message处理订单 ORD001* 示例http://localhost:8080/chat/order?message你叫什么名字*/GetMapping(/chat/order)publicString chatWithOrderAssistant(RequestParam(value message, defaultValue 处理订单 ORD001) String message) {System.out.println(用户消息 message);String aiResponse orderProcessingAiService.chat(message);System.out.println(AI 回复 aiResponse);returnaiResponse;}}六、测试运行http://localhost:8080/chat/order?message处理订单 ORD00112345678910111213141516用户消息处理订单 ORD001工具正在验证订单ORD001订单 ORD001 有效。工具正在为订单预留库存ORD001订单 ORD001 的库存已预留。工具正在为订单扣款ORD001工具正在为订单发送确认邮件ORD001AI 回复✅ 订单 ORD001 处理完成处理结果- ✅ 订单验证有效- ✅ 库存预留成功- ✅ 支付扣款成功- ✅ 确认邮件已发送订单 ORD001 已成功处理完毕客户将收到确认邮件。http://localhost:8080/chat/order?message处理订单 ORD002123456789101112131415用户消息处理订单 ORD002工具正在验证订单ORD002订单 ORD002 有效。工具正在为订单预留库存ORD002为订单 ORD002 预留库存失败。库存不足。工具因失败正在回滚订单ORD002AI 回复❌ 订单 ORD002 处理失败处理结果- ✅ 订单验证有效- ❌ 库存预留失败库存不足- ➖ 支付扣款未执行因库存预留失败- ➖ 确认邮件未发送
langchain4j 学习系列(10)-Skill使用示例
接上节继续今天来学习Skill的使用要说明的是目前langchain4j关于SKILL的API尚在试验阶段未来可能会有较大变化生产环境使用时请大家谨慎。先添加pom依赖View Code以下是使用步骤一、编写SKILL.md说明这里我们以订单处理为示例写1个process-order的skill---name: process-orderdescription: 处理客户订单---处理订单的步骤1. 调用 validateOrder(orderId) 检查订单是否有效。2. 调用 reserveInventory(orderId) 预留所需库存。3. 仅当预留成功时调用 chargePayment(orderId) 进行扣款。4. 最后调用 sendConfirmationEmail(orderId) 发送确认邮件。如果任何步骤失败在报告错误之前调用 rollbackOrder(orderId) 回滚订单。skill有多种存储方式本例直接存放于文件src/main/resources/skills/process-order/SKILL.md二、定义Toolsprocess-order的skill中会用到一系列Tool这里给出mock实现1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162packagecom.cnblogs.yjmyzz.langchain4j.study.tools;importdev.langchain4j.agent.tool.Tool;importorg.springframework.stereotype.Component;/*** 一组用于处理客户订单的工具。* 当 process-order SKILL激活时LLM 将调用这些方法。*/ComponentpublicclassOrderTools {Tool(验证订单ID是否有效)publicString validateOrder(String orderId) {System.out.println(工具正在验证订单 orderId);// 模拟验证逻辑if(orderId !null orderId.startsWith(ORD)) {System.out.println(订单 orderId 有效。);return订单 orderId 有效。;}else{System.out.println(订单 orderId 无效。);return订单 orderId 无效。;}}Tool(为指定订单ID预留库存。返回成功或失败信息。)publicString reserveInventory(String orderId) {System.out.println(工具正在为订单预留库存 orderId);// 模拟库存预留if(ORD001.equals(orderId)) {// 模拟成功示例System.out.println(订单 orderId 的库存已预留。);return订单 orderId 的库存已预留。;}elseif(ORD002.equals(orderId)) {// 模拟失败示例System.out.println(为订单 orderId 预留库存失败。库存不足。);return为订单 orderId 预留库存失败。库存不足。;}else{System.out.println(订单 orderId 的库存预留状态未知。);return订单 orderId 的库存预留状态未知。;}}Tool(为指定订单ID扣款。返回支付状态。)publicString chargePayment(String orderId) {System.out.println(工具正在为订单扣款 orderId);// 模拟支付处理return订单 orderId 扣款成功。;}Tool(向客户发送指定订单ID的确认邮件。返回确认状态。)publicString sendConfirmationEmail(String orderId) {System.out.println(工具正在为订单发送确认邮件 orderId);// 模拟邮件发送return订单 orderId 的确认邮件已发送。;}Tool(因处理出错回滚订单。返回回滚状态。)publicString rollbackOrder(String orderId) {System.out.println(工具因失败正在回滚订单 orderId);// 模拟回滚return订单 orderId 已成功回滚。;}}三、定义AIService123456789packagecom.cnblogs.yjmyzz.langchain4j.study.service;importdev.langchain4j.service.UserMessage;publicinterfaceOrderProcessingAiService {// 系统消息由 Spring 配置中的 AiServices.builder(...).systemMessage(...) 提供String chat(UserMessageString userMessage);}四、添加配置(注入skill)12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576packagecom.cnblogs.yjmyzz.langchain4j.study.config;importcom.cnblogs.yjmyzz.langchain4j.study.service.OrderProcessingAiService;importcom.cnblogs.yjmyzz.langchain4j.study.tools.OrderTools;importdev.langchain4j.memory.chat.MessageWindowChatMemory;importdev.langchain4j.model.chat.ChatModel;importdev.langchain4j.service.AiServices;importdev.langchain4j.service.tool.ToolProvider;importdev.langchain4j.skills.ClassPathSkillLoader;importdev.langchain4j.skills.FileSystemSkill;importdev.langchain4j.skills.Skill;importdev.langchain4j.skills.Skills;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjava.util.List;importjava.util.stream.Collectors;ConfigurationpublicclassLangChain4jConfig {privatefinalOrderTools orderTools;// 自动注入 OrderTools// 注入 OrderTools用于技能作用域的工具publicLangChain4jConfig(OrderTools orderTools) {this.orderTools orderTools;}BeanpublicSkills skills() {// 从类路径下的 skills 目录加载所有技能// 假设你的 SKILL.md 文件位于 src/main/resources/skills/ 下ListFileSystemSkill loadedSkills ClassPathSkillLoader.loadSkills(skills);// 为 process-order 技能附加 OrderTools 作为技能作用域的工具// 这意味着 OrderTools 中的方法只有在显式激活 process-order 技能后// 才会对 LLM 可见ListSkill configuredSkills loadedSkills.stream().map(fsSkill - {if(process-order.equals(fsSkill.name())) {returnSkill.builder().name(fsSkill.name()).description(fsSkill.description()).content(fsSkill.content()).resources(fsSkill.resources()).tools(orderTools)// 附加 OrderTools 作为技能作用域的工具.build();}returnfsSkill;}).collect(Collectors.toList());returnSkills.from(configuredSkills);}BeanpublicToolProvider skillsToolProvider(Skills skills) {// 该 ToolProvider 将处理 activate_skill、read_skill_resource// 并在技能激活时动态暴露技能作用域的工具例如 OrderTools 中的工具returnskills.toolProvider();}BeanpublicOrderProcessingAiService orderProcessingAiService(ChatModel chatModel, Skills skills, ToolProvider skillsToolProvider) {// 构建 AI 服务整合聊天模型、聊天记忆以及技能 ToolProviderreturnAiServices.builder(OrderProcessingAiService.class).chatModel(chatModel).chatMemory(MessageWindowChatMemory.withMaxMessages(100))// 保留对话历史.toolProvider(skillsToolProvider)// 注册技能工具提供者// 将技能目录注入到系统消息中以便 LLM 知道它可以激活哪些技能.systemMessage(你是一个订单处理助手。你可以使用以下技能\n skills.formatAvailableSkills()// 将技能格式化为 XML 提供给 LLM\n当用户请求与这些技能之一相关时请先使用 activate_skill 工具激活该技能然后再继续处理。).build();}}五、使用Skill123456789101112131415161718192021222324252627282930313233packagecom.cnblogs.yjmyzz.langchain4j.study.controller;importcom.cnblogs.yjmyzz.langchain4j.study.service.OrderProcessingAiService;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;/*** 与使用技能的 LangChain4j AI 服务进行交互的 REST 控制器。*/RestControllerpublicclassOrderController {privatefinalOrderProcessingAiService orderProcessingAiService;// 自动注入 AI 服务publicOrderController(OrderProcessingAiService orderProcessingAiService) {this.orderProcessingAiService orderProcessingAiService;}/*** 与订单处理 AI 助手进行聊天的端点。* 示例http://localhost:8080/chat/order?message处理订单 ORD001* 示例http://localhost:8080/chat/order?message你叫什么名字*/GetMapping(/chat/order)publicString chatWithOrderAssistant(RequestParam(value message, defaultValue 处理订单 ORD001) String message) {System.out.println(用户消息 message);String aiResponse orderProcessingAiService.chat(message);System.out.println(AI 回复 aiResponse);returnaiResponse;}}六、测试运行http://localhost:8080/chat/order?message处理订单 ORD00112345678910111213141516用户消息处理订单 ORD001工具正在验证订单ORD001订单 ORD001 有效。工具正在为订单预留库存ORD001订单 ORD001 的库存已预留。工具正在为订单扣款ORD001工具正在为订单发送确认邮件ORD001AI 回复✅ 订单 ORD001 处理完成处理结果- ✅ 订单验证有效- ✅ 库存预留成功- ✅ 支付扣款成功- ✅ 确认邮件已发送订单 ORD001 已成功处理完毕客户将收到确认邮件。http://localhost:8080/chat/order?message处理订单 ORD002123456789101112131415用户消息处理订单 ORD002工具正在验证订单ORD002订单 ORD002 有效。工具正在为订单预留库存ORD002为订单 ORD002 预留库存失败。库存不足。工具因失败正在回滚订单ORD002AI 回复❌ 订单 ORD002 处理失败处理结果- ✅ 订单验证有效- ❌ 库存预留失败库存不足- ➖ 支付扣款未执行因库存预留失败- ➖ 确认邮件未发送