Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
434af56a
authored
May 09, 2024
by
Archer
Committed by
GitHub
May 09, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
4.8-alpha fix (#1424)
parent
6463427d
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
253 additions
and
146 deletions
+253
-146
packages/global/common/string/textSplitter.ts
+74
-11
packages/service/common/string/tiktoken/index.ts
+1
-1
packages/service/common/vectorStore/controller.d.ts
+2
-2
packages/service/common/vectorStore/pg/controller.ts
+3
-5
packages/service/core/dataset/search/controller.ts
+1
-2
packages/service/core/workflow/dispatch/agent/classifyQuestion.ts
+2
-2
packages/service/worker/file/extension/csv.ts
+7
-3
packages/service/worker/file/extension/xlsx.ts
+14
-13
packages/service/worker/file/read.ts
+1
-1
packages/service/worker/htmlStr2Md/index.ts
+1
-2
packages/service/worker/tiktoken/countGptMessagesTokens.ts
+82
-77
packages/service/worker/utils.ts
+4
-1
projects/app/public/docs/versionIntro.md
+33
-11
projects/app/src/components/ChatBox/MessageInput.tsx
+13
-6
projects/app/src/components/Markdown/index.tsx
+1
-1
projects/app/src/pages/api/plugins/textEditor/v2/index.ts
+6
-0
projects/app/src/pages/api/v1/chat/completions.ts
+6
-6
projects/app/src/pages/dataset/detail/components/Import/diffSource/TableLocal.tsx
+1
-1
projects/app/src/web/core/dataset/store/searchTest.ts
+1
-1
No files found.
packages/global/common/string/textSplitter.ts
View file @
434af56a
import
{
getErrText
}
from
'../error/utils'
;
import
{
getErrText
}
from
'../error/utils'
;
import
{
replaceRegChars
}
from
'./tools'
;
import
{
replaceRegChars
}
from
'./tools'
;
/**
export
const
CUSTOM_SPLIT_SIGN
=
'-----CUSTOM_SPLIT_SIGN-----'
;
* text split into chunks
* chunkLen - one chunk len. max: 3500
type
SplitProps
=
{
* overlapLen - The size of the before and after Text
* chunkLen > overlapLen
* markdown
*/
export
const
splitText2Chunks
=
(
props
:
{
text
:
string
;
text
:
string
;
chunkLen
:
number
;
chunkLen
:
number
;
overlapRatio
?:
number
;
overlapRatio
?:
number
;
customReg
?:
string
[];
customReg
?:
string
[];
}):
{
};
type
SplitResponse
=
{
chunks
:
string
[];
chunks
:
string
[];
chars
:
number
;
chars
:
number
;
overlapRatio
?:
number
;
};
}
=>
{
// 判断字符串是否为markdown的表格形式
const
strIsMdTable
=
(
str
:
string
)
=>
{
const
regex
=
/^
(\|
.*
\|[\r]
*
)
$/m
;
return
regex
.
test
(
str
);
};
const
markdownTableSplit
=
(
props
:
SplitProps
):
SplitResponse
=>
{
let
{
text
=
''
,
chunkLen
}
=
props
;
const
splitText2Lines
=
text
.
split
(
'\n'
);
const
header
=
splitText2Lines
[
0
];
const
headerSize
=
header
.
split
(
'|'
).
length
-
2
;
const
mdSplitString
=
`|
${
new
Array
(
headerSize
)
.
fill
(
0
)
.
map
(()
=>
'---'
)
.
join
(
' | '
)}
|`
;
const
chunks
:
string
[]
=
[];
let
chunk
=
`
${
header
}
${
mdSplitString
}
`
;
for
(
let
i
=
2
;
i
<
splitText2Lines
.
length
;
i
++
)
{
if
(
chunk
.
length
+
splitText2Lines
[
i
].
length
>
chunkLen
*
1.2
)
{
chunks
.
push
(
chunk
);
chunk
=
`
${
header
}
${
mdSplitString
}
`
;
}
chunk
+=
`
${
splitText2Lines
[
i
]}
\n`
;
}
return
{
chunks
,
chars
:
chunks
.
reduce
((
sum
,
chunk
)
=>
sum
+
chunk
.
length
,
0
)
};
};
const
commonSplit
=
(
props
:
SplitProps
):
SplitResponse
=>
{
let
{
text
=
''
,
chunkLen
,
overlapRatio
=
0.2
,
customReg
=
[]
}
=
props
;
let
{
text
=
''
,
chunkLen
,
overlapRatio
=
0.2
,
customReg
=
[]
}
=
props
;
const
splitMarker
=
'SPLIT_HERE_SPLIT_HERE'
;
const
splitMarker
=
'SPLIT_HERE_SPLIT_HERE'
;
const
codeBlockMarker
=
'CODE_BLOCK_LINE_MARKER'
;
const
codeBlockMarker
=
'CODE_BLOCK_LINE_MARKER'
;
const
overlapLen
=
Math
.
round
(
chunkLen
*
overlapRatio
);
const
overlapLen
=
Math
.
round
(
chunkLen
*
overlapRatio
);
...
@@ -253,3 +290,29 @@ export const splitText2Chunks = (props: {
...
@@ -253,3 +290,29 @@ export const splitText2Chunks = (props: {
throw
new
Error
(
getErrText
(
err
));
throw
new
Error
(
getErrText
(
err
));
}
}
};
};
/**
* text split into chunks
* chunkLen - one chunk len. max: 3500
* overlapLen - The size of the before and after Text
* chunkLen > overlapLen
* markdown
*/
export
const
splitText2Chunks
=
(
props
:
SplitProps
):
SplitResponse
=>
{
let
{
text
=
''
}
=
props
;
const
splitWithCustomSign
=
text
.
split
(
CUSTOM_SPLIT_SIGN
);
const
splitResult
=
splitWithCustomSign
.
map
((
item
)
=>
{
if
(
strIsMdTable
(
text
))
{
return
markdownTableSplit
(
props
);
}
return
commonSplit
(
props
);
});
return
{
chunks
:
splitResult
.
map
((
item
)
=>
item
.
chunks
).
flat
(),
chars
:
splitResult
.
reduce
((
sum
,
item
)
=>
sum
+
item
.
chars
,
0
)
};
};
packages/service/common/string/tiktoken/index.ts
View file @
434af56a
...
@@ -57,7 +57,7 @@ export const countGptMessagesTokens = (
...
@@ -57,7 +57,7 @@ export const countGptMessagesTokens = (
// 检测是否有内存泄漏
// 检测是否有内存泄漏
// addLog.info(`Count token time: ${Date.now() - start}, token: ${data}`);
// addLog.info(`Count token time: ${Date.now() - start}, token: ${data}`);
// console.log(
Object.keys(global.tiktokenWorker.callbackMap
));
// console.log(
process.memoryUsage(
));
};
};
worker
.
postMessage
({
worker
.
postMessage
({
...
...
packages/service/common/vectorStore/controller.d.ts
View file @
434af56a
...
@@ -15,6 +15,6 @@ export type InsertVectorProps = {
...
@@ -15,6 +15,6 @@ export type InsertVectorProps = {
export
type
EmbeddingRecallProps
=
{
export
type
EmbeddingRecallProps
=
{
teamId
:
string
;
teamId
:
string
;
datasetIds
:
string
[];
datasetIds
:
string
[];
similarity
?:
number
;
//
similarity?: number;
efSearch
?:
number
;
//
efSearch?: number;
};
};
packages/service/common/vectorStore/pg/controller.ts
View file @
434af56a
...
@@ -129,17 +129,15 @@ export const embeddingRecall = async (
...
@@ -129,17 +129,15 @@ export const embeddingRecall = async (
):
Promise
<
{
):
Promise
<
{
results
:
EmbeddingRecallItemType
[];
results
:
EmbeddingRecallItemType
[];
}
>
=>
{
}
>
=>
{
const
{
teamId
,
datasetIds
,
vectors
,
limit
,
similarity
=
0
,
retry
=
2
,
efSearch
=
100
}
=
props
;
const
{
datasetIds
,
vectors
,
limit
,
retry
=
2
}
=
props
;
try
{
try
{
const
results
:
any
=
await
PgClient
.
query
(
const
results
:
any
=
await
PgClient
.
query
(
`BEGIN;
`BEGIN;
SET LOCAL hnsw.ef_search =
${
efSearch
}
;
SET LOCAL hnsw.ef_search =
${
global
.
systemEnv
?.
pgHNSWEfSearch
||
100
};
select
id
,
collection_id
,
vector
<
#
>
'[${vectors[0]}]'
AS
score
select
id
,
collection_id
,
vector
<
#
>
'[${vectors[0]}]'
AS
score
from
$
{
PgDatasetTableName
}
from
$
{
PgDatasetTableName
}
where team_id='
${
teamId
}
'
where
dataset_id
IN
(
$
{
datasetIds
.
map
((
id
)
=>
`'
${
String
(
id
)}
'`
).
join
(
','
)})
AND dataset_id IN (
${
datasetIds
.
map
((
id
)
=>
`'
${
String
(
id
)}
'`
).
join
(
','
)}
)
AND vector <#> '[
${
vectors
[
0
]}
]' < -
${
similarity
}
order
by
score
limit
$
{
limit
};
order
by
score
limit
$
{
limit
};
COMMIT
;
`
COMMIT
;
`
);
);
...
...
packages/service/core/dataset/search/controller.ts
View file @
434af56a
...
@@ -85,8 +85,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) {
...
@@ -85,8 +85,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) {
teamId
,
teamId
,
datasetIds
,
datasetIds
,
vectors
,
vectors
,
limit
,
limit
efSearch
:
global
.
systemEnv
?.
pgHNSWEfSearch
});
});
// get q and a
// get q and a
...
...
packages/service/core/workflow/dispatch/agent/classifyQuestion.ts
View file @
434af56a
...
@@ -127,8 +127,8 @@ const completions = async ({
...
@@ -127,8 +127,8 @@ const completions = async ({
});
});
const
answer
=
data
.
choices
?.[
0
].
message
?.
content
||
''
;
const
answer
=
data
.
choices
?.[
0
].
message
?.
content
||
''
;
console
.
log
(
JSON
.
stringify
(
chats2GPTMessages
({
messages
,
reserveId
:
false
}),
null
,
2
));
//
console.log(JSON.stringify(chats2GPTMessages({ messages, reserveId: false }), null, 2));
console
.
log
(
answer
,
'----'
);
//
console.log(answer, '----');
const
id
=
const
id
=
agents
.
find
((
item
)
=>
answer
.
includes
(
item
.
key
))?.
key
||
agents
.
find
((
item
)
=>
answer
.
includes
(
item
.
key
))?.
key
||
...
...
packages/service/worker/file/extension/csv.ts
View file @
434af56a
...
@@ -10,9 +10,13 @@ export const readCsvRawText = async (params: ReadRawTextByBuffer): Promise<ReadF
...
@@ -10,9 +10,13 @@ export const readCsvRawText = async (params: ReadRawTextByBuffer): Promise<ReadF
const
header
=
csvArr
[
0
];
const
header
=
csvArr
[
0
];
const
formatText
=
header
// format to md table
?
csvArr
.
map
((
item
)
=>
item
.
map
((
item
,
i
)
=>
`
${
header
[
i
]}
:
${
item
}
`
).
join
(
'\n'
)).
join
(
'\n'
)
const
formatText
=
`|
${
header
.
join
(
' | '
)}
|
:
''
;
|
${
header
.
map
(()
=>
'---'
).
join
(
' | '
)}
|
${
csvArr
.
slice
(
1
)
.
map
((
row
)
=>
`|
${
row
.
map
((
item
)
=>
item
.
replace
(
/
\n
/g
,
'\\n'
)).
join
(
' | '
)}
|`
)
.
join
(
'\n'
)}
`
;
return
{
return
{
rawText
,
rawText
,
...
...
packages/service/worker/file/extension/xlsx.ts
View file @
434af56a
import
{
CUSTOM_SPLIT_SIGN
}
from
'@fastgpt/global/common/string/textSplitter'
;
import
{
ReadRawTextByBuffer
,
ReadFileResponse
}
from
'../type'
;
import
{
ReadRawTextByBuffer
,
ReadFileResponse
}
from
'../type'
;
import
xlsx
from
'node-xlsx'
;
import
xlsx
from
'node-xlsx'
;
import
Papa
from
'papaparse'
;
import
Papa
from
'papaparse'
;
...
@@ -18,25 +19,25 @@ export const readXlsxRawText = async ({
...
@@ -18,25 +19,25 @@ export const readXlsxRawText = async ({
});
});
const
rawText
=
format2Csv
.
map
((
item
)
=>
item
.
csvText
).
join
(
'\n'
);
const
rawText
=
format2Csv
.
map
((
item
)
=>
item
.
csvText
).
join
(
'\n'
);
const
formatText
=
format2Csv
const
formatText
=
format2Csv
.
map
((
item
)
=>
{
.
map
((
item
)
=>
{
const
csvArr
=
Papa
.
parse
(
item
.
csvText
).
data
as
string
[][];
const
csvArr
=
Papa
.
parse
(
item
.
csvText
).
data
as
string
[][];
const
header
=
csvArr
[
0
];
const
header
=
csvArr
[
0
];
const
formatText
=
header
if
(
!
header
)
return
;
?
csvArr
.
map
((
item
)
=>
const
formatText
=
`|
${
header
.
join
(
' | '
)}
|
item
|
${
header
.
map
(()
=>
'---'
).
join
(
' | '
)}
|
.
map
((
item
,
i
)
=>
(
item
?
`
${
header
[
i
]}
:
${
item
}
`
:
''
))
${
csvArr
.
filter
(
Boolean
)
.
slice
(
1
)
.
join
(
'\n'
)
.
map
((
row
)
=>
`|
${
row
.
map
((
item
)
=>
item
.
replace
(
/
\n
/g
,
'\\n'
)).
join
(
' | '
)}
|`
)
)
.
join
(
'\n'
)}
`
;
.
join
(
'\n'
)
:
''
;
return
formatText
;
return
`
${
item
.
title
}
\n
${
formatText
}
`
;
})
})
.
join
(
'\n'
);
.
filter
(
Boolean
)
.
join
(
CUSTOM_SPLIT_SIGN
);
return
{
return
{
rawText
:
rawText
,
rawText
:
rawText
,
...
...
packages/service/worker/file/read.ts
View file @
434af56a
...
@@ -67,5 +67,5 @@ parentPort?.on('message', async (props: ReadRawTextProps<Uint8Array>) => {
...
@@ -67,5 +67,5 @@ parentPort?.on('message', async (props: ReadRawTextProps<Uint8Array>) => {
});
});
}
}
global
?.
close
?.
();
process
.
exit
();
});
});
packages/service/worker/htmlStr2Md/index.ts
View file @
434af56a
...
@@ -15,6 +15,5 @@ parentPort?.on('message', (params: { html: string }) => {
...
@@ -15,6 +15,5 @@ parentPort?.on('message', (params: { html: string }) => {
data
:
error
data
:
error
});
});
}
}
process
.
exit
();
global
?.
close
?.();
});
});
packages/service/worker/tiktoken/countGptMessagesTokens.ts
View file @
434af56a
...
@@ -26,91 +26,96 @@ parentPort?.on(
...
@@ -26,91 +26,96 @@ parentPort?.on(
tools
?:
ChatCompletionTool
[];
tools
?:
ChatCompletionTool
[];
functionCall
?:
ChatCompletionCreateParams
.
Function
[];
functionCall
?:
ChatCompletionCreateParams
.
Function
[];
})
=>
{
})
=>
{
const
start
=
Date
.
now
();
try
{
/* count one prompt tokens */
/* count one prompt tokens */
const
countPromptTokens
=
(
const
countPromptTokens
=
(
prompt
:
string
|
ChatCompletionContentPart
[]
|
null
|
undefined
=
''
,
prompt
:
string
|
ChatCompletionContentPart
[]
|
null
|
undefined
=
''
,
role
:
''
|
`
${
ChatCompletionRequestMessageRoleEnum
}
`
=
''
role
:
''
|
`
${
ChatCompletionRequestMessageRoleEnum
}
`
=
''
)
=>
{
)
=>
{
const
promptText
=
(()
=>
{
const
promptText
=
(()
=>
{
if
(
!
prompt
)
return
''
;
if
(
!
prompt
)
return
''
;
if
(
typeof
prompt
===
'string'
)
return
prompt
;
if
(
typeof
prompt
===
'string'
)
return
prompt
;
let
promptText
=
''
;
let
promptText
=
''
;
prompt
.
forEach
((
item
)
=>
{
prompt
.
forEach
((
item
)
=>
{
if
(
item
.
type
===
'text'
)
{
if
(
item
.
type
===
'text'
)
{
promptText
+=
item
.
text
;
promptText
+=
item
.
text
;
}
else
if
(
item
.
type
===
'image_url'
)
{
}
else
if
(
item
.
type
===
'image_url'
)
{
promptText
+=
item
.
image_url
.
url
;
promptText
+=
item
.
image_url
.
url
;
}
}
});
});
return
promptText
;
return
promptText
;
})();
})();
const
text
=
`
${
role
}
\n
${
promptText
}
`
.
trim
();
try
{
const
text
=
`
${
role
}
\n
${
promptText
}
`
.
trim
();
const
encodeText
=
enc
.
encode
(
text
);
const
supplementaryToken
=
role
?
4
:
0
;
return
encodeText
.
length
+
supplementaryToken
;
}
catch
(
error
)
{
return
text
.
length
;
}
};
const
countToolsTokens
=
(
tools
?:
ChatCompletionTool
[]
|
ChatCompletionCreateParams
.
Function
[]
)
=>
{
if
(
!
tools
||
tools
.
length
===
0
)
return
0
;
const
toolText
=
tools
try
{
?
JSON
.
stringify
(
tools
)
const
encodeText
=
enc
.
encode
(
text
);
.
replace
(
'"'
,
''
)
const
supplementaryToken
=
role
?
4
:
0
;
.
replace
(
'\n'
,
''
)
return
encodeText
.
length
+
supplementaryToken
;
.
replace
(
/
(
){2,}
/g
,
' '
)
}
catch
(
error
)
{
:
''
;
return
text
.
length
;
}
};
const
countToolsTokens
=
(
tools
?:
ChatCompletionTool
[]
|
ChatCompletionCreateParams
.
Function
[]
)
=>
{
if
(
!
tools
||
tools
.
length
===
0
)
return
0
;
return
enc
.
encode
(
toolText
).
length
;
const
toolText
=
tools
};
?
JSON
.
stringify
(
tools
)
.
replace
(
'"'
,
''
)
.
replace
(
'\n'
,
''
)
.
replace
(
/
(
){2,}
/g
,
' '
)
:
''
;
const
total
=
return
enc
.
encode
(
toolText
).
length
;
messages
.
reduce
((
sum
,
item
)
=>
{
};
// Evaluates the text of toolcall and functioncall
const
functionCallPrompt
=
(()
=>
{
let
prompt
=
''
;
if
(
item
.
role
===
ChatCompletionRequestMessageRoleEnum
.
Assistant
)
{
const
toolCalls
=
item
.
tool_calls
;
prompt
+=
toolCalls
?.
map
((
item
)
=>
`
${
item
?.
function
?.
name
}
$
{
item
?.
function
?.
arguments
}
`.trim())
?.join('') || '';
const functionCall = item.function_call;
const
total
=
prompt += `
$
{
functionCall
?.
name
}
$
{
functionCall
?.
arguments
}
`.trim();
messages
.
reduce
((
sum
,
item
)
=>
{
}
// Evaluates the text of toolcall and functioncall
return prompt;
const
functionCallPrompt
=
(()
=>
{
})();
let
prompt
=
''
;
if
(
item
.
role
===
ChatCompletionRequestMessageRoleEnum
.
Assistant
)
{
const
toolCalls
=
item
.
tool_calls
;
prompt
+=
toolCalls
?.
map
((
item
)
=>
`
${
item
?.
function
?.
name
}
$
{
item
?.
function
?.
arguments
}
`.trim())
?.join('') || '';
const contentPrompt = (() => {
const functionCall = item.function_call;
if (!item.content) return '';
prompt += `
$
{
functionCall
?.
name
}
$
{
functionCall
?.
arguments
}
`.trim();
if (typeof item.content === 'string') return item.content;
}
return item.content
return prompt;
.map((item) => {
})();
if (item.type === 'text') return item.text;
return '';
})
.join('');
})();
return sum + countPromptTokens(`
$
{
contentPrompt
}
$
{
functionCallPrompt
}
`, item.role);
const contentPrompt = (() => {
}, 0) +
if (!item.content) return '';
countToolsTokens(tools) +
if (typeof item.content === 'string') return item.content;
countToolsTokens(functionCall);
return item.content
.map((item) => {
if (item.type === 'text') return item.text;
return '';
})
.join('');
})();
parentPort?.postMessage({
return sum + countPromptTokens(`
$
{
contentPrompt
}
$
{
functionCallPrompt
}
`, item.role);
id,
}, 0) +
type: 'success',
countToolsTokens(tools) +
data: total
countToolsTokens(functionCall);
});
global?.close?.();
parentPort?.postMessage({
id,
type: 'success',
data: total
});
} catch (error) {
parentPort?.postMessage({
id,
type: 'success',
data: 0
});
}
}
}
);
);
packages/service/worker/utils.ts
View file @
434af56a
...
@@ -25,9 +25,12 @@ export const runWorker = <T = any>(name: WorkerNameEnum, params?: Record<string,
...
@@ -25,9 +25,12 @@ export const runWorker = <T = any>(name: WorkerNameEnum, params?: Record<string,
});
});
worker
.
on
(
'error'
,
(
err
)
=>
{
worker
.
on
(
'error'
,
(
err
)
=>
{
reject
(
err
);
worker
.
terminate
();
worker
.
terminate
();
});
worker
.
on
(
'messageerror'
,
(
err
)
=>
{
reject
(
err
);
reject
(
err
);
worker
.
terminate
();
});
});
});
});
};
};
projects/app/public/docs/versionIntro.md
View file @
434af56a
### FastGPT V4.7.1
### FastGPT V4.8
1.
新增 - 语音输入完整配置。支持选择是否打开语音输入(包括分享页面),支持语音输入后自动发送,支持语音输入后自动语音播放(流式)。
本次更新的重点是对工作流 (高级编排) 进行了重构,使其更加简洁和强大。但由于新旧工作流机制有较大变化,尽管我们进行了一定的自动转换,仍有部分工作流需要您手动重建。请尽快更新到新版本,并对工作流进行必要的调试和重新发布。
2.
新增 - Pptx 和 xlsx 文件读取。但所有文件读取都放服务端,会消耗更多的服务器资源,以及无法在上传时预览更多内容。
3.
新增 - 集成 Laf 云函数,可以读取 Laf 账号中的云函数作为 HTTP 模块。
❗ 重要提示:
4.
修改 - csv导入模板,取消 header 校验,自动获取前两列。
1️⃣ 旧工作流更新后暂不失效,打开旧工作流会弹出自动转换提示,重新编排后点 “发布” 按钮发布新工作流
5.
修复 - 问题补全历史记录BUG
2️⃣ 发布新工作流前,工作流自动保存功能暂不生效
6.
[
点击查看高级编排介绍文档
](
https://doc.fastgpt.in/docs/workflow/intro
)
3️⃣ 应用和插件新增 version 字段,标识适用新/旧版工作流,以实现兼容
7.
[
使用文档
](
https://doc.fastgpt.in/docs/intro/
)
8.
[
点击查看商业版
](
https://doc.fastgpt.in/docs/commercial/
)
✨ 新增功能亮点:
\ No newline at end of file
1️⃣ 判断器:支持 if/elseIf/else 判断逻辑,工作流控制更灵活
2️⃣ 变量更新节点:运行中可动态修改工作流输出变量或全局变量值
3️⃣ 工作流自动保存和版本管理:自动保存修改,支持查看和回滚历史版本
4️⃣ 工作流调试模式:更直观高效,可调试单节点或逐步执行,实时查看输入输出数据
5️⃣ 定时执行应用:支持简单配置实现各种定时任务
🛠️ 其他优化与修复:
-
优化工作流节点连线方式,支持四向连接,易构建循环工作流
-
显著提升工作流上下文数据传递性能
-
简易模式下修改配置自动刷新调试框,免手动保存
-
改进 worker 进程管理,支持 Token 计算任务分配,提高效率
-
工具调用支持 string、boolean、number 数据类型
-
完善 completions 接口对 size 参数限制
-
重构 Node.js API 中间件和服务端代码
-
对话记录长度调整为偶数,最大长度增至 50 轮,避免奇数导致部分模型不兼容
-
HTTP 节点出错将终止进程,避免异常影响
-
修复工具调用名称不能以数字开头问题
-
修复分享链接 query 参数缓存 bug
-
修复工具调用和 HTTP 模块兼容性问题
-
[
点击查看高级编排介绍文档
](
https://doc.fastgpt.in/docs/workflow/intro
)
-
[
使用文档
](
https://doc.fastgpt.in/docs/intro/
)
-
[
点击查看商业版
](
https://doc.fastgpt.in/docs/commercial/
)
\ No newline at end of file
projects/app/src/components/ChatBox/MessageInput.tsx
View file @
434af56a
...
@@ -55,6 +55,8 @@ const MessageInput = ({
...
@@ -55,6 +55,8 @@ const MessageInput = ({
const
{
t
}
=
useTranslation
();
const
{
t
}
=
useTranslation
();
const
havInput
=
!!
inputValue
||
fileList
.
length
>
0
;
const
havInput
=
!!
inputValue
||
fileList
.
length
>
0
;
const
hasFileUploading
=
fileList
.
some
((
item
)
=>
!
item
.
url
);
const
canSendMessage
=
havInput
&&
!
hasFileUploading
;
/* file selector and upload */
/* file selector and upload */
const
{
File
,
onOpen
:
onOpenSelectFile
}
=
useSelectFile
({
const
{
File
,
onOpen
:
onOpenSelectFile
}
=
useSelectFile
({
...
@@ -142,7 +144,8 @@ const MessageInput = ({
...
@@ -142,7 +144,8 @@ const MessageInput = ({
);
);
/* on send */
/* on send */
const
handleSend
=
useCallback
(
async
()
=>
{
const
handleSend
=
async
()
=>
{
if
(
!
canSendMessage
)
return
;
const
textareaValue
=
TextareaDom
.
current
?.
value
||
''
;
const
textareaValue
=
TextareaDom
.
current
?.
value
||
''
;
onSendMessage
({
onSendMessage
({
...
@@ -150,7 +153,7 @@ const MessageInput = ({
...
@@ -150,7 +153,7 @@ const MessageInput = ({
files
:
fileList
files
:
fileList
});
});
replaceFile
([]);
replaceFile
([]);
}
,
[
TextareaDom
,
fileList
,
onSendMessage
,
replaceFile
])
;
};
/* whisper init */
/* whisper init */
const
{
const
{
...
@@ -466,16 +469,20 @@ const MessageInput = ({
...
@@ -466,16 +469,20 @@ const MessageInput = ({
h=
{
[
'28px'
,
'32px'
]
}
h=
{
[
'28px'
,
'32px'
]
}
w=
{
[
'28px'
,
'32px'
]
}
w=
{
[
'28px'
,
'32px'
]
}
borderRadius=
{
'md'
}
borderRadius=
{
'md'
}
bg=
{
isSpeaking
||
isChatting
?
''
:
!
havInput
?
'#E5E5E5'
:
'primary.500'
}
bg=
{
isSpeaking
||
isChatting
?
''
:
!
havInput
||
hasFileUploading
?
'#E5E5E5'
:
'primary.500'
}
cursor=
{
havInput
?
'pointer'
:
'not-allowed'
}
cursor=
{
havInput
?
'pointer'
:
'not-allowed'
}
lineHeight=
{
1
}
lineHeight=
{
1
}
onClick=
{
()
=>
{
onClick=
{
()
=>
{
if
(
isChatting
)
{
if
(
isChatting
)
{
return
onStop
();
return
onStop
();
}
}
if
(
havInput
)
{
return
handleSend
();
return
handleSend
();
}
}
}
}
}
>
>
{
isChatting
?
(
{
isChatting
?
(
...
...
projects/app/src/components/Markdown/index.tsx
View file @
434af56a
...
@@ -53,7 +53,7 @@ const Markdown = ({
...
@@ -53,7 +53,7 @@ const Markdown = ({
);
);
const
formatSource
=
source
const
formatSource
=
source
.
replace
(
/
\\
n/g
,
'\n
'
)
// .replace(/\\n/g, '\n
')
.
replace
(
/
(
http
[
s
]?
:
\/\/[^\s
,。
]
+
)([
。,
])
/g
,
'$1 $2'
)
.
replace
(
/
(
http
[
s
]?
:
\/\/[^\s
,。
]
+
)([
。,
])
/g
,
'$1 $2'
)
.
replace
(
/
\n
*
(\[
QUOTE SIGN
\]\(
.*
\))
/g
,
'$1'
);
.
replace
(
/
\n
*
(\[
QUOTE SIGN
\]\(
.*
\))
/g
,
'$1'
);
...
...
projects/app/src/pages/api/plugins/textEditor/v2/index.ts
View file @
434af56a
...
@@ -40,3 +40,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...
@@ -40,3 +40,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
res
.
status
(
500
).
send
(
getErrText
(
err
));
res
.
status
(
500
).
send
(
getErrText
(
err
));
}
}
}
}
export
const
config
=
{
api
:
{
responseLimit
:
'16mb'
}
};
projects/app/src/pages/api/v1/chat/completions.ts
View file @
434af56a
...
@@ -362,12 +362,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
...
@@ -362,12 +362,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}
}
export
default
NextAPI
(
handler
);
export
default
NextAPI
(
handler
);
export
const
config
=
{
api
:
{
responseLimit
:
'20mb'
}
};
const
authShareChat
=
async
({
const
authShareChat
=
async
({
chatId
,
chatId
,
...
data
...
data
...
@@ -526,3 +520,9 @@ const authHeaderRequest = async ({
...
@@ -526,3 +520,9 @@ const authHeaderRequest = async ({
canWrite
canWrite
};
};
};
};
export
const
config
=
{
api
:
{
responseLimit
:
'20mb'
}
};
projects/app/src/pages/dataset/detail/components/Import/diffSource/TableLocal.tsx
View file @
434af56a
...
@@ -28,7 +28,7 @@ export default React.memo(FileLocal);
...
@@ -28,7 +28,7 @@ export default React.memo(FileLocal);
const
csvTemplate
=
`"第一列内容","第二列内容"
const
csvTemplate
=
`"第一列内容","第二列内容"
"必填列","可选列。CSV 中请注意内容不能包含双引号,双引号是列分割符号"
"必填列","可选列。CSV 中请注意内容不能包含双引号,双引号是列分割符号"
"只会
讲
第一和第二列内容导入,其余列会被忽略",""
"只会
将
第一和第二列内容导入,其余列会被忽略",""
"结合人工智能的演进历程,AIGC的发展大致可以分为三个阶段,即:早期萌芽阶段(20世纪50年代至90年代中期)、沉淀积累阶段(20世纪90年代中期至21世纪10年代中期),以及快速发展展阶段(21世纪10年代中期至今)。",""
"结合人工智能的演进历程,AIGC的发展大致可以分为三个阶段,即:早期萌芽阶段(20世纪50年代至90年代中期)、沉淀积累阶段(20世纪90年代中期至21世纪10年代中期),以及快速发展展阶段(21世纪10年代中期至今)。",""
"AIGC发展分为几个阶段?","早期萌芽阶段(20世纪50年代至90年代中期)、沉淀积累阶段(20世纪90年代中期至21世纪10年代中期)、快速发展展阶段(21世纪10年代中期至今)"`
;
"AIGC发展分为几个阶段?","早期萌芽阶段(20世纪50年代至90年代中期)、沉淀积累阶段(20世纪90年代中期至21世纪10年代中期)、快速发展展阶段(21世纪10年代中期至今)"`
;
...
...
projects/app/src/web/core/dataset/store/searchTest.ts
View file @
434af56a
...
@@ -32,7 +32,7 @@ export const useSearchTestStore = create<State>()(
...
@@ -32,7 +32,7 @@ export const useSearchTestStore = create<State>()(
datasetTestList
:
[],
datasetTestList
:
[],
pushDatasetTestItem
(
data
)
{
pushDatasetTestItem
(
data
)
{
set
((
state
)
=>
{
set
((
state
)
=>
{
state
.
datasetTestList
=
[
data
,
...
state
.
datasetTestList
].
slice
(
0
,
10
0
);
state
.
datasetTestList
=
[
data
,
...
state
.
datasetTestList
].
slice
(
0
,
5
0
);
});
});
},
},
delDatasetTestItemById
(
id
)
{
delDatasetTestItemById
(
id
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment