huaanglimeng/utils/questionFilter.js

234 lines
7.0 KiB
JavaScript
Raw Permalink Normal View History

/**
* 塔罗小程序 - 提问过滤与质量评分模块
* 纯本地规则不依赖外部 API
*/
/**
* 验证问题并返回过滤结果
* @param {string} question - 用户输入的问题
* @returns {Object} { status: "pass"|"rewrite"|"reject", reason: "", suggestions: [] }
*/
function validateQuestion(question) {
if (!question || question.trim().length === 0) {
return {
status: 'reject',
reason: '请输入您的问题',
suggestions: []
};
}
const q = question.trim();
// ========== 1. 直接拒绝规则 (reject) ==========
// 1.1 联系方式检测
const contactPatterns = [
/微信|wx|weixin|vx/i,
/qq|扣扣|q q/i,
/电话|手机|tel|phone/i,
/tg|telegram|飞机/i,
/\d{5,}/ // 5位以上数字可能是QQ号、电话等
];
if (contactPatterns.some(pattern => pattern.test(q))) {
return {
status: 'reject',
reason: '为了保证内容健康与占卜体验,该问题暂不支持占卜。',
suggestions: []
};
}
// 1.2 广告引流检测
const adPatterns = [
/加我|联系我|找我|私信|咨询我/i,
/推广|代理|兼职|赚钱|刷单/i,
/链接|网址|http|www\./i
];
if (adPatterns.some(pattern => pattern.test(q))) {
return {
status: 'reject',
reason: '为了保证内容健康与占卜体验,该问题暂不支持占卜。',
suggestions: []
};
}
// 1.3 成人/违法内容检测
const illegalPatterns = [
/黄色|色情|裸|性爱/i,
/毒品|大麻|冰毒/i,
/枪支|炸药|爆炸/i
];
if (illegalPatterns.some(pattern => pattern.test(q))) {
return {
status: 'reject',
reason: '为了保证内容健康与占卜体验,该问题暂不支持占卜。',
suggestions: []
};
}
// 1.4 专业决策类检测(医疗/法律/金融/赌博)
const professionalPatterns = [
/病|癌|肿瘤|手术|治疗|吃药|诊断/i,
/官司|诉讼|判决|坐牢|犯法/i,
/股票|期货|基金|投资.*收益|炒股/i,
/彩票|赌博|赌|博彩|中奖号码/i
];
if (professionalPatterns.some(pattern => pattern.test(q))) {
return {
status: 'reject',
reason: '为了让占卜更聚焦你自身的成长,建议调整提问方式。塔罗牌无法替代专业咨询。',
suggestions: []
};
}
// 1.5 危险内容检测
const dangerPatterns = [
/自杀|轻生|结束生命|不想活/i,
/杀人|伤害.*人|报复/i,
/什么时候死|何时去世|死亡时间/i
];
if (dangerPatterns.some(pattern => pattern.test(q))) {
return {
status: 'reject',
reason: '为了保证内容健康与占卜体验,该问题暂不支持占卜。如您正面临困境,建议寻求专业心理咨询帮助。',
suggestions: []
};
}
// ========== 2. 建议改写规则 (rewrite) ==========
const rewritePatterns = [
{
// 他/她爱不爱我
pattern: /(他|她|ta|TA|对方|那个人)(爱不爱|喜不喜欢|有没有感觉|在乎)/i,
suggestions: [
'我在这段感情中感受到爱了吗',
'我对这段关系的真实期待是什么',
'我需要怎样的爱才能感到满足'
]
},
{
// 是否出轨
pattern: /(他|她|ta|TA|对方).*(出轨|劈腿|有别人|背叛)/i,
suggestions: [
'我内心的不安来自哪里',
'我在这段关系中缺失了什么',
'我该如何重建内心的安全感'
]
},
{
// TA在干嘛
pattern: /(他|她|ta|TA|对方).*(在干嘛|在做什么|在想什么|想法)/i,
suggestions: [
'我为什么会如此在意对方的动态',
'我现在最需要关注的是什么',
'我该如何平复内心的焦虑'
]
},
{
// 控制类问题
pattern: /(怎么|如何).*(让|使|控制|改变).*(他|她|ta|TA|对方)/i,
suggestions: [
'我可以如何让自己变得更有吸引力',
'我在关系中真正想要的是什么',
'我该如何更好地表达自己的需求'
]
},
{
// 怎么让他喜欢我
pattern: /(怎么|如何).*(让|使).*(他|她|ta|TA|对方).*(喜欢|爱上|回来)/i,
suggestions: [
'我身上最值得被爱的特质是什么',
'我该如何在关系中保持真实的自己',
'我准备好迎接一段健康的关系了吗'
]
}
];
for (const item of rewritePatterns) {
if (item.pattern.test(q)) {
console.log('匹配到改写规则:', item.pattern);
return {
status: 'rewrite',
reason: '为了让占卜更聚焦你的成长,我们建议这样提问:',
suggestions: item.suggestions
};
}
}
// ========== 3. 通过验证 ==========
console.log('问题通过所有过滤规则');
return {
status: 'pass',
reason: '',
suggestions: []
};
}
/**
* 评估问题质量
* @param {string} question - 用户输入的问题
* @returns {Object} { score: 0-5, level: "普通"|"良好"|"优秀", icon: "🌱"|"🌿"|"🌳" }
*/
function scoreQuestion(question) {
if (!question || question.trim().length === 0) {
return {
score: 0,
level: '普通',
icon: '🌱'
};
}
const q = question.trim();
let score = 0;
// 规则1: 以"我"为主体 (+2分)
if (/^我|[,。!?\s]我/.test(q)) {
score += 2;
}
// 规则2: 包含情绪或状态词 (+1分)
const emotionWords = /感受|状态|心情|情绪|焦虑|迷茫|困惑|压力|快乐|幸福|痛苦|难过/;
if (emotionWords.test(q)) {
score += 1;
}
// 规则3: 开放式问题 (+1分)
const openQuestions = /如何|怎样|什么|哪些|为什么/;
if (openQuestions.test(q)) {
score += 1;
}
// 规则4: 包含绝对预测词 (-2分)
const absoluteWords = /会不会|能不能|一定会|肯定|必然|到底|结果是/;
if (absoluteWords.test(q)) {
score -= 2;
}
// 确保分数在 0-5 范围内
score = Math.max(0, Math.min(5, score));
// 映射等级
let level, icon;
if (score <= 2) {
level = '普通';
icon = '🌱';
} else if (score <= 4) {
level = '良好';
icon = '🌿';
} else {
level = '优秀';
icon = '🌳';
}
return {
score,
level,
icon
};
}
module.exports = {
validateQuestion,
scoreQuestion
};