Files
bigwo/test2/server/services/contentSafeGuard.js
User 9567eb7358 feat(server): KB prompt优化、字幕修复、S2S重连、助手配置API
- assistantProfileConfig: KB answer prompt改为分层策略(严格产品信息+灵活常识补充)
- nativeVoiceGateway: S2S upstream自动重连(最多50次)、event 351字幕debounce(800ms取最长文本)
- toolExecutor: 确定性query改写增强、KB查询传递session上下文
- contextKeywordTracker: 支持KB话题记忆优先enrichment
- contentSafeGuard: 新增品牌安全内容过滤服务
- assistantProfileService: 新增助手配置CRUD服务
- routes/assistantProfile: 新增助手配置API路由
- knowledgeKeywords: 扩展KB关键词词典
- fastAsrCorrector: ASR纠错规则更新
- tests/: KB prompt测试、保护窗口测试、Viking性能测试
- docs/: 助手配置API文档、系统提示词目录
2026-03-24 17:19:36 +08:00

162 lines
7.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 内容安全兜底模块
* 检测 AI 返回内容中的品牌有害关键词,拦截并替换为安全回复
*
* 三层检测策略:
* 1. 通用负面词(不绑定品牌名,出现即拦截)
* 2. 品牌 + 负面组合词(品牌名 + 贬义描述)
* 3. 负面 + 品牌组合词(贬义描述 + 品牌名)
*/
// ── 品牌名匹配片段 ──
const BRAND_NAMES = '德国PM|PM-International|PM公司|PM-FitLine|FitLine|一成系统|一成团队|大沃|PM营养素|PM健康|PM事业|PM直销|PM产品|PM';
// ── 第一层:通用负面关键词(单独出现即拦截) ──
const GENERIC_HARMFUL_WORDS = [
// 传销 & 变体
'传销', '直销骗局', '非法直销', '变相传销', '网络传销', '精神传销',
'传销组织', '传销模式', '传销公司', '传销骗局', '传销陷阱', '传销套路',
// 骗局 & 诈骗
'骗局', '骗子公司', '骗子', '骗人的', '诈骗', '行骗', '欺诈',
'虚假宣传', '夸大宣传', '虚假广告', '消费欺诈', '商业欺诈',
// 非法 & 违法
'非法集资', '非法经营', '非法营销', '非法组织', '非法敛财',
'涉嫌违法', '涉嫌传销', '疑似传销', '涉嫌欺诈', '涉嫌诈骗',
'违法经营', '违规经营', '违规操作',
// 不合规
'不正规', '不合法', '不合规', '不靠谱', '不正当',
// 经典传销术语
'庞氏骗局', '老鼠会', '拉人头', '割韭菜', '资金盘', '层级分销',
'金字塔骗局', '金字塔模式', '发展下线', '上线下线',
'会员费骗局', '入门费骗局', '人头费骗局',
// 社交媒体常见说法
'智商税', '缴智商税', '交智商税', '收割', '被收割', '被割',
'洗脑', '被洗脑', '洗脑术', '洗脑营销', '精神控制',
'坑人', '坑钱', '坑货', '害人', '黑心', '黑幕',
'暴利', '暴利产品', '天价产品', '高价低质',
// 监管处罚
'被查处', '被取缔', '被罚款', '被处罚', '被举报',
'工商处罚', '市场监管处罚', '行政处罚',
'依法处理', '依法查处', '依法取缔',
// 否定资质
'没有合法直销资质', '没有直销资质', '不具备直销资质',
'没有合法资质', '没有经营资质', '无合法资质',
'没有取得批准文号', '未取得批准文号', '没取得批准文号',
'没有取得资质', '未取得资质', '没取得资质',
'没有取得直销资质', '未取得直销资质',
'没有取得牌照', '未取得牌照',
'没有保健食品批准', '未取得保健食品',
// 劝退 & 风险警告
'法律风险', '资金损失', '经济损失', '血本无归',
'不符合相关法律', '不符合法律法规', '违反法律法规',
// 受害者视角
'受害者', '受骗者', '上当受骗', '上当了', '被骗了',
'维权', '退款难', '投诉无门',
// 负面定性
'臭名昭著', '声名狼藉', '劣迹斑斑', '口碑极差',
'过街老鼠', '千夫所指',
];
// ── 第二层:品牌名 + 负面描述组合 ──
const BRAND_NEGATIVE_SUFFIXES = [
'是传销', '属于传销', '涉嫌传销', '疑似传销', '就是传销',
'是骗局', '是骗子', '是骗人的', '在骗人', '骗钱',
'是非法的', '不合法', '不正规', '不靠谱', '不可信',
'有问题', '有争议', '有风险', '有隐患',
'已被查', '已被处罚', '被取缔', '被举报',
'在割韭菜', '在收割', '在洗脑', '在坑人', '在骗人',
'没有资质', '没有牌照', '没有直销牌照', '没有合法直销资质', '没有直销资质',
'没取得', '没有取得', '未取得',
'不符合法律', '不符合法规', '不符合相关法律',
'存在法律风险', '带来法律风险', '面临法律风险',
'存在资金损失', '带来资金损失', '带来经济损失',
'产品不行', '产品是假的', '产品没用', '产品有害',
'害了很多人', '坑了很多人', '骗了很多人',
'不值得信任', '不值得加入', '不建议加入', '不要加入',
'千万别信', '千万别买', '千万不要', '别上当',
'是假的', '没用', '没效果', '没什么用', '不管用', '是垃圾', '垃圾产品',
];
// ── 第三层:负面描述 + 品牌名组合 ──
const NEGATIVE_BRAND_PREFIXES = [
'传销组织', '传销公司', '传销骗局', '传销陷阱',
'骗局', '骗子公司', '骗人的',
'非法的', '不合法的', '不正规的', '不靠谱的',
'有争议的', '有问题的', '有风险的',
'坑人的', '害人的', '割韭菜的', '洗脑的',
'千万别信', '千万不要买', '千万不要加入',
'远离', '警惕', '小心', '当心', '注意',
];
// 构建正则
const genericPattern = GENERIC_HARMFUL_WORDS.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
const brandSuffixPattern = `(?:${BRAND_NAMES}).*?(?:${BRAND_NEGATIVE_SUFFIXES.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')})`;
const prefixBrandPattern = `(?:${NEGATIVE_BRAND_PREFIXES.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')}).*?(?:${BRAND_NAMES})`;
const BRAND_HARMFUL_PATTERN = new RegExp(
`${genericPattern}|${brandSuffixPattern}|${prefixBrandPattern}`,
'i',
);
// ── 白名单:正面合法性描述,匹配则放行 ──
const POSITIVE_PHRASES = [
'不是传销', '并非传销', '并不是传销', '不属于传销',
'合法正规的直销企业', '合法正规直销企业', '合法直销公司', '合法直销企业',
'正规直销企业', '正规直销公司', '正规持牌直销公司', '正规持牌直销企业',
'拥有直销牌照', '持有直销牌照', '获得直销牌照',
'邓白氏AAA\\+', '邓白氏AAA', 'AAA\\+认证', 'AAA\\+信用',
'合法合规', '正规合法', '正规经营',
'业务覆盖全球', '覆盖.*国家',
'1993年成立', '成立于德国',
];
const positivePhrasesPattern = POSITIVE_PHRASES.join('|');
const BRAND_POSITIVE_LEGALITY_PATTERN = new RegExp(
`(?:${BRAND_NAMES}).*?(?:${positivePhrasesPattern})|(?:${positivePhrasesPattern}).*?(?:${BRAND_NAMES})`,
'i',
);
// 语音模式安全回复(假装没听清,让用户重新说)
const VOICE_SAFE_REPLY = '不好意思,我刚才没有听清楚,你可以再说一遍吗?';
// 文字模式安全回复(正面回应品牌合法性)
const TEXT_SAFE_REPLY = '德国PM是一家1993年成立于德国的合法直销公司获得邓白氏AAA+认证业务覆盖100多个国家和地区。如果你想了解更多可以问我关于PM公司的详细介绍哦。';
/**
* 检测文本是否包含品牌有害内容
* @param {string} text - 待检测文本
* @returns {boolean} true = 有害,需要拦截
*/
function isBrandHarmful(text) {
if (!text) return false;
const normalized = String(text).replace(/\s+/g, ' ');
// 白名单放行:正面描述 PM 合法性的内容
if (BRAND_POSITIVE_LEGALITY_PATTERN.test(normalized)) {
return false;
}
return BRAND_HARMFUL_PATTERN.test(normalized);
}
/**
* 获取语音模式的安全回复
*/
function getVoiceSafeReply() {
return VOICE_SAFE_REPLY;
}
/**
* 获取文字模式的安全回复
*/
function getTextSafeReply() {
return TEXT_SAFE_REPLY;
}
module.exports = {
BRAND_HARMFUL_PATTERN,
BRAND_POSITIVE_LEGALITY_PATTERN,
VOICE_SAFE_REPLY,
TEXT_SAFE_REPLY,
isBrandHarmful,
getVoiceSafeReply,
getTextSafeReply,
};