Files
memind/chat-intent-router-rules.mjs
T
john 9332bacabd
Memind CI / Test, build, and release guards (push) Failing after 12m44s
feat(router): improve direct_chat fast-path and add 103 token env sync
Route explicit text-only Q&A away from Agent before page-generation rules,
and add a script to enable Router + tighter memory budgets on 103 without
changing the global deepseek-v4-pro model.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-25 15:13:22 +08:00

160 lines
6.4 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.
/**
* 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,
],
},
{
id: 'text_only_declined_page',
reason: '明确要求纯文字、不生成页面/链接',
patterns: [
/(?:不要|别|无需|不需要|禁止).{0,12}(?:生成|做|制作|创建|发布).{0,8}(?:页面|网页|HTML|html|H5|h5|链接)/u,
/(?:纯文字|只要文字|文字回答|不要页面|不用页面|别做页面)/u,
],
},
{
id: 'brief_intro',
reason: '短篇幅介绍/说明(纯文字)',
patterns: [
/(?:用|以).{0,6}(?:一|两|二|三|四|五|几|\d+).{0,4}(?:句话|句).{0,32}(?:介绍|说明|描述|讲讲|推荐)/u,
/^(?:简单|简要|大概|概括)(?:介绍|说明|描述|讲讲).{0,48}[?]?$/u,
/^简要介绍.{0,48}(?:区别|差异|不同|对比|比较)[?]?$/u,
/^(?:推荐|介绍)(?:一个|一下).{0,32}(?:理由|原因)[,]?一句话/u,
/(?:推荐|介绍).{0,32}一句话.{0,16}(?:说明|讲讲).{0,12}(?:理由|原因)/u,
],
},
];
const MAX_FAQ_TEXT_LENGTH = 200;
/**
* @param {string} text
* @returns {{ id: string, reason: string } | null}
*/
const EXPLICIT_TEXT_ONLY_PAGE_DECLINE = /(?:不要|别|无需|不需要|禁止).{0,12}(?:生成|做|制作|创建|发布).{0,8}(?:页面|网页|HTML|html|H5|h5|链接)/u;
export function isExplicitTextOnlyRequest(text) {
const normalized = String(text ?? '').trim();
if (!normalized) return false;
return EXPLICIT_TEXT_ONLY_PAGE_DECLINE.test(normalized)
|| /(?:纯文字|只要文字|文字回答|不要页面|不用页面|别做页面)/u.test(normalized);
}
export function matchDirectChatFaqRule(text) {
const normalized = String(text ?? '').trim();
if (!normalized || normalized.length > MAX_FAQ_TEXT_LENGTH) return null;
const declinedPage = EXPLICIT_TEXT_ONLY_PAGE_DECLINE.test(normalized)
|| /(?:纯文字|只要文字|文字回答|不要页面|不用页面|别做页面)/u.test(normalized);
if (
!declinedPage
&& 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;
}