feat: 添加realtime_dialog和realtime_dialog_external_rag_test项目,更新test2项目

This commit is contained in:
User
2026-03-13 13:06:46 +08:00
parent 9dab61345c
commit 5521b673f5
215 changed files with 7626 additions and 1876 deletions

View File

@@ -1,172 +0,0 @@
const { v4: uuidv4 } = require('uuid');
class VoiceChatConfigBuilder {
/**
* 构建 StartVoiceChat 的完整配置S2S 端到端语音大模型 + LLM 混合编排)
* OutputMode=1: 混合模式S2S 处理普通对话LLM 处理工具调用
*/
static build(options) {
const {
roomId,
taskId,
userId,
botName = '小智',
systemRole = '你是一个友善的智能助手。',
speakingStyle = '请使用温和、清晰的口吻。',
modelVersion = '1.2.1.0',
speaker = 'zh_female_vv_jupiter_bigtts',
tools = [],
llmSystemPrompt = '',
enableWebSearch = false,
vadEndMs = 1200,
chatHistory = [],
} = options;
const botUserId = `bot_${uuidv4().slice(0, 8)}`;
const providerParams = {
app: {
appid: process.env.VOLC_S2S_APP_ID,
token: process.env.VOLC_S2S_TOKEN,
},
dialog: this._buildDialogConfig(modelVersion, botName, systemRole, speakingStyle, enableWebSearch, chatHistory),
tts: {
speaker: speaker,
},
asr: {
extra: {
enable_custom_vad: true,
end_smooth_window_ms: vadEndMs,
},
},
};
// === 调试模式:纯 S2SOutputMode=0排除 LLM 干扰 ===
// ARK 端点已配置正确,启用混合编排模式
const DEBUG_PURE_S2S = false;
const llmConfig = {
Mode: 'ArkV3',
EndPointId: process.env.VOLC_ARK_ENDPOINT_ID,
MaxTokens: 1024,
Temperature: 0.1,
TopP: 0.3,
SystemMessages: [llmSystemPrompt || this._buildDefaultLLMPrompt(tools)],
HistoryLength: 10,
ThinkingType: 'disabled',
};
if (tools.length > 0) {
llmConfig.Tools = tools;
}
// 混合模式:通过 UserPrompts 传入聊天历史作为上下文(官方推荐方式)
if (chatHistory && chatHistory.length > 0 && !DEBUG_PURE_S2S) {
const userPrompts = chatHistory.slice(-10).map(m => ({
Role: m.role === 'user' ? 'user' : 'assistant',
Content: m.content,
}));
llmConfig.UserPrompts = userPrompts;
console.log(`[VoiceChatConfig] Injected ${userPrompts.length} UserPrompts into LLMConfig`);
}
const config = {
AppId: process.env.VOLC_RTC_APP_ID,
RoomId: roomId,
TaskId: taskId,
AgentConfig: {
TargetUserId: [userId],
WelcomeMessage: `你好,我是${botName},有什么需要帮忙的吗?`,
UserId: botUserId,
EnableConversationStateCallback: true,
},
Config: {
S2SConfig: {
Provider: 'volcano',
OutputMode: DEBUG_PURE_S2S ? 0 : 1,
ProviderParams: providerParams,
},
// 注意S2S 端到端模式下不需要独立 TTSConfig
// ExternalTextToSpeech 在 S2S 模式下不产生音频,只用 Command:function
SubtitleConfig: {
SubtitleMode: 1,
},
InterruptMode: 0,
},
};
// 混合模式才需要 LLMConfig
if (!DEBUG_PURE_S2S) {
config.Config.LLMConfig = llmConfig;
// Function Calling 回调配置RTC 服务通过此 URL 发送 tool call 请求
if (tools.length > 0) {
const serverUrl = process.env.FC_SERVER_URL || 'https://demo.tensorgrove.com.cn/api/voice/fc_callback';
config.Config.FunctionCallingConfig = {
ServerMessageUrl: serverUrl,
ServerMessageSignature: process.env.FC_SIGNATURE || 'default_signature',
};
console.log(`[VoiceChatConfig] FunctionCallingConfig enabled, URL: ${serverUrl}`);
}
}
console.log('[VoiceChatConfig] DEBUG_PURE_S2S:', DEBUG_PURE_S2S);
console.log('[VoiceChatConfig] OutputMode:', config.Config.S2SConfig.OutputMode);
console.log('[VoiceChatConfig] ProviderParams type:', typeof config.Config.S2SConfig.ProviderParams);
console.log('[VoiceChatConfig] S2S AppId:', providerParams.app.appid);
console.log('[VoiceChatConfig] S2S Token:', providerParams.app.token ? '***set***' : '***MISSING***');
return { config, botUserId };
}
static _buildDialogConfig(modelVersion, botName, systemRole, speakingStyle, enableWebSearch, chatHistory = []) {
const isOSeries = modelVersion === 'O' || modelVersion.startsWith('1.');
const dialog = {
extra: { model: modelVersion },
};
// 如果有文字聊天历史,将其追加到 system_role 作为上下文
let fullSystemRole = systemRole;
if (chatHistory && chatHistory.length > 0) {
const historyText = chatHistory
.slice(-10)
.map(m => `${m.role === 'user' ? '用户' : '助手'}${m.content}`)
.join('\n');
fullSystemRole += `\n\n## 之前的对话记录(请延续此上下文)\n${historyText}`;
console.log(`[VoiceChatConfig] Injected ${chatHistory.length} chat history messages into system_role`);
}
if (isOSeries) {
dialog.bot_name = botName;
dialog.system_role = fullSystemRole;
dialog.speaking_style = speakingStyle;
} else {
dialog.character_manifest = `${fullSystemRole}\n你的名字是${botName}${speakingStyle}`;
}
if (enableWebSearch && process.env.VOLC_WEBSEARCH_API_KEY) {
dialog.extra.enable_volc_websearch = true;
dialog.extra.volc_websearch_api_key = process.env.VOLC_WEBSEARCH_API_KEY;
dialog.extra.volc_websearch_type = 'web_summary';
dialog.extra.volc_websearch_no_result_message = '抱歉,我没有查到相关信息。';
}
return dialog;
}
static _buildDefaultLLMPrompt(tools) {
const toolNames = tools.map((t) => t.function?.name).filter(Boolean);
if (toolNames.length === 0) {
return '你是一个智能助手。对于所有问题直接回答即可。';
}
return `你是一个企业智能客服助手。你可以使用以下工具:${toolNames.join('、')}
## 最高优先级规则
1. 每次用户提问,你**必须**先调用 search_knowledge 工具查询知识库
2. 收到工具返回的知识库内容后,你**必须完整、详细地朗读**知识库返回的内容给用户
3. 不要省略、总结或缩写知识库的内容,要逐字朗读
4. 如果知识库没有相关内容,再用你自己的知识简洁回答
5. 如果知识库返回"未找到相关信息",直接告诉用户并提供建议`;
}
}
module.exports = VoiceChatConfigBuilder;