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

@@ -0,0 +1,95 @@
const { Client } = require('ssh2');
const fs = require('fs');
const path = require('path');
const SERVER = { host: '119.45.10.34', port: 22, username: 'root', password: '#xyzh%CS#2512@28' };
const REMOTE_DIR = '/www/wwwroot/demo.tensorgrove.com.cn/server';
const FILES = [
{
local: path.join(__dirname, '..', 'services', 'assistantProfileConfig.js'),
remote: REMOTE_DIR + '/services/assistantProfileConfig.js',
},
];
function sshExec(client, cmd) {
return new Promise((resolve, reject) => {
client.exec(cmd, (err, stream) => {
if (err) return reject(err);
let out = '', errOut = '';
stream.on('data', (d) => (out += d.toString()));
stream.stderr.on('data', (d) => (errOut += d.toString()));
stream.on('close', (code) => resolve({ out: out.trim(), err: errOut.trim(), code }));
});
});
}
function sshUpload(client, localPath, remotePath) {
return new Promise((resolve, reject) => {
client.sftp((err, sftp) => {
if (err) return reject(err);
sftp.fastPut(localPath, remotePath, (err) => {
if (err) return reject(err);
resolve();
});
});
});
}
async function deploy() {
const client = new Client();
client.on('ready', async () => {
try {
console.log('✅ SSH connected\n');
const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
// 1. 先查看服务器当前prompt
console.log('📋 服务器当前prompt:');
const before = await sshExec(client, `grep -n 'buildKnowledgeAnswerPrompt\\|知识库涵盖\\|产品用法' ${REMOTE_DIR}/services/assistantProfileConfig.js | head -5`);
console.log(' ' + (before.out || '(not found)') + '\n');
// 2. 备份 + 上传
for (const { local, remote } of FILES) {
const name = path.basename(remote);
await sshExec(client, `cp ${remote} ${remote}.bak_${ts}`);
console.log('📦 Backup: ' + name);
await sshUpload(client, local, remote);
console.log('📤 Uploaded: ' + name);
const syntax = await sshExec(client, `node -c ${remote}`);
if (syntax.code !== 0) {
console.error('❌ Syntax error in ' + name + '! Rolling back...');
await sshExec(client, `cp ${remote}.bak_${ts} ${remote}`);
client.end();
return;
}
console.log('🔍 Syntax OK: ' + name + '\n');
}
// 3. 重启PM2
const pm2Result = await sshExec(client, `cd ${REMOTE_DIR} && pm2 restart all --update-env`);
console.log('🔄 PM2 restarted');
if (pm2Result.out) console.log(' ' + pm2Result.out.split('\n').slice(0, 3).join('\n '));
await new Promise(r => setTimeout(r, 5000));
// 4. 验证新prompt已生效
console.log('\n📋 服务器新prompt:');
const after = await sshExec(client, `grep -n '知识库涵盖\\|产品常有别名\\|不得编造' ${REMOTE_DIR}/services/assistantProfileConfig.js | head -5`);
console.log(' ' + (after.out || '(not found)'));
// 5. PM2 状态
const status = await sshExec(client, 'pm2 status');
console.log('\n📊 PM2 Status:');
console.log(' ' + status.out.split('\n').slice(0, 6).join('\n '));
console.log('\n✅ 部署完成KB answer prompt 已更新为优化版本');
} catch (e) {
console.error('❌ Error:', e.message);
} finally {
client.end();
}
});
client.on('error', (err) => console.error('❌ SSH Error:', err.message));
client.connect(SERVER);
}
deploy();