编写布尔组件
完成依赖与配置后,通过 JevBooleanComponent 声明是非判断,再使用已有的 IF 语法编排。依赖、服务入口与连接配置和选择组件相同,这里不再重复。
# 区分判断标准与判断内容
待判断的内容放在 state() 中;instructions() 说明判断标准,即“怎样算是”。 例如客户消息“我已经反馈三次了,能让我和真人说话吗?”属于待判断的内容;“客户明确要求人工客服介入”属于判断标准。
| 方法 | 职责 | 示例 |
|---|---|---|
state() | 提供本次待判断的内容及相关业务数据 | 客户原话、工单正文 |
instructions() | 定义是非判断的标准,高概率应代表“是” | 客户明确要求人工客服介入 |
probabilityThreshold() | 按需覆写;“是”的概率达到该值(含)走 true 分支 | 默认读取 liteflow.agent.jev.noul-threshold |
onDecision(result) | 按需覆写,接收原始结果 | 保存概率用于审计或二次分流 |
state() 可返回字符串、可序列化为 JSON 对象的业务数据或数组。instructions() 必须返回非空白字符串,只问一个是非问题;有两个条件时拆成两个布尔组件,用 AND 组合,判断会更稳定。
# 准备业务上下文
输入和决策结果都保存在上下文中,不放到共享组件的实例字段里:
import com.yomahub.liteflow.agent.jev.JevNoulResult;
public class SupportContext {
private final String message;
private JevNoulResult escalation;
public SupportContext(String message) {
this.message = message;
}
public String getMessage() { return message; }
public JevNoulResult getEscalation() { return escalation; }
public void setEscalation(JevNoulResult escalation) { this.escalation = escalation; }
}
# 声明布尔组件
import com.yomahub.liteflow.agent.jev.JevBooleanComponent;
import com.yomahub.liteflow.agent.jev.JevNoulResult;
import com.yomahub.liteflow.annotation.LiteflowComponent;
@LiteflowComponent("humanEscalation")
public class HumanEscalation extends JevBooleanComponent {
@Override
protected Object state() {
// 待判断的内容,从流程上下文读取。
return getContextBean(SupportContext.class).getMessage();
}
@Override
protected String instructions() {
// 判断标准:高概率代表“是”。
return "客户明确要求人工客服介入";
}
@Override
protected void onDecision(JevNoulResult result) {
getContextBean(SupportContext.class).setEscalation(result);
}
}
processBoolean() 由框架实现且为 final,业务只需实现 state() 和 instructions()。
# 配置流程并执行
在 src/main/resources/flow.el.xml 中编排。IF 的两个分支可以是普通组件、Agent 组件或子链:
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="support">
IF(humanEscalation, manual, SWITCH(supportRouter).to(refund, exchange).DEFAULT(manual));
</chain>
</flow>
在已注入 FlowExecutor 的业务方法中传入上下文:
SupportContext context = new SupportContext("我已经反馈三次了,能让我和真人说话吗?");
LiteflowResponse response = flowExecutor.execute2Resp("support", null, context);
if (!response.isSuccess()) {
throw new IllegalStateException("客服分流执行失败", response.getCause());
}
JevNoulResult escalation = context.getEscalation();
double probability = escalation.probability(); // “是”的概率,例如 0.99
String actualModel = escalation.model();
JevNoulResult 是 record,提供 model() 和 probability()。Noul 没有独立的置信度字段,概率本身同时表达答案与确定程度;概率接近阈值时应视为不确定,可以在 onDecision() 中读取原始概率,自行安排人工复核。
# 阈值选择与组件级覆写
全局默认阈值为 liteflow.agent.jev.noul-threshold: 0.5,组件可覆写:
@Override
protected double probabilityThreshold() {
return 0.8;
}
阈值的取值取决于误判代价:误报代价高就调高(例如分页人工、执行退款前),漏报代价高就调低(例如安全风险识别)。阈值需要用真实业务样本校准,概率不等于单次判断的正确率。
# 异常处理
鉴权失败、限流、超时或非法响应抛出 JevInvocationException,不会伪装成 false 分支;HTTP 错误可通过 getStatusCode() 读取状态码,客户端不自动重试。技术故障需要统一处理时,使用现有的 CATCH(...).DO(...):
<chain name="supportSafe">
CATCH(IF(humanEscalation, manual, autoReply)).DO(manual);
</chain>
运行效果可结合演示项目观察:是非判断页输入判断标准与内容,展示“是”的概率、阈值与执行路径,见客服演示与测试。



