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:
@@ -1,7 +1,8 @@
|
||||
const axios = require('axios');
|
||||
const https = require('https');
|
||||
const arkChatService = require('./arkChatService');
|
||||
const { buildKnowledgeAnswerPrompt } = require('./assistantProfileConfig');
|
||||
const { buildKnowledgeAnswerPrompt, resolveAssistantProfile } = require('./assistantProfileConfig');
|
||||
const { getAssistantProfile } = require('./assistantProfileService');
|
||||
|
||||
// HTTP keep-alive agent:复用TCP连接,避免每次请求重新握手
|
||||
const kbHttpAgent = new https.Agent({
|
||||
@@ -43,14 +44,14 @@ const {
|
||||
SCIENCE_TRAINING_ROUTE_KEYWORDS,
|
||||
} = require('./knowledgeKeywords');
|
||||
|
||||
// KB查询缓存:相同effectiveQuery + datasetIds在TTL内直接返回缓存结果
|
||||
// KB查询缓存:相同effectiveQuery + datasetIds + userId在TTL内直接返回缓存结果
|
||||
const KB_CACHE_TTL_MS = 5 * 60 * 1000; // 5分钟 (hit结果)
|
||||
const KB_CACHE_NOHIT_TTL_MS = 2 * 60 * 1000; // 2分钟 (no-hit结果,较短TTL)
|
||||
const KB_CACHE_MAX_SIZE = 200;
|
||||
const kbQueryCache = new Map();
|
||||
|
||||
function getKbCacheKey(query, datasetIds) {
|
||||
return `${(query || '').trim()}|${(datasetIds || []).sort().join(',')}`;
|
||||
function getKbCacheKey(query, datasetIds, profileScope = 'global') {
|
||||
return `${String(profileScope || 'global').trim() || 'global'}|${(query || '').trim()}|${(datasetIds || []).sort().join(',')}`;
|
||||
}
|
||||
|
||||
function getKbCache(key) {
|
||||
@@ -698,6 +699,16 @@ class ToolExecutor {
|
||||
query = query || '';
|
||||
const responseMode = response_mode === 'snippet' ? 'snippet' : 'answer';
|
||||
const knowledgeEndpointId = process.env.VOLC_ARK_KNOWLEDGE_ENDPOINT_ID || process.env.VOLC_ARK_ENDPOINT_ID;
|
||||
const profileUserId = _session?.profileUserId || _session?.userId || null;
|
||||
const assistantProfileResult = await getAssistantProfile({ userId: profileUserId });
|
||||
const assistantProfile = resolveAssistantProfile({
|
||||
...(assistantProfileResult?.profile || {}),
|
||||
...(_session?.assistantProfile || {}),
|
||||
});
|
||||
if (_session && assistantProfileResult?.profile) {
|
||||
_session.assistantProfile = assistantProfile;
|
||||
}
|
||||
const profileScope = profileUserId || 'global';
|
||||
console.log(`[ToolExecutor] searchKnowledge called with query="${query}"`);
|
||||
|
||||
// 注意:answer 模式必须依据知识库回答,因此不再允许本地热答案直接绕过知识库。
|
||||
@@ -748,7 +759,7 @@ class ToolExecutor {
|
||||
}
|
||||
try {
|
||||
// 缓存检查:相同effectiveQuery + datasetIds命中缓存时直接返回,避免重复API调用
|
||||
const cacheKey = getKbCacheKey(effectiveQuery, kbTarget.datasetIds);
|
||||
const cacheKey = getKbCacheKey(effectiveQuery, kbTarget.datasetIds, profileScope);
|
||||
const cached = getKbCache(cacheKey);
|
||||
if (cached) {
|
||||
const latencyMs = Date.now() - startTime;
|
||||
@@ -764,7 +775,7 @@ class ToolExecutor {
|
||||
};
|
||||
}
|
||||
console.log('[ToolExecutor] Trying Ark Knowledge Search...');
|
||||
const arkResult = await this.searchArkKnowledge(effectiveQuery, context, responseMode, kbTarget.datasetIds, query, _session?.assistantProfile || null);
|
||||
const arkResult = await this.searchArkKnowledge(effectiveQuery, context, responseMode, kbTarget.datasetIds, query, assistantProfile);
|
||||
const latencyMs = Date.now() - startTime;
|
||||
console.log(`[ToolExecutor] Ark KB search succeeded in ${latencyMs}ms`);
|
||||
// 缓存所有结果(hit用5分钟TTL,no-hit用2分钟TTL),避免重复API调用
|
||||
|
||||
Reference in New Issue
Block a user