feat(server): KB prompt优化、字幕修复、S2S重连、助手配置API

- assistantProfileConfig: KB answer prompt改为分层策略(严格产品信息+灵活常识补充)
- nativeVoiceGateway: S2S upstream自动重连(最多50次)、event 351字幕debounce(800ms取最长文本)
- toolExecutor: 确定性query改写增强、KB查询传递session上下文
- contextKeywordTracker: 支持KB话题记忆优先enrichment
- contentSafeGuard: 新增品牌安全内容过滤服务
- assistantProfileService: 新增助手配置CRUD服务
- routes/assistantProfile: 新增助手配置API路由
- knowledgeKeywords: 扩展KB关键词词典
- fastAsrCorrector: ASR纠错规则更新
- tests/: KB prompt测试、保护窗口测试、Viking性能测试
- docs/: 助手配置API文档、系统提示词目录
This commit is contained in:
User
2026-03-24 17:19:36 +08:00
parent 57a03677a9
commit 9567eb7358
34 changed files with 7076 additions and 46 deletions

View File

@@ -85,23 +85,31 @@ class ContextKeywordTracker {
return data.keywords;
}
enrichQueryWithContext(sessionId, query) {
enrichQueryWithContext(sessionId, query, session = null) {
const normalized = (query || '').trim();
const keywords = this.getSessionKeywords(sessionId);
if (keywords.length === 0) {
const isSimpleFollowUp = /^(这个|那个|它|它的|他|他的|该|这款|那款|详细|继续|怎么|为什么|适合谁|什么意思|怎么吃|怎么用|功效|成分|多少钱|哪里买|价格|副作用|正规吗|地址|电话|联系方式|区别|哪个好|规格|包装|剂型|形态|一天几次|每天几次|每日几次)/i.test(normalized);
if (!isSimpleFollowUp) {
return normalized;
}
const isSimpleFollowUp = /^(这个|那个|它|该|这款|那款|详细|继续|怎么|为什么|适合谁|什么意思|怎么吃|怎么用|功效|成分|多少钱|哪里买|价格|副作用|正规吗|地址|电话|联系方式|区别|哪个好)/i.test(normalized);
if (isSimpleFollowUp) {
const keywordStr = keywords.slice(-3).join(' ');
console.log(`[ContextTracker] Enriching: "${normalized}" + "${keywordStr}"`);
return `${keywordStr} ${normalized}`;
// 优先用session的KB话题记忆60秒内有效
// 解决:聊了"一成系统"再聊"骨关节"后追问"这款怎么吃",应关联"骨关节"而非"一成系统"
const KB_TOPIC_TTL = 60000;
if (session?._lastKbTopic && session?._lastKbHitAt && (Date.now() - session._lastKbHitAt < KB_TOPIC_TTL)) {
console.log(`[ContextTracker] Enriching from KB topic memory: "${normalized}" + "${session._lastKbTopic}"`);
return `${session._lastKbTopic} ${normalized}`;
}
return normalized;
// fallback: 原有keyword tracker逻辑
const keywords = this.getSessionKeywords(sessionId);
if (keywords.length === 0) {
return normalized;
}
const keywordStr = keywords.slice(-3).join(' ');
console.log(`[ContextTracker] Enriching: "${normalized}" + "${keywordStr}"`);
return `${keywordStr} ${normalized}`;
}
cleanup() {