ErpAiAgent.java
11.9 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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
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);
}