- 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文档、系统提示词目录
162 lines
7.2 KiB
JavaScript
162 lines
7.2 KiB
JavaScript
/**
|
||
* 内容安全兜底模块
|
||
* 检测 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,
|
||
};
|