- vstore 独立安装包(8094):解析/嵌入/加密 vault/faiss 检索,存储路径支持本地 file 与 http(s):// URL,启动握手校验,集群化预留(embed 独立模块) - BFF docgen 路由:上传入库/generate/编辑/导出/下载/主库管理,意图护栏(与前端同词典),vstore 失败兜底,quota 507 与 TTL 惰性清理 - 前端:自然触发意图路由、拖拽上传 chips、能力徽标、右侧文档 TAB(WYSIWYG 编辑/prompt 修改/PDF+DOCX 导出下载)、右栏拖宽+手柄仿左栏 - 批量导入工具 docgen_import.py(并发 8、导入即加密+删源明文) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
75 lines
4.3 KiB
JavaScript
75 lines
4.3 KiB
JavaScript
// intent.js —— 前端意图路由(P3/dev3 归属;纯函数,无 Vue 依赖,可直接 node 直测)
|
||
// 唯一事实源:docs/team/cases_intent.md(与后端 services/docgen/intent.py 同词典同规则同用例表)
|
||
// 判定顺序(优先级从高到低,命中即返回;漏判安全:不命中一律 qa):
|
||
// 1. export:hasActiveArtifact 且含 EXPORT_WORD 且含 FORMAT_WORD
|
||
// 2. edit: hasActiveArtifact 且含 EDIT_WORD
|
||
// 3. docgen:含 WRITE_VERB 且含 DOC_TYPE(排除词优先,防误判)
|
||
// 4. docgen:hasAttachments 且含 WRITE_VERB(附件兜底信号)
|
||
// 5. qa
|
||
|
||
// —— 导出意图词典 ——
|
||
const EXPORT_WORD = ['导出', '转成', '转为', '转换成', '下载成', '输出为', '存为', '转pdf', '转word'];
|
||
// FORMAT_WORD 英文不区分大小写;"doc" 是 "docx" 的子串,判定时逐一 contains 即可
|
||
const FORMAT_WORD = ['pdf', 'docx', 'doc', 'word'];
|
||
|
||
// —— 编辑意图词典(仅当存在活动文档时生效)——
|
||
const EDIT_WORD = ['改', '修改', '调整', '删', '删除', '加一段', '补充', '润色', '缩写', '扩写', '重写', '改写', '优化', '加个', '增加一段'];
|
||
|
||
// —— 写文档意图词典 ——
|
||
const WRITE_VERB = ['写', '撰写', '拟', '起草', '编制', '生成', '编写', '拟定', '草拟', '制定'];
|
||
const DOC_TYPE = [
|
||
'论文', '报告', '通知', '通告', '公告', '请示', '批复', '函', '申请书', '申请',
|
||
'申报书', '标书', '合同', '协议', '方案', '计划', '总结', '汇报', '讲话稿', '致辞',
|
||
'证明', '纪要', '简报', '材料', '说明书', '指南', '文档', '申报材料', '工作总结',
|
||
'调研报告', '可行性报告', '项目书', '策划书', '演讲稿', '新闻稿', '文案', '简历',
|
||
'制度', '规定', '办法', '细则', '章程', '声明', '邀请函', '感谢信', '慰问信',
|
||
'介绍信', '推荐信', '倡议书', '述职报告', '开题报告', '结题报告', '实验报告',
|
||
'分析报告', '会议纪要',
|
||
];
|
||
// 明确排除(不属于 DOC_TYPE,防误判):介绍、内容、代码、诗、作业、问题、建议、想法
|
||
const DOC_TYPE_EXCLUDE = ['介绍', '内容', '代码', '诗', '作业', '问题', '建议', '想法'];
|
||
|
||
/** 文本是否含词典中任一词(子串判定;英文不区分大小写——中文不受影响,与后端一致) */
|
||
export function hasAnyWord(text, words) {
|
||
const s = String(text == null ? '' : text).toLowerCase();
|
||
for (const w of words) {
|
||
if (s.includes(String(w).toLowerCase())) return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/** 文本是否含任一排除词(排除词优先于 DOC_TYPE 命中——防误判) */
|
||
export function hasAnyExcludeWord(text) {
|
||
return hasAnyWord(text, DOC_TYPE_EXCLUDE);
|
||
}
|
||
|
||
/** 导出文档类型词词典(任务书约定的导出类型词;判定走 EXPORT_WORD+FORMAT_WORD,此处导出供组件复用) */
|
||
export const EXPORT_DOC_TYPE_WORDS = [
|
||
'论文', '报告', '通知', '通告', '公告', '请示', '批复', '函', '申请书', '申报书',
|
||
'标书', '合同', '协议', '方案', '计划', '总结', '汇报', '讲话稿', '致辞',
|
||
'证明', '纪要', '简报', '材料', '说明书', '指南',
|
||
];
|
||
|
||
/**
|
||
* 意图路由(唯一事实源 docs/team/cases_intent.md 的 route 签名)
|
||
* @param {string} text 用户输入文本
|
||
* @param {boolean} hasAttachments 本轮是否带附件(资料 chips)
|
||
* @param {boolean} hasActiveArtifact 是否存在活动文档(文档 TAB 当前打开的 artifact)
|
||
* @returns {'qa'|'docgen'|'edit'|'export'}
|
||
*/
|
||
export function route(text, hasAttachments, hasActiveArtifact) {
|
||
const s = String(text == null ? '' : text);
|
||
// 1. 导出意图(需活动文档)
|
||
if (hasActiveArtifact && hasAnyWord(s, EXPORT_WORD) && hasAnyWord(s, FORMAT_WORD)) return 'export';
|
||
// 2. 编辑意图(需活动文档)
|
||
if (hasActiveArtifact && hasAnyWord(s, EDIT_WORD)) return 'edit';
|
||
// 3. 写文档意图:写类动词 + 文档类型词(排除词防误判优先)
|
||
if (hasAnyWord(s, WRITE_VERB) && !hasAnyExcludeWord(s) && hasAnyWord(s, DOC_TYPE)) return 'docgen';
|
||
// 4. 附件兜底:拖入文件 + 写类动词,即使无文档类型词也视为生成意图
|
||
if (hasAttachments && hasAnyWord(s, WRITE_VERB)) return 'docgen';
|
||
// 5. 漏判安全:一律 qa
|
||
return 'qa';
|
||
}
|
||
|
||
export default route;
|