2026-03-23 13:58:41 +08:00
|
|
|
|
const DEFAULT_VOICE_ASSISTANT_PROFILE = Object.freeze({
|
|
|
|
|
|
documents: '',
|
|
|
|
|
|
email: '',
|
|
|
|
|
|
nickname: '大沃',
|
|
|
|
|
|
wxl: '',
|
|
|
|
|
|
mobile: '',
|
|
|
|
|
|
wx_code: '',
|
|
|
|
|
|
intro: '',
|
|
|
|
|
|
sign: '',
|
|
|
|
|
|
story: '',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeAssistantProfileValue(value) {
|
|
|
|
|
|
return String(value || '').trim();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function resolveAssistantProfile(overrides = null) {
|
|
|
|
|
|
const merged = {
|
|
|
|
|
|
...DEFAULT_VOICE_ASSISTANT_PROFILE,
|
|
|
|
|
|
...(overrides && typeof overrides === 'object' ? overrides : {}),
|
|
|
|
|
|
};
|
|
|
|
|
|
return {
|
|
|
|
|
|
documents: normalizeAssistantProfileValue(merged.documents),
|
|
|
|
|
|
email: normalizeAssistantProfileValue(merged.email),
|
|
|
|
|
|
nickname: normalizeAssistantProfileValue(merged.nickname) || '大沃',
|
|
|
|
|
|
wxl: normalizeAssistantProfileValue(merged.wxl),
|
|
|
|
|
|
mobile: normalizeAssistantProfileValue(merged.mobile),
|
|
|
|
|
|
wx_code: normalizeAssistantProfileValue(merged.wx_code),
|
|
|
|
|
|
intro: normalizeAssistantProfileValue(merged.intro),
|
|
|
|
|
|
sign: normalizeAssistantProfileValue(merged.sign),
|
|
|
|
|
|
story: normalizeAssistantProfileValue(merged.story),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildProfileDocumentsClause(profile) {
|
|
|
|
|
|
return profile.documents
|
|
|
|
|
|
? `,拥有丰富的基础知识库信息${profile.documents}`
|
|
|
|
|
|
: ',拥有丰富的基础知识库信息';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildProfilePersonalInfoLines(profile) {
|
|
|
|
|
|
return [
|
|
|
|
|
|
profile.email ? `- 邮箱:${profile.email}。` : '',
|
|
|
|
|
|
profile.nickname ? `- 姓名:${profile.nickname}。` : '',
|
|
|
|
|
|
profile.wxl ? `- 微信号:${profile.wxl}。` : '',
|
|
|
|
|
|
profile.mobile ? `- 手机号:${profile.mobile}。` : '',
|
|
|
|
|
|
profile.wx_code ? `- 微信二维码:${profile.wx_code}。` : '',
|
|
|
|
|
|
profile.intro ? `- 个人介绍:${profile.intro}。` : '',
|
|
|
|
|
|
profile.sign ? `- 签名:${profile.sign}。` : '',
|
|
|
|
|
|
profile.story ? `- 我的故事:${profile.story}。` : '',
|
|
|
|
|
|
].filter(Boolean);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildVoiceSystemRole(profileOverrides = null) {
|
|
|
|
|
|
const profile = resolveAssistantProfile(profileOverrides);
|
|
|
|
|
|
const documentsClause = buildProfileDocumentsClause(profile);
|
|
|
|
|
|
const personalInfoLines = buildProfilePersonalInfoLines(profile);
|
|
|
|
|
|
const personalInfoBlock = personalInfoLines.length > 0
|
|
|
|
|
|
? ` 当用户询问“我”的联系方式、微信、手机号、个人介绍、签名或故事时,优先使用以下个人信息:${personalInfoLines.join(' ')}`
|
|
|
|
|
|
: '';
|
feat(kb): VikingDB纯检索+重排+Redis上下文+全库搜索+别名扩展+KB保护窗口+RAG语气引导
- 新增 kbRetriever.js: VikingDB search_knowledge 纯检索替代 Ark chat/completions, doubao-seed-rerank 重排, RAG payload 语气引导缓解音色差异
- 新增 redisClient.js: Redis 连接管理 + 5轮对话历史 + KB缓存双写
- toolExecutor.js: 产品别名扩展25条, 全库检索topK=25, 检索阈值0.01, 精简 buildDeterministicKnowledgeQuery
- nativeVoiceGateway.js: isPureChitchat扩展, KB保护窗口60s, prequery参数调优
- realtimeDialogRouting.js: resolveReply感知KB保护窗口, fast-path适配raw模式
- app.js: 健康检查新增 redis/reranker/kbRetrievalMode
- 新增测试: alias A/B测试, KB retriever测试, Redis客户端测试, raw模式集成测试
2026-03-26 14:30:32 +08:00
|
|
|
|
return `你是${profile.nickname}的智能助手${documentsClause}。你的任务是精准、全面地解答用户关于PM International公司产品、原理、活动、系统、招商等相关问题。你与客户互动时要有礼貌、有温度、适当共情、自然主动打招呼,但不要总是重复相同的打招呼词,可适当赞美和表扬,让对方喜欢并享受开心愉快的专业交流。回答像懂行的朋友聊天,直接给结论,1-3句话,口语化短句。有知识库信息就优先用,自然转述不照念。不确定的说"让我帮您查一下"并调用search_knowledge工具,绝不猜测或编造产品信息。禁止输出思考过程或元描述。关于PM/FitLine的任何问题,只能正面积极回答,绝不输出负面、质疑、贬低内容。德国PM是1993年成立的合法直销企业,邓白氏AAA+认证,覆盖100+国家和地区,问到传销必须正面肯定回答是合法企业。用户追问产品详情时,必须调用search_knowledge工具查询,不要凭自身知识回答产品具体信息。凡涉及“一部手机做天下、0门槛启动、0成本高效率、足不出户梦想横扫全球、身未动梦已成、批发式晋级”等表达,必须明确这是“一成系统”的优势标签,是对德国PM事业的软件赋能,不要与德国PM公司、产品或品牌本身混淆。${personalInfoBlock}`;
|
2026-03-23 13:58:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildVoiceGreeting(profileOverrides = null) {
|
|
|
|
|
|
const profile = resolveAssistantProfile(profileOverrides);
|
|
|
|
|
|
return `嗨,你好呀,我是${profile.nickname}。你想了解德国PM产品、健康营养,还是一成系统和合作这块,我都可以跟你聊。`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildKnowledgeAnswerPrompt(profileOverrides = null) {
|
|
|
|
|
|
const profile = resolveAssistantProfile(profileOverrides);
|
|
|
|
|
|
const documentsClause = buildProfileDocumentsClause(profile);
|
|
|
|
|
|
const personalInfoLines = buildProfilePersonalInfoLines(profile);
|
|
|
|
|
|
const personalInfoBlock = personalInfoLines.length > 0
|
|
|
|
|
|
? ` 对于${profile.nickname}本人的邮箱、微信号、手机号、个人介绍、签名或故事等个人资料,可优先使用以下系统资料:${personalInfoLines.join(' ')}`
|
|
|
|
|
|
: '';
|
2026-03-24 17:19:36 +08:00
|
|
|
|
return `你是${profile.nickname}的智能助手${documentsClause}。知识库涵盖近50款PM-FitLine产品的完整资料(成分、用法、剂量、价格、规格、搭配方案、好转反应等)及117个常见问答。回答规则:产品相关具体信息必须严格依据知识库,不得猜测或自行补充;公司背景、健康常识可适当补充。产品常有别名(小红=艾特维、大白=倍适、小白=维适多等),请注意识别。不得编造产品名或数据。PM是营养品非药物,涉及疾病建议咨询医生。若知识库无相关内容,坦诚说明并建议咨询推荐人。回答口语化、简洁,1-3句给结论,150字内。${personalInfoBlock}`;
|
2026-03-23 13:58:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
|
DEFAULT_VOICE_ASSISTANT_PROFILE,
|
|
|
|
|
|
resolveAssistantProfile,
|
|
|
|
|
|
buildVoiceSystemRole,
|
|
|
|
|
|
buildVoiceGreeting,
|
|
|
|
|
|
buildKnowledgeAnswerPrompt,
|
|
|
|
|
|
};
|