diff --git a/src/handlers/genAIContent.js b/src/handlers/genAIContent.js index db73f14..cb8492b 100644 --- a/src/handlers/genAIContent.js +++ b/src/handlers/genAIContent.js @@ -6,7 +6,7 @@ import { generateGenAiPageHtml } from '../htmlGenerators.js'; import { dataSources } from '../dataFetchers.js'; // Import dataSources import { getSystemPromptSummarizationStepOne } from '../prompt/summarizationPromptStepOne.js'; import { getSystemPromptSummarizationStepTwo } from '../prompt/summarizationPromptStepTwo.js'; -import { getSystemPromptPodcastFormatting } from '../prompt/podcastFormattingPrompt.js'; +import { getSystemPromptPodcastFormatting, getSystemPromptShortPodcastFormatting } from '../prompt/podcastFormattingPrompt.js'; import { getSystemPromptDailyAnalysis } from '../prompt/dailyAnalysisPrompt.js'; // Import new prompt import { insertFoot } from '../foot.js'; @@ -17,8 +17,8 @@ export async function handleGenAIPodcastScript(request, env) { let outputOfCall1 = null; // This will be the summarized content from Call 1 let userPromptPodcastFormattingData = null; - let fullPromptForCall2_System = null; - let fullPromptForCall2_User = null; + let fullPromptForCall3_System = null; + let fullPromptForCall3_User = null; let finalAiResponse = null; try { @@ -32,40 +32,64 @@ export async function handleGenAIPodcastScript(request, env) { return new Response(errorHtml, { status: 400, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } - userPromptPodcastFormattingData = outputOfCall1; - fullPromptForCall2_System = getSystemPromptPodcastFormatting(env); - fullPromptForCall2_User = userPromptPodcastFormattingData; - console.log("Call 2 to Chat (Podcast Formatting): User prompt length:", userPromptPodcastFormattingData.length); + fullPromptForCall3_System = getSystemPromptPodcastFormatting(env); + userPromptPodcastFormattingData = outputOfCall1; + fullPromptForCall3_User = userPromptPodcastFormattingData; + + console.log("Call 3 to Chat (Podcast Formatting): User prompt length:", userPromptPodcastFormattingData.length); try { let podcastChunks = []; - for await (const chunk of callChatAPIStream(env, userPromptPodcastFormattingData, fullPromptForCall2_System)) { + for await (const chunk of callChatAPIStream(env, userPromptPodcastFormattingData, fullPromptForCall3_System)) { podcastChunks.push(chunk); } finalAiResponse = podcastChunks.join(''); if (!finalAiResponse || finalAiResponse.trim() === "") throw new Error("Chat podcast formatting call returned empty content."); finalAiResponse = removeMarkdownCodeBlock(finalAiResponse); // Clean the output - console.log("Call 2 (Podcast Formatting) successful. Final output length:", finalAiResponse.length); + console.log("Call 3 (Podcast Formatting) successful. Final output length:", finalAiResponse.length); } catch (error) { - console.error("Error in Chat API Call 2 (Podcast Formatting):", error); - const errorHtml = generateGenAiPageHtml(env, '生成AI播客脚本出错(播客文案)', `

Failed during podcast formatting: ${escapeHtml(error.message)}

${error.stack ? `
${escapeHtml(error.stack)}
` : ''}`, dateStr, true, selectedItemsParams, null, null, fullPromptForCall2_System, fullPromptForCall2_User); + console.error("Error in Chat API Call 3 (Podcast Formatting):", error); + const errorHtml = generateGenAiPageHtml(env, '生成AI播客脚本出错(播客文案)', `

Failed during podcast formatting: ${escapeHtml(error.message)}

${error.stack ? `
${escapeHtml(error.stack)}
` : ''}`, dateStr, true, selectedItemsParams, null, null, fullPromptForCall3_System, fullPromptForCall3_User); return new Response(errorHtml, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } - + let finalAiResponseOut = `## Full: Podcast Formatting ` + `\n\n` + finalAiResponse; let promptsMarkdownContent = `# Prompts for ${dateStr}\n\n`; - promptsMarkdownContent += `## Call 2: Podcast Formatting\n\n`; - if (fullPromptForCall2_System) promptsMarkdownContent += `### System Instruction\n\`\`\`\n${fullPromptForCall2_System}\n\`\`\`\n\n`; - if (fullPromptForCall2_User) promptsMarkdownContent += `### User Input (Output of Call 1)\n\`\`\`\n${fullPromptForCall2_User}\n\`\`\`\n\n`; + promptsMarkdownContent += `## Call 3: Podcast Formatting\n\n`; + if (fullPromptForCall3_System) promptsMarkdownContent += `### System One Instruction\n\`\`\`\n${fullPromptForCall3_System}\n\`\`\`\n\n`; + - let podcastScriptMarkdownContent = `# ${env.PODCAST_TITLE} ${formatDateToChinese(dateStr)}\n\n${removeMarkdownCodeBlock(finalAiResponse)}`; + let fullPromptForCall4_System = getSystemPromptShortPodcastFormatting(env); + console.log("Call 4 to Chat (Podcast Formatting): User prompt length:", userPromptPodcastFormattingData.length); + try { + let podcastChunks = []; + for await (const chunk of callChatAPIStream(env, userPromptPodcastFormattingData, fullPromptForCall4_System)) { + podcastChunks.push(chunk); + } + finalAiResponse = podcastChunks.join(''); + if (!finalAiResponse || finalAiResponse.trim() === "") throw new Error("Chat podcast formatting call returned empty content."); + finalAiResponse = removeMarkdownCodeBlock(finalAiResponse); // Clean the output + console.log("Call 4 (Podcast Formatting) successful. Final output length:", finalAiResponse.length); + } catch (error) { + console.error("Error in Chat API Call 4 (Podcast Formatting):", error); + const errorHtml = generateGenAiPageHtml(env, '生成AI播客脚本出错(播客文案)', `

Failed during podcast formatting: ${escapeHtml(error.message)}

${error.stack ? `
${escapeHtml(error.stack)}
` : ''}`, dateStr, true, selectedItemsParams, null, null, fullPromptForCall3_System, fullPromptForCall3_User); + return new Response(errorHtml, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); + } + finalAiResponseOut += `\n\n` + `## Short: Podcast Formatting ` + `\n\n` + finalAiResponse; + let fullPromptForCallSystem = fullPromptForCall3_System + `\n\n` + fullPromptForCall4_System; + + promptsMarkdownContent += `## Call 4: Podcast Formatting\n\n`; + if (fullPromptForCall4_System) promptsMarkdownContent += `### System Two Instruction\n\`\`\`\n${fullPromptForCall4_System}\n\`\`\`\n\n`; + if (fullPromptForCall3_User) promptsMarkdownContent += `### User Input (Output of Call 1)\n\`\`\`\n${fullPromptForCall3_User}\n\`\`\`\n\n`; + + let podcastScriptMarkdownContent = `# ${env.PODCAST_TITLE} ${formatDateToChinese(dateStr)}\n\n${removeMarkdownCodeBlock(finalAiResponseOut)}`; const successHtml = generateGenAiPageHtml( env, 'AI播客脚本', - escapeHtml(finalAiResponse), + escapeHtml(finalAiResponseOut), dateStr, false, selectedItemsParams, null, null, // No Call 1 prompts for this page - fullPromptForCall2_System, fullPromptForCall2_User, + fullPromptForCallSystem, fullPromptForCall3_User, convertEnglishQuotesToChinese(removeMarkdownCodeBlock(promptsMarkdownContent)), outputOfCall1, // No daily summary for this page convertEnglishQuotesToChinese(podcastScriptMarkdownContent) @@ -76,7 +100,7 @@ export async function handleGenAIPodcastScript(request, env) { console.error("Error in /genAIPodcastScript (outer try-catch):", error); const pageDateForError = dateStr || getISODate(); const itemsForActionOnError = Array.isArray(selectedItemsParams) ? selectedItemsParams : []; - const errorHtml = generateGenAiPageHtml(env, '生成AI播客脚本出错', `

Unexpected error: ${escapeHtml(error.message)}

${error.stack ? `
${escapeHtml(error.stack)}
` : ''}`, pageDateForError, true, itemsForActionOnError, null, null, fullPromptForCall2_System, fullPromptForCall2_User); + const errorHtml = generateGenAiPageHtml(env, '生成AI播客脚本出错', `

Unexpected error: ${escapeHtml(error.message)}

${error.stack ? `
${escapeHtml(error.stack)}
` : ''}`, pageDateForError, true, itemsForActionOnError, null, null, fullPromptForCall3_System, fullPromptForCall3_User); return new Response(errorHtml, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } } diff --git a/src/helpers.js b/src/helpers.js index b946957..e47c306 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -105,7 +105,10 @@ export function stripHtml(html) { }); processedHtml = processedHtml.replace(/]*src="([^"]*)"[^>]*>/gi, '[图片: $1]'); - // 移除所有其他 HTML 標籤,並正規化空白 + // 处理 video 标签,保留其 src 属性 + processedHtml = processedHtml.replace(/]*src="([^"]*)"[^>]*>.*?<\/video>/gi, '[视频: $1]'); + + // 移除所有其他 HTML 标签,并规范化空白 return processedHtml.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim(); } diff --git a/src/htmlGenerators.js b/src/htmlGenerators.js index 7dc68f7..c93b55d 100644 --- a/src/htmlGenerators.js +++ b/src/htmlGenerators.js @@ -242,7 +242,10 @@ export function generateContentSelectionPageHtml(env, dateStr, allData, dataCate event.preventDefault(); // Prevent form submission return false; } + const button = event.currentTarget; // 获取触发事件的按钮 if (confirm('确定要从选中内容生成 AI 日报吗?此操作将调用 AI 模型生成内容。')) { + button.innerText = '生成中...'; // 更改按钮文案 + //button.disabled = true; // 禁用按钮,防止重复提交 return true; // Allow form submission } else { event.preventDefault(); // Prevent form submission @@ -299,8 +302,9 @@ export function generateGenAiPageHtml(env, title, bodyContent, pageDate, isError ${selectedItemsForAction.map(item => ``).join('')} - `; - } + + `; + } let githubSaveFormHtml = ''; let generatePodcastButtonHtml = ''; diff --git a/src/prompt/podcastFormattingPrompt.js b/src/prompt/podcastFormattingPrompt.js index f2a7e54..5ad364b 100644 --- a/src/prompt/podcastFormattingPrompt.js +++ b/src/prompt/podcastFormattingPrompt.js @@ -1,4 +1,13 @@ -// Add new data sources +export function getSystemPromptShortPodcastFormatting(env) { + return ` + 你是一位播客主持人,你需要根据提供的内容,将内容改写为播客的文案。内容以中文撰写,内容中不能出现时间。 + 你的任务是根据收到的内容改编成一个紧凑,简洁的单人播客脚本。 + 将原始副本转化为自然、口语化的表达,就像与听众聊天一样,每部分内容都能用一句话表述清楚。 + 不要有解释性语句,不要有过渡性语言,直接播报新闻,只用在表达上稍微美化。 + 开场白结束语:固定的开场白:“${env.PODCAST_BEGIN}”,并以固定的结束语结束:“${env.PODCAST_END}”。 + `; +} + export function getSystemPromptPodcastFormatting(env) { return ` 你是一位经验丰富的播客脚本撰写人和编辑。你的任务是根据收到的内容改编成一个引人入胜的单人播客脚本。 @@ -20,4 +29,4 @@ export function getSystemPromptPodcastFormatting(env) { 结尾处的关键词列表。 不要包含任何其他解释性文字。 `; -} +} \ No newline at end of file