欢迎光临
我们一直在努力

body是什么厂策略模式+工厂服务实现规则过滤

定义

策略模式(Strategy Pattern)是一种行为设计模式,它定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户,从而达到算法的变化不会影响到客户。这种模式涉及到三个角色:

使用场景

营销类型实现的策略模式的简图

实现步骤

以下是使用Java实现策略模式的基本步骤:

需求:

我们完成的ChatGPT项目, 虽然这里实现了问答的功能, 但是对于一个需要上线的项目来说,还需要必要的管理。 只有这样,你才不会被“约谈“。
因为ChatGPT是外国的东西, 他并不会对我们国内的敏感内容进行过滤, 虽然它本身也实现了相关的过滤功能, 但那是相对而言的, 所以如果你的网站被某些不良用户恶意利用。 到时候网站被强制下线, 损失的可就不是零星半点了。
所以, 我们在这里需要对用户输入的问答内容做敏感词过滤规则。 同时,如果每个用户都能够无限次数的使用你的项目, 那么你这个白菜被割的可就真香了。 所以我们还需要做限制使用次数的规则。再者, 如果如果多个用户在同一时间段内, 一直做问答,那么这个接口的访问粒度就会非常大, 所以我们还得需要做限频限次的操作。

为什么使用策略模式

频次、频率、白名单、敏感词等,都是用于支撑核心业务之外辅助流程,这些流程都是比较容易随着业务的变动而发生变化。所以我们要把这类东西分别封装起来,让它们的改变不会影响到核心业务流程。同时使用工厂服务, 实现业务的统一调用。经过这样一套策略模式 + 工厂服务的,我们实现的业务代码就会显得美观而又实用。

规则过滤的业务逻辑

首先根据工厂服务的特点, 我们首先定义**统一的规则接口(ILogicFilter接口)**, 这样其他模块调用的时候就有了统一的访问地址。

/**
 * 规则过滤统一接口
 */
public interface ILogicFilter {
    // 规则校验方法, 实现敏感词过滤和访问次数
    RuleLogicEntity<ChatProcessAggregate> filter(ChatProcessAggregate chatProcess) throws Exception;

}

接下来,我们实现的两种规则算法就可以继承这个接口

访问次数限制算法

在这里我们通过访问配置文件中的白名单用户(无任何限制的用户), 来进行匹配。 如果未匹配,那么就需要将用户存入限制访问次数的缓存中。 完成问答之后visitCount进行累加。, 最后再通过配置的上下文类进行返回。

/**
 * 访问次数过滤
 * 通过继承规则过滤接口, 实现规则过滤的次数限制规则,这里我们实现对每个用户限制使用的次数是10次
 */
@Slf4j
@Component
@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.ACCESS_LIMIT)
public class AccessLimitFilter implements ILogicFilter {

    @Value("${app.config.limit-count:10}")
    private Integer limitCount; // 限制访问次数
    @Value("${app.config.white-list}")
    private String whiteListStr; // 不进行限制次数的白名单用户, 后续需要优化作为数组来实现, 并且不能在配置类中实现
    // todo 后续使用数据库之后, 可以通过使用定时任务的方式来做缓存
    @Resource
    private Cache<String, Integer> visitCache; // 访问次数的缓存

    @Override
    public RuleLogicEntity<ChatProcessAggregate> filter(ChatProcessAggregate chatProcess) throws Exception {

        log.info("访问的用户(Token):{}, openId是:{}", chatProcess.getToken(), chatProcess.getOpenid());
        // 1. 对白名单中的用户直接放行
        if(chatProcess.isWhiteList(whiteListStr)){
            return RuleLogicEntity.<ChatProcessAggregate>builder()
                    .type(RuleLogicEntity.LogicCheckTypeVO.SUCCESS)
                    .data(chatProcess)
                    .build();
        }
        //2. 如果不是, 那么就先查找用户使用的次数 , 然后计算剩余次数, 最后给用户响应
        String openId = chatProcess.getOpenid();
        int visitCount = visitCache.get(openId, () -> 0);
        // 2.1 判断次数是否超过限制次数
        if(visitCount < limitCount) {
            visitCache.put(openId, visitCount + 1);
            return RuleLogicEntity.<ChatProcessAggregate>builder()
                    .type(RuleLogicEntity.LogicCheckTypeVO.SUCCESS)
                    .data(chatProcess)
                    .build();
        }
        // 2.2 如果是,直接进行false
        return RuleLogicEntity.<ChatProcessAggregate>builder()
                .type(RuleLogicEntity.LogicCheckTypeVO.REFUSE)
                .data(chatProcess)
                .info("您今日的免费 " + limitCount + "次,已耗尽。 请明天再来!!!").build();
    }

}

敏感词过滤规则算法

同样的, 首先判断是否为白名单用户, 如果不是再进行规则过滤
通过解析携带用户问答消息的ChatProcessAggregate, 得到用户的问答内容。
接下来通过SensitiveWordBs敏感词库,实现对用户问答Content的检测。如果检测到了敏感词, 那么就直接返回即可。

/**
 * 实现规则过滤接口, 判断用户输入的内容是否为敏感词中的内容, 如果是, 那么就拒绝回答
 */
@Slf4j
@Component
@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.SENSITIVE_WORD)
public class SensitiveWordFilter implements ILogicFilter {

    // 敏感词库中的词
    @Resource
    private SensitiveWordBs words;

    // 还是对白名单中的用户放行
    @Value("${app.config.white-list}")
    private String whiteListStr;

    @Override
    public RuleLogicEntity<ChatProcessAggregate> filter(ChatProcessAggregate chatProcess) throws Exception 
        //2. 如果不是 白名单用户, 那么需要进行判断
        //2.1 创建一个新的ChatProcessAggregate, 然后获取用户会话携带的所有信息
        ChatProcessAggregate newChatProcessAggregate = new ChatProcessAggregate();
        newChatProcessAggregate.setOpenid(chatProcess.getOpenid());
        newChatProcessAggregate.setModel(chatProcess.getModel());

        //2.2  获取用户输入的内容, 进行判断
        List<MessageEntity> newMessages = chatProcess.getMessages().stream()
                .map(message -> ).collect(Collectors.toList());

        newChatProcessAggregate.setMessages(newMessages);
        // 2.3 将敏感词进行过滤之后, 返回新的用户聊天信息的聚合ChatProcessAggregate
        return RuleLogicEntity.<ChatProcessAggregate>builder()
                .type(RuleLogicEntity.LogicCheckTypeVO.SUCCESS)
                .data(newChatProcessAggregate)
                .build();
    }
}

工厂服务暴露规则

我们这里使用的工厂服务是简单工厂模式中提供的工厂服务,他的作用是:

当然我们这里的统一管理并不是通过if-else这种方式实现, 而不同过map存储。 同时在不同的规则算法上通过自定义注解 LogicStrategy 将各类规则通过工厂的方式进行处理并对外提供服务。

/**
 * @description 规则工厂
 *  实现规则过滤接口所需要实现的内容
 */
@Service
public class DefaultLogicFactory 
        });
    }
    // 将获取的注解内容暴露出去, 供服务访问
    public Map<String, ILogicFilter> openLogicFilter() {
        return logicFilterMap;
    }

}

在业务中使用规则

应答服务业务

@Slf4j
public abstract class AbstractChatService implements IChatService {

    @Resource
    protected OpenAiSession openAiSession;

    @Override
    public ResponseBodyEmitter completions(ResponseBodyEmitter emitter, ChatProcessAggregate chatProcess) {
        try {
            emitter.onCompletion(() -> {
                log.info("流式问答请求完成,使用模型:{}", chatProcess.getModel());
            });

            emitter.onError(throwable -> log.error("流式问答请求疫情,使用模型:{}", chatProcess.getModel(), throwable));

            // 1. 校验权限
            // 在authController中已经实现了

            // 2. 规则过滤
            RuleLogicEntity<ChatProcessAggregate> ruleLogicEntity = this.doCheckLogic(chatProcess,
                    LogicModel.ACCESS_LIMIT.getCode(),
                    LogicModel.SENSITIVE_WORD.getCode());
            // 规则校验失败, 直接返回。 不进行问答
            if (!LogicCheckTypeVO.SUCCESS.equals(ruleLogicEntity.getType())) 
            // 3. 应答处理
            // todo 请求问答这里
                this.doMessageResponse(ruleLogicEntity.getData(), emitter);
        } catch (Exception e) 
        // 4. 返回结果
        return emitter;
    }
    //检查提供的规则过滤逻辑
    protected abstract RuleLogicEntity<ChatProcessAggregate> doCheckLogic(ChatProcessAggregate chatProcess, String... logics) throws Exception;

    protected abstract void doMessageResponse(ChatProcessAggregate chatProcess, ResponseBodyEmitter responseBodyEmitter) throws JsonProcessingException;

}

规则过滤调用:

// 2. 规则过滤
       RuleLogicEntity<ChatProcessAggregate> ruleLogicEntity = this.doCheckLogic(chatProcess,
               LogicModel.ACCESS_LIMIT.getCode(),
               LogicModel.SENSITIVE_WORD.getCode());
       // 规则校验失败, 直接返回。 不进行问答
       if (!LogicCheckTypeVO.SUCCESS.equals(ruleLogicEntity.getType())) 

doCheckLogic规则

/**
 */
@Service
public class ChatService extends AbstractChatService 
        return entity != null ? entity : RuleLogicEntity.<ChatProcessAggregate>builder()
                .type(LogicCheckTypeVO.SUCCESS).data(chatProcess).build();
    }

过滤规则实现所需model

/**
 * 用户聊天信息的聚合
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatProcessAggregate 
        return false;
    }

}
/**
 * 通过自定义注解 LogicStrategy 将各类规则通过工厂的方式进行处理并对外提供服务。
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogicStrategy {

    LogicModel logicMode();

}
/**
 * 规则校验结果实体
 *
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class RuleLogicEntity<T> {

    private LogicCheckTypeVO type; // 规则校验类型
    private String info; // 规则校验信息
    private T data;

}
/**
 * @description 逻辑校验类型,值对象
 */
@Getter
@AllArgsConstructor
public enum LogicCheckTypeVO {

    SUCCESS("0000", "校验通过"),
    REFUSE("0001","校验拒绝"),
    ;

    private final String code;
    private final String info;

}
/**
* 规则过滤种类的逻辑枚举
*/
@Getter
public enum LogicModel {
    ACCESS_LIMIT("ACCESS_LIMIT", "访问次数过滤"),
    SENSITIVE_WORD("SENSITIVE_WORD", "敏感词过滤"),
    ;
    private String code;
    private String info;

    LogicModel(String code, String info) {
        this.code = code;
        this.info = info;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

学习自: 小傅哥项目

赞(0)
未经允许不得转载:上海聚慕医疗器械有限公司 » body是什么厂策略模式+工厂服务实现规则过滤

登录

找回密码

注册