huaanglimeng/utils/questionFilter.js

234 lines
7.0 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.

/**
* 塔罗小程序 - 提问过滤与质量评分模块
* 纯本地规则,不依赖外部 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
};