From 06aa52f15266b8fa2931b987b4919ba22c956dde Mon Sep 17 00:00:00 2001 From: songjvcheng Date: Tue, 12 Aug 2025 21:40:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=81=E7=99=BD=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/llm_stream.js | 65 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/src/llm_stream.js b/src/llm_stream.js index 71de939..bef2cf6 100644 --- a/src/llm_stream.js +++ b/src/llm_stream.js @@ -1,5 +1,35 @@ // 以流式方式请求LLM大模型接口,并打印流式返回内容 +// 过滤旁白内容的函数 +function filterNarration(text) { + if (!text) return text; + + // 匹配各种括号内的旁白内容 + // 包括:()、【】、[]、{}、〈〉、《》等 + const narrationPatterns = [ + /([^)]*)/g, // 中文圆括号 + /\([^)]*\)/g, // 英文圆括号 + /【[^】]*】/g, // 中文方括号 + /\[[^\]]*\]/g, // 英文方括号 + /\{[^}]*\}/g, // 花括号 + /〈[^〉]*〉/g, // 中文尖括号 + /《[^》]*》/g, // 中文书名号 + /<[^>]*>/g // 英文尖括号 + ]; + + let filteredText = text; + + // 逐个应用过滤规则 + narrationPatterns.forEach(pattern => { + filteredText = filteredText.replace(pattern, ''); + }); + + // 清理多余的空格和换行 + filteredText = filteredText.replace(/\s+/g, ' ').trim(); + + return filteredText; +} + async function requestLLMStream({ apiKey, model, messages, onSegment }) { const response = await fetch('https://ark.cn-beijing.volces.com/api/v3/bots/chat/completions', { method: 'POST', @@ -54,7 +84,14 @@ async function requestLLMStream({ apiKey, model, messages, onSegment }) { // 处理最后的待处理文本(无论长度是否大于5个字) if (pendingText.trim() && onSegment) { console.log('处理最后的待处理文本:', pendingText.trim()); - await onSegment(pendingText.trim(), true); + // 过滤旁白内容 + const filteredText = filterNarration(pendingText.trim()); + if (filteredText.trim()) { + console.log('过滤旁白后的最后文本:', filteredText); + await onSegment(filteredText, true); + } else { + console.log('最后的文本被完全过滤,跳过'); + } } continue; } @@ -67,10 +104,13 @@ async function requestLLMStream({ apiKey, model, messages, onSegment }) { pendingText += deltaContent; console.log('LLM内容片段:', deltaContent); - // 检查是否包含分段分隔符 - if (segmentDelimiters.test(pendingText)) { - // 按分隔符分割文本 - const segments = pendingText.split(segmentDelimiters); + // 先过滤旁白,再检查分段分隔符 + const filteredPendingText = filterNarration(pendingText); + + // 检查过滤后的文本是否包含分段分隔符 + if (segmentDelimiters.test(filteredPendingText)) { + // 按分隔符分割已过滤的文本 + const segments = filteredPendingText.split(segmentDelimiters); // 重新组合处理:只处理足够长的完整段落 let accumulatedText = ''; @@ -81,7 +121,7 @@ async function requestLLMStream({ apiKey, model, messages, onSegment }) { if (segment) { accumulatedText += segment; // 找到分隔符 - const delimiterMatch = pendingText.match(segmentDelimiters); + const delimiterMatch = filteredPendingText.match(segmentDelimiters); if (delimiterMatch) { accumulatedText += delimiterMatch[0]; } @@ -89,17 +129,22 @@ async function requestLLMStream({ apiKey, model, messages, onSegment }) { // 如果累积文本长度大于5个字,处理它 if (accumulatedText.length > 8 && onSegment) { console.log('检测到完整段落:', accumulatedText); - await onSegment(accumulatedText, false); + // 文本已经过滤过旁白,直接使用 + if (accumulatedText.trim()) { + console.log('处理过滤后的文本:', accumulatedText); + await onSegment(accumulatedText, false); + } hasProcessed = true; accumulatedText = ''; // 重置 } } } - // 更新pendingText + // 更新pendingText - 使用原始文本但需要相应调整 if (hasProcessed) { - // 保留未处理的累积文本和最后一个不完整段落 - pendingText = accumulatedText + (segments[segments.length - 1] || ''); + // 计算已处理的原始文本长度,更新pendingText + const processedLength = pendingText.length - (segments[segments.length - 1] || '').length; + pendingText = pendingText.substring(processedLength); } } }