SkillService.java
2.12 KB
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
package com.xly.service;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* Skill 注册表服务(架构 §6)。
*
* <p>Skill = 针对重复任务的 playbook(新建报价 / 月度对账 / 库存盘点)。渐进披露:
* {@link #promptDigest()} 把「name + 何时用」摘要注入 system prompt(便宜、常驻);
* {@link #load(String)} 在 {@code load_skill} 工具被调用时返回完整指令。数据在 {@code ai_skill} 表。
*/
@Service
public class SkillService {
private final JdbcTemplate jdbc;
public SkillService(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
/** 供 system prompt 的 Skill 摘要(name + 何时用),一行一个。KG/表缺失时降级为空串。 */
public String promptDigest() {
try {
List<Map<String, Object>> rows = jdbc.queryForList(
"SELECT sName, sWhenToUse FROM ai_skill WHERE bEnabled=1 ORDER BY iOrder");
if (rows.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
for (Map<String, Object> r : rows) {
sb.append("- ").append(r.get("sName")).append(":").append(r.get("sWhenToUse")).append("\n");
}
return sb.toString();
} catch (Exception e) {
return "";
}
}
/** 按名称加载完整 playbook(精确优先,模糊兜底)。返回 null = 找不到。 */
public Map<String, Object> load(String name) {
if (name == null || name.isBlank()) {
return null;
}
List<Map<String, Object>> r = jdbc.queryForList(
"SELECT sName, sInstructions, sSuggested FROM ai_skill WHERE bEnabled=1 AND sName=? LIMIT 1", name.trim());
if (r.isEmpty()) {
r = jdbc.queryForList(
"SELECT sName, sInstructions, sSuggested FROM ai_skill WHERE bEnabled=1 AND sName LIKE ? ORDER BY iOrder LIMIT 1",
"%" + name.trim() + "%");
}
return r.isEmpty() ? null : r.get(0);
}
}