mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-15 15:41:05 +00:00
@@ -28,6 +28,8 @@ weight: 794
|
|||||||
4. 知识库工具调用结果,自动补充图片域名。
|
4. 知识库工具调用结果,自动补充图片域名。
|
||||||
5. Github action runner 升级成 unbuntu24
|
5. Github action runner 升级成 unbuntu24
|
||||||
6. 去除飞书、公众号等三方渠道,回复时,可能前后多一个换行的问题。
|
6. 去除飞书、公众号等三方渠道,回复时,可能前后多一个换行的问题。
|
||||||
|
7. 调整分块策略,大表格时,不进行超大块合并,而是独立拆块。
|
||||||
|
8. Iframe 嵌套组件,内置允许麦克风声明。
|
||||||
|
|
||||||
## 🐛 修复
|
## 🐛 修复
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { defaultMaxChunkSize } from '../../core/dataset/training/utils';
|
import { defaultMaxChunkSize } from '../../core/dataset/training/utils';
|
||||||
import { getErrText } from '../error/utils';
|
import { getErrText } from '../error/utils';
|
||||||
|
import { getTextValidLength } from './utils';
|
||||||
|
|
||||||
export const CUSTOM_SPLIT_SIGN = '-----CUSTOM_SPLIT_SIGN-----';
|
export const CUSTOM_SPLIT_SIGN = '-----CUSTOM_SPLIT_SIGN-----';
|
||||||
|
|
||||||
@@ -73,7 +74,11 @@ ${mdSplitString}
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
for (let i = 2; i < splitText2Lines.length; i++) {
|
for (let i = 2; i < splitText2Lines.length; i++) {
|
||||||
if (chunk.length + splitText2Lines[i].length > chunkSize * 1.2) {
|
const chunkLength = getTextValidLength(chunk);
|
||||||
|
const nextLineLength = getTextValidLength(splitText2Lines[i]);
|
||||||
|
|
||||||
|
// Over size
|
||||||
|
if (chunkLength + nextLineLength > chunkSize) {
|
||||||
chunks.push(chunk);
|
chunks.push(chunk);
|
||||||
chunk = `${header}
|
chunk = `${header}
|
||||||
${mdSplitString}
|
${mdSplitString}
|
||||||
@@ -112,10 +117,28 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
const codeBlockMarker = 'CODE_BLOCK_LINE_MARKER';
|
const codeBlockMarker = 'CODE_BLOCK_LINE_MARKER';
|
||||||
const overlapLen = Math.round(chunkSize * overlapRatio);
|
const overlapLen = Math.round(chunkSize * overlapRatio);
|
||||||
|
|
||||||
|
// 特殊模块处理
|
||||||
|
// 1. 代码块处理 - 去除空字符
|
||||||
// replace code block all \n to codeBlockMarker
|
// replace code block all \n to codeBlockMarker
|
||||||
text = text.replace(/(```[\s\S]*?```|~~~[\s\S]*?~~~)/g, function (match) {
|
text = text.replace(/(```[\s\S]*?```|~~~[\s\S]*?~~~)/g, function (match) {
|
||||||
return match.replace(/\n/g, codeBlockMarker);
|
return match.replace(/\n/g, codeBlockMarker);
|
||||||
});
|
});
|
||||||
|
// 2. 表格处理 - 单独提取表格出来,进行表头合并
|
||||||
|
const tableReg =
|
||||||
|
/(\n\|(?:(?:[^\n|]+\|){1,})\n\|(?:[:\-\s]+\|){1,}\n(?:\|(?:[^\n|]+\|)*\n?)*)(?:\n|$)/g;
|
||||||
|
const tableDataList = text.match(tableReg);
|
||||||
|
if (tableDataList) {
|
||||||
|
tableDataList.forEach((tableData) => {
|
||||||
|
const { chunks } = markdownTableSplit({
|
||||||
|
text: tableData.trim(),
|
||||||
|
chunkSize
|
||||||
|
});
|
||||||
|
|
||||||
|
const splitText = chunks.join('\n');
|
||||||
|
text = text.replace(tableData, `\n${splitText}\n`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// replace invalid \n
|
// replace invalid \n
|
||||||
text = text.replace(/(\r?\n|\r){3,}/g, '\n\n\n');
|
text = text.replace(/(\r?\n|\r){3,}/g, '\n\n\n');
|
||||||
|
|
||||||
@@ -137,7 +160,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
{ reg: /([\n](```[\s\S]*?```|~~~[\s\S]*?~~~))/g, maxLen: maxSize }, // code block
|
{ reg: /([\n](```[\s\S]*?```|~~~[\s\S]*?~~~))/g, maxLen: maxSize }, // code block
|
||||||
{
|
{
|
||||||
reg: /(\n\|(?:(?:[^\n|]+\|){1,})\n\|(?:[:\-\s]+\|){1,}\n(?:\|(?:[^\n|]+\|)*\n)*)/g,
|
reg: /(\n\|(?:(?:[^\n|]+\|){1,})\n\|(?:[:\-\s]+\|){1,}\n(?:\|(?:[^\n|]+\|)*\n)*)/g,
|
||||||
maxLen: maxSize
|
maxLen: Math.min(chunkSize * 1.5, maxSize)
|
||||||
}, // Table 尽可能保证完整性
|
}, // Table 尽可能保证完整性
|
||||||
{ reg: /(\n{2,})/g, maxLen: chunkSize },
|
{ reg: /(\n{2,})/g, maxLen: chunkSize },
|
||||||
{ reg: /([\n])/g, maxLen: chunkSize },
|
{ reg: /([\n])/g, maxLen: chunkSize },
|
||||||
@@ -230,7 +253,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
for (let i = splitTexts.length - 1; i >= 0; i--) {
|
for (let i = splitTexts.length - 1; i >= 0; i--) {
|
||||||
const currentText = splitTexts[i].text;
|
const currentText = splitTexts[i].text;
|
||||||
const newText = currentText + overlayText;
|
const newText = currentText + overlayText;
|
||||||
const newTextLen = newText.length;
|
const newTextLen = getTextValidLength(newText);
|
||||||
|
|
||||||
if (newTextLen > overlapLen) {
|
if (newTextLen > overlapLen) {
|
||||||
if (newTextLen > maxOverlapLen) {
|
if (newTextLen > maxOverlapLen) {
|
||||||
@@ -259,15 +282,16 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
const isMarkdownStep = checkIsMarkdownSplit(step);
|
const isMarkdownStep = checkIsMarkdownSplit(step);
|
||||||
const isCustomStep = checkIsCustomStep(step);
|
const isCustomStep = checkIsCustomStep(step);
|
||||||
const forbidConcat = isCustomStep; // forbid=true时候,lastText肯定为空
|
const forbidConcat = isCustomStep; // forbid=true时候,lastText肯定为空
|
||||||
|
const textLength = getTextValidLength(text);
|
||||||
|
|
||||||
// Over step
|
// Over step
|
||||||
if (step >= stepReges.length) {
|
if (step >= stepReges.length) {
|
||||||
if (text.length < maxSize) {
|
if (textLength < maxSize) {
|
||||||
return [text];
|
return [text];
|
||||||
}
|
}
|
||||||
// use slice-chunkSize to split text
|
// use slice-chunkSize to split text
|
||||||
const chunks: string[] = [];
|
const chunks: string[] = [];
|
||||||
for (let i = 0; i < text.length; i += chunkSize - overlapLen) {
|
for (let i = 0; i < textLength; i += chunkSize - overlapLen) {
|
||||||
chunks.push(text.slice(i, i + chunkSize));
|
chunks.push(text.slice(i, i + chunkSize));
|
||||||
}
|
}
|
||||||
return chunks;
|
return chunks;
|
||||||
@@ -282,10 +306,10 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
|
|
||||||
const maxLen = item.chunkMaxSize; // 当前块最大长度
|
const maxLen = item.chunkMaxSize; // 当前块最大长度
|
||||||
|
|
||||||
const lastTextLen = lastText.length;
|
const lastTextLen = getTextValidLength(lastText);
|
||||||
const currentText = item.text;
|
const currentText = item.text;
|
||||||
const newText = lastText + currentText;
|
const newText = lastText + currentText;
|
||||||
const newTextLen = newText.length;
|
const newTextLen = getTextValidLength(newText);
|
||||||
|
|
||||||
// Markdown 模式下,会强制向下拆分最小块,并再最后一个标题深度,给小块都补充上所有标题(包含父级标题)
|
// Markdown 模式下,会强制向下拆分最小块,并再最后一个标题深度,给小块都补充上所有标题(包含父级标题)
|
||||||
if (isMarkdownStep) {
|
if (isMarkdownStep) {
|
||||||
@@ -349,7 +373,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
if (!lastChunk) continue;
|
if (!lastChunk) continue;
|
||||||
|
|
||||||
// last chunk is too small, concat it to lastText(next chunk start)
|
// last chunk is too small, concat it to lastText(next chunk start)
|
||||||
if (lastChunk.length < minChunkLen) {
|
if (getTextValidLength(lastChunk) < minChunkLen) {
|
||||||
chunks.push(...innerChunks.slice(0, -1));
|
chunks.push(...innerChunks.slice(0, -1));
|
||||||
lastText = lastChunk;
|
lastText = lastChunk;
|
||||||
continue;
|
continue;
|
||||||
@@ -378,7 +402,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
|
|
||||||
/* If the last chunk is independent, it needs to be push chunks. */
|
/* If the last chunk is independent, it needs to be push chunks. */
|
||||||
if (lastText && chunks[chunks.length - 1] && !chunks[chunks.length - 1].endsWith(lastText)) {
|
if (lastText && chunks[chunks.length - 1] && !chunks[chunks.length - 1].endsWith(lastText)) {
|
||||||
if (lastText.length < chunkSize * 0.4) {
|
if (getTextValidLength(lastText) < chunkSize * 0.4) {
|
||||||
chunks[chunks.length - 1] = chunks[chunks.length - 1] + lastText;
|
chunks[chunks.length - 1] = chunks[chunks.length - 1] + lastText;
|
||||||
} else {
|
} else {
|
||||||
chunks.push(lastText);
|
chunks.push(lastText);
|
||||||
|
3
packages/global/common/string/utils.ts
Normal file
3
packages/global/common/string/utils.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const getTextValidLength = (chunk: string) => {
|
||||||
|
return chunk.replaceAll(/[\s\n]/g, '').length;
|
||||||
|
};
|
@@ -31,6 +31,7 @@ import { TabEnum } from './NavBar';
|
|||||||
import { ImportDataSourceEnum } from '@fastgpt/global/core/dataset/constants';
|
import { ImportDataSourceEnum } from '@fastgpt/global/core/dataset/constants';
|
||||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||||
import TrainingStates from './CollectionCard/TrainingStates';
|
import TrainingStates from './CollectionCard/TrainingStates';
|
||||||
|
import { getTextValidLength } from '@fastgpt/global/common/string/utils';
|
||||||
|
|
||||||
const DataCard = () => {
|
const DataCard = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@@ -327,7 +328,7 @@ const DataCard = () => {
|
|||||||
w={'14px'}
|
w={'14px'}
|
||||||
mr={1}
|
mr={1}
|
||||||
/>
|
/>
|
||||||
{item.q.length + (item.a?.length || 0)}
|
{getTextValidLength(item.q + item.a || '')}
|
||||||
</Flex>
|
</Flex>
|
||||||
{canWrite && (
|
{canWrite && (
|
||||||
<IconButton
|
<IconButton
|
||||||
|
@@ -77,6 +77,7 @@ const formatIndexes = async ({
|
|||||||
|
|
||||||
// Recompute default indexes, Merge ids of the same index, reduce the number of rebuilds
|
// Recompute default indexes, Merge ids of the same index, reduce the number of rebuilds
|
||||||
const defaultIndexes = getDefaultIndex({ q, a, indexSize });
|
const defaultIndexes = getDefaultIndex({ q, a, indexSize });
|
||||||
|
|
||||||
const concatDefaultIndexes = defaultIndexes.map((item) => {
|
const concatDefaultIndexes = defaultIndexes.map((item) => {
|
||||||
const oldIndex = indexes!.find((index) => index.text === item.text);
|
const oldIndex = indexes!.find((index) => index.text === item.text);
|
||||||
if (oldIndex) {
|
if (oldIndex) {
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
"测试的呀,第一个表格\n\n| 序号 | 姓名 | 年龄 | 职业 | 城市 |\n| --- | --- | --- | --- | --- |\n| 1 | 张三 | 25 | 工程师 | 北京 |\n| 2 | 李四 | 30 | 教师 | 上海 |\n| 3 | 王五 | 28 | 医生 | 广州 |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 4 | 赵六 | 35 | 律师 | 深圳 |\n| 5 | 孙七 | 27 | 设计师 | 杭州 |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 7 | 吴九 | 29 | 销售 | 武汉 |\n| 8 | 郑十 | 31 | 记者 | 南京 |\n| 9 | 刘一 | 33 | 建筑师 | 天津 |\n| 10 | 陈二 | 26 | 程序员 | 重庆 |\n| 1000 | 黄末 | 28 | 作家 | 厦门 |\n| 1001 | 杨一 | 34 | 程序员 | 厦门 |\n| 1002 | 杨二 | 34 | 程序员 | 厦门 |\n| 1003 | 杨三 | 34 | 程序员 | 厦门 |",
|
||||||
|
"| 序号 | 姓名 | 年龄 | 职业 | 城市 |\n| --- | --- | --- | --- | --- |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 1004 | 杨四 | 34 | 程序员 | 厦门 |\n| 1005 | 杨五 | 34 | 程序员 | 厦门 |\n| 1000 | 黄末 | 28 | 作家 | 厦门 |\n| 1000 | 黄末 | 28 | 作家 | 厦门 |\n| 1000 | 黄末 | 28 | 作家 | 厦门 |\n| 9 | 刘一 | 33 | 建筑师 | 天津 |\n| 10 | 陈二 | 26 | 程序员 | 重庆 |\n| 1000 | 黄末 | 28 | 作家 | 厦门 |\n| 1001 | 杨一 | 34 | 程序员 | 厦门 |\n| 1002 | 杨二 | 34 | 程序员 | 厦门 |\n| 1003 | 杨三 | 34 | 程序员 | 厦门 |\n| 1004 | 杨四 | 34 | 程序员 | 厦门 |\n| 1005 | 杨五 | 34 | 程序员 | 厦门 |\n\n| 序号 | 姓名 | 年龄 | 职业 | 城市 |\n| --- | --- | --- | --- | --- |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 1000 | 黄末 | 28 | 作家 | 厦门 |\n| 1000 | 黄末 | 28 | 作家 | 厦门 |\n| 1000 | 黄末 | 28 | 作家 | 厦门 |",
|
||||||
|
"这是第二段了,第二表格\n\n| 序号 | 姓名 | 年龄 | 职业 | 城市 |\n| --- | --- | --- | --- | --- |\n| 1 | 张三 | 25 | 工程师 | 北京 |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 2 | 李四 | 30 | 教师 | 上海 |\n| 3 | 王五 | 28 | 医生 | 广州 |\n| 4 | 赵六 | 35 | 律师 | 深圳 |\n| 5 | 孙七 | 27 | 设计师 | 杭州 |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 7 | 吴九 | 29 | 销售 | 武汉 |\n| 8 | 郑十 | 31 | 记者 | 南京 |\n| 9 | 刘一 | 33 | 建筑师 | 天津 |\n| 10 | 陈二 | 26 | 程序员 | 重庆 |\n| 10004 | 黄末 | 28 | 作家 | 厦门 |\n| 10013 | 杨一 | 34 | 程序员 | 厦门 |\n\n\n结束了\n\n| 序号22 | 姓名 | 年龄 | 职业 | 城市 |\n| --- | --- | --- | --- | --- |\n| 1 | 张三 | 25 | 工程师 | 北京 |\n| 2 | 李四 | 30 | 教师 | 上海 |\n| 3 | 王五 | 28 | 医生 | 广州 |\n| 4 | 赵六 | 35 | 律师 | 深圳 |\n| 5 | 孙七 | 27 | 设计师 | 杭州 |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 6 | 周八 | 32 | 会计 | 成都 |\n| 7 | 吴九 | 29 | 销售 | 武汉 |\n| 8 | 郑十 | 31 | 记者 | 南京 |\n| 9 | 刘一 | 33 | 建筑师 | 天津 |\n| 10 | 陈二 | 26 | 程序员 | 重庆 |\n| 10002 | 黄末 | 28 | 作家 | 厦门 |\n| 10012 | 杨一 | 34 | 程序员 | 厦门 |"
|
||||||
|
]
|
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user