package com.xly.service; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; /** * 构建 agent 的**唯一** system prompt:模板 {@code prompts/system.txt} + 业务域地图(DB,缓存一次) * + 技能索引({@link SkillService},目录模式下热更)。 * *
所有轮次共用同一份提示 + 同一组固定工具(useSkill/findForms/readFormData/lookupRecord/ * collectForm/proposeWrite/askUser):稳定前缀利于 KV-cache;流程知识在技能文本里, * 由模型按需 useSkill 载入,不再压进 prompt。基准脚本(bench/bench_ext.py --arch new) * 读取同一模板与技能文件,避免复刻漂移。 */ @Service public class SystemPromptService { private final JdbcTemplate jdbc; private final SkillService skills; private volatile String template; private volatile String domainMap; public SystemPromptService(JdbcTemplate jdbc, SkillService skills) { this.jdbc = jdbc; this.skills = skills; } public String prompt() { String t = template; if (t == null) { t = loadTemplate(); template = t; } String d = domainMap; if (d == null) { d = renderDomainMap(); domainMap = d; } String index = skills.indexLines(); if (index.isBlank()) { // 零技能优雅降级:索引空渲染,裸工具 ReAct 正常聊 index = "(当前未配置任何技能,直接用下方工具完成任务。)\n"; } return t.replace("{DOMAIN_MAP}", d).replace("{SKILL_INDEX}", index); } private static String loadTemplate() { try { return new String(new ClassPathResource("prompts/system.txt") .getInputStream().readAllBytes(), StandardCharsets.UTF_8); } catch (Exception e) { throw new IllegalStateException("system prompt 模板缺失(prompts/system.txt)", e); } } private String renderDomainMap() { List