用户请求限制规则配置

本文档介绍如何使用 LiteFlow 规则引擎配置用户请求的敏感词过滤、风控规则等限制策略,帮助您更好地管理 AI 大模型调用流程。

处理流程概览

下图展示了用户调用大模型时的完整处理流程,包括敏感词过滤、风控检测、聊天类型选择等环节:

graph LR
    A[用户输入] --> B{敏感词过滤<br/>SensitiveWordsRule}
    B -->|触发敏感词| C[流程结束]
    B -->|未触发| D{是否白名单用户<br/>IsNoLimitRule}

    D -->|是白名单用户| E[跳过风控<br/>NoLimitRule]
    D -->|非白名单用户| F{是否内部调用<br/>IsInnerChatRule}

    F -->|是内部调用| G[用户维度风控<br/>UserRiskControlRule]
    F -->|外部调用| H[IP维度风控<br/>IPRiskControlRule]

    G --> I[Token风控检查<br/>TokensRiskControlRule]
    H --> I

    I -->|触发风控| C
    I -->|通过风控| J{聊天类型选择<br/>ChatTypeSelectRule}
    E --> J

    J -->|vectorChat| K[向量知识库聊天<br/>VectorChatRule]
    J -->|simpleChat| L[简单对话<br/>SimpleChatRule]
    J -->|databaseChat| M[Chat2SQL<br/>DatabaseChatRule]
    J -->|functionChat| N[函数调用<br/>FunctionChatRule]
    J -->|mcpChat| O[MCP调用<br/>McpChatRule]
    J -->|jsonChat| P[JSON结构化<br/>JsonChatRule]
    J -->|reasonChat| Q[深度推理<br/>ReasonChatRule]
    J -->|text2MarkMapChat| R[文本转脑图<br/>Text2MarkMapChatRule]
    J -->|infographicChatRule| S[信息图生成<br/>InfographicChatRule]

    K --> T[计入账单]
    L --> T
    M --> T
    N --> T
    O --> T
    P --> T
    Q --> T
    R --> T
    S --> T

    T --> U[返回结果]

业务背景

随着大模型应用场景的复杂化,传统的 if-else 判断已无法满足敏感词过滤、风控检测等多维度的判断需求。为此,PIGX 引入了 LiteFlow 规则引擎来规范化大模型调用流程,实现:

  • 流程可视化:通过 XML 配置文件定义规则执行顺序和条件分支
  • 高可维护性:规则逻辑解耦,易于扩展和调整
  • 灵活配置:支持动态调整敏感词和风控策略
了解更多

访问 LiteFlow 官方文档 深入了解规则引擎的使用方法。

配置参数

application.yml 或 Nacos 配置中心添加以下配置:

pig:
  ai:
    risk-control: # 风控配置
      sensitive-word: false # 是否开启敏感词过滤
      enabled: false        # 是否启用风控规则
      times: 20             # 单账户每天最多调用次数
      no-limit-usernames:   # 不受风控限制的账号列表
        - admin

配置说明:

参数类型默认值说明
sensitive-wordBooleanfalse是否开启敏感词过滤
enabledBooleanfalse是否启用风控规则检查
timesInteger20单个用户每天最多调用次数
no-limit-usernamesArray[]白名单用户列表,不受风控限制
生产环境配置

生产环境建议开启敏感词过滤(sensitive-word: true)和风控规则(enabled: true),以保障系统安全和资源合理使用。

核心规则说明

PIGX AI 模块实现了完整的规则体系,涵盖风控检测、类型路由和聊天执行三个层次:

风控规则层

规则类说明触发条件
SensitiveWordsRule敏感词过滤规则用户输入包含敏感词汇
IsNoLimitRule白名单用户判断检查用户是否在白名单中
NoLimitRule跳过风控处理白名单用户直接放行
IsInnerChatRule内外部调用判断区分内部系统调用和外部用户调用
UserRiskControlRule用户维度风控基于用户名统计调用次数,超过限制则拦截
IPRiskControlRuleIP维度风控基于IP地址统计调用次数,防止单IP恶意调用
TokensRiskControlRuleToken使用量风控控制Token消耗配额(预留功能)

聊天类型路由

规则类说明
ChatTypeSelectRule根据 datasetId 动态选择聊天类型,路由到对应的执行规则

聊天执行规则

规则类聊天类型功能说明
VectorChatRulevectorChat向量知识库检索(RAG),支持标准问答和语义检索
SimpleChatRulesimpleChat简单对话,支持文本、图片理解、文件问答、网络搜索
DatabaseChatRuledatabaseChatChat2SQL,将自然语言转换为SQL查询并执行
FunctionChatRulefunctionChat函数调用,通过语义匹配自动选择并执行函数
McpChatRulemcpChatMCP协议调用,支持外部工具集成
JsonChatRulejsonChatJSON结构化输出,基于Schema生成结构化数据
ReasonChatRulereasonChat深度推理,使用推理模型处理复杂问题
Text2MarkMapChatRuletext2MarkMapChat文本转思维导图,生成MarkMap格式
InfographicChatRuleinfographicChatRule信息图生成,输出AntV Infographic语法
规则扩展

所有规则类位于 pigx-knowledge/src/main/java/com/pig4cloud/pigx/knowledge/support/rule/ 目录下,您可以参考现有实现创建自定义规则。

规则引擎实现

PIGX 通过 LiteFlow 实现了灵活的规则配置和执行机制。

实际 LiteFlow 配置

系统使用的实际配置文件位于 pigx-knowledge/src/main/resources/rules/chat-rule.xml

<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <chain name="chat">
        THEN(
        // 敏感词判断,触发直接退出流程
        sensitive,
        // 判断是否执行风控规则,触发直接退出流程
        // 内部调用按用户名+总量控制,外部调用按IP+总量控制
        IF(isNoLimit, noLimit, IF(isInner, WHEN(user,tokens), WHEN(ip,tokens)))
        );
    </chain>
</flow>

配置说明:

  • sensitive:敏感词过滤节点
  • isNoLimit:判断是否为白名单用户
  • noLimit:白名单用户的空处理节点
  • isInner:判断是否为内部调用
  • user:用户维度风控(内部调用时使用)
  • ip:IP维度风控(外部调用时使用)
  • tokens:Token使用量风控(预留)

规则实现示例

1. 敏感词过滤规则

// 敏感词过滤规则
@Slf4j
@Component("sensitive")
@RequiredArgsConstructor
public class SensitiveWordsRule extends NodeComponent {

    private final AiChatRecordMapper aiChatRecordMapper;
    private final AiKnowledgeProperties aiKnowledgeProperties;

    @Override
    public void process() {
        ChatMessageContext messageContext = this.getContextBean(ChatMessageContext.class);
        AiDatasetEntity aiDataset = messageContext.getAiDataset();

        // 判断是否开启了敏感词过滤
        if (YesNoEnum.NO.getCode().equals(aiDataset.getSensitiveFlag())) {
            return;
        }

        // 敏感词过滤
        SensitiveWordBs sensitiveWordBs = SpringUtil.getBean(SensitiveWordBs.class);
        if (sensitiveWordBs.contains(messageContext.getChatMessageDTO().getContent())) {
            Long messageKey = messageContext.getChatMessageDTO().getMessageKey();
            AiChatRecordEntity aiChatRecordEntity = new AiChatRecordEntity();
            messageContext.setErrorMessage(aiDataset.getSensitiveMsg());
            setIsEnd(true);  // 设置错误消息并终止流程
        }
    }
}

2. 用户维度风控规则

// 用户维度风控规则
@Slf4j
@Component("user")
@RequiredArgsConstructor
public class UserRiskControlRule extends NodeComponent {

    private final AiKnowledgeProperties aiKnowledgeProperties;
    private final AiBillService aiBillService;

    @Override
    public void process() {
        ChatMessageContext messageContext = this.getContextBean(ChatMessageContext.class);
        String risked = riskControl(messageContext.getUsername());
        if (StrUtil.isNotBlank(risked)) {
            messageContext.setErrorMessage(risked);
            setIsEnd(true);
        }
    }

    private String riskControl(String username) {
        // 统计用户从昨天到现在的调用次数
        long count = aiBillService.count(Wrappers.<AiBillEntity>lambdaQuery()
            .eq(StrUtil.isNotBlank(username), AiBillEntity::getCreateBy, username)
            .ge(AiBillEntity::getCreateTime, DateUtil.yesterday()));

        log.info("username:{}, count:{}", username, count);
        if (count > riskControl.getTimes()) {
            return riskControl.getErrorMsg();
        }
        return null;
    }
}

3. 布尔判断规则(白名单)

// 白名单判断规则
@Slf4j
@Component("isNoLimit")
@RequiredArgsConstructor
public class IsNoLimitRule extends NodeBooleanComponent {

    private final AiKnowledgeProperties aiKnowledgeProperties;

    @Override
    public boolean processBoolean() throws Exception {
        // 如果白名单为空,所有用户都需要风控
        if (CollUtil.isEmpty(aiKnowledgeProperties.getRiskControl().getNoLimitUsernames())) {
            return false;
        }

        String username = SecurityUtils.getUser().getUsername();
        return aiKnowledgeProperties.getRiskControl().getNoLimitUsernames().contains(username);
    }
}
规则类型说明
  • NodeComponent:普通处理节点,可以通过 setIsEnd(true) 终止流程
  • NodeBooleanComponent:布尔判断节点,返回 true/false 用于条件分支
  • NodeSwitchComponent:选择节点,返回字符串用于多路分支

4. 聊天类型选择规则

// 聊天类型选择规则
@Slf4j
@Component("selectChatType")
public class ChatTypeSelectRule extends NodeSwitchComponent {

    @Override
    public String processSwitch() throws Exception {
        ChatMessageContext messageContext = this.getContextBean(ChatMessageContext.class);
        ChatMessageDTO lastUserMessage = messageContext.getChatMessageDTO();

        // 根据数据集ID选择对应的聊天类型
        ChatTypeEnums chatTypeEnums = ChatTypeEnums.fromCode(lastUserMessage.getDatasetId());
        return Objects.requireNonNullElse(chatTypeEnums, ChatTypeEnums.VECTOR_CHAT).getType();
    }
}

扩展指南

添加自定义风控规则

当您需要新增自定义风控规则时,可以按照以下步骤进行扩展。

步骤 1:创建规则实现类

pigx-knowledge/src/main/java/com/pig4cloud/pigx/knowledge/support/rule/ 目录下创建新的规则类:

// 自定义内容质量风控规则
@Slf4j
@Component("contentQuality")
@RequiredArgsConstructor
public class ContentQualityRule extends NodeComponent {

    private final YourCustomService customService;

    @Override
    public void process() {
        ChatMessageContext messageContext = this.getContextBean(ChatMessageContext.class);
        String content = messageContext.getChatMessageDTO().getContent();

        boolean isLowQuality = checkContentQuality(content);

        if (isLowQuality) {
            log.warn("内容质量不达标,用户:{}", messageContext.getUsername());
            messageContext.setErrorMessage("输入内容质量不符合要求,请重新输入");
            setIsEnd(true);
        }
    }

    private boolean checkContentQuality(String content) {
        // 自定义质量检查逻辑
        if (content.length() < 5) {
            return true;
        }
        return customService.scoreContent(content) < 0.6;
    }
}

步骤 2:更新 LiteFlow 配置

修改 pigx-knowledge/src/main/resources/rules/chat-rule.xml,将新规则加入流程:

<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <chain name="chat">
        THEN(
        // 敏感词判断
        sensitive,
        // 新增:内容质量检查
        contentQuality,
        // 风控规则判断
        IF(isNoLimit, noLimit, IF(isInner, WHEN(user,tokens), WHEN(ip,tokens)))
        );
    </chain>
</flow>

并行执行优化:

如果需要并行执行多个风控规则,可以使用 WHEN 语法:

WHEN(user, ip, contentQuality, tokens)

这样多个规则会并行执行,提高性能。

添加新的聊天类型

如果需要添加新的聊天类型(如 customChat),需要完成以下步骤:

1. 创建 ChatRule 实现

// 自定义聊天规则实现
@Slf4j
@Component("customChat")
@RequiredArgsConstructor
public class CustomChatRule implements ChatRule {

    private final ModelProvider modelProvider;

    @Override
    public Flux<AiMessageResultDTO> process(ChatMessageDTO chatMessageDTO) {
        AiStreamAssistantService streamAssistantService = modelProvider
            .getAiStreamAssistant(chatMessageDTO.getModelName())
            .getValue();

        return streamAssistantService
            .chat(chatMessageDTO.getConversationId(), chatMessageDTO.getContent())
            .map(AiMessageResultDTO::new);
    }
}

2. 添加聊天类型枚举

ChatTypeEnums 中添加新的类型:

public enum ChatTypeEnums {
    VECTOR_CHAT("vectorChat", "向量聊天"),
    SIMPLE_CHAT("simpleChat", "简单聊天"),
    CUSTOM_CHAT("customChat", "自定义聊天"),  // 新增
    // ... 其他类型
}

3. 更新路由逻辑

确保 ChatTypeSelectRule 能够正确识别并路由到新的聊天类型。

如何调试规则执行流程?

LiteFlow 提供了详细的执行日志,可以通过以下配置开启:

liteflow:
  print-execution-log: true  # 打印执行日志
  enable-log: true           # 启用日志
  log-level: debug           # 日志级别

开启后,控制台会输出类似以下的日志:

[LiteFlow] 执行链路: chat [LiteFlow] 执行节点: sensitive [LiteFlow] 节点 sensitive 执行完成,耗时: 5ms [LiteFlow] 执行节点: isNoLimit [LiteFlow] 节点 isNoLimit 返回: false ...