当前位置: 首页 > news >正文

langchain4j 学习系列(10)-Skill使用示例

接上节继续,今天来学习Skill的使用,要说明的是:目前langchain4j关于SKILL的API尚在试验阶段,未来可能会有较大变化,生产环境使用时,请大家谨慎。

先添加pom依赖:

View Code

以下是使用步骤:

一、编写SKILL.md说明

这里我们以订单处理为示例,写1个process-order的skill

---

name: process-order

description: 处理客户订单

---

处理订单的步骤:

1. 调用 validateOrder(orderId) 检查订单是否有效。

2. 调用 reserveInventory(orderId) 预留所需库存。

3. 仅当预留成功时,调用 chargePayment(orderId) 进行扣款。

4. 最后,调用 sendConfirmationEmail(orderId) 发送确认邮件。

如果任何步骤失败,在报告错误之前调用 rollbackOrder(orderId) 回滚订单。

skill有多种存储方式,本例直接存放于文件src/main/resources/skills/process-order/SKILL.md

二、定义Tools

process-order的skill中,会用到一系列Tool,这里给出mock实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

packagecom.cnblogs.yjmyzz.langchain4j.study.tools;

importdev.langchain4j.agent.tool.Tool;

importorg.springframework.stereotype.Component;

/**

* 一组用于处理客户订单的工具。

* 当 'process-order' SKILL激活时,LLM 将调用这些方法。

*/

@Component

publicclassOrderTools {

@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 +" 已成功回滚。";

}

}

三、定义AIService

1

2

3

4

5

6

7

8

9

packagecom.cnblogs.yjmyzz.langchain4j.study.service;

importdev.langchain4j.service.UserMessage;

publicinterfaceOrderProcessingAiService {

// 系统消息由 Spring 配置中的 AiServices.builder(...).systemMessage(...) 提供

String chat(@UserMessageString userMessage);

}

四、添加配置(注入skill)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

packagecom.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;

@Configuration

publicclassLangChain4jConfig {

privatefinalOrderTools orderTools;// 自动注入 OrderTools

// 注入 OrderTools,用于技能作用域的工具

publicLangChain4jConfig(OrderTools orderTools) {

this.orderTools = orderTools;

}

@Bean

publicSkills skills() {

// 从类路径下的 'skills' 目录加载所有技能

// 假设你的 SKILL.md 文件位于 src/main/resources/skills/ 下

List<FileSystemSkill> loadedSkills = ClassPathSkillLoader.loadSkills("skills");

// 为 "process-order" 技能附加 OrderTools 作为技能作用域的工具

// 这意味着 OrderTools 中的方法只有在显式激活 "process-order" 技能后,

// 才会对 LLM 可见

List<Skill> 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);

}

@Bean

publicToolProvider skillsToolProvider(Skills skills) {

// 该 ToolProvider 将处理 'activate_skill'、'read_skill_resource'

// 并在技能激活时动态暴露技能作用域的工具(例如 OrderTools 中的工具)

returnskills.toolProvider();

}

@Bean

publicOrderProcessingAiService orderProcessingAiService(ChatModel chatModel, Skills skills, ToolProvider skillsToolProvider) {

// 构建 AI 服务,整合聊天模型、聊天记忆以及技能 ToolProvider

returnAiServices.builder(OrderProcessingAiService.class)

.chatModel(chatModel)

.chatMemory(MessageWindowChatMemory.withMaxMessages(100))// 保留对话历史

.toolProvider(skillsToolProvider)// 注册技能工具提供者

// 将技能目录注入到系统消息中,以便 LLM 知道它可以激活哪些技能

.systemMessage("你是一个订单处理助手。你可以使用以下技能:\n"

+ skills.formatAvailableSkills()// 将技能格式化为 XML 提供给 LLM

+"\n当用户请求与这些技能之一相关时,请先使用 `activate_skill` 工具激活该技能,然后再继续处理。")

.build();

}

}

五、使用Skill

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

packagecom.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 控制器。

*/

@RestController

publicclassOrderController {

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=处理订单 ORD001

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

用户消息:处理订单 ORD001

工具:正在验证订单:ORD001

订单 ORD001 有效。

工具:正在为订单预留库存:ORD001

订单 ORD001 的库存已预留。

工具:正在为订单扣款:ORD001

工具:正在为订单发送确认邮件:ORD001

AI 回复:✅ 订单 ORD001 处理完成!

处理结果:

- ✅ 订单验证:有效

- ✅ 库存预留:成功

- ✅ 支付扣款:成功

- ✅ 确认邮件:已发送

订单 ORD001 已成功处理完毕,客户将收到确认邮件。

http://localhost:8080/chat/order?message=处理订单 ORD002

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

用户消息:处理订单 ORD002

工具:正在验证订单:ORD002

订单 ORD002 有效。

工具:正在为订单预留库存:ORD002

为订单 ORD002 预留库存失败。库存不足。

工具:因失败正在回滚订单:ORD002

AI 回复:❌ 订单 ORD002 处理失败!

处理结果:

- ✅ 订单验证:有效

- ❌ 库存预留:失败(库存不足)

- ➖ 支付扣款:未执行(因库存预留失败)

- ➖ 确认邮件:未发送

http://www.jsqmd.com/news/1106291/

相关文章:

  • LinuxShell编程基础学习笔记
  • 2026年无线物联网融合网络设备十大品牌排行榜
  • 量子优化算法FPC-QAOA:突破参数爆炸难题
  • 35岁转行AI大模型:挑战、机遇与实战路径
  • 服务端开发爱好者
  • 心情值游戏系统实现
  • [特殊字符] 搬砖的秘密:为什么一次搬 64 块砖最快?
  • 车间地坪养护秘籍
  • Rust项目开发完整教程
  • 从WAIC看AI办公新趋势:会议助手正在从“记录工具”变成“组织智能体”
  • Rust语言基础开发教程
  • 一个老股民的十年自白十年炒股没亏,但我劝你别学我
  • 本地化AI漫剧制作:Qwen与ComfyUI实战指南
  • 从 VMware 迁移到 Proxmox VE 的完整方案
  • MAX9744与PIC18LF45K50的音频功率放大系统设计
  • Vue组件开发技巧
  • 单系统登录机制
  • vim源码编译安装 _
  • 贵阳婚纱照拍的最好的是哪一家?
  • view_source
  • 大气层系统完整指南:5个步骤快速安装Switch自定义固件
  • [特殊字符]️ 性能调优手册:把 chunk size 思路落地到你的项目
  • 出现“WSL 安装似乎已损坏”的错误通常意味着Windows子系统对于Linux(WSL)的某些组件可能未正确安装或注册。要解决这个问题,你可以尝试以
  • 【课程设计/毕业设计】基于 Java Web 的乡村茶产业文化传播平台的设计与实现【附源码、数据库、万字文档】
  • Go语言并发模式之WorkerPool设计实践
  • Java接口开发最佳实践
  • 可变系数的脉冲压缩
  • 2026年大模型API选型指南:六大聚合平台多维度实测与避坑建议
  • [Saturate节点]原理解析与实际应用
  • 终极图片浏览神器:ImageGlass完整指南,轻松查看90+图片格式