早期 Agent 珍贵录像

项目 url:https://gitee.com/hazhenyu/mgterp.git

自然语言转化为订单的流程如下:

首先用户输入 input-> 判断用户输入的问题是不是和 erp 有关系的

如何判断用户输入的问题是不是和 erp 有关系的:简单的字符串匹配即可。比如

1
2
3
4
5
6
7
8
9
10
11
12
13
String[] generalKnowledgeKeywords = {
"什么是", "如何实现", "怎么做", "介绍一下", "解释", "定义",
"历史", "原理", "方法", "区别", "比较", "教程", "讲解",
"写一篇", "生成", "创作", "编写", "设计", "总结", "推荐"
};
String[] questionPatterns = {
"能不能", "可以吗", "如何", "为什么", "是什么", "在哪里",
"什么时候", "怎样", "有哪些", "告诉我", "知道", "请介绍"
};
String[] erpTerms = {
"订单", "客户", "供应商", "商品", "价格", "销售", "采购",
"库存", "入库", "出库", "账单", "财务", "报表", "erp", "系统"
};

如果包含上面的 generalKnowledgeKeywords 或者是 questionPatterns 但是不包含 erpTerms 则说明和 ERP 无关。比如用户问”什么是苹果”,这时候就是典型的与 ERP 无关的,这时候我们就需要走对话模式了。

对话模式(handleConversation)就是普通的调用 deepseek 的 API。只不过添加了以下过程:

  1. 添加一些提示词,比如”你是 xxx,一个 xxx,用户问你,你应该友好的回答。”
  2. 然后把这些全部打包发送给 deepseek 并获取 ds 的回复。
  3. 使用失败重传机制。只有三次都发送失败之后才会显示失败。

如果和 ERP 有关则走下面这条路:

首先对用户的对话进行意图识别分析(analyzeIntent):

  1. 传入用户的 input。
  2. 添加 prompt。示例如下:主要是告诉他的身份,以及怎么识别,识别的类别等等。
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
你是智能意图识别专家。分析用户输入,判断其真实意图。

🎯 **识别类型:**
1. **COMMAND** - 要求执行具体系统操作
- 关键词:创建、查询、删除、修改、统计、导出等
- 示例:「创建订单」「查询销售额」「删除库存」
- 🆕 价格补充:「单价5元」「每个3元」「一瓶5元」等价格信息也属于COMMAND

2. **CONVERSATION** - 日常对话交流
- 关键词:问候、感谢、询问、闲聊、求助等
- 示例:「你好」「谢谢」「今天天气」「你是谁」

3. **MIXED** - 既有操作需求又有对话元素
- 示例:「你好,帮我查一下订单」「麻烦创建个订单,谢谢」

🔍 **特殊识别规则:**
- 含有价格信息的短语(如「单价X元」「每个X元」「一瓶X元」「价格X」)都应识别为COMMAND
- 纯数字+单位+货币(如「5元/个」「3块钱」)也应识别为COMMAND
- 这些通常是对之前订单创建请求的价格补充信息

📊 **返回格式 (严格JSON):**
{
"intent_type": "COMMAND/CONVERSATION/MIXED",
"confidence": 0.0-1.0,
"command": "提取的核心操作指令(仅COMMAND/MIXED)",
"reasoning": "判断依据(简短说明)"
}

🚨 **重要**: 只返回JSON,不要任何额外文字!
""";
  1. 将用户的 input 和 prompt 一同发送给 ds。接收 ds 返回的 json。如果这个时候 AI 检测失败了就需要使用兜底的检测方法,这个检测方法依旧是字符串匹配。根据下面这些字符串进行匹配检测之后最后确定指令的类型(纯指令/纯对话/混合)
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
// ERP指令关键词 - 更全面的业务关键词列表
String[] erpKeywords = {
// 订单操作
"创建订单", "新订单", "下单", "采购", "销售", "出售", "买", "卖", "供应商", "客户订单",
"删除订单", "取消订单", "订单查询", "查询订单", "确认订单", "完成订单",
// 库存操作
"库存", "入库", "出库", "盘点", "商品", "产品", "材料",
// 财务操作
"财务", "金额", "账单", "收款", "付款", "报表", "利润", "成本",
// 分析操作
"统计数据", "分析订单", "分析销售", "分析趋势"
};
String[] conversationKeywords = {
"你好", "谢谢", "再见", "怎么样", "是什么", "为什么", "你能", "能不能",
"?", "帮我", "请问", "如何", "怎么", "帮我", "认为", "觉得", "聊聊"
};
// 当确定是ERP指令
if (isErpCommand) {
return new IntentResult(IntentType.COMMAND, 0.95, input);
}
// 混合意图检测
else if (hasCommandKeyword && hasConversationKeyword) {
return new IntentResult(IntentType.MIXED, 0.8, input);
}
// 可能是一般指令
else if (hasCommandKeyword) {
return new IntentResult(IntentType.COMMAND, 0.7, input);
}
// 默认为对话
else {
return new IntentResult(IntentType.CONVERSATION, 0.8, "");
}
  1. 得到返回的 json 之后,构造并返回意图识别结果对象。提取其中的intent_type来进行判断
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
ds返回的json
{
"intent_type": "COMMAND/CONVERSATION/MIXED",
"confidence": 0.0-1.0,
"command": "提取的核心操作指令(仅COMMAND/MIXED)",
"reasoning": "判断依据(简短说明)"
}
示例:
{
"intent_type":"COMMAND",
"confidence":0.95,
"command":"向北京科技有限公司采购二十个苹果,每个苹果五块钱",
"reasoning":"包含明确的采购指令和价格信息,属于系统操作请求"
}

返回的json:
// 解析AI返回的JSON格式结果
JsonNode result = mapper.readTree(response);
// 获取意图类型,默认为对话类型
String type = result.path("intent_type").asText("CONVERSATION");
// 获取置信度,默认为0.5
double confidence = result.path("confidence").asDouble(0.5);
// 获取提取的指令内容,默认为空字符串
String extractedCommand = result.path("command").asText("");
// 构造并返回意图识别结果对象
return new IntentResult(
IntentType.valueOf(type.toUpperCase()),
confidence,
extractedCommand
);

判断:
//下面的confirmed是指用户是否已经确认,比如用户要购买十个苹果,每个苹果需要5元,然后系统自动创建订单,创建之后需要用户确认,也就是confirmed
switch (intent.type) {
case COMMAND: //纯指令
return handleCommand(input, intent.extractedCommand, confirmed);
case CONVERSATION: //纯对话
return handleConversation(input);
case MIXED: //混合意图
return handleMixedIntent(input, intent.extractedCommand, confirmed);
default:
return handleConversation(input); // 默认当作对话处理
}
  1. 纯对话(handleConversation)上面已经说了,接下来先说纯指令。
  2. 纯指令(handleCommand):依旧是换汤不换药。把上一个 AI 返回的 json 中的 command 提取出来。这里是向北京科技有限公司采购二十个苹果,每个苹果五块钱。然后添加提示词:
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
你是智能ERP指令解析器。从用户输入中提取信息,转换为标准JSON。

🎯 **解析规则(按优先级):**
1. 识别操作类型:
- 🔥 含有"卖给"、"卖给了"、"卖了"、"出售"、"售给"等动词 → create_order
- 含有"买"、"购买"、"采购"、"进货"等动词 → create_order
- 含有"查询"、"查看"、"查找"等动词 → query_order
- 含有"删除"、"取消"等动词 → delete_order
- 含有"分析"、"统计"等动词 → analyze_order
2. 识别订单类型:采购关键词→PURCHASE,销售关键词→SALE,默认SALE
3. 提取客户/供应商:匹配"为[姓名]"、"给[姓名]"、"从[姓名]"、"向[姓名]"等
4. 提取商品:匹配商品名称+数量+价格的组合模式
5. 智能推断缺失信息:缺价格设为0,但不要自动填充客户名或商品信息
6. 保留原始输入:将用户的原始输入添加到original_input字段

📦 **订单类型识别:**
• **PURCHASE(采购)**: 采购、进货、购买、进料、补货、订购、从供应商、向厂家、从XX那里买、买了、购买了、从XX买、从XX购买
• **SALE(销售)**: 销售、出售、卖给、卖给了、卖了、售给、发货、交付、为客户、给客户、出售给

🚨 **重要:采购识别优先级**
⚠️ 特别注意:"从XX买了50台电脑" → 这是采购订单(PURCHASE),不是销售订单!
⚠️ 特别注意:"从冯天祎那里买了1台笔记本电脑" → 这是采购订单(PURCHASE),不是销售订单!
⚠️ 关键模式:"从[任何人名/公司名]买/购买/采购" → 必须识别为 PURCHASE
⚠️ 关键模式:"从[任何人名/公司名]那里买/购买/采购" → 必须识别为 PURCHASE
⚠️ 销售模式:"卖给[客户]/为[客户]" → 识别为 SALE

🔴 **采购关键模式识别 - 优先级最高:**
• "从XX买" → PURCHASE
• "从XX那里买" → PURCHASE
• "从XX这里买" → PURCHASE
• "从XX处买" → PURCHASE
• "从XX购买" → PURCHASE
• "从XX采购" → PURCHASE
• "向XX买" → PURCHASE
• "和XX买" → PURCHASE

📝 **解析示例(严格按此格式):**

===== 🔵 销售订单示例 =====
输入:"创建订单"
输出:{"action": "create_order", "order_type": "SALE", "customer": "", "products": [], "original_input": "创建订单"}

输入:"为张三创建销售订单,苹果10个单价5元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "张三", "products": [{"name": "苹果", "quantity": 10, "unit_price": 5.0}], "original_input": "为张三创建销售订单,苹果10个单价5元"}

输入:"卖给李四20个橙子每个3元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "李四", "products": [{"name": "橙子", "quantity": 20, "unit_price": 3.0}], "original_input": "卖给李四20个橙子每个3元"}

输入:"卖给了冯天祎三瓶水"
输出:{"action": "create_order", "order_type": "SALE", "customer": "冯天祎", "products": [{"name": "水", "quantity": 3, "unit_price": 0}], "original_input": "卖给了冯天祎三瓶水"}

输入:"发货给王五,香蕉15个单价2元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "王五", "products": [{"name": "香蕉", "quantity": 15, "unit_price": 2.0}], "original_input": "发货给王五,香蕉15个单价2元"}

输入:"卖了5个苹果给张三"
输出:{"action": "create_order", "order_type": "SALE", "customer": "张三", "products": [{"name": "苹果", "quantity": 5, "unit_price": 0}], "original_input": "卖了5个苹果给张三"}

输入:"出售给客户王五10瓶饮料"
输出:{"action": "create_order", "order_type": "SALE", "customer": "王五", "products": [{"name": "饮料", "quantity": 10, "unit_price": 0}], "original_input": "出售给客户王五10瓶饮料"}

===== 🟠 采购订单示例 =====
输入:"创建采购订单"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "", "products": [], "original_input": "创建采购订单"}

输入:"从供应商张三采购苹果100个单价3元"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "张三", "products": [{"name": "苹果", "quantity": 100, "unit_price": 3.0}], "original_input": "从供应商张三采购苹果100个单价3元"}

输入:"向厂家进货橙子200个每个2.5元"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "厂家", "products": [{"name": "橙子", "quantity": 200, "unit_price": 2.5}], "original_input": "向厂家进货橙子200个每个2.5元"}

输入:"从哈振宇那里买了5瓶水,一瓶3元"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "哈振宇", "products": [{"name": "水", "quantity": 5, "unit_price": 3.0}], "original_input": "从哈振宇那里买了5瓶水,一瓶3元"}

输入:"从冯天祎那里买了1台笔记本电脑,每台1000元"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "冯天祎", "products": [{"name": "笔记本电脑", "quantity": 1, "unit_price": 1000.0}], "original_input": "从冯天祎那里买了1台笔记本电脑,每台1000元"}

输入:"从李老板那里采购大米50袋单价80元"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "李老板", "products": [{"name": "大米", "quantity": 50, "unit_price": 80.0}], "original_input": "从李老板那里采购大米50袋单价80元"}

输入:"购买原料,大米50袋单价80元"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "", "products": [{"name": "大米", "quantity": 50, "unit_price": 80.0}], "original_input": "购买原料,大米50袋单价80元"}

输入:"补货梨子30个价格4元"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "", "products": [{"name": "梨子", "quantity": 30, "unit_price": 4.0}], "original_input": "补货梨子30个价格4元"}

===== 🆕 自然语言表达示例 =====
输入:"从王小明那里买10瓶饮料每瓶5块钱"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "王小明", "products": [{"name": "饮料", "quantity": 10, "unit_price": 5.0}], "original_input": "从王小明那里买10瓶饮料每瓶5块钱"}

输入:"给客户刘大海发货,苹果20个一个3.5元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "刘大海", "products": [{"name": "苹果", "quantity": 20, "unit_price": 3.5}], "original_input": "给客户刘大海发货,苹果20个一个3.5元"}

输入:"和张师傅订了30斤大米每斤6元"
输出:{"action": "create_order", "order_type": "PURCHASE", "customer": "张师傅", "products": [{"name": "大米", "quantity": 30, "unit_price": 6.0}], "original_input": "和张师傅订了30斤大米每斤6元"}

输入:"帮李阿姨买香蕉15个单价2块"
输出:{"action": "create_order", "order_type": "SALE", "customer": "李阿姨", "products": [{"name": "香蕉", "quantity": 15, "unit_price": 2.0}], "original_input": "帮李阿姨买香蕉15个单价2块"}

===== 🔍 查询示例 =====
输入:"查询王五的订单"
输出:{"action": "query_order", "customer": "王五", "original_input": "查询王五的订单"}

输入:"查询采购订单"
输出:{"action": "query_order", "order_type": "PURCHASE", "original_input": "查询采购订单"}

输入:"查询销售订单"
输出:{"action": "query_order", "order_type": "SALE", "original_input": "查询销售订单"}

输入:"删除订单123"
输出:{"action": "delete_order", "order_id": 123, "original_input": "删除订单123"}

===== 📊 分析示例 =====
输入:"分析这些订单"
输出:{"action": "analyze_order", "original_input": "分析这些订单"}

输入:"分析订单数据"
输出:{"action": "analyze_order", "original_input": "分析订单数据"}

输入:"帮我分析一下订单情况"
输出:{"action": "analyze_order", "original_input": "帮我分析一下订单情况"}

输入:"订单分析"
输出:{"action": "analyze_order", "original_input": "订单分析"}

输入:"分析张三的订单"
输出:{"action": "analyze_order", "customer": "张三", "original_input": "分析张三的订单"}

输入:"分析销售订单"
输出:{"action": "analyze_order", "order_type": "SALE", "original_input": "分析销售订单"}

===== 🆕 缺失信息处理示例 =====
输入:"创建订单,苹果10个单价5元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "", "products": [{"name": "苹果", "quantity": 10, "unit_price": 5.0}], "original_input": "创建订单,苹果10个单价5元"}

输入:"为张三创建订单"
输出:{"action": "create_order", "order_type": "SALE", "customer": "张三", "products": [], "original_input": "为张三创建订单"}

输入:"客户是李四"
输出:{"action": "create_order", "order_type": "SALE", "customer": "李四", "products": [], "original_input": "客户是李四"}

输入:"苹果10个单价5元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "", "products": [{"name": "苹果", "quantity": 10, "unit_price": 5.0}], "original_input": "苹果10个单价5元"}

输入:"补充客户信息:王五"
输出:{"action": "create_order", "order_type": "SALE", "customer": "王五", "products": [], "original_input": "补充客户信息:王五"}

===== 💰 纯价格补充示例 =====
输入:"单价5元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "", "products": [{"name": "", "quantity": 0, "unit_price": 5.0}], "original_input": "单价5元"}

输入:"每瓶5元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "", "products": [{"name": "", "quantity": 0, "unit_price": 5.0}], "original_input": "每瓶5元"}

输入:"一个3元"
输出:{"action": "create_order", "order_type": "SALE", "customer": "", "products": [{"name": "", "quantity": 0, "unit_price": 3.0}], "original_input": "一个3元"}

输入:"价格4块钱"
输出:{"action": "create_order", "order_type": "SALE", "customer": "", "products": [{"name": "", "quantity": 0, "unit_price": 4.0}], "original_input": "价格4块钱"}

输入:"3元/个"
输出:{"action": "create_order", "order_type": "SALE", "customer": "", "products": [{"name": "", "quantity": 0, "unit_price": 3.0}], "original_input": "3元/个"}

🔧 **提取技巧:**
- 订单类型:优先检查采购关键词(从XX买、采购、进货),再检查销售关键词,默认销售
- 客户/供应商:在"为/给/从/向/和/跟"后面,或"的"前面,"那里/这里/处"前面
- 商品名:常见中文词汇(水果、食品、用品、原料、水、饮料等)
- 数量:数字+个/件/只/袋/箱/瓶/斤等单位,或"数量X"
- 单价:数字+元/块/钱等,或"单价/每个/一个/一瓶/价格X"
- 多商品用逗号分隔解析

🚨 **严格要求:**
1. 只返回JSON,不要解释文字
2. JSON格式必须标准,可直接解析
3. 宁可字段为空也不要缺失必需字段
4. 数字类型用数值,文本用字符串
5. 订单类型必须是"SALE"或"PURCHASE"
6. 客户名可以是任何中文或英文姓名
7. 必须包含original_input字段记录原始输入
  1. 最后得到 json 格式如下:
1
2
3
4
5
6
7
{
"action": "create_order",
"order_type": "PURCHASE",
"customer": "北京科技有限公司",
"products": [{ "name": "苹果", "quantity": 20, "unit_price": 5.0 }],
"original_input": "向北京科技有限公司采购二十个苹果,每个苹果五块钱"
}
  1. 如果 json 格式有误就需要修复一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 // 解析并验证JSON指令
JsonNode commandNode;
try {
commandNode = mapper.readTree(jsonCommand);
} catch (Exception e) {
System.out.println("❌ JSON解析失败,尝试修复...");
// 尝试修复常见的JSON格式问题
String fixedJson = fixJsonFormat(jsonCommand);
commandNode = mapper.readTree(fixedJson);
System.out.println("✅ JSON修复成功:" + fixedJson);
}

String action = commandNode.path("action").asText();

if (action.isEmpty()) {
// 如果无法识别为系统指令,尝试当作通用对话处理
System.out.println("⚠️ 无法识别操作类型,尝试作为普通对话处理");
return handleConversation(input);
}
  1. 现在开始判断命令的类型:

    • 如果是创建订单 create_order:

      则给这个 node 添加上会话 ID 确保上下文能够共享

      1
      2
      3
      4
      5
      6
      7
      8
       // 为订单创建操作添加会话ID,确保上下文能够共享
      if ("create_order".equals(action)) {
      // 生成或使用现有的会话ID
      String sessionId = generateSessionId(input);
      ((com.fasterxml.jackson.databind.node.ObjectNode) commandNode)
      .put("session_id", sessionId);
      System.out.println("🔗 设置会话ID: " + sessionId);
      }
    • 如果是删除订单 delete_order 则需要获取 order_id 并给用户返回确定要删除订单的信息。

  2. 接下来就是执行命令:

    • 首先就是根据指令来选择类型

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      return switch (action) {
      case "create_order" -> handleCreateOrder(root, sessionId);
      case "delete_order" -> handleDeleteOrder(root);
      case "query_order" -> handleQueryOrder(root);
      case "confirm_order" -> handleConfirmOrder(root);
      case "query_sales" -> handleQuerySales(root);
      case "query_inventory" -> handleQueryInventory(root);
      case "analyze_finance" -> handleAnalyzeFinance(root);
      case "analyze_order" -> handleAnalyzeOrder(root);
      default -> "❓ 未知操作类型:" + action + "\n\n💡 支持的操作:\n• create_order (创建订单)\n• query_order (查询订单)\n• delete_order (删除订单)\n• confirm_order (确认订单)\n• query_sales (销售查询)\n• query_inventory (库存查询)\n• analyze_finance (财务分析)\n• analyze_order (订单分析)";
      };
    • 比如 handleCreateOrder()里面就是根据 sessionId 来判断整个上下文。(获取最近的一次聊天的时间和现在如果超过五分钟就不算完整,如果没超过就算完整)。如果完整的话则直接去创建订单。

      • 创建订单就是先创建一个订单对象。然后从 root 里面获取到供应商,如果没有获取到,则把 original_input 拿出来和正则表达式做匹配来判断。正则表达式如下:

        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
         String[] patterns = {
        // 🆕 优先检查:从XX处/那里购买的模式 (采购订单)
        "从\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*那里", // 从哈振宇那里
        "从\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*这里", // 从张三这里
        "从\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*处", // 从李四处
        "从\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*买", // 从王五买
        "从\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*购买", // 从张三购买
        "从\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*采购", // 从供应商采购
        "从\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*进", // 从供应商进
        "向\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*买", // 向厂家买
        "向\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*购买", // 向供应商购买

        // 销售给XX的模式
        "卖给了?\\s*([\\u4e00-\\u9fa5a-zA-Z]+?)(?:\\s|$|[\\d一二三四五六七八九十])", // 卖给张三 / 卖给了张三(非贪婪匹配)
        "售给\\s*([\\u4e00-\\u9fa5a-zA-Z]+?)(?:\\s|$|[\\d一二三四五六七八九十])", // 售给李四
        "发给\\s*([\\u4e00-\\u9fa5a-zA-Z]+?)(?:\\s|$|[\\d一二三四五六七八九十])", // 发给王五
        "交付给\\s*([\\u4e00-\\u9fa5a-zA-Z]+?)(?:\\s|$|[\\d一二三四五六七八九十])", // 交付给客户
        "出售给\\s*([\\u4e00-\\u9fa5a-zA-Z]+?)(?:\\s|$|[\\d一二三四五六七八九十])", // 出售给张三
        "卖了.*给\\s*([\\u4e00-\\u9fa5a-zA-Z]+?)(?:\\s|$|[\\d一二三四五六七八九十])", // 卖了XX给张三

        // 基础创建模式
        "为\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*创建", // 为张三创建
        "给\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*创建", // 给张三创建
        "帮\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*创建", // 帮张三创建
        "为\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*下", // 为张三下单
        "给\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*下", // 给张三下单
        "帮\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*买", // 帮张三买
        // 标准格式
        "客户[::]?\\s*([\\u4e00-\\u9fa5a-zA-Z]+)", // 客户:张三
        "供应商[::]?\\s*([\\u4e00-\\u9fa5a-zA-Z]+)", // 供应商:张三
        "([\\u4e00-\\u9fa5a-zA-Z]+)\\s*的订单", // 张三的订单
        "([\\u4e00-\\u9fa5a-zA-Z]+)\\s*要", // 张三要
        "([\\u4e00-\\u9fa5a-zA-Z]+)\\s*订购", // 张三订购

        // 灵活的中文表达模式
        "([\\u4e00-\\u9fa5a-zA-Z]+)\\s*说", // 张三说
        "([\\u4e00-\\u9fa5a-zA-Z]+)\\s*需要", // 李四需要
        "([\\u4e00-\\u9fa5a-zA-Z]+)\\s*想要", // 王五想要
        "和\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*", // 和张三
        "跟\\s*([\\u4e00-\\u9fa5a-zA-Z]+)\\s*" // 跟李四
        };
      • 判断之后提取出供应商/客户的名字。然后把相关的信息插入到 order 对象里面。如果没有供应商/客户的名字则需要问用户了。

      • 接着创建商品和订单相关联的信息,这里就纯手动关联了。

      • 创建完商品和订单的关联之后调用:

        1
        Order savedOrder = orderService.createOrder(order, goodsList);
      • 创建订单的步骤就是前缀+时间戳。如果是销售出去则要判断库存。买入则不需要判断。最后插入这条数据并设置类型为 PENDING。

      • 接着把相关的信息返回给前端。告诉用户订单创建成功,单号是 xxx 什么的。

    • 混合模式就是纯指令+对话,这里就不多讲了。

    1. 学习客户的偏好:

      • 首先就是更新客户的经常买的商品,并且更新偏好价格(加权平均)。按照加权平均:70%历史价格 + 30%新价格的模式来修改。同时把这个修改添加到数据库里面。
    2. 智能识别别名:

      • 写一些常见的错误:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        if ("customer".equals(fieldType)) {
        // 客户名常见错误
        corrections.put("冯天一", "冯天祎");
        corrections.put("张3", "张三");
        corrections.put("李4", "李四");
        corrections.put("老张", "张三");
        corrections.put("小李", "李四");
        corrections.put("小王", "王五");
        } else if ("product".equals(fieldType)) {
        // 商品名常见错误和简写
        corrections.put("苹果🍎", "苹果");
        corrections.put("apple", "苹果");
        corrections.put("water", "水");
        corrections.put("🍎", "苹果");
        corrections.put("🍌", "香蕉");
        corrections.put("🍊", "橙子");
        corrections.put("💧", "水");
        corrections.put("饮用水", "水");
        corrections.put("矿泉水", "水");
        }

        根据映射来查询(这里可能就涉及到query重写)

    3. 系统架构和组件:

      • AI 控制器(AIController):REST API 接口层,接收前端请求并调用 AI 服务
      • AI 服务接口(AIService):定义 AI 处理逻辑的接口
      • AI 服务实现(AIServiceImpl):实现 AI 服务接口,处理意图识别、指令解析和对话模式
      • 外部 AI 服务(DeepSeekAIService):与 DeepSeek API 通信,执行各种 AI 任务

      整个系统采用分层架构,各组件职责明确:

      • AIController 负责 HTTP 请求处理和响应
      • AIServiceImpl 负责业务逻辑处理,包括意图识别、指令解析和执行
      • DeepSeekAIService 负责与外部 AI 模型通信
    4. 错误处理和重试机制:

      • 系统实现了多层错误处理和重试机制:
        • 意图识别失败时,使用基于关键词的备用分析方法
        • JSON 解析失败时,尝试修复格式问题
        • AI 服务调用失败时,使用指数退避重试机制(最多 3 次)
        • 网络超时时,提供本地分析作为备用方案
        • 指令执行失败时,尝试降级为普通对话模式
    5. 会话管理和上下文保持:

      • 系统使用会话 ID 来维护订单创建的上下文
      • 会话超时时间为 5 分钟
      • 同一会话内的操作可以共享上下文信息
      • 过期会话会被自动清理
    6. 安全和确认机制:

      • 对于危险操作(如删除订单)需要用户确认
      • 系统会生成简洁明了的确认消息
      • 只有在用户明确确认后才会执行危险操作

整个 sout 如下:

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
🎯 处理用户输入: 给我向北京科技有限公司采购二十个苹果,每个苹果五块钱 (已确认: false)
🤖 AI调用[INTENT] - 尝试1/3
🔍 意图分析原始回复:{"intent_type":"COMMAND","confidence":0.95,"command":"向北京科技有限公司采购二十个苹果,每个苹果五块钱","reasoning":"包含明确的采购指令和价格信息,属于系统操作请求"}
🎯 意图识别结果:COMMAND (置信度: 0.95)
🎮 开始处理指令,原始输入:给我向北京科技有限公司采购二十个苹果,每个苹果五块钱
🤖 AI调用[COMMAND] - 尝试1/3
🎮 AI生成的JSON指令:{"action":"create_order","order_type":"PURCHASE","customer":"北京科技有限公司","products":[{"name":"苹果","quantity":20,"unit_price":5.0}],"original_input":"向北京科技有限公司采购二十个苹果,每个苹果五块钱"}
🆕 创建新会话: order_creation_1762917858
🔗 设置会话ID: order_creation_1762917858
🚀 执行指令: create_order
🎮 执行指令: create_order - {"action":"create_order","order_type":"PURCHASE","customer":"北京科技有限公司","products":[{"name":"苹果","quantity":20,"unit_price":5.0}],"original_input":"给我向北京科技有限公司采购二十个苹果,每个苹果五块钱","session_id":"order_creation_1762917858"}
🧠 启动超智能订单分析: {"action":"create_order","order_type":"PURCHASE","customer":"北京科技有限公司","products":[{"name":"苹果","quantity":20,"unit_price":5.0}],"original_input":"给我向北京科技有限公司采购二十个苹果,每个苹果五块钱","session_id":"order_creation_1762917858"}
🛒 检测到采购模式: 向.*采购 在文本: 给我向北京科技有限公司采购二十个苹果,每个苹果五块钱
🔴 本地强制纠正:检测到采购模式,忽略AI结果: 给我向北京科技有限公司采购二十个苹果,每个苹果五块钱
🛒 从数组提取商品: 苹果 x20 @5.0
🔍 检测缺失信息 - 原始输入: 给我向北京科技有限公司采购二十个苹果,每个苹果五块钱
📋 检测到确认信息,等待用户确认
🎯 处理用户输入: 给我向北京科技有限公司采购二十个苹果,每个苹果五块钱 (已确认: true)
🤖 AI调用[INTENT] - 尝试1/3
🔍 意图分析原始回复:{"intent_type":"COMMAND","confidence":0.95,"command":"采购二十个苹果,单价五元","reasoning":"包含明确的采购指令和价格信息'每个苹果五块钱'"}
🎯 意图识别结果:COMMAND (置信度: 0.95)
🎮 开始处理指令,原始输入:给我向北京科技有限公司采购二十个苹果,每个苹果五块钱
🤖 AI调用[COMMAND] - 尝试1/3
🎮 AI生成的JSON指令:{"action":"create_order","order_type":"PURCHASE","customer":"","products":[{"name":"苹果","quantity":20,"unit_price":5.0}],"original_input":"采购二十个苹果,单价五元"}
🔄 复用现有会话: order_creation_1762917858
🔗 设置会话ID: order_creation_1762917858
✅ 用户已确认,直接执行指令: create_order
🚀 执行指令: create_order
🎮 执行指令: create_order - {"action":"create_order","order_type":"PURCHASE","customer":"","products":[{"name":"苹果","quantity":20,"unit_price":5.0}],"original_input":"给我向北京科技有限公司采购二十个苹果,每个苹果五块钱","session_id":"order_creation_1762917858"}
🧠 启动超智能订单分析: {"action":"create_order","order_type":"PURCHASE","customer":"","products":[{"name":"苹果","quantity":20,"unit_price":5.0}],"original_input":"给我向北京科技有限公司采购二十个苹果,每个苹果五块钱","session_id":"order_creation_1762917858"}
✅ 检测到完整上下文,直接执行订单创建
2025-11-12T11:25:27.898+08:00 INFO 24944 --- [nio-8081-exec-3] com.mogutou.erp.service.OrderService : 开始创建订单,前端type: null, orderType: PURCHASE
2025-11-12T11:25:27.898+08:00 INFO 24944 --- [nio-8081-exec-3] com.mogutou.erp.service.OrderService : 生成订单编号: ORD1762917927898
2025-11-12T11:25:27.898+08:00 INFO 24944 --- [nio-8081-exec-3] com.mogutou.erp.service.OrderService : 最终订单类型: PURCHASE
2025-11-12T11:25:27.898+08:00 INFO 24944 --- [nio-8081-exec-3] com.mogutou.erp.service.OrderService : 处理订单商品,数量: 1
Hibernate: select g1_0.id,g1_0.category,g1_0.code,g1_0.created_at,g1_0.description,g1_0.name,g1_0.purchase_price,g1_0.selling_price,g1_0.specification,g1_0.status,g1_0.stock,g1_0.unit,g1_0.updated_at from goods g1_0 where g1_0.name=?
2025-11-12T11:25:27.910+08:00 INFO 24944 --- [nio-8081-exec-3] com.mogutou.erp.service.OrderService : 使用现有商品: 苹果
2025-11-12T11:25:27.910+08:00 INFO 24944 --- [nio-8081-exec-3] com.mogutou.erp.service.OrderService : 商品价格计算 - 名称: 苹果, 单价: 5.0, 数量: 20, 总价: 100.0
Hibernate: insert into orders (address,amount,contact_person,created_at,customer_name,delivery_time,freight,operator_id,order_no,order_type,remarks,status,tel,updated_at) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
Hibernate: insert into order_goods (created_at,goods_id,order_id,quantity,total_price,unit_price,updated_at) values (?,?,?,?,?,?,?)
2025-11-12T11:25:27.934+08:00 INFO 24944 --- [nio-8081-exec-3] com.mogutou.erp.service.OrderService : 订单保存成功: ID=6, 类型=PURCHASE, 金额=100.0, 状态=PENDING
🧠 学习客户偏好: 北京科技有限公司 喜欢 苹果
🔒 JWT拦截器处理请求: GET /api/inventory/list
🎫 请求头中的Authorization: Bearer eyJhbGciOiJIU...
🔑 提取的实际token长度: 174
✅ Token验证结果: 有效
👤 从token中解析的用户名: admin
Hibernate: select u1_0.id,u1_0.avatar,u1_0.created_at,u1_0.email,u1_0.last_login,u1_0.password,u1_0.role,u1_0.status,u1_0.tel,u1_0.updated_at,u1_0.username from users u1_0 where u1_0.username=?
🔍 数据库中查找用户结果: 找到
👤 用户状态: 活跃
✅ JWT认证成功,允许访问
2025-11-12T11:36:14.365+08:00 INFO 24944 --- [nio-8081-exec-5] c.m.erp.controller.InventoryController : 接收到获取库存列表请求: page=0, size=10
Hibernate: select i1_0.id,i1_0.category,i1_0.created_at,i1_0.description,i1_0.location,i1_0.product_code,i1_0.product_name,i1_0.quantity,i1_0.unit,i1_0.unit_price,i1_0.updated_at,i1_0.warning_threshold from inventory i1_0 limit ?,?
2025-11-12T11:36:14.370+08:00 INFO 24944 --- [nio-8081-exec-5] c.m.erp.controller.InventoryController : 成功返回库存列表,数量: 10
2025-11-12T11:36:14.371+08:00 WARN 24944 --- [nio-8081-exec-5] ration$PageModule$WarningLoggingModifier : Serializing PageImpl instances as-is is not supported, meaning that there is no guarantee about the stability of the resulting JSON structure!
For a stable JSON structure, please use Spring Data's PagedModel (globally via @EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO))
or Spring HATEOAS and Spring Data's PagedResourcesAssembler as documented in https://docs.spring.io/spring-data/commons/reference/repositories/core-extensions.html#core.web.pageables.

🔒 JWT拦截器处理请求: GET /api/inventory/list
🎫 请求头中的Authorization: Bearer eyJhbGciOiJIU...
🔑 提取的实际token长度: 174
✅ Token验证结果: 有效
👤 从token中解析的用户名: admin
Hibernate: select u1_0.id,u1_0.avatar,u1_0.created_at,u1_0.email,u1_0.last_login,u1_0.password,u1_0.role,u1_0.status,u1_0.tel,u1_0.updated_at,u1_0.username from users u1_0 where u1_0.username=?
🔍 数据库中查找用户结果: 找到
👤 用户状态: 活跃
✅ JWT认证成功,允许访问