package com.xly.agent; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONWriter; import com.xly.entity.ParamRule; import com.xly.entity.UserSceneSession; import java.util.List; import java.util.stream.Collectors; public class SystemPromptGenerator { public static String generate(String toolName, UserSceneSession session,String sKnowledgeBase) { StringBuilder sb = new StringBuilder(); sb.append("你是一个无情的参数提取器,不是聊天助手。\n\n"); sb.append("【核心任务】\n"); sb.append("从用户输入中提取参数,并立即调用工具 ").append(toolName).append("。\n\n"); sb.append("【绝对指令】\n"); sb.append("1. 严禁与用户对话,严禁输出任何纯文本回复。\n"); sb.append("2. 无论参数缺失多么严重,都必须直接调用工具,缺失字段填空字符串或0。\n"); if(ObjectUtil.isNotEmpty(sKnowledgeBase)){ sb.append("3. 印刷行业知识库:提取参数前,请先理解行业知识库,再进行方法匹配和参数提取,知识库内容如下: \n"); sb.append(" - "+sKnowledgeBase); } sb.append("【参数提取规则】\n"); sb.append("用户输入格式为 \"参数名: 值\" 或 \"参数名 值\",你必须识别参数名并提取对应的值。\n\n"); sb.append("【可提取的参数列表】\n"); List dynamicParamRuleAll = session.getCurrentTool().getParamRuleListAll(); // 从参数定义中提取 for (ParamRule paramRule : dynamicParamRuleAll) { sb.append("- ").append(paramRule.getSParam()).append("\n"); } sb.append("\n【提取示例】\n"); // 动态生成示例(取前3个参数作为示例) int count = 0; for (ParamRule paramRule : dynamicParamRuleAll) { if (count++ >= 3) break; sb.append("- 用户输入 \"").append(paramRule.getSParam()).append(": {值}\" → 提取 ").append(paramRule.getSParam()).append("\n"); } if(ObjectUtil.isNotEmpty(session.getArgs())){ sb.append("【已提取参数】\n"); sb.append(JSON.toJSONString(session.getArgs(), JSONWriter.Feature.PrettyFormat)); } sb.append("\n【工具调用规则】\n"); sb.append("1. 每次只调用一次工具\n"); sb.append("2. 调用后立即停止,不要重复调用\n"); sb.append("3. 不要总结,不要回复用户,只调用工具"); return sb.toString(); } /** * 缺失参数统一提示模板:强制AI调用自定义方法,一次性回填所有参数 */ public static String buildMissParamPrompt(UserSceneSession session, List paramRuleDataMiss) { String methodNo = session.getCurrentTool().getSMethodNo(); // 1. 拼接缺失参数的描述(增加“参数名”和“英文名”的对应,方便模型映射) String paramDesc = paramRuleDataMiss.stream() .map(p -> String.format("- 参数名:%s (对应字段: %s),示例值:%s", p.getSParam(), p.getSParamValue(), p.getSExampleValue())) .collect(Collectors.joining("\n")); // 但根据你的需求,其实 prompt 里并不需要强行插入一个空的 JSON 片段, // 直接告诉模型去“合并”即可。 return String.format(""" 请你根据用户最新的输入,补充缺失的参数,并带着【所有完整参数】立即发起工具调用。 【核心执行规则】 1. **参数合并(至关重要)**:你必须保留上一轮对话中已经获取的参数(如 sSlaveId, operateType 等),并将用户本次提供的新参数与旧参数合并。 2. **必须调用工具**:必须调用工具 `%s`。绝对禁止直接输出 JSON 文本,也绝对禁止向用户反问或索要信息。 3. **完整调用**:请直接生成包含所有参数的 tool_calls 请求。 【已获取数据】 %s 【当前缺失的参数说明】 %s """, methodNo,JSONObject.toJSONString(session.getArgs()), paramDesc); } public static String buildDynamicSystemPrompt(UserSceneSession session) { // 获取当前工具编号(用于 JSON 的 name 字段) String methodNo = session.getCurrentTool().getSMethodNo(); return """ 【极强约束·必须执行】 1. 禁止说话!禁止解释! 2. 必须调用工具! 3. 只输出标准工具调用JSON! ### 任务背景 ### 用户会输入自然语言指令(如“第1行确认”、“全部合并”等)。 你的任务是:解析出【操作类型】和【目标行号】。 ### 解析规则(必须严格遵守) ### 1. **操作类型 (operateType)**: - 如果用户说“全部确认”、“生成多个单据”,识别为:"全部确认" - 如果用户说“合并确认”、“生成一个单据”,识别为:"合并确认" - 其他情况,默认为:"单行确认" 2. **行号提取 (rowNumbers)**: - 单选:如“第5行”,提取为 [5] - 多选:如“第1、3、5行”,提取为 [1, 3, 5] - 范围:如“第2到4行”,提取为 [2, 3, 4] - 全选:如“全部”、“所有”,提取为 ["ALL"] ### 输出格式规范 ### 请直接输出以下 JSON(不要任何 Markdown 格式,不要 ```json): {"name": "%s", "parameters": {"operateType": "解析出的类型", "rowNumbers": [行号数组或"ALL"]}} """.formatted(methodNo); } }