Adapt findLast api;perf: markdown zh format. (#3066)
* perf: context code * fix: adapt findLast api * perf: commercial plugin run error * perf: markdown zh format
This commit is contained in:
parent
f90803c558
commit
fd49ad1342
@ -11,5 +11,9 @@ weight: 811
|
|||||||
|
|
||||||
1.
|
1.
|
||||||
2. 新增 - 文件上传方案调整,节点直接支持接收文件链接,插件自定义变量支持文件上传。
|
2. 新增 - 文件上传方案调整,节点直接支持接收文件链接,插件自定义变量支持文件上传。
|
||||||
3. 优化 - 知识库上传文件,优化报错提示
|
3. 新增 - 对话记录增加时间显示。
|
||||||
4. 修复 - BI 图表生成无法写入文件
|
4. 优化 - 知识库上传文件,优化报错提示。
|
||||||
|
5. 优化 - 全文检索语句,减少一轮查询。
|
||||||
|
6. 优化 - 修改 findLast 为 [...array].reverse().find,适配旧版浏览器。
|
||||||
|
7. 优化 - Markdown 组件自动空格,避免分割 url 中的中文。
|
||||||
|
8. 修复 - BI 图表生成无法写入文件。
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number
|
|||||||
2. Check that the workflow starts at the interaction node
|
2. Check that the workflow starts at the interaction node
|
||||||
*/
|
*/
|
||||||
export const getLastInteractiveValue = (histories: ChatItemType[]) => {
|
export const getLastInteractiveValue = (histories: ChatItemType[]) => {
|
||||||
const lastAIMessage = histories.findLast((item) => item.obj === ChatRoleEnum.AI);
|
const lastAIMessage = [...histories].reverse().find((item) => item.obj === ChatRoleEnum.AI);
|
||||||
|
|
||||||
if (lastAIMessage) {
|
if (lastAIMessage) {
|
||||||
const lastValue = lastAIMessage.value[lastAIMessage.value.length - 1];
|
const lastValue = lastAIMessage.value[lastAIMessage.value.length - 1];
|
||||||
|
|||||||
@ -7,14 +7,20 @@ import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
|
|||||||
1. Commercial plugin: n points per times
|
1. Commercial plugin: n points per times
|
||||||
2. Other plugin: sum of children points
|
2. Other plugin: sum of children points
|
||||||
*/
|
*/
|
||||||
export const computedPluginUsage = async (
|
export const computedPluginUsage = async ({
|
||||||
plugin: PluginRuntimeType,
|
plugin,
|
||||||
childrenUsage: ChatNodeUsageType[]
|
childrenUsage,
|
||||||
) => {
|
error
|
||||||
|
}: {
|
||||||
|
plugin: PluginRuntimeType;
|
||||||
|
childrenUsage: ChatNodeUsageType[];
|
||||||
|
error?: boolean;
|
||||||
|
}) => {
|
||||||
const { source } = await splitCombinePluginId(plugin.id);
|
const { source } = await splitCombinePluginId(plugin.id);
|
||||||
|
|
||||||
// Commercial plugin: n points per times
|
// Commercial plugin: n points per times
|
||||||
if (source === PluginSourceEnum.commercial) {
|
if (source === PluginSourceEnum.commercial) {
|
||||||
|
if (error) return 0;
|
||||||
return plugin.currentCost ?? 0;
|
return plugin.currentCost ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -112,7 +112,11 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
|||||||
output.moduleLogo = plugin.avatar;
|
output.moduleLogo = plugin.avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
const usagePoints = await computedPluginUsage(plugin, flowUsages);
|
const usagePoints = await computedPluginUsage({
|
||||||
|
plugin,
|
||||||
|
childrenUsage: flowUsages,
|
||||||
|
error: !!output?.pluginOutput?.error
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// 嵌套运行时,如果 childApp stream=false,实际上不会有任何内容输出给用户,所以不需要存储
|
// 嵌套运行时,如果 childApp stream=false,实际上不会有任何内容输出给用户,所以不需要存储
|
||||||
|
|||||||
@ -29,11 +29,13 @@ const QuestionGuide = dynamic(() => import('./chat/QuestionGuide'), { ssr: false
|
|||||||
const Markdown = ({
|
const Markdown = ({
|
||||||
source = '',
|
source = '',
|
||||||
showAnimation = false,
|
showAnimation = false,
|
||||||
isDisabled = false
|
isDisabled = false,
|
||||||
|
forbidZhFormat = false
|
||||||
}: {
|
}: {
|
||||||
source?: string;
|
source?: string;
|
||||||
showAnimation?: boolean;
|
showAnimation?: boolean;
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
|
forbidZhFormat?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const components = useMemo<any>(
|
const components = useMemo<any>(
|
||||||
() => ({
|
() => ({
|
||||||
@ -46,15 +48,35 @@ const Markdown = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const formatSource = useMemo(() => {
|
const formatSource = useMemo(() => {
|
||||||
const formatSource = source
|
if (showAnimation || forbidZhFormat) return source;
|
||||||
|
|
||||||
|
// 保护 URL 格式:https://, http://, /api/xxx
|
||||||
|
const urlPlaceholders: string[] = [];
|
||||||
|
const textWithProtectedUrls = source.replace(
|
||||||
|
/(https?:\/\/[^\s<]+[^<.,:;"')\]\s]|\/api\/[^\s]+)(?=\s|$)/g,
|
||||||
|
(match) => {
|
||||||
|
urlPlaceholders.push(match);
|
||||||
|
return `__URL_${urlPlaceholders.length - 1}__`;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 处理中文与英文数字之间的分词
|
||||||
|
const textWithSpaces = textWithProtectedUrls
|
||||||
.replace(
|
.replace(
|
||||||
/([\u4e00-\u9fa5\u3000-\u303f])([a-zA-Z0-9])|([a-zA-Z0-9])([\u4e00-\u9fa5\u3000-\u303f])/g,
|
/([\u4e00-\u9fa5\u3000-\u303f])([a-zA-Z0-9])|([a-zA-Z0-9])([\u4e00-\u9fa5\u3000-\u303f])/g,
|
||||||
'$1$3 $2$4'
|
'$1$3 $2$4'
|
||||||
) // Chinese and english chars separated by space
|
)
|
||||||
|
// 处理引用标记
|
||||||
.replace(/\n*(\[QUOTE SIGN\]\(.*\))/g, '$1');
|
.replace(/\n*(\[QUOTE SIGN\]\(.*\))/g, '$1');
|
||||||
|
|
||||||
return formatSource;
|
// 还原 URL
|
||||||
}, [source]);
|
const finalText = textWithSpaces.replace(
|
||||||
|
/__URL_(\d+)__/g,
|
||||||
|
(_, index) => urlPlaceholders[parseInt(index)]
|
||||||
|
);
|
||||||
|
|
||||||
|
return finalText;
|
||||||
|
}, [showAnimation, source]);
|
||||||
|
|
||||||
const urlTransform = useCallback((val: string) => {
|
const urlTransform = useCallback((val: string) => {
|
||||||
return val;
|
return val;
|
||||||
|
|||||||
@ -137,9 +137,8 @@ const ChatItem = (props: Props) => {
|
|||||||
};
|
};
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { isChatting, chatType } = useContextSelector(ChatBoxContext, (v) => {
|
const { isChatting, chatType } = useContextSelector(ChatBoxContext, (v) => v);
|
||||||
return { isChatting: v.isChatting, chatType: v.chatType };
|
const isChatLog = chatType === 'log';
|
||||||
});
|
|
||||||
|
|
||||||
const { copyData } = useCopyData();
|
const { copyData } = useCopyData();
|
||||||
|
|
||||||
@ -218,14 +217,14 @@ const ChatItem = (props: Props) => {
|
|||||||
<Flex w={'100%'} alignItems={'flex-end'} gap={2} justifyContent={styleMap.justifyContent}>
|
<Flex w={'100%'} alignItems={'flex-end'} gap={2} justifyContent={styleMap.justifyContent}>
|
||||||
{isChatting && type === ChatRoleEnum.AI && isLastChild ? null : (
|
{isChatting && type === ChatRoleEnum.AI && isLastChild ? null : (
|
||||||
<Flex order={styleMap.order} ml={styleMap.ml} align={'center'} gap={'0.62rem'}>
|
<Flex order={styleMap.order} ml={styleMap.ml} align={'center'} gap={'0.62rem'}>
|
||||||
{chat.time && (isPc || chatType === 'log') && (
|
{chat.time && (isPc || isChatLog) && (
|
||||||
<Box
|
<Box
|
||||||
order={type === ChatRoleEnum.AI ? 2 : 0}
|
order={type === ChatRoleEnum.AI ? 2 : 0}
|
||||||
className={'time-label'}
|
className={'time-label'}
|
||||||
fontSize={styleMap.fontSize}
|
fontSize={styleMap.fontSize}
|
||||||
color={styleMap.color}
|
color={styleMap.color}
|
||||||
fontWeight={styleMap.fontWeight}
|
fontWeight={styleMap.fontWeight}
|
||||||
display={chatType === 'log' ? 'block' : 'none'}
|
display={isChatLog ? 'block' : 'none'}
|
||||||
>
|
>
|
||||||
{t(formatTimeToChatItemTime(chat.time) as any, {
|
{t(formatTimeToChatItemTime(chat.time) as any, {
|
||||||
time: dayjs(chat.time).format('HH:mm')
|
time: dayjs(chat.time).format('HH:mm')
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const WelcomeBox = ({ welcomeText }: { welcomeText: string }) => {
|
|||||||
bg={'white'}
|
bg={'white'}
|
||||||
boxShadow={'0 0 8px rgba(0,0,0,0.15)'}
|
boxShadow={'0 0 8px rgba(0,0,0,0.15)'}
|
||||||
>
|
>
|
||||||
<Markdown source={`~~~guide \n${welcomeText}`} />
|
<Markdown source={`~~~guide \n${welcomeText}`} forbidZhFormat />
|
||||||
</Card>
|
</Card>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -64,7 +64,7 @@ const Header = () => {
|
|||||||
useDebounceEffect(
|
useDebounceEffect(
|
||||||
() => {
|
() => {
|
||||||
const savedSnapshot =
|
const savedSnapshot =
|
||||||
future.findLast((snapshot) => snapshot.isSaved) ||
|
[...future].reverse().find((snapshot) => snapshot.isSaved) ||
|
||||||
past.find((snapshot) => snapshot.isSaved);
|
past.find((snapshot) => snapshot.isSaved);
|
||||||
|
|
||||||
const val = compareSnapshot(
|
const val = compareSnapshot(
|
||||||
|
|||||||
@ -70,7 +70,7 @@ const Header = () => {
|
|||||||
useDebounceEffect(
|
useDebounceEffect(
|
||||||
() => {
|
() => {
|
||||||
const savedSnapshot =
|
const savedSnapshot =
|
||||||
future.findLast((snapshot) => snapshot.isSaved) ||
|
[...future].reverse().find((snapshot) => snapshot.isSaved) ||
|
||||||
past.find((snapshot) => snapshot.isSaved);
|
past.find((snapshot) => snapshot.isSaved);
|
||||||
|
|
||||||
const val = compareSnapshot(
|
const val = compareSnapshot(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user