import { ChatMessage, MessageCategory } from '../types/workbench'; /** * deriveFallbackCategory * 依据消息的 role、intentTag、meta、phaseEvents 以及上下文推导分类 (Spec §3.5 A5) * 避免在纯前端/离线回退模式下出现大量 'uncategorized'。 */ export function deriveFallbackCategory( msg: Partial, prevUserMsg?: Partial ): MessageCategory { if (msg.category && msg.category !== 'uncategorized') { return msg.category; } if (msg.role === 'system') { return 'system'; } // 1. milestone: 里程碑与阶段标记 if (msg.meta && msg.meta.milestone) { return 'milestone'; } // 2. file: 文件/附件收发 if ((msg.attachments && msg.attachments.length > 0) || (msg.meta && (msg.meta.attachments || msg.meta.file_op))) { return 'file'; } // 3. review: 审批流转与交互卡片 if (msg.interactiveCard || (msg.meta && msg.meta.interactive_card)) { return 'review'; } // 4. task: 包含阶段进度/执行追踪 if ((msg.phaseEvents && msg.phaseEvents.length > 0) || msg.taskRequest || (msg.meta && msg.meta.task_request)) { return 'task'; } const intentTag = msg.intentTag || ''; const content = msg.content || ''; // 5. 意图标签与关键词启发式推导 if ( /法规|咨询|参数|研判|建议|查询|要点|指南/.test(intentTag) || /法规|参数|规范|请教|咨询/.test(content.slice(0, 100)) ) { return 'consult'; } if (/立项|责任人|画像|阶段|里程碑|拍板|就绪/.test(intentTag)) { return 'milestone'; } if (/任务|执行|推进|生成|建模|仿真|门禁/.test(intentTag)) { return 'task'; } if (/审批|审核|驳回|认领|签字|提交/.test(intentTag)) { return 'review'; } if (/闲聊|问候|你好|早安|晚安/.test(intentTag)) { return 'casual'; } // 6. 若助手回复缺失分类,尝试继承本轮上一条用户消息的推导分类 if (msg.role === 'assistant' && prevUserMsg) { const prevCat = deriveFallbackCategory(prevUserMsg); if (prevCat && prevCat !== 'uncategorized' && prevCat !== 'system') { return prevCat; } } // 7. 有实质内容的提问/回复默认归入咨询,短句问候归入闲聊 if (content.length > 20) { return 'consult'; } return 'casual'; } /** * enrichMessagesWithCategories * 遍历并填充缺失分类的消息列表 */ export function enrichMessagesWithCategories(messages: ChatMessage[]): ChatMessage[] { let lastUserMsg: ChatMessage | undefined; return messages.map((m) => { const enrichedCat = deriveFallbackCategory(m, lastUserMsg); if (m.role === 'user') { lastUserMsg = m; } if (!m.category || m.category === 'uncategorized') { return { ...m, category: enrichedCat }; } return m; }); }