🧠 企业级AI系统后端能力全链路实现:从权限配置到回答命中,从超时控制到标准响应
2025-04-10
本文记录了一个企业AI系统后台的构建全过程,涵盖配置驱动、请求控制、敏感词识别、回答复用、超时终止、统一响应结构等高复杂度场景的落地实践,适合后端开发、架构师、系统设计师参考与复用。
一、企业级AI能力配置体系设计
我们首先构建了一个高度可配置、精细可控的企业AI权限模型,存储在 HeadOfficeCapacityModel
的 ai_config
字段中,内容为 JSON 格式:
{ "enabled": true, "request_interval_sec": 60, "token_limit": 100000, "token_used": 4300, "access_start_time": "2025-03-01 00:00:00", "access_end_time": "2025-12-31 23:59:59", "memory": { "enabled": true, "depth": 1, "cross_session": false }, "sensitive_fuzzy_match": true, "suggested_keywords_enabled": true, "max_active_users": 100, "same_question_answer": true, "pre_defined_answer": true, "ai_answer_timeout": 86400}
注入全局参数
在 Controller 的 beforeAction()
中,我们统一读取并注入到 Yii::$app->params['ai_config']
,确保后续模块能统一调用:
$config = HeadOfficeCapacityModel::getAiConfig($orgId); Yii::$app->params['ai_config'] = $config;
二、请求频率控制与企业活跃人数上限校验
请求间隔控制
通过配置字段 request_interval_sec
,结合 ai_messages
表中记录的上次提问时间,对每次提问做频率控制。
辅助方法:
public static function getLastAskTime($userId, $orgId): ?string
当前活跃用户统计
使用 UserHeadOfficeDetailModel
联表 User
,统计 IsCurrent = 1
且 IsLocked = 1
的用户数量,实现企业最大活跃用户数控制:
public static function checkActiveUserLimit($orgId): bool
三、敏感词识别逻辑支持“精确 + 模糊”双模式
配置项 sensitive_fuzzy_match
控制敏感词检测模式:
true
:使用stripos()
进行模糊匹配false
:使用===
进行精确匹配
方法封装如下:
public static function hasSensitiveWord($text): bool
该方法动态读取配置,判断是否命中任一敏感词。场景包括问题审核、AI拒答策略触发等。
四、AI回答复用机制(缓存命中判断)
配置项 same_question_answer
用于判断是否开启回答缓存机制:
public static function isSameQuestionAnswerMatched(string $question): bool
我们同时引入了 pre_defined_answer
配置项,用于控制是否允许使用管理员预设答案。
判断逻辑如下(简化):
if ( $match && $config['same_question_answer'] && ( ($match->admin_answer_id && $config['pre_defined_answer']) || ($match->ai_answer_id && !$match->admin_answer_id) ) )
该逻辑兼顾两类答案源(ADMIN/AI),并可灵活控制来源优先级。
五、历史答案过期机制(超时刷新)
为了避免长期使用过期的AI答案,我们设计了 ai_answer_timeout
超时时间策略:
public static function isAIAnswerExpired(?AiAnswers $answer): bool
该方法会判断该问题对应的历史AI答案的 updated_at
与当前时间的间隔,是否超过 ai_config
中的秒数配置(如 86400 秒 = 1 天),若超时则触发重新请求。
六、请求 AI 接口的超时控制与失败容错机制
我们封装了对外请求 AI 模型接口的统一方法:
public static function requestAiAnswer($question, &$modelId, $apiType = 'deepseek')
并实现以下关键能力:
请求超时控制
通过配置的 ai_answer_timeout
控制 HTTP 请求的最大等待时间(秒),通过 cURL 参数实现:
CURLOPT_TIMEOUT => $timeoutSec
异常捕获与分类日志
我们对请求异常进行了智能分类处理:
错误信息中包含 | 分类标签 |
---|---|
timeout | 【超时】 |
could not resolve | 【DNS错误】 |
connection refused | 【连接被拒绝】 |
其他 | 【异常】 |
分类日志记录到:
/runtime/logs/ai_request_exception_YYYYMMDD.log
示例日志片段:
2025-04-10 23:55:10 【超时】发送问题失败:请帮我生成一份日报 异常信息:cURL error 28: Operation timed out after 30000ms...
七、标准化响应结构与客户端兼容优化
我们通过监听 Yii::$app->response->on(Response::EVENT_BEFORE_SEND)
实现响应格式统一:
$response->data = [ 'IsSuccess' => 0, 'ErrMsg' => $response->data['message'] ?? '系统异常', 'Data' => $route === 'v1/ai-chat/ask' ? (object)[] : [] ]; $response->statusCode = 200; // 避免 Word 插件屏蔽 403/500 错误体
这确保了所有错误响应结构固定,且适配 Postman、Web 客户端、Word 插件等不同客户端解析行为。
八、其他重要封装与规范
所有
AiAnswers
相关的匹配、记录引用、更新次数等操作均封装为模型方法,如:AiAnswerReferences::recordAnswerReference(...) AiSuggestedKeywordReferences::recordReference(...)
所有参数校验均通过统一封装返回结构:
ErrorCode::wordReturnData('提示信息', 0|1, $data);
请求发起者来源、模型类型、预设 vs 历史来源都通过
answer_type
字段标记。
九、总结:这一天,我们构建了什么?
能力模块 | 核心逻辑或方法 | 说明 |
---|---|---|
企业级AI功能权限控制 | ai_config + 全局注入 | 控制访问、token、功能 |
请求频率限制 | getLastAskTime | 控制用户提交间隔 |
同步在线用户限制 | checkActiveUserLimit | 防止高并发压垮AI |
敏感词过滤双模式 | hasSensitiveWord() | 区分模糊 / 精确匹配 |
历史回答缓存判断 | isSameQuestionAnswerMatched() | 同问同答策略 |
AI答案过期检测 | isAIAnswerExpired() | 控制内容新鲜度 |
接口调用容错封装 | requestAiAnswer() | 含超时与分类日志 |
标准响应统一输出 | beforeSend 监听器 | 适配不同客户端行为 |
发表评论: