目录
[1. 规则定义 (RuleDefinition)](#1. 规则定义 (RuleDefinition))
[2. 匹配逻辑](#2. 匹配逻辑)
[3. 意图结果 (IntentResult)](#3. 意图结果 (IntentResult))
[1. RuleDefinition (规则定义类)](#1. RuleDefinition (规则定义类))
[2. GenericIntentRuleEngine (规则引擎核心)](#2. GenericIntentRuleEngine (规则引擎核心))
[3. GenericIntentUtil (工具类)](#3. GenericIntentUtil (工具类))
[1. 基础使用](#1. 基础使用)
[2. 在Activity中使用](#2. 在Activity中使用)
[3. 批量测试](#3. 批量测试)
[4. 动态管理人名](#4. 动态管理人名)
[1. 带人名的意图识别](#1. 带人名的意图识别)
[2. 规则热加载](#2. 规则热加载)
[3. 性能监控](#3. 性能监控)
[4. 自定义匹配策略](#4. 自定义匹配策略)
[1. 缓存优化](#1. 缓存优化)
[2. 线程池配置](#2. 线程池配置)
[3. 规则索引优化](#3. 规则索引优化)
[4. 内存优化](#4. 内存优化)
[Q1: 如何添加新规则](#Q1: 如何添加新规则)
[Q2: 规则匹配顺序是怎样的?](#Q2: 规则匹配顺序是怎样的?)
[Q3: 如何提高匹配准确率?](#Q3: 如何提高匹配准确率?)
[Q4: 7x24小时运行会内存泄漏吗?](#Q4: 7x24小时运行会内存泄漏吗?)
[Q6: 支持正则表达式吗?](#Q6: 支持正则表达式吗?)
[Q7: 如何处理同义词?](#Q7: 如何处理同义词?)
一、概述
1、什么是规则匹配引擎?
规则匹配引擎是一种基于预定义规则进行意图识别的系统。它通过关键词匹配、排除词过滤等机制,从用户输入中识别出用户意图。
2、适用场景
-
智能语音助手
-
聊天机器人
-
命令控制系统
-
用户意图识别
-
医疗健康监测
3、核心优势
-
配置灵活:通过JSON文件管理规则,无需修改代码
-
高性能:支持缓存和并发处理
-
可扩展:支持动态添加/删除规则
-
易维护:规则集中管理
二、核心概念
1. 规则定义 (RuleDefinition)
规则是最基本的匹配单元,包含以下要素:
| 字段 | 类型 | 说明 | 示例 |
|---|---|---|---|
| ruleName | String | 规则名称 | "血压测量" |
| intent | String | 意图标识 | "血压监测" |
| requiredKeywords | List<String> | 必需关键词 | ["血压"] |
| actionKeywords | List<String> | 动作关键词 | ["测", "量", "看"] |
| excludePatterns | List<String> | 排除词 | ["学习", "了解"] |
2. 匹配逻辑
用户输入 → 排除词检查 → 必需关键词检查 → 动作关键词检查 → 返回意图
3. 意图结果 (IntentResult)
public class IntentResult {
private String intent; // 识别到的意图
private String userName; // 提取的人名
private boolean hasUserName;// 是否包含人名
}
三、架构设计
1、系统架构图
┌─────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
├─────────────────────────────────────────────────────────┤
│ GenericIntentUtil (工具类) │
│ ┌──────────────────────────────────────────────────┐ │
│ │ • 初始化加载规则 │ │
│ │ • 同步/异步识别 │ │
│ │ • 缓存管理 │ │
│ │ • 人名提取 │ │
│ └──────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ GenericIntentRuleEngine (规则引擎) │
│ ┌──────────────────────────────────────────────────┐ │
│ │ • 规则加载 │ │
│ │ • 意图匹配 │ │
│ │ • 结果返回 │ │
│ └──────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Easy Rules (基础框架) │
│ ┌──────────────────────────────────────────────────┐ │
│ │ • RulesEngine │ │
│ │ • Rule │ │
│ │ • Facts │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
2、数据流
JSON文件 → 加载规则 → 规则引擎 → 用户输入 → 匹配 → 返回结果
↓
缓存存储 ← 结果缓存
四、核心类详解
导入包
// EasyRule 规则引擎
api 'org.jeasy:easy-rules-core:4.1.0'
api 'org.jeasy:easy-rules-mvel:4.1.0' // 可选,MVEL 表达式支持
1. RuleDefinition (规则定义类)
package csu.xiaoya.robotApp.ui.pagemanage.airule;
import java.util.ArrayList;
import java.util.List;
/**
* 规则定义类
*/
public class RuleDefinition {
private String ruleName; // 规则名称
private String intent; // 意图
private List<String> requiredKeywords; // 必需关键词
private List<String> actionKeywords; // 动作关键词
private List<String> excludePatterns; // 排除模式
public RuleDefinition() {
this.requiredKeywords = new ArrayList<>();
this.actionKeywords = new ArrayList<>();
this.excludePatterns = new ArrayList<>();
}
public RuleDefinition(String ruleName, String intent,
List<String> requiredKeywords,
List<String> actionKeywords,
List<String> excludePatterns) {
this.ruleName = ruleName;
this.intent = intent;
this.requiredKeywords = requiredKeywords;
this.actionKeywords = actionKeywords;
this.excludePatterns = excludePatterns;
}
// Getters and Setters
public String getRuleName() { return ruleName; }
public void setRuleName(String ruleName) { this.ruleName = ruleName; }
public String getIntent() { return intent; }
public void setIntent(String intent) { this.intent = intent; }
public List<String> getRequiredKeywords() { return requiredKeywords; }
public void setRequiredKeywords(List<String> requiredKeywords) {
this.requiredKeywords = requiredKeywords;
}
public List<String> getActionKeywords() { return actionKeywords; }
public void setActionKeywords(List<String> actionKeywords) {
this.actionKeywords = actionKeywords;
}
public List<String> getExcludePatterns() { return excludePatterns; }
public void setExcludePatterns(List<String> excludePatterns) {
this.excludePatterns = excludePatterns;
}
}
2. GenericIntentRuleEngine (规则引擎核心)
package csu.xiaoya.robotApp.ui.pagemanage.airule;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.api.RulesEngineParameters;
import org.jeasy.rules.core.DefaultRulesEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 通用意图规则引擎
*/
public class GenericIntentRuleEngine {
private static volatile GenericIntentRuleEngine instance;
private RulesEngine rulesEngine;
private Rules rules;
private final Map<String, String> resultCache = new ConcurrentHashMap<>();
private List<RuleDefinition> loadedRules = new ArrayList<>();
private GenericIntentRuleEngine() {
initEngine();
}
public static GenericIntentRuleEngine getInstance() {
if (instance == null) {
synchronized (GenericIntentRuleEngine.class) {
if (instance == null) {
instance = new GenericIntentRuleEngine();
}
}
}
return instance;
}
private void initEngine() {
RulesEngineParameters parameters = new RulesEngineParameters()
.priorityThreshold(Integer.MAX_VALUE)
.skipOnFirstAppliedRule(true);
rulesEngine = new DefaultRulesEngine(parameters);
rules = new Rules();
}
/**
* 加载规则
*/
public void loadRules(List<RuleDefinition> ruleDefinitions) {
this.loadedRules = ruleDefinitions;
for (RuleDefinition def : ruleDefinitions) {
try {
rules.register(new GenericRule(def));
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 识别意图
*/
public String recognizeIntent(String input) {
if (input == null || input.trim().isEmpty()) {
return "unknown";
}
String cached = resultCache.get(input);
if (cached != null) {
return cached;
}
try {
for (RuleDefinition rule : loadedRules) {
if (matchRule(input, rule)) {
resultCache.put(input, rule.getIntent());
return rule.getIntent();
}
}
return "unknown";
} catch (Exception e) {
e.printStackTrace();
return "unknown";
}
}
/**
* 规则匹配逻辑
*/
private boolean matchRule(String input, RuleDefinition rule) {
if (input == null || input.isEmpty()) return false;
String lowerInput = input.toLowerCase();
// 1. 检查排除词
for (String exclude : rule.getExcludePatterns()) {
if (lowerInput.contains(exclude.toLowerCase())) {
return false;
}
}
// 2. 检查必需关键词
boolean hasRequired = false;
for (String keyword : rule.getRequiredKeywords()) {
if (lowerInput.contains(keyword.toLowerCase())) {
hasRequired = true;
break;
}
}
if (!hasRequired) return false;
// 3. 检查动作关键词
for (String action : rule.getActionKeywords()) {
if (lowerInput.contains(action.toLowerCase())) {
return true;
}
}
return false;
}
public void clearCache() { resultCache.clear(); }
public int getRuleCount() { return loadedRules.size(); }
private static class GenericRule implements Rule {
private final RuleDefinition definition;
public GenericRule(RuleDefinition definition) {
this.definition = definition;
}
@Override
public String getName() { return definition.getRuleName(); }
@Override
public String getDescription() { return definition.getIntent(); }
@Override
public int getPriority() { return 1; }
@Override
public boolean evaluate(Facts facts) { return true; }
@Override
public void execute(Facts facts) throws Exception {}
@Override
public int compareTo(Rule o) {
return Integer.compare(this.getPriority(), o.getPriority());
}
}
}
3. GenericIntentUtil (工具类)
package csu.xiaoya.robotApp.ui.pagemanage.airule;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import com.google.gson.Gson;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 意图识别工具类
*/
public class GenericIntentUtil {
private static final String TAG = "GenericIntentUtil";
private static final String RULES_FILE = "aicmd/ai_cmd_rules.json";
private static final String UNKNOWN = "unknown";
private static GenericIntentRuleEngine ruleEngine;
private static boolean isInitialized = false;
private static ExecutorService executorService = Executors.newSingleThreadExecutor();
private static Handler mainHandler = new Handler(Looper.getMainLooper());
/**
* 初始化
*/
public static void init(Context context) {
if (isInitialized) return;
ruleEngine = GenericIntentRuleEngine.getInstance();
List<RuleDefinition> rules = loadRulesFromJson(context);
if (rules.isEmpty()) {
Log.e(TAG, "警告: 没有加载到任何规则");
} else {
ruleEngine.loadRules(rules);
isInitialized = true;
Log.i(TAG, "规则引擎初始化成功,共加载 " + rules.size() + " 条规则");
}
}
/**
* 从JSON加载规则
*/
private static List<RuleDefinition> loadRulesFromJson(Context context) {
List<RuleDefinition> rules = new ArrayList<>();
try {
InputStream is = context.getAssets().open(RULES_FILE);
InputStreamReader reader = new InputStreamReader(is, "UTF-8");
Gson gson = new Gson();
RuleDefinition[] ruleArray = gson.fromJson(reader, RuleDefinition[].class);
if (ruleArray != null && ruleArray.length > 0) {
rules.addAll(Arrays.asList(ruleArray));
}
reader.close();
is.close();
} catch (Exception e) {
Log.e(TAG, "加载规则文件失败: " + e.getMessage());
}
return rules;
}
/**
* 同步识别
*/
public static String recognizeIntent(String text) {
if (TextUtils.isEmpty(text)) return UNKNOWN;
if (!isInitialized) return UNKNOWN;
return ruleEngine.recognizeIntent(text);
}
/**
* 异步识别
*/
public static void recognizeIntent(String text, IntentCallback callback) {
if (TextUtils.isEmpty(text)) {
mainHandler.post(() -> callback.onResult(UNKNOWN));
return;
}
executorService.execute(() -> {
String result = ruleEngine.recognizeIntent(text);
mainHandler.post(() -> callback.onResult(result));
});
}
/**
* 清除缓存
*/
public static void clearCache() {
if (isInitialized) ruleEngine.clearCache();
}
/**
* 获取规则数量
*/
public static int getRuleCount() {
return isInitialized ? ruleEngine.getRuleCount() : 0;
}
/**
* 回调接口
*/
public interface IntentCallback {
void onResult(String intent);
}
}
五、JSON规则配置
1、基础格式
[
{
"ruleName": "规则名称",
"intent": "意图标识",
"requiredKeywords": ["必需词1", "必需词2"],
"actionKeywords": ["动作词1", "动作词2"],
"excludePatterns": ["排除词1", "排除词2"]
}
]
六、使用指南
1. 基础使用
// 1. 在Application中初始化
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
GenericIntentUtil.init(this);
}
}
// 2. 同步识别
String intent = GenericIntentUtil.recognizeIntent("我要测血压");
Log.d("结果", intent); // 输出: 血压监测
// 3. 异步识别
GenericIntentUtil.recognizeIntent("量体温", new GenericIntentUtil.IntentCallback() {
@Override
public void onResult(String intent) {
Log.d("结果", intent); // 输出: 体温监测
}
});
2. 在Activity中使用
public class MainActivity extends AppCompatActivity {
private EditText inputEditText;
private TextView resultTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inputEditText = findViewById(R.id.input);
resultTextView = findViewById(R.id.result);
Button recognizeButton = findViewById(R.id.recognize);
recognizeButton.setOnClickListener(v -> {
String input = inputEditText.getText().toString().trim();
if (!input.isEmpty()) {
// 异步识别
GenericIntentUtil.recognizeIntent(input, intent -> {
resultTextView.setText("识别结果: " + intent);
});
}
});
}
}
3. 批量测试
public void batchTest() {
String[] testCases = {
"帮我测下血压",
"我想量体温",
"测血糖",
"称体重",
"看看心率",
"学习血压知识"
};
for (String test : testCases) {
String intent = GenericIntentUtil.recognizeIntent(test);
Log.d("测试", test + " -> " + intent);
}
}
4. 动态管理人名
// 添加人名
GenericIntentUtil.addUserName("刘丹");
GenericIntentUtil.addUserName("王小明");
// 删除人名
GenericIntentUtil.removeUserName("李四");
// 批量更新
List<String> users = Arrays.asList("张三", "李四", "王五");
GenericIntentUtil.setUserNames(users);
// 获取人名列表
List<String> names = GenericIntentUtil.getUserNameList();
七、高级特性
1. 带人名的意图识别
// JSON配置人名识别规则
{
"ruleName": "人名识别",
"intent": "人名识别",
"requiredKeywords": [],
"actionKeywords": ["张三", "李四", "王五"],
"excludePatterns": []
}
// 使用
IntentResult result = GenericIntentUtil.recognizeIntent("给张三测血压");
String intent = result.getIntent(); // "血压监测"
String userName = result.getUserName(); // "张三"
2. 规则热加载
// 重新加载规则(修改JSON后调用)
GenericIntentUtil.reloadRules(context);
// 清除缓存
GenericIntentUtil.clearCache();
3. 性能监控
// 获取线程池状态
String status = GenericIntentUtil.getThreadPoolStatus();
// 获取统计信息
String stats = GenericIntentUtil.getStats();
// 获取规则数量
int count = GenericIntentUtil.getRuleCount();
4. 自定义匹配策略
// 扩展匹配逻辑(需要修改matchRule方法)
private boolean matchRule(String input, RuleDefinition rule) {
// 1. 支持正则表达式
if (Pattern.matches(rule.getRegexPattern(), input)) {
return true;
}
// 2. 支持模糊匹配
if (StringUtils.similarity(input, rule.getKeyword()) > 0.8) {
return true;
}
// 3. 原始匹配逻辑
// ...
}
八、性能优化
1. 缓存优化
// LRU缓存,自动淘汰旧数据
private static final int MAX_CACHE_SIZE = 10000;
private static final LinkedHashMap<String, IntentResult> resultCache =
new LinkedHashMap<String, IntentResult>(MAX_CACHE_SIZE, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, IntentResult> eldest) {
return size() > MAX_CACHE_SIZE;
}
};
2. 线程池配置
// 适合7x24小时运行的线程池配置
private static ExecutorService executorService = new ThreadPoolExecutor(
2, // 核心线程数
4, // 最大线程数
60, // 空闲线程存活时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(5000), // 队列大小
r -> {
Thread t = new Thread(r, "IntentRecognition");
t.setDaemon(true); // 守护线程
return t;
},
new ThreadPoolExecutor.DiscardPolicy() // 丢弃策略
);
3. 规则索引优化
// 建立关键词索引
private static Map<String, List<RuleDefinition>> keywordIndex = new HashMap<>();
private void buildIndex(List<RuleDefinition> rules) {
for (RuleDefinition rule : rules) {
for (String keyword : rule.getRequiredKeywords()) {
keywordIndex.computeIfAbsent(keyword, k -> new ArrayList<>())
.add(rule);
}
}
}
// 快速查找
private List<RuleDefinition> findCandidateRules(String input) {
List<RuleDefinition> candidates = new ArrayList<>();
for (String keyword : keywordIndex.keySet()) {
if (input.contains(keyword)) {
candidates.addAll(keywordIndex.get(keyword));
}
}
return candidates;
}
4. 内存优化
// 使用StringBuilder避免字符串拼接
StringBuilder result = new StringBuilder();
result.append("意图: ").append(intent);
if (userName != null) {
result.append(", 用户: ").append(userName);
}
return result.toString();
// 及时释放资源
public static void clearCache() {
synchronized (cacheLock) {
resultCache.clear();
}
}
九、常见问题
Q1: 如何添加新规则
A: 只需修改 ai_cmd_rules.json 文件,添加新的规则对象即可,无需修改代码。
{
"ruleName": "新规则",
"intent": "新意图",
"requiredKeywords": ["关键词"],
"actionKeywords": ["动作词"],
"excludePatterns": []
}
Q2: 规则匹配顺序是怎样的?
A: 规则按JSON文件中的顺序匹配,匹配到第一个规则就返回。建议将最常用的规则放在前面。
Q3: 如何提高匹配准确率?
A:
-
使用更精确的关键词
-
添加排除词过滤干扰项
-
使用同义词扩展
-
调整规则顺序
Q4: 7x24小时运行会内存泄漏吗?
A: 不会。我们做了以下优化:
-
使用LRU缓存自动清理
-
线程池使用守护线程
-
使用有界队列防止堆积
-
定期清理缓存
Q6: 支持正则表达式吗?
A: 基础版不支持,但可以扩展。在 matchRule 方法中添加正则匹配逻辑即可。
Q7: 如何处理同义词?
A: 在 actionKeywords 中添加同义词即可。
"actionKeywords": ["测", "量", "看", "查", "检查", "检测", "验", "测试", "测量"]
十、总结
1、核心要点
-
规则驱动:所有识别逻辑通过JSON配置
-
高性能:缓存 + 线程池优化
-
易扩展:添加规则无需修改代码
-
稳定运行:支持7x24小时运行
-
灵活使用:同步/异步多种调用方式
2、最佳实践
-
规则JSON文件放在
assets目录 -
定期清理缓存避免内存过大
-
使用异步识别避免阻塞UI线程
-
规则按优先级排列
-
添加排除词过滤干扰项
3、扩展方向
-
添加正则表达式支持
-
集成机器学习模型
-
支持多语言识别
-
添加规则优先级
-
实现动态规则更新