/** * H5 Chat Intent Router — FAQ / fast-path rule library. * * Add patterns here for messages that should bypass LLM routing latency. * Consumed by chat-intent-router.mjs → classifyWithRules(). * * Keep rules conservative: task execution, page generation, and realtime lookup * must stay on Agent paths (checked via FAQ_EXCLUSION_PATTERNS). */ /** Block FAQ match when the message clearly needs Agent / tools. */ export const FAQ_EXCLUSION_PATTERNS = [ /\bpublic\/[^\s"'<>]+\.html\b/i, /MindSpace\/[^/\s]+\/public\/[^\s"'<>]+\.html/i, /(?:生成|创建|制作|做|写|设计|发布|搭建).{0,24}(?:H5|h5|HTML|html|网页|页面|活动页|宣传页|落地页|分享页|链接)/u, /(?:H5|h5|HTML|html|网页|页面).{0,24}(?:生成|创建|制作|做|写|设计|发布|链接)/u, /(?:写|做|生成|制作|设计).{0,16}主题(?:页面|文章)/u, /(?:服务号|公众号).{0,16}(?:页面|文章|推文|图文)/u, /(?:今天|今日|现在|最新|当前|实时).{0,12}(?:新闻|赛况|比分|天气|行情|股价|汇率|热点)/u, /(?:查(?:一下|查)?|搜索|打听).{0,16}(?:今天|今日|现在|最新|当前)/u, /(?:世界杯|欧冠|NBA|英超).{0,16}(?:赛况|赛程|比分)/u, /(?:load_skill|page-data|sqlite|express|后端服务)/iu, /(?:修|改|测试|回归|verify).{0,12}(?:bug|问卷|policy|public)/iu, ]; /** * @typedef {{ id: string, reason: string, patterns: RegExp[] }} DirectChatFaqRule */ /** @type {DirectChatFaqRule[]} */ export const DIRECT_CHAT_FAQ_RULES = [ { id: 'concept_what_is', reason: '概念解释类问答(FAQ)', patterns: [ /^什么是[\s\S]{1,48}[??]?$/u, /^何为[\s\S]{1,48}[??]?$/u, /^什么叫[\s\S]{1,48}[??]?$/u, /^[\s\S]{1,40}是什么[??]?$/u, /^[\s\S]{1,40}是什么意思[??]?$/u, /^[\s\S]{1,40}(?:是什么东西|指什么|啥意思)[??]?$/u, ], }, { id: 'concept_explain', reason: '解释说明类问答(FAQ)', patterns: [ /^(?:请)?(?:解释|说明|介绍|讲解|阐述)(?:一下|下)?[\s\S]{1,48}[??]?$/u, /^帮我(?:解释|说明|介绍|讲解)(?:一下|下)?[\s\S]{1,48}[??]?$/u, /^能(?:不能|否)(?:解释|说明|介绍)(?:一下|下)?[\s\S]{1,40}[??]?$/u, ], }, { id: 'concept_compare', reason: '概念对比类问答(FAQ)', patterns: [ /^[\s\S]{1,32}(?:和|与|跟)[\s\S]{1,32}(?:的)?(?:区别|差异|不同|对比|比较)[是什么]?[??]?$/u, /^(?:对比|比较)(?:一下|下)?[\s\S]{1,48}[??]?$/u, /^[\s\S]{1,24}(?:vs|VS|Vs)[\s\S]{1,24}(?:区别|差异|不同)?[??]?$/u, ], }, { id: 'concept_how_works', reason: '原理/机制类问答(FAQ)', patterns: [ /^[\s\S]{1,40}(?:是怎么|是如何)(?:工作|运行|实现|运作)的[??]?$/u, /^[\s\S]{1,40}(?:原理|机制|流程)(?:是什么|是怎样的)[??]?$/u, /^为什么[\s\S]{1,48}[??]?$/u, ], }, { id: 'text_transform', reason: '纯文字处理(总结/翻译/改写)', patterns: [ /^(?:请)?(?:帮我|帮忙)?(?:总结|概括|归纳|提炼)(?:一下|下)?[\s\S]{1,80}[??]?$/u, /^(?:请)?(?:帮我|帮忙)?(?:翻译|改写|润色|扩写|缩写|校对)(?:一下|下)?[\s\S]{1,80}[??]?$/u, ], }, { id: 'tech_acronym', reason: '常见技术名词解释(FAQ)', patterns: [ /^(?:什么是|解释一下|介绍一下)?\s*(?:SSE|WebSocket|REST(?:ful)?|GraphQL|JWT|OAuth|RAG|Embedding|向量数据库|Server-Sent Events)[\s\S]{0,24}[??]?$/iu, /^(?:SSE|WebSocket|REST(?:ful)?|GraphQL|JWT|OAuth|RAG)(?:是什么|什么意思|怎么用)[??]?$/iu, ], }, { id: 'learning_advice', reason: '学习/选型建议(纯文字)', patterns: [ /^(?:学|学习|入门).{0,24}(?:应该|该|推荐|建议).{0,32}(?:先|从哪|哪个)[??]?$/u, /^(?:初学者|新手|入门).{0,24}(?:应该|该|推荐|建议).{0,32}[??]?$/u, /^.{0,24}(?:先学|从哪学|怎么学).{0,32}[??]?$/u, ], }, { id: 'casual_opinion', reason: '主观建议/闲聊(无任务执行)', patterns: [ /^你觉得.{1,48}[??]?$/u, /^你认为.{1,48}[??]?$/u, /^(?:随便|随意)(?:聊|说说|谈谈).{0,24}[??]?$/u, /^.{0,16}(?:有什么建议|给点建议|怎么看)[??]?$/u, ], }, ]; const MAX_FAQ_TEXT_LENGTH = 200; /** * @param {string} text * @returns {{ id: string, reason: string } | null} */ export function matchDirectChatFaqRule(text) { const normalized = String(text ?? '').trim(); if (!normalized || normalized.length > MAX_FAQ_TEXT_LENGTH) return null; if (FAQ_EXCLUSION_PATTERNS.some((pattern) => pattern.test(normalized))) return null; for (const rule of DIRECT_CHAT_FAQ_RULES) { if (rule.patterns.some((pattern) => pattern.test(normalized))) { return { id: rule.id, reason: rule.reason }; } } return null; }