Discusión

Diseñar un algoritmo basado en LLM para organizar subtítulos en párrafos y capítulos.

De Wikiprompt, la enciclopedia libre de prompts

宝玉
Contribuido por宝玉XFuente

19 dic 2024

Diseñar un algoritmo basado en LLM para organizar subtítulos en párrafos y capítulos. Una solicitud detallada pidiendo diseñar un algoritmo usando LLM para organizar segmentos de subtítulos en párrafos y capítulos, con restricciones específicas sobre la ventana de contexto, la paginación, el costo y el formato de salida.

Contenido del PromptGuardar

🌐
// 算法设计:基于大语言模型的字幕分段分章算法 interface SubtitleSegment { start: number; end: number; text: string; words: { word: string; start: number; end: number }[]; } interface Subtitle { segments: SubtitleSegment[]; } interface Paragraph { start: number; end: number; text: string; segments: SubtitleSegment[]; } interface Chapter { title: string; paragraphs: Paragraph[]; } interface Transcription { chapters: Chapter[]; } // 分页策略:基于字符数或段数,保留上下文重叠 const PAGE_SIZE = 3000; // 每页字符数 const OVERLAP_SIZE = 500; // 重叠字符数,用于保持上下文连贯 function paginateSegments(segments: SubtitleSegment[]): SubtitleSegment[][] { const pages: SubtitleSegment[][] = []; let currentPage: SubtitleSegment[] = []; let currentLength = 0; for (const segment of segments) { const segmentLength = segment.text.length; // 如果当前页超过大小且已有内容,开始新页 if (currentLength + segmentLength > PAGE_SIZE && currentPage.length > 0) { // 添加重叠部分:从当前页末尾取一部分段落到新页开头 const overlapSegments = getOverlapSegments(currentPage, OVERLAP_SIZE); pages.push(currentPage); currentPage = [...overlapSegments]; currentLength = overlapSegments.reduce((sum, seg) => sum + seg.text.length, 0); } currentPage.push(segment); currentLength += segmentLength; } if (currentPage.length > 0) { pages.push(currentPage); } return pages; } function getOverlapSegments(segments: SubtitleSegment[], overlapChars: number): SubtitleSegment[] { const result: SubtitleSegment[] = []; let totalLength = 0; // 从末尾向前收集段落到达到重叠字符数 for (let i = segments.length - 1; i >= 0; i--) { result.unshift(segments[i]); totalLength += segments[i].text.length; if (totalLength >= overlapChars) break; } return result; } // 大语言模型调用函数(模拟) async function callLLMForChapters( pageSegments: SubtitleSegment[], previousContext: { title: string; lastParagraphText: string } | null ): Promise<{ chapters: { title: string; paragraphIndices: number[] }[] }> { // 构建提示词,包含上下文信息 const prompt = buildPrompt(pageSegments, previousContext); // 调用LLM,要求返回JSON格式的章节和段落索引映射 // 注意:不要求LLM输出字符位置,只输出段落索引 const response = await llmAPI(prompt); // 解析响应,处理可能的格式错误 return parseLLMResponse(response); } function buildPrompt( pageSegments: SubtitleSegment[], previousContext: { title: string; lastParagraphText: string } | null ): string { let prompt = `请分析以下字幕内容,将其组织成章节(Chapter)和段落(Paragraph)。\n\n`; if (previousContext) { prompt += `上一页的上下文信息:\n`; prompt += `上一章节标题:${previousContext.title}\n`; prompt += `上一段落结尾:${previousContext.lastParagraphText}\n\n`; prompt += `请注意,如果当前内容与上一章节主题连续,请继续使用相同章节标题。\n\n`; } prompt += `字幕内容(每行格式:索引: 文本):\n`; pageSegments.forEach((seg, index) => { prompt += `${index}: ${seg.text}\n`; }); prompt += `\n请返回JSON格式结果:\n`; prompt += `{ "chapters": [ { "title": "章节标题", "paragraphIndices": [[startIndex, endIndex], [startIndex, endIndex]] } ] }\n`; prompt += `其中paragraphIndices中的每个[startIndex, endIndex]表示一个段落包含的字幕索引范围。\n`; prompt += `注意:\n`; prompt += `1. 只返回索引范围,不要返回文本内容\n`; prompt += `2. 索引范围必须连续\n`; prompt += `3. 如果内容与上一章节连续,使用相同标题\n`; return prompt; } // 主算法 async function segmentToTranscription(subtitle: Subtitle): Promise<Transcription> { const pages = paginateSegments(subtitle.segments); const allChapters: Chapter[] = []; let previousContext: { title: string; lastParagraphText: string } | null = null; for (const page of pages) { // 调用LLM获取该页的章节和段落结构 const llmResult = await callLLMForChapters(page, previousContext); // 将LLM返回的索引映射到实际的SubtitleSegment const pageChapters: Chapter[] = []; for (const llmChapter of llmResult.chapters) { const paragraphs: Paragraph[] = []; for (const [startIdx, endIdx] of llmChapter.paragraphIndices) { // 确保索引在有效范围内 const validStart = Math.max(0, startIdx); const validEnd = Math.min(page.length - 1, endIdx); if (validStart > validEnd) continue; const paragraphSegments = page.slice(validStart, validEnd + 1); const paragraph: Paragraph = { start: paragraphSegments[0].start, end: paragraphSegments[paragraphSegments.length - 1].end, text: paragraphSegments.map(seg => seg.text).join(' '), segments: paragraphSegments }; paragraphs.push(paragraph); } if (paragraphs.length > 0) { const chapter: Chapter = { title: llmChapter.title, paragraphs }; pageChapters.push(chapter); } } // 合并章节:如果与上一页的最后一个章节标题相同,则合并 if (previousContext && pageChapters.length > 0) { const lastChapter = allChapters[allChapters.length - 1]; const firstPageChapter = pageChapters[0]; if (lastChapter.title === firstPageChapter.title) { // 合并段落 lastChapter.paragraphs.push(...firstPageChapter.paragraphs); pageChapters.shift(); // 移除已合并的章节 } } allChapters.push(...pageChapters); // 更新上下文信息 if (allChapters.length > 0) { const lastChapter = allChapters[allChapters.length - 1]; const lastParagraph = lastChapter.paragraphs[lastChapter.paragraphs.length - 1]; previousContext = { title: lastChapter.title, lastParagraphText: lastParagraph ? lastParagraph.text.slice(-200) : '' }; } } return { chapters: allChapters }; } // 辅助函数:解析LLM响应,处理可能的格式错误 function parseLLMResponse(response: string): { chapters: { title: string; paragraphIndices: number[][] }[] } { try { // 尝试直接解析JSON return JSON.parse(response); } catch { // 如果解析失败,尝试提取JSON部分 const jsonMatch = response.match(/\{[\s\S]*\}/); if (jsonMatch) { try { return JSON.parse(jsonMatch[0]); } catch { // 如果仍然失败,返回空结果 return { chapters: [] }; } } return { chapters: [] }; } } // 模拟LLM API调用 async function llmAPI(prompt: string): Promise<string> { // 实际实现中,这里会调用真实的LLM API // 返回示例JSON return JSON.stringify({ chapters: [ { title: "第一章", paragraphIndices: [[0, 5], [6, 12]] }, { title: "第二章", paragraphIndices: [[13, 20]] } ] }); } ``` ## 算法设计说明 ### 1. 分页策略 - **基于字符数分页**:每页约3000字符,确保在LLM上下文窗口内 - **重叠机制**:每页末尾500字符与下一页开头重叠,保证章节连续性 - **段落完整性**:分页时不会切断单个字幕段 ### 2. 上下文连贯性处理 - **重叠分页**:通过重叠部分,LLM能看到上一页的结尾内容 - **上下文传递**:将上一页的章节标题和最后段落文本传给下一页 - **章节合并**:如果相邻页的章节标题相同,自动合并 ### 3. 避免LLM数数问题 - **只返回索引**:要求LLM返回段落索引范围,而非字符位置 - **索引验证**:代码中验证索引范围的有效性 - **容错处理**:解析JSON失败时返回空结果 ### 4. 成本优化 - **单次调用**:每页只调用一次LLM,同时返回章节和段落结构 - **减少传输**:只传输字幕文本和索引,不传输重复数据 - **重叠最小化**:重叠部分控制在500字符,平衡上下文和成本 ### 5. 数据完整性 - **段落重建**:根据索引从原始数据重建段落,避免LLM删减文字 - **时间戳保留**:段落和章节保留原始时间戳范围 - **文本拼接**:段落文本由原始字幕段拼接,保证准确性

Iniciá sesión para ver el prompt completo

Continuar con:

Al iniciar sesión, aceptás nuestros Términos de uso y Política de privacidad

Uso

Este prompt está diseñado para usarse con coding. Copiá el contenido de arriba y pegalo en tu herramienta de IA preferida.

Para mejores resultados, personalizá los marcadores (indicados con corchetes o mayúsculas) con tus requisitos específicos.

Referencias

Categorías:coding| twitter| llm-algorithm| subtitle-processing

Discusión