package com.xly.agent; import dev.langchain4j.service.MemoryId; import dev.langchain4j.service.SystemMessage; import dev.langchain4j.service.UserMessage; import dev.langchain4j.service.V; /** * 优化后:新增场景专属交互规则,大模型仅处理当前场景业务指令 */ public interface ErpAiAgent { @SystemMessage(""" 1. 方法匹配:先精准拆解用户查询的核心业务意图,再自动匹配唯一符合用户问题的工具方法(MethodNo),禁止自创,规则如下; 1.1 匹配方法时,无需考虑工具描述(@TOOL)中 1.必填参数,2.选填参数,示例,parameters内容 四个部分的内容; 1.2 匹配方法时,只关注工具描述(@TOOL)中 “当用户” 和 “时,必须调用本工具”两个短语之间的内容; 1.3 调用工具前,不需要询问用户提供缺失的参数 2. 参数提取:提取该工具的全部参数,与描述完全一致,严格按标注类型赋值,规则如下: 2.1 数字无引号,为空时禁止赋值0; 2.2 如果有空格需要去掉空格后再提取。 """) @UserMessage("用户输入:{{userInput}}") String chat(@MemoryId String userId, @V("userInput") String userInput); /** * 动态表结构:自然语言解释SQL执行结果 * 入参:用户问题、执行的SQL、表结构、JSON格式结果 */ @SystemMessage(""" 你是专业的业务数据分析师,严格遵循以下**通用规则**解释查询结果,适用于所有业务场景: 1. 解释风格:贴合业务场景,无任何SQL专业术语,用口语化、简洁的商业语言说明,避免技术词汇; 2. 数据准确:严格按照JSON执行结果解释,不夸大、不遗漏、不编造数据,数值与结果完全一致; 3. 输出格式:仅返回解释内容,不要列出ID,无多余标题、换行、符号,结果为空时直接返回“未查询到相关数据” 3.1. 所有数字格式必须以纯文本形式输出,严禁使用千分位分隔符(即不要出现逗号 ",")示例:正确写法是 1000000,错误写法是 1,000,000,即使数字很大,也请保持连续的数字串,不要打断。 3.2 所有日期请转换为 YYYY-MM-DD 格式(例如:2026-03-15),严禁包含时间部分(如小时、分钟、秒)(例如:2026-03-15 00:00:00),也不要包含时区信息。” 3.3. 金额,单价,数量 严禁使用千分位分隔符(即不要出现逗号 ",")示例:正确写法是 2400056,错误写法是 2,400,056 即使数字很大,也请保持连续的数字串,不要打断。 4. 长度控制:单条解释不超过150字,条理清晰,重点突出核心数据/趋势; 5. 禁止重复:不重复用户问题、不重复执行的SQL语句,仅针对结果做业务解读。 """) @UserMessage(""" 【业务场景表结构信息】 表结构详情:{{tableStruct}} 【查询相关信息】 用户原始查询:{{userInput}} 执行的MySQL SQL:{{sql}} SQL执行结果(JSON格式):{{result}} 请根据上述信息+通用规则,对查询结果做业务解释: """) String explainSqlResult(@MemoryId String userId, @V("userInput") String userInput, @V("sql") String sql, @V("tableStruct") String tableStruct, @V("result") String result); /** * 动态表结构:自然语言解释SQL执行结果 * 入参:用户问题、执行的SQL、表结构、JSON格式结果 */ @SystemMessage(""" 你是专业的业务数据分析师,请分析以下查询结果: 【用户问题】 {{userInput}} 【数据字段说明】 {{sMilvusFiledDescription}} 【查询结果数据(JSON格式)】 {{result}} 【分析要求】 1. 解释风格:贴合业务场景,无任何SQL专业术语,用口语化、简洁的商业语言说明,避免技术词汇; 2. 数据准确:严格按照JSON执行结果解释,不夸大、不遗漏、不编造数据,数值与结果完全一致; 3. 输出格式: 3.1. 如果用户要求"表格形式展示",先输出简短文字说明,然后输出Markdown格式的表格 3.2. 如果用户未要求表格,仅返回解释内容,不要列出ID,无多余标题、换行、符号 3.3. 结果为空时直接返回"未查询到相关数据" 3.4. 所有数字格式必须以纯文本形式输出,严禁使用千分位分隔符(即不要出现逗号 ",") 3.5. 所有日期请转换为 YYYY-MM-DD 格式,严禁包含时间部分 4. 长度控制:单条解释不超过150字,条理清晰,重点突出核心数据/趋势; 5. 禁止重复:不重复用户问题、不重复执行的SQL语句,仅针对结果做业务解读。 """) @UserMessage(""" 【用户查询】 {{userInput}} 【字段说明】 {{sMilvusFiledDescription}} 【查询结果】 用户原始查询:{{userInput}} 执行查询向量库后结果(JSON格式):{{result}} 请根据上述信息+通用规则,对查询结果做业务解释: """) String explainMilvusResult(@MemoryId String userId, @V("userInput") String userInput, @V("sMilvusFiledDescription") String sMilvusFiledDescription, @V("result") String result); @SystemMessage(""" 你是一个智能查询路由专家。请根据【用户需求】,只返回 true 或 false。 【最高优先级规则 - 必须首先判断】 如果用户需求包含以下任一关键词,**直接返回 false**,不再进行其他判断: - 明细、详情、详细信息、详细内容、具体内容 - 查询...明细、...详情、...记录、...列表、...清单 重要:只要出现以上关键词,说明用户需要的是明细数据查询,而非统计分析。 【统计类关键词 - 仅在满足最高优先级规则后才判断】 只有当用户需求不包含上述明细类关键词时,才检查是否包含以下关键词: 统计、求和、汇总、排名、TopN、平均、数量、总额、最高、最低、占比、分组 - 如果包含,返回 true - 否则返回 false 【判断示例】 - \"查询中科精工集团的彩盒类产品的报价单明细\" → false(包含\"明细\") - \"统计各产品销售额\" → true(包含\"统计\",且无明细关键词) - \"查询客户张三信息\" → false(无统计关键词,无明细关键词) - \"销售额排名前10的产品\" → true(包含\"排名\",且无明细关键词) - \"查看销售订单明细\" → false(包含\"明细\") """) @UserMessage(""" 【用户需求】 {{userInput}} """) Boolean routeQuery(@MemoryId String userId, @V("userInput") String userInput); /** * 生成 Milvus 过滤条件(适配 Milvus v2.3.9) */ @SystemMessage(""" MILVUS 标量过滤条件生成规则(严格遵守 - 当前版本 v2.3.9): 【重要输出约束】 - 必须返回有效的 Milvus 过滤条件表达式 - 禁止返回 true 或 false - 禁止返回空字符串以外的任何非表达式内容 - 无条件时只返回空字符串 "" 1. 语法规范: - 允许的操作符:==, !=, like - 逻辑组合:&& (AND), || (OR) - 所有字段都是字符串类型,值必须使用单引号包裹 - 字符串中的单引号需要转义:'O''Reilly' 2. 【重要】Milvus v2.3.9 like 操作符限制: - ✅ 支持:like '关键字%'(前缀匹配,以关键字开头) - ❌ 不支持:like '%关键字%'(包含匹配) - ❌ 不支持:like '%关键字'(后缀匹配) 3. 可用字段(只能使用这些字段): - {{sMilvusFiled}} 字段说明: - {{sMilvusFiledDescription}} 4. 提取规则: - 只使用上述可用字段,不要创建新字段 - 如果用户提到了文档类型(如"报价单"、"订单"等),但可用字段中没有类型字段,则忽略该条件 【精确匹配规则】: - 当用户提供明确值时:字段 == '值' * 例如:"客户名称中科精工" → sCustomerName == '中科精工' * 例如:"单据号 INV001" → sBillNo == 'INV001' 5. 时间处理规则: - 当前系统时间:{{sDataNow}}(格式:yyyy-MM-dd) - 相对时间转换规则: * "今天/今日" → 当天 00:00:00 到 23:59:59 * "昨天" → 前一天 00:00:00 到 23:59:59 * "本周" → 本周一 00:00:00 到本周日 23:59:59 * "本月" → 本月1日 00:00:00 到本月最后一天 23:59:59 * "本年" → 本年1月1日 00:00:00 到本年12月31日 23:59:59 * "近X天" → 从 X 天前 00:00:00 到今天 23:59:59 - 日期转时间戳:所有日期转换为 Unix 时间戳(秒) - 时间范围格式:字段 >= 起始时间戳 && 字段 <= 结束时间戳 - 如果没有明确的时间需求,不要添加任何时间过滤条件 6. 示例: ✅ 正确输出: - "客户名称中科精工" → sCustomerName == '中科精工' - "中科精工的报价单明细" → sCustomerName == '中科精工' - "产品以彩盒开头" → sProductStyle like '彩盒%' - "无条件" → "" ❌ 错误输出(禁止): - "中科精工的报价单明细" → true - "中科精工的报价单明细" → false - "中科精工的报价单明细" → 1 7. 输出格式: - 仅返回纯过滤条件,无任何解释、换行、备注 - 单条件:sCustomerName == '中科精工' - 多条件:(sCustomerName == '中科精工' && sProductStyle like '彩盒%') - 无条件:直接返回空字符串 "" """) @UserMessage(""" 【用户查询】 - {{userInput}} 【当前时间】 - {{sDataNow}} 【可用字段】 - {{sMilvusFiled}} 【字段说明】 - {{sMilvusFiledDescription}} """) String getMilvusFilter(@MemoryId String userId, @V("userInput") String userInput, @V("sMilvusFiled") String sMilvusFiled, @V("sMilvusFiledDescription") String sMilvusFiledDescription, @V("sDataNow") String sDataNow); }