- 文档
- 教程
- 后端
【免费下载链接】CodeGuide
:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、点赞、分享)!
导读
本章聚焦于 OpenAI 生成式服务中"规则过滤引擎"的设计与实现:在 chatgpt-api 的 openai 领域模型内,通过策略模式 + 工厂服务抽象出统一规则过滤接口,落地白名单、敏感词两类规则的过滤,并将其挂载到会话应答流程中,实现核心业务与易变旁路分支的彻底解耦。读完本文,你将掌握一种可复用的规则引擎建模思路,并能够举一反三地扩展频次限制、模型校验等更多规则。
一、本章诉求:生成式服务还缺"控制与管理"
在 《ChatGPT 微服务应用体系构建》 前几章中,我们完成了工程搭建、访问认证、公众号验签对接以及流式异步应答接口(见 第4节:工程重构和流式异步响应接口实现)。但一个真正能对外提供服务的应用,仅有"生成式服务的调用和响应"是远远不够的——它只能算是一个半成品,还缺少必备的控制和管理能力:
- 频次限制:服务部署上线后,外部用户调用接口时必须做调用频次限制,防止单个用户滥用免费额度或恶意刷接口;
- 敏感词过滤:生成式模型输出的内容具有不确定性,问答输入输出必须做敏感词过滤,这是内容安全的基础要求;
- 白名单控制:部分能力(如体验额度、内部接口)需要按用户白名单放行,而非对所有用户开放。
本章的目标就是设计一个规则过滤模型,教会大家开发这类功能。在原设计中,规则做了两个实现:一个频次、一个敏感词;同时作者建议读者在学习完成后,再自行添加一个频率限制规则,这样就能彻底掌握这套规则模型的设计与实现。
二、流程设计:把易变的规则隔离在核心流程之外
在设计之初需要明确一个核心观点:频次、频率、白名单、敏感词等,都是用于支撑核心业务之外的辅助流程,这些流程都非常容易随着业务的变动而发生变化。例如:
- 敏感词库需要随政策、舆情持续更新;
- 频次阈值需要根据运营策略动态调整;
- 白名单名单需要随用户运营不断增删。
如果把这些规则代码与核心业务代码写在一块,那么区分不出边界的代码会让工程的腐化程度不断加剧——每次规则调整都要改动核心逻辑,核心代码的稳定性和可维护性都会被破坏。
因此,本章的设计原则是:把规则设计在核心流程之外,通过一个独立的规则引擎来承载这些"快内容"的实现。
从整体流程上看:
- 在前面章节中,我们把应答的处理设计为一个独立的openai 领域模型结构,并为应答流程设计了接口和抽象类(详见 第4节 DDD 架构分层);
- 在此基础上,在 openai 领域模型中设计规则模型的实现和调用,来处理会话流程中的规则内容处理;
- 规则引擎对外提供统一的过滤入口,核心流程只依赖引擎接口,而不感知具体规则实现。
这样就形成了"核心流程稳定、规则实现可替换"的架构:核心的代码不会总调整,而规则可以随着业务频繁变动。
三、规则引擎的核心设计:策略模式 + 工厂服务
1. 统一规则过滤接口
规则引擎的建模核心是定义一个统一的规则过滤接口,把不同规则的"差异点"收敛到各自的实现类中。在该项目的面试与复盘资料 《ChatGPT 微服务应用体系构建》面试技能与问题汇总 中,对这一设计有明确描述:
其实除了账户、额度、模型,还有敏感词过滤,在这部分实现中我定义了统一的
ILogicFilter过滤接口,分别实现不同的过滤诉求。再通过工厂的封装,装配上不同的过滤规则类。用户进行问答后,会对用户的信息分别进行校验。这部分也就是整体 OpenAI 应答中使用的模板、工厂、策略三个设计模式。
由此可以梳理出规则引擎的三层结构:
| 层次 | 职责 | 说明 |
|---|---|---|
| 接口层 | ILogicFilter统一过滤接口 | 定义规则过滤的统一方法签名,是所有规则实现类的契约 |
| 实现层 | 各规则策略类 | 白名单、敏感词、频次等各自实现接口,封装自身过滤逻辑 |
| 装配层 | 工厂封装 | 通过工厂装配并路由到对应的规则实现类,核心流程只与工厂交互 |
这种"接口 + 多实现 + 工厂装配"的组合,正是策略模式与工厂模式在真实业务中的典型落地:策略模式让每个规则可以独立替换、独立演进,工厂模式则屏蔽了规则对象的创建与选择细节。
2. 工厂装配与规则路由
从上述描述可以推断,规则过滤在会话应答中的调用形态大致如下:
- 核心应答流程在进入模型调用前,先经过规则引擎的统一校验入口;
- 引擎内部通过工厂按规则类型(或配置)装配出对应的
ILogicFilter实现; - 每个规则依次对用户信息进行校验,任一规则校验不通过,则中断流程并返回对应提示;
- 全部规则校验通过后,才进入真正的模型应答环节。
另外需要说明的是,这种调用验证方式也可以使用责任链的方式处理(notes.md 中同样提到了这一点)。责任链与"工厂 + 策略"是两种常见的规则编排方案:策略 + 工厂适合"按类型选择一个规则执行"的场景,责任链适合"多个规则依次串行过滤"的场景,二者可以按业务复杂度灵活选择。
3. 与会话模型的结合时机
规则过滤不是孤立存在的,它必须"结合到会话模型中"运行。结合 第4节 介绍的 DDD 分层结构(app / domain / infrastructure / trigger / types五模块),规则引擎被放置在openai 领域模型(domain 层)中,由领域服务在应答流程中调用,而上层的 trigger 触发器层(HTTP 接口实现)无需感知规则细节。这样的分层保证了:
- 高内聚:规则引擎与应答流程同属 openai 领域,职责聚焦;
- 低耦合:接口层(trigger)只负责暴露 HTTP 接口,规则变化不影响接口契约;
- 可扩展:新增规则只需新增一个
ILogicFilter实现并装配进工厂,无需改动核心流程。
四、两种规则的落地实现
1. 白名单规则
白名单规则的作用是:只允许指定的用户(如内部人员、体验用户、付费用户)访问某些能力。实现要点可以归纳为:
- 白名单数据可从配置、Redis 或数据库中加载,支持动态维护;
- 规则过滤时以用户标识(如 openid、userId)为入参,命中白名单则放行,未命中则拒绝或降级;
- 白名单的变化频率高(用户运营频繁),因此必须独立于核心流程之外,通过配置或缓存热更新。
2. 敏感词规则
敏感词规则的作用是:对问答的输入与输出内容进行敏感词过滤,防止生成式服务输出或处理违规内容。实现要点可以归纳为:
- 敏感词库可加载通用敏感词数据,支持分词与匹配;
- 校验时机通常覆盖"用户提问内容"与"模型应答内容"两段;
- 命中敏感词时,需要给出准确的业务提示,而不是抛出笼统的异常(这与项目"错误要抛出准确的异常便于快速排查,给用户的提示要温馨且温暖"的一贯诉求一致,见 复盘:OpenAi 项目复盘总结)。
需要注意的是,敏感词规则属于强业务变动的部分:词库本身需要持续更新,单一静态词库往往"校验过严且不动态";在真实上线项目中,通常会进一步对接云服务厂商的敏感词过滤服务与图片审核服务,可按广告、舆情、敏感等类别分别配置过滤策略。
五、源码级佐证:DDD 规则树中的同源设计
虽然 chatgpt-api 的规则引擎源码不在本仓库内,但仓库中收录了作者同一设计思想下的另一个完整案例—— DDD 专题案例二《领域层决策规则树服务设计》,其中展示了规则引擎在 DDD 领域层中的标准建模,可以作为本章设计的直接参照。
该案例以"商品下单规则"为场景,同样强调:规则会随业务发展而增加或变动,所以不能写死,需要开发一个可扩展的规则引擎服务,通过给外部提供非常简单的接口来获取最终结果。其核心结构包括:
LogicFilter逻辑决策接口:定义统一的规则决策方法(如filter决策器、matterValue决策值获取),让不同规则通过不同实现完成各自的决策逻辑;EngineFilter引擎执行定义:定义规则树的统一执行入口process;MallRuleService应用层服务:对外提供规则决策能力,领域层 service 实现并组合引擎;- 仓储实现:在 infrastructure 基础层实现领域层定义的仓储接口,组合装配 DAO、Redis 等数据源。
// 逻辑决策定义(摘自 DDD 规则树案例 domain/service/logic/LogicFilter.java) public interface LogicFilter { /** * 逻辑决策器 * @param matterValue 决策值 * @param treeNodeLineInfoList 决策节点 * @return 下一个节点Id */ Long filter(String matterValue, List<TreeNodeLineInfo> treeNodeLineInfoList); /** * 获取决策值 * @param decisionMatter 决策物料 * @return 决策值 */ String matterValue(DecisionMatter decisionMatter); }对照可见,本章规则引擎的设计与该案例一脉相承:
- 都以"统一接口 + 多实现"收敛规则差异(
LogicFilter之于ILogicFilter); - 都由领域层服务组合执行引擎,对外只暴露简单入口;
- 都强调规则可扩展、可配置,不与核心业务写死在一块。
不同点在于:规则树案例面向"多节点、多条件的分支决策"(树形结构),而本章面向"会话应答前的线性规则过滤"(白名单、敏感词、频次依次校验)。二者可以根据场景复杂度互相借鉴。
六、扩展练习:为规则引擎添加"频率限制"规则
原文档专门留下了一个作业:在完成频次、敏感词两个规则后,再添加一个频率限制规则。基于上面的建模方式,扩展一个规则只需要四步:
- 实现接口:新建
FrequencyLimitFilter实现统一过滤接口,在过滤方法中完成频率校验逻辑(例如从 Redis 以userId + 时间窗口为 key 计数,超过阈值则拒绝); - 定义规则标识:为频率限制规则定义一个枚举或配置键,便于工厂识别;
- 装配进工厂:在工厂中把新实现类按规则标识注册进去,使引擎能够路由到该规则;
- 接入会话流程:在规则校验链路中加入频率限制规则(与白名单、敏感词一起按序校验)。
完成这个练习后,你将完整经历"定义接口 → 实现规则 → 工厂装配 → 流程接入"的闭环,真正吃透这套规则模型的设计与实现。同样的思路也适用于后续章节中的账户额度校验、模型类型校验等——从 notes.md 的描述看,这些校验正是被统一纳入了该规则过滤体系("除了账户、额度、模型,还有敏感词过滤……分别实现不同的过滤诉求"),这也验证了规则引擎具备极佳的横向扩展能力。
七、本章小结
- 生成式服务的调用与响应只是基础,频次限制、敏感词过滤、白名单控制等控制与管理能力是服务上线的必备要素;
- 规则属于易变的旁路分支,必须与核心业务流程分离设计,避免工程腐化;
- 通过策略模式 + 工厂服务抽象统一规则过滤接口(
ILogicFilter),实现"核心流程稳定、规则实现可替换"; - 规则引擎置于 openai 领域模型内,与会话应答流程结合,DDD 分层保障了高内聚、低耦合与可扩展;
- 仓库中收录的 DDD 领域层决策规则树服务设计 提供了同一思想下的完整源码级参照,可用于对比学习。
掌握这套规则引擎的建模方式后,无论后续新增"频率限制""模型校验""账户额度校验"还是任何新的业务规则,都只需"新增一个实现类 + 装配进工厂",核心代码几乎零改动——这正是本章解耦设计的价值所在。
- 文档
- 教程
- 后端
【免费下载链接】CodeGuide
:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、点赞、分享)!
相关推荐
Ceedling深度配置教程:YAML配置文件完全解析与最佳实践
Ceedling深度配置教程:YAML配置文件完全解析与最佳实践 Ceedling是一款专为C项目打造的单元测试和构建系统,通过YAML配置文件可以灵活定制项目
开发工具嵌入式980个公开数据集怎么挑?Awesome Public Datasets 检索与上手实战
980个公开数据集怎么挑?Awesome Public Datasets 检索与上手实战 做数据分析和模型训练,最耗时间的往往不是写代码,而是找一份靠谱的公开数
文档知识库数据集iOS国密加密终极指南:如何5分钟搞定SM2/SM3/SM4安全开发
iOS国密加密终极指南:如何5分钟搞定SM2/SM3/SM4安全开发 在移动应用开发中,数据安全已成为不可忽视的重要环节。随着中国国密算法标准的普及,越来越多的
密码学应用安全移动开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考