ForcePilot/web/src/utils/chunkUtils.js

134 lines
3.4 KiB
JavaScript
Raw Normal View History

/**
* Chunk合并工具函数
* 用于合并多个chunk并处理重叠内容
*/
/**
* 查找两个字符串的重叠部分
* @param {string} str1 - 第一个字符串
* @param {string} str2 - 第二个字符串
* @returns {string} - 重叠部分的内容
*/
export function findOverlap(str1, str2) {
if (!str1 || !str2) return '';
const maxOverlap = Math.min(str1.length, str2.length);
let overlap = '';
// 从最长可能的重叠开始检查
for (let i = maxOverlap; i > 0; i--) {
const endStr1 = str1.slice(-i);
const startStr2 = str2.slice(0, i);
if (endStr1 === startStr2) {
overlap = endStr1;
break;
}
}
return overlap;
}
/**
* 合并chunks并处理重叠内容
* @param {Array} chunks - chunk数组每个chunk包含id, content, chunk_order_index
* @returns {Object} - 合并结果包含content和chunks数组
*/
export function mergeChunks(chunks) {
if (!chunks || chunks.length === 0) {
return { content: '', chunks: [] };
}
// 按order排序
const sorted = [...chunks].sort((a, b) => a.chunk_order_index - b.chunk_order_index);
const merged = [];
let currentContent = '';
for (let i = 0; i < sorted.length; i++) {
const chunk = sorted[i];
const content = chunk.content;
if (i === 0) {
// 第一个chunk直接添加
currentContent = content;
merged.push({
...chunk,
startOffset: 0,
endOffset: content.length
});
} else {
// 查找重叠部分
const overlap = findOverlap(currentContent, content);
const newContent = content.slice(overlap.length);
if (newContent.length > 0) {
const startOffset = currentContent.length;
currentContent += newContent;
merged.push({
...chunk,
startOffset,
endOffset: currentContent.length
});
}
}
}
return { content: currentContent, chunks: merged };
}
/**
* 将文本分割成段落
* @param {string} content - 文本内容
* @returns {Array} - 段落数组
*/
export function splitIntoParagraphs(content) {
if (!content) return [];
// 按换行符分割,保留空段落
return content.split(/\n\n+/).filter(para => para.trim() !== '');
}
/**
* 为每个段落找到对应的chunk
* @param {Array} paragraphs - 段落数组
* @param {Array} mappedChunks - 映射后的chunks
* @returns {Array} - 包含chunk信息的段落
*/
export function mapParagraphsToChunks(paragraphs, mappedChunks) {
if (!paragraphs || !mappedChunks) return [];
let currentOffset = 0;
return paragraphs.map(paragraph => {
const paragraphLength = paragraph.length + 2; // +2 for the \n\n
// 找到包含此位置的chunk
const chunk = mappedChunks.find(chunk =>
currentOffset >= chunk.startOffset && currentOffset < chunk.endOffset
) || mappedChunks[0];
const result = {
content: paragraph,
chunk,
startOffset: currentOffset,
endOffset: currentOffset + paragraphLength
};
currentOffset += paragraphLength;
return result;
});
}
/**
* 获取chunk的预览文本
* @param {string} content - chunk内容
* @param {number} maxLength - 最大长度
* @returns {string} - 预览文本
*/
export function getChunkPreview(content, maxLength = 100) {
if (!content) return '';
const text = content.replace(/\n+/g, ' ').trim();
if (text.length <= maxLength) return text;
return text.slice(0, maxLength) + '...';
}