mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-21 11:43:56 +00:00
v4.4.5-3 (#357)
This commit is contained in:
@@ -26,6 +26,7 @@ ARG name
|
||||
|
||||
# copy common node_modules and one project node_modules
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY --from=deps /app/packages ./packages
|
||||
COPY ./projects/$name ./projects/$name
|
||||
COPY --from=deps /app/projects/$name/node_modules ./projects/$name/node_modules
|
||||
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||
|
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: '升级到 V4.4.5'
|
||||
description: 'FastGPT 从旧版本升级到 V4.4.5 操作指南'
|
||||
title: 'V4.4.5'
|
||||
description: 'FastGPT V4.4.5 更新(需执行升级脚本)'
|
||||
icon: 'upgrade'
|
||||
draft: false
|
||||
toc: true
|
||||
@@ -21,3 +21,11 @@ curl --location --request POST 'https://{{host}}/api/admin/initv445' \
|
||||
|
||||
初始化了 variable 模块,将其合并到用户引导模块中。
|
||||
|
||||
## 功能介绍
|
||||
|
||||
### Fast GPT V4.4.5
|
||||
|
||||
1. 新增 - 下一步指引选项,可以通过模型生成 3 个预测问题。
|
||||
2. 新增 - 分享链接 hook 身份校验。
|
||||
3. 新增 - Api Key 使用。增加别名、额度限制和过期时间。自带 appId,无需额外连接。
|
||||
4. 优化 - 全局变量与开场白合并成同一模块。
|
@@ -1,7 +1,7 @@
|
||||
---
|
||||
weight: 760
|
||||
title: "版本升级"
|
||||
description: "FastGPT 升级指南"
|
||||
title: "版本更新/升级操作"
|
||||
description: "FastGPT 版本更新介绍及升级操作"
|
||||
icon: upgrade
|
||||
draft: false
|
||||
images: []
|
||||
|
@@ -75,5 +75,13 @@
|
||||
"maxToken": 16000,
|
||||
"price": 0,
|
||||
"prompt": ""
|
||||
},
|
||||
"QGModel": {
|
||||
"model": "gpt-3.5-turbo",
|
||||
"name": "GPT35-4k",
|
||||
"maxToken": 4000,
|
||||
"price": 0,
|
||||
"prompt": "",
|
||||
"functionCall": false
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,10 @@
|
||||
### Fast GPT V4.4.5
|
||||
|
||||
1. 优化 - Api Key 使用。增加别名、额度限制和过期时间。自带 appId,无需额外连接。
|
||||
2. 去除 - 限定词。目前旧应用仍生效,9/25 后全面去除,请及时替换。
|
||||
3. 新增 - 引用模板/引用提示词设置,可以 DIY 引用内容的格式,从而更好的适配场景。[参考文档](https://doc.fastgpt.run/docs/use-cases/prompt/)
|
||||
4. [使用文档](https://doc.fastgpt.run/docs/intro/)
|
||||
5. [点击查看高级编排介绍文档](https://doc.fastgpt.run/docs/workflow)
|
||||
6. [点击查看商业版](https://doc.fastgpt.run/docs/commercial/)
|
||||
1. 新增 - 下一步指引选项,可以通过模型生成 3 个预测问题。
|
||||
2. 新增 - 分享链接 hook 身份校验。
|
||||
3. 新增 - Api Key 使用。增加别名、额度限制和过期时间。自带 appId,无需额外连接。
|
||||
4. 去除 - 限定词。目前旧应用仍生效,9/25 后全面去除,请及时替换。
|
||||
5. 新增 - 引用模板/引用提示词设置,可以 DIY 引用内容的格式,从而更好的适配场景。[参考文档](https://doc.fastgpt.run/docs/use-cases/prompt/)
|
||||
6. [使用文档](https://doc.fastgpt.run/docs/intro/)
|
||||
7. [点击查看高级编排介绍文档](https://doc.fastgpt.run/docs/workflow)
|
||||
8. [点击查看商业版](https://doc.fastgpt.run/docs/commercial/)
|
||||
|
@@ -67,6 +67,7 @@
|
||||
"Mark Description": "The annotation feature is currently in beta. \n\n After clicking Add annotation, you need to select a knowledge base in order to store annotation data. You can use this feature to quickly annotate questions and expected answers to guide the model to the next answer. At present, the annotation function, like other data in the knowledge base, is affected by the model, which does not mean that the annotation meets 100% expectations. The \n\n annotation data is only unidirectional synchronization with the knowledge base. If the knowledge base modifies the annotation data, the annotation data displayed in the log cannot be synchronized",
|
||||
"Mark Description Title": "Mark Description",
|
||||
"New Chat": "New Chat",
|
||||
"Question Guide Tips": "I guess what you're asking is",
|
||||
"Read Mark Description": "Read mark description",
|
||||
"Read User Feedback": "Read user feedback",
|
||||
"Select Mark Kb": "Select Dataset",
|
||||
|
@@ -67,6 +67,7 @@
|
||||
"Mark Description": "当前标注功能为测试版。\n\n点击添加标注后,需要选择一个知识库,以便存储标注数据。你可以通过该功能快速的标注问题和预期回答,以便引导模型下次的回答。\n\n目前,标注功能同知识库其他数据一样,受模型的影响,不代表标注后 100% 符合预期。\n\n标注数据仅单向与知识库同步,如果知识库修改了该标注数据,日志展示的标注数据无法同步",
|
||||
"Mark Description Title": "标注功能介绍",
|
||||
"New Chat": "新对话",
|
||||
"Question Guide Tips": "猜你想问",
|
||||
"Read Mark Description": "查看标注功能介绍",
|
||||
"Read User Feedback": "查看用户反馈",
|
||||
"Select Mark Kb": "选择知识库",
|
||||
|
5
projects/app/src/api/core/ai/agent/api.ts
Normal file
5
projects/app/src/api/core/ai/agent/api.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { GET, POST, PUT, DELETE } from '@/api/request';
|
||||
import { CreateQuestionGuideProps } from './type';
|
||||
|
||||
export const postQuestionGuide = (data: CreateQuestionGuideProps, cancelToken: AbortController) =>
|
||||
POST<string[]>('/core/ai/agent/createQuestionGuide', data, { cancelToken });
|
5
projects/app/src/api/core/ai/agent/type.d.ts
vendored
Normal file
5
projects/app/src/api/core/ai/agent/type.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { ChatCompletionRequestMessage } from '@fastgpt/core/aiApi/type';
|
||||
|
||||
export type CreateQuestionGuideProps = {
|
||||
messages: ChatCompletionRequestMessage[];
|
||||
};
|
@@ -12,6 +12,7 @@ interface ConfigType {
|
||||
hold?: boolean;
|
||||
timeout?: number;
|
||||
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
||||
cancelToken?: AbortController;
|
||||
}
|
||||
interface ResponseDataType {
|
||||
code: number;
|
||||
@@ -88,7 +89,12 @@ instance.interceptors.request.use(requestStart, (err) => Promise.reject(err));
|
||||
/* 响应拦截 */
|
||||
instance.interceptors.response.use(responseSuccess, (err) => Promise.reject(err));
|
||||
|
||||
function request(url: string, data: any, config: ConfigType, method: Method): any {
|
||||
function request(
|
||||
url: string,
|
||||
data: any,
|
||||
{ cancelToken, ...config }: ConfigType,
|
||||
method: Method
|
||||
): any {
|
||||
/* 去空 */
|
||||
for (const key in data) {
|
||||
if (data[key] === null || data[key] === undefined) {
|
||||
@@ -103,6 +109,7 @@ function request(url: string, data: any, config: ConfigType, method: Method): an
|
||||
method,
|
||||
data: ['POST', 'PUT'].includes(method) ? data : null,
|
||||
params: !['POST', 'PUT'].includes(method) ? data : null,
|
||||
signal: cancelToken?.signal,
|
||||
...config // 用户自定义配置,可以覆盖前面的配置
|
||||
})
|
||||
.then((res) => checkRes(res.data))
|
||||
|
5
projects/app/src/api/response/chat.d.ts
vendored
5
projects/app/src/api/response/chat.d.ts
vendored
@@ -1,13 +1,12 @@
|
||||
import type { AppSchema } from '@/types/mongoSchema';
|
||||
import type { ChatItemType } from '@/types/chat';
|
||||
import { VariableItemType } from '@/types/app';
|
||||
import { AppModuleItemType, VariableItemType } from '@/types/app';
|
||||
|
||||
export interface InitChatResponse {
|
||||
chatId: string;
|
||||
appId: string;
|
||||
app: {
|
||||
variableModules?: VariableItemType[];
|
||||
welcomeText?: string;
|
||||
userGuideModule?: AppModuleItemType;
|
||||
chatModels?: string[];
|
||||
name: string;
|
||||
avatar: string;
|
||||
|
@@ -24,7 +24,7 @@ import { feConfigs } from '@/store/static';
|
||||
import { event } from '@/utils/plugin/eventbus';
|
||||
import { adaptChat2GptMessages } from '@/utils/common/adapt/message';
|
||||
import { useMarkdown } from '@/hooks/useMarkdown';
|
||||
import { VariableItemType } from '@/types/app';
|
||||
import { AppModuleItemType, VariableItemType } from '@/types/app';
|
||||
import { VariableInputEnum } from '@/constants/app';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { MessageItemType } from '@/pages/api/openapi/v1/chat/completions';
|
||||
@@ -51,6 +51,8 @@ const InputDataModal = dynamic(() => import('@/pages/kb/detail/components/InputD
|
||||
|
||||
import styles from './index.module.scss';
|
||||
import Script from 'next/script';
|
||||
import { postQuestionGuide } from '@/api/core/ai/agent/api';
|
||||
import { splitGuideModule } from './utils';
|
||||
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
|
||||
|
||||
@@ -137,8 +139,7 @@ const ChatBox = (
|
||||
chatId,
|
||||
appAvatar,
|
||||
userAvatar,
|
||||
variableModules,
|
||||
welcomeText,
|
||||
userGuideModule,
|
||||
active = true,
|
||||
onUpdateVariable,
|
||||
onStartChat,
|
||||
@@ -151,8 +152,7 @@ const ChatBox = (
|
||||
chatId?: string;
|
||||
appAvatar?: string;
|
||||
userAvatar?: string;
|
||||
variableModules?: VariableItemType[];
|
||||
welcomeText?: string;
|
||||
userGuideModule?: AppModuleItemType;
|
||||
active?: boolean;
|
||||
onUpdateVariable?: (e: Record<string, any>) => void;
|
||||
onStartChat?: (e: StartChatFnProps) => Promise<{
|
||||
@@ -171,24 +171,28 @@ const ChatBox = (
|
||||
const { toast } = useToast();
|
||||
const { isPc } = useGlobalStore();
|
||||
const TextareaDom = useRef<HTMLTextAreaElement>(null);
|
||||
const controller = useRef(new AbortController());
|
||||
const chatController = useRef(new AbortController());
|
||||
const questionGuideController = useRef(new AbortController());
|
||||
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [variables, setVariables] = useState<Record<string, any>>({});
|
||||
const [variables, setVariables] = useState<Record<string, any>>({}); // settings variable
|
||||
const [chatHistory, setChatHistory] = useState<ChatSiteItemType[]>([]);
|
||||
const [feedbackId, setFeedbackId] = useState<string>();
|
||||
const [readFeedbackData, setReadFeedbackData] = useState<{
|
||||
// read feedback modal data
|
||||
chatItemId: string;
|
||||
content: string;
|
||||
isMarked: boolean;
|
||||
}>();
|
||||
const [adminMarkData, setAdminMarkData] = useState<{
|
||||
// mark modal data
|
||||
kbId?: string;
|
||||
chatItemId: string;
|
||||
dataId?: string;
|
||||
q: string;
|
||||
a: string;
|
||||
}>();
|
||||
const [questionGuides, setQuestionGuide] = useState<string[]>([]);
|
||||
|
||||
const isChatting = useMemo(
|
||||
() =>
|
||||
@@ -196,6 +200,12 @@ const ChatBox = (
|
||||
chatHistory[chatHistory.length - 1]?.status !== 'finish',
|
||||
[chatHistory]
|
||||
);
|
||||
|
||||
const { welcomeText, variableModules, questionGuide } = useMemo(
|
||||
() => splitGuideModule(userGuideModule),
|
||||
[userGuideModule]
|
||||
);
|
||||
|
||||
// compute variable input is finish.
|
||||
const [variableInputFinish, setVariableInputFinish] = useState(false);
|
||||
const variableIsFinish = useMemo(() => {
|
||||
@@ -287,6 +297,32 @@ const ChatBox = (
|
||||
}, 100);
|
||||
}, []);
|
||||
|
||||
// create question guide
|
||||
const createQuestionGuide = useCallback(
|
||||
async ({ history }: { history: ChatSiteItemType[] }) => {
|
||||
if (!questionGuide || chatController.current?.signal?.aborted) return;
|
||||
|
||||
try {
|
||||
const abortSignal = new AbortController();
|
||||
questionGuideController.current = abortSignal;
|
||||
|
||||
const result = await postQuestionGuide(
|
||||
{
|
||||
messages: adaptChat2GptMessages({ messages: history, reserveId: false }).slice(-6)
|
||||
},
|
||||
abortSignal
|
||||
);
|
||||
if (Array.isArray(result)) {
|
||||
setQuestionGuide(result);
|
||||
setTimeout(() => {
|
||||
scrollToBottom();
|
||||
}, 100);
|
||||
}
|
||||
} catch (error) {}
|
||||
},
|
||||
[questionGuide, scrollToBottom]
|
||||
);
|
||||
|
||||
/**
|
||||
* user confirm send prompt
|
||||
*/
|
||||
@@ -300,6 +336,7 @@ const ChatBox = (
|
||||
});
|
||||
return;
|
||||
}
|
||||
questionGuideController.current?.abort('stop');
|
||||
// get input value
|
||||
const val = inputVal.trim();
|
||||
|
||||
@@ -332,6 +369,7 @@ const ChatBox = (
|
||||
|
||||
// 清空输入内容
|
||||
resetInputVal('');
|
||||
setQuestionGuide([]);
|
||||
setTimeout(() => {
|
||||
scrollToBottom();
|
||||
}, 100);
|
||||
@@ -339,11 +377,11 @@ const ChatBox = (
|
||||
try {
|
||||
// create abort obj
|
||||
const abortSignal = new AbortController();
|
||||
controller.current = abortSignal;
|
||||
chatController.current = abortSignal;
|
||||
|
||||
const messages = adaptChat2GptMessages({ messages: newChatList, reserveId: true });
|
||||
|
||||
const { responseData } = await onStartChat({
|
||||
const { responseData, responseText } = await onStartChat({
|
||||
chatList: newChatList,
|
||||
messages,
|
||||
controller: abortSignal,
|
||||
@@ -364,6 +402,16 @@ const ChatBox = (
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
createQuestionGuide({
|
||||
history: newChatList.map((item, i) =>
|
||||
i === newChatList.length - 1
|
||||
? {
|
||||
...item,
|
||||
value: responseText
|
||||
}
|
||||
: item
|
||||
)
|
||||
});
|
||||
generatingScroll();
|
||||
isPc && TextareaDom.current?.focus();
|
||||
}, 100);
|
||||
@@ -393,13 +441,14 @@ const ChatBox = (
|
||||
}
|
||||
},
|
||||
[
|
||||
isChatting,
|
||||
chatHistory,
|
||||
onStartChat,
|
||||
isChatting,
|
||||
resetInputVal,
|
||||
toast,
|
||||
scrollToBottom,
|
||||
onStartChat,
|
||||
generatingMessage,
|
||||
createQuestionGuide,
|
||||
generatingScroll,
|
||||
isPc
|
||||
]
|
||||
@@ -494,7 +543,8 @@ const ChatBox = (
|
||||
// page change and abort request
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
controller.current?.abort('leave');
|
||||
chatController.current?.abort('leave');
|
||||
questionGuideController.current?.abort('leave');
|
||||
// close voice
|
||||
cancelBroadcast();
|
||||
};
|
||||
@@ -528,6 +578,7 @@ const ChatBox = (
|
||||
<Flex flexDirection={'column'} h={'100%'}>
|
||||
<Script src="/js/html2pdf.bundle.min.js" strategy="lazyOnload"></Script>
|
||||
|
||||
{/* chat box container */}
|
||||
<Box ref={ChatBoxRef} flex={'1 0 0'} h={0} w={'100%'} overflow={'overlay'} px={[4, 0]} pb={3}>
|
||||
<Box id="chat-container" maxW={['100%', '92%']} h={'100%'} mx={'auto'}>
|
||||
{showEmpty && <Empty />}
|
||||
@@ -839,6 +890,43 @@ const ChatBox = (
|
||||
contentId={item.dataId}
|
||||
responseData={item.responseData}
|
||||
/>
|
||||
{/* question guide */}
|
||||
{index === chatHistory.length - 1 &&
|
||||
!isChatting &&
|
||||
questionGuides.length > 0 && (
|
||||
<Flex
|
||||
mt={2}
|
||||
borderTop={theme.borders.sm}
|
||||
alignItems={'center'}
|
||||
flexWrap={'wrap'}
|
||||
>
|
||||
<Box
|
||||
color={'myGray.500'}
|
||||
mt={2}
|
||||
mr={2}
|
||||
fontSize={'sm'}
|
||||
fontStyle={'italic'}
|
||||
>
|
||||
{t('chat.Question Guide Tips')}
|
||||
</Box>
|
||||
{questionGuides.map((item) => (
|
||||
<Button
|
||||
mt={2}
|
||||
key={item}
|
||||
mr="2"
|
||||
borderRadius={'md'}
|
||||
variant={'outline'}
|
||||
colorScheme={'gray'}
|
||||
size={'xs'}
|
||||
onClick={() => {
|
||||
resetInputVal(item);
|
||||
}}
|
||||
>
|
||||
{item}
|
||||
</Button>
|
||||
))}
|
||||
</Flex>
|
||||
)}
|
||||
{/* admin mark content */}
|
||||
{showMarkIcon && item.adminFeedback && (
|
||||
<Box>
|
||||
@@ -928,7 +1016,7 @@ const ChatBox = (
|
||||
cursor={'pointer'}
|
||||
name={'stop'}
|
||||
color={'gray.500'}
|
||||
onClick={() => controller.current?.abort('stop')}
|
||||
onClick={() => chatController.current?.abort('stop')}
|
||||
/>
|
||||
) : (
|
||||
<MyIcon
|
||||
|
@@ -3,18 +3,24 @@ import { FlowModuleTypeEnum } from '@/constants/flow';
|
||||
import { getChatModel } from '@/service/utils/data';
|
||||
import { AppModuleItemType, VariableItemType } from '@/types/app';
|
||||
|
||||
export const getGuideModules = (modules: AppModuleItemType[]) => {
|
||||
const guideModules = modules.find((item) => item.flowType === FlowModuleTypeEnum.userGuide);
|
||||
export const getGuideModule = (modules: AppModuleItemType[]) =>
|
||||
modules.find((item) => item.flowType === FlowModuleTypeEnum.userGuide);
|
||||
|
||||
export const splitGuideModule = (guideModules?: AppModuleItemType) => {
|
||||
const welcomeText: string =
|
||||
guideModules?.inputs?.find((item) => item.key === SystemInputEnum.welcomeText)?.value || '';
|
||||
|
||||
const variableModules: VariableItemType[] =
|
||||
guideModules?.inputs.find((item) => item.key === SystemInputEnum.variables)?.value || [];
|
||||
|
||||
const questionGuide: boolean =
|
||||
guideModules?.inputs?.find((item) => item.key === SystemInputEnum.questionGuide)?.value ||
|
||||
false;
|
||||
|
||||
return {
|
||||
welcomeText,
|
||||
variableModules
|
||||
variableModules,
|
||||
questionGuide
|
||||
};
|
||||
};
|
||||
export const getChatModelNameList = (modules: AppModuleItemType[]): string[] => {
|
||||
|
@@ -0,0 +1,5 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M10.8275 1.33325H5.17245C4.63581 1.33324 4.19289 1.33324 3.8321 1.36272C3.45737 1.39333 3.1129 1.45904 2.78934 1.6239C2.28758 1.87956 1.87963 2.28751 1.62397 2.78928C1.45911 3.11284 1.3934 3.4573 1.36278 3.83204C1.3333 4.19283 1.33331 4.63574 1.33332 5.17239L1.33328 9.42497C1.333 9.95523 1.33278 10.349 1.42418 10.6901C1.67076 11.6103 2.38955 12.3291 3.3098 12.5757C3.51478 12.6306 3.73878 12.6525 3.99998 12.6611L3.99998 13.5806C3.99995 13.7374 3.99992 13.8973 4.01182 14.0283C4.0232 14.1536 4.05333 14.3901 4.21844 14.5969C4.40843 14.8349 4.69652 14.9734 5.00106 14.973C5.26572 14.9728 5.46921 14.8486 5.57416 14.7792C5.6839 14.7066 5.80872 14.6067 5.93117 14.5087L7.53992 13.2217C7.88564 12.9451 7.98829 12.8671 8.09494 12.8126C8.20192 12.7579 8.3158 12.718 8.43349 12.6938C8.55081 12.6697 8.67974 12.6666 9.12248 12.6666H10.8275C11.3642 12.6666 11.8071 12.6666 12.1679 12.6371C12.5426 12.6065 12.8871 12.5408 13.2106 12.3759C13.7124 12.1203 14.1203 11.7123 14.376 11.2106C14.5409 10.887 14.6066 10.5425 14.6372 10.1678C14.6667 9.80701 14.6667 9.36411 14.6667 8.82747V5.17237C14.6667 4.63573 14.6667 4.19283 14.6372 3.83204C14.6066 3.4573 14.5409 3.11284 14.376 2.78928C14.1203 2.28751 13.7124 1.87956 13.2106 1.6239C12.8871 1.45904 12.5426 1.39333 12.1679 1.36272C11.8071 1.33324 11.3642 1.33324 10.8275 1.33325ZM8.99504 4.99992C8.99504 4.44763 9.44275 3.99992 9.99504 3.99992C10.5473 3.99992 10.995 4.44763 10.995 4.99992C10.995 5.5522 10.5473 5.99992 9.99504 5.99992C9.44275 5.99992 8.99504 5.5522 8.99504 4.99992ZM4.92837 7.79996C5.222 7.57974 5.63816 7.63837 5.85961 7.93051C5.90071 7.98295 5.94593 8.03229 5.99199 8.08035C6.09019 8.18282 6.23775 8.32184 6.42882 8.4608C6.81353 8.74059 7.3454 8.99996 7.99504 8.99996C8.64469 8.99996 9.17655 8.74059 9.56126 8.4608C9.75233 8.32184 9.89989 8.18282 9.99809 8.08035C10.0441 8.0323 10.0894 7.98294 10.1305 7.93051C10.3519 7.63837 10.7681 7.57974 11.0617 7.79996C11.3563 8.02087 11.416 8.43874 11.195 8.73329C11.1967 8.73112 11.1928 8.7361 11.186 8.74466C11.1697 8.7651 11.1372 8.80597 11.1261 8.81916C11.087 8.86575 11.0317 8.92884 10.9607 9.00289C10.8194 9.15043 10.6128 9.34474 10.3455 9.53912C9.81353 9.92599 9.01206 10.3333 7.99504 10.3333C6.97802 10.3333 6.17655 9.92599 5.64459 9.53912C5.37733 9.34474 5.17072 9.15043 5.02934 9.00289C4.95837 8.92884 4.90305 8.86575 4.86395 8.81916C4.84438 8.79585 4.82881 8.77659 4.81731 8.76207C4.58702 8.46455 4.61798 8.03275 4.92837 7.79996ZM5.99504 3.99992C5.44275 3.99992 4.99504 4.44763 4.99504 4.99992C4.99504 5.5522 5.44275 5.99992 5.99504 5.99992C6.54732 5.99992 6.99504 5.5522 6.99504 4.99992C6.99504 4.44763 6.54732 3.99992 5.99504 3.99992Z"
|
||||
fill="#06AED4"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
@@ -86,7 +86,8 @@ const iconPaths = {
|
||||
rightArrowLight: () => import('./icons/light/rightArrow.svg'),
|
||||
searchLight: () => import('./icons/light/search.svg'),
|
||||
plusFill: () => import('./icons/fill/plus.svg'),
|
||||
moveLight: () => import('./icons/light/move.svg')
|
||||
moveLight: () => import('./icons/light/move.svg'),
|
||||
questionGuide: () => import('./icons/app/questionGuide.svg')
|
||||
};
|
||||
|
||||
export type IconName = keyof typeof iconPaths;
|
||||
|
@@ -4,7 +4,8 @@ export enum SystemInputEnum {
|
||||
'variables' = 'variables',
|
||||
'switch' = 'switch', // a trigger switch
|
||||
'history' = 'history',
|
||||
'userChatInput' = 'userChatInput'
|
||||
'userChatInput' = 'userChatInput',
|
||||
'questionGuide' = 'questionGuide'
|
||||
}
|
||||
|
||||
export enum VariableInputEnum {
|
||||
|
@@ -26,6 +26,7 @@ export const welcomeTextTip =
|
||||
'每次对话开始前,发送一个初始内容。支持标准 Markdown 语法,可使用的额外标记:\n[快捷按键]: 用户点击后可以直接发送该问题';
|
||||
export const variableTip =
|
||||
'可以在对话开始前,要求用户填写一些内容作为本轮对话的特定变量。该模块位于开场引导之后。\n变量可以通过 {{变量key}} 的形式注入到其他模块 string 类型的输入中,例如:提示词、限定词等';
|
||||
export const questionGuideTip = `对话结束后,会为生成 3 个引导性问题。`;
|
||||
|
||||
export const VariableModule: FlowModuleTemplateType = {
|
||||
flowType: FlowModuleTypeEnum.variable,
|
||||
@@ -52,14 +53,19 @@ export const UserGuideModule: FlowModuleTemplateType = {
|
||||
inputs: [
|
||||
{
|
||||
key: SystemInputEnum.welcomeText,
|
||||
type: FlowInputItemTypeEnum.input,
|
||||
type: FlowInputItemTypeEnum.hidden,
|
||||
label: '开场白'
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.variables,
|
||||
type: FlowInputItemTypeEnum.systemInput,
|
||||
type: FlowInputItemTypeEnum.hidden,
|
||||
label: '对话框变量',
|
||||
value: []
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.questionGuide,
|
||||
type: FlowInputItemTypeEnum.switch,
|
||||
label: '问题引导'
|
||||
}
|
||||
],
|
||||
outputs: []
|
||||
|
@@ -10,6 +10,7 @@ export enum FlowInputItemTypeEnum {
|
||||
custom = 'custom',
|
||||
target = 'target',
|
||||
none = 'none',
|
||||
switch = 'switch',
|
||||
hidden = 'hidden'
|
||||
}
|
||||
|
||||
|
@@ -6,7 +6,7 @@ import { authUser } from '@/service/utils/auth';
|
||||
import { ChatItemType } from '@/types/chat';
|
||||
import { authApp } from '@/service/utils/auth';
|
||||
import type { ChatSchema } from '@/types/mongoSchema';
|
||||
import { getGuideModules, getChatModelNameList } from '@/components/ChatBox/utils';
|
||||
import { getChatModelNameList, getGuideModule } from '@/components/ChatBox/utils';
|
||||
import { TaskResponseKeyEnum } from '@/constants/chat';
|
||||
|
||||
/* 初始化我的聊天框,需要身份验证 */
|
||||
@@ -81,7 +81,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
chatId,
|
||||
appId,
|
||||
app: {
|
||||
...getGuideModules(app.modules),
|
||||
userGuideModule: getGuideModule(app.modules),
|
||||
chatModels: getChatModelNameList(app.modules),
|
||||
name: app.name,
|
||||
avatar: app.avatar,
|
||||
|
@@ -0,0 +1,77 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { CreateQuestionGuideProps } from '@/api/core/ai/agent/type';
|
||||
import { getAIChatApi } from '@fastgpt/core/aiApi/config';
|
||||
import { Prompt_QuestionGuide } from '@/prompts/core/agent';
|
||||
import { pushQuestionGuideBill } from '@/service/common/bill/push';
|
||||
import { defaultQGModel } from '@/pages/api/system/getInitData';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { messages } = req.body as CreateQuestionGuideProps;
|
||||
const { user } = await authUser({ req, authToken: true, authApiKey: true, authBalance: true });
|
||||
|
||||
if (!user) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
const qgModel = global.qgModel || defaultQGModel;
|
||||
|
||||
const chatAPI = getAIChatApi(user.openaiAccount);
|
||||
|
||||
const { data } = await chatAPI.createChatCompletion({
|
||||
model: qgModel.model,
|
||||
temperature: 0,
|
||||
max_tokens: 200,
|
||||
messages: [
|
||||
...messages,
|
||||
{
|
||||
role: 'user',
|
||||
content: Prompt_QuestionGuide
|
||||
}
|
||||
],
|
||||
stream: false
|
||||
});
|
||||
|
||||
const answer = data.choices?.[0].message?.content || '';
|
||||
const totalTokens = data.usage?.total_tokens || 0;
|
||||
|
||||
const start = answer.indexOf('[');
|
||||
const end = answer.lastIndexOf(']');
|
||||
|
||||
if (start === -1 || end === -1) {
|
||||
return jsonRes(res, {
|
||||
data: []
|
||||
});
|
||||
}
|
||||
|
||||
const jsonStr = answer
|
||||
.substring(start, end + 1)
|
||||
.replace(/(\\n|\\)/g, '')
|
||||
.replace(/ /g, '');
|
||||
|
||||
try {
|
||||
jsonRes(res, {
|
||||
data: JSON.parse(jsonStr)
|
||||
});
|
||||
|
||||
pushQuestionGuideBill({
|
||||
tokens: totalTokens,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
return jsonRes(res, {
|
||||
data: []
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
@@ -4,7 +4,7 @@ import { connectToDatabase, OutLink, User } from '@/service/mongo';
|
||||
import type { InitShareChatResponse } from '@/api/response/chat';
|
||||
import { authApp } from '@/service/utils/auth';
|
||||
import { HUMAN_ICON } from '@/constants/chat';
|
||||
import { getChatModelNameList, getGuideModules } from '@/components/ChatBox/utils';
|
||||
import { getChatModelNameList, getGuideModule } from '@/components/ChatBox/utils';
|
||||
import { authShareChatInit } from '@/service/support/outLink/auth';
|
||||
|
||||
/* init share chat window */
|
||||
@@ -46,7 +46,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
data: {
|
||||
userAvatar: user?.avatar || HUMAN_ICON,
|
||||
app: {
|
||||
...getGuideModules(app.modules),
|
||||
userGuideModule: getGuideModule(app.modules),
|
||||
chatModels: getChatModelNameList(app.modules),
|
||||
name: app.name,
|
||||
avatar: app.avatar,
|
||||
|
@@ -97,6 +97,14 @@ export const defaultCQModel: FunctionModelItemType = {
|
||||
prompt: '',
|
||||
functionCall: true
|
||||
};
|
||||
export const defaultQGModel: FunctionModelItemType = {
|
||||
model: 'gpt-3.5-turbo',
|
||||
name: 'FastAI-4k',
|
||||
maxToken: 4000,
|
||||
price: 1.5,
|
||||
prompt: '',
|
||||
functionCall: false
|
||||
};
|
||||
|
||||
const defaultVectorModels: VectorModelItemType[] = [
|
||||
{
|
||||
@@ -130,6 +138,7 @@ export async function getInitConfig() {
|
||||
global.qaModel = res.QAModel || defaultQAModel;
|
||||
global.extractModel = res.ExtractModel || defaultExtractModel;
|
||||
global.cqModel = res.CQModel || defaultCQModel;
|
||||
global.qgModel = res.QGModel || defaultQGModel;
|
||||
global.vectorModels = res.VectorModels || defaultVectorModels;
|
||||
} catch (error) {
|
||||
setDefaultData();
|
||||
@@ -143,6 +152,9 @@ export function setDefaultData() {
|
||||
global.chatModels = defaultChatModels;
|
||||
global.qaModel = defaultQAModel;
|
||||
global.vectorModels = defaultVectorModels;
|
||||
global.extractModel = defaultExtractModel;
|
||||
global.cqModel = defaultCQModel;
|
||||
global.qgModel = defaultQGModel;
|
||||
}
|
||||
|
||||
export function getSystemVersion() {
|
||||
|
@@ -15,7 +15,7 @@ import { streamFetch } from '@/api/fetch';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useUserStore } from '@/store/user';
|
||||
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
|
||||
import { getGuideModules } from '@/components/ChatBox/utils';
|
||||
import { getGuideModule } from '@/components/ChatBox/utils';
|
||||
|
||||
export type ChatTestComponentRef = {
|
||||
resetChatTest: () => void;
|
||||
@@ -114,7 +114,7 @@ const ChatTest = (
|
||||
appAvatar={app.avatar}
|
||||
userAvatar={userInfo?.avatar}
|
||||
showMarkIcon
|
||||
{...getGuideModules(modules)}
|
||||
userGuideModule={getGuideModule(modules)}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={() => {}}
|
||||
/>
|
||||
|
@@ -4,19 +4,20 @@ import {
|
||||
Box,
|
||||
Flex,
|
||||
Textarea,
|
||||
Button,
|
||||
useTheme,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Tr,
|
||||
Th,
|
||||
Td,
|
||||
TableContainer
|
||||
TableContainer,
|
||||
Switch
|
||||
} from '@chakra-ui/react';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import { FlowModuleItemType } from '@/types/flow';
|
||||
import { SystemInputEnum } from '@/constants/app';
|
||||
import { welcomeTextTip, variableTip } from '@/constants/flow/ModuleTemplate';
|
||||
import { welcomeTextTip, variableTip, questionGuideTip } from '@/constants/flow/ModuleTemplate';
|
||||
|
||||
import VariableEditModal, { addVariable } from '../../../VariableEditModal';
|
||||
import MyIcon from '@/components/Icon';
|
||||
@@ -26,14 +27,18 @@ import NodeCard from '../modules/NodeCard';
|
||||
import { VariableItemType } from '@/types/app';
|
||||
|
||||
const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<>
|
||||
<NodeCard minW={'300px'} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||
<WelcomeText data={data} />
|
||||
<Box mt={3}>
|
||||
<Box pt={4} pb={2}>
|
||||
<ChatStartVariable data={data} />
|
||||
</Box>
|
||||
<Box pt={3} borderTop={theme.borders.base}>
|
||||
<QuestionGuide data={data} />
|
||||
</Box>
|
||||
</Container>
|
||||
</NodeCard>
|
||||
</>
|
||||
@@ -196,3 +201,40 @@ function ChatStartVariable({ data }: { data: FlowModuleItemType }) {
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function QuestionGuide({ data }: { data: FlowModuleItemType }) {
|
||||
const { inputs, moduleId, onChangeNode } = data;
|
||||
const questionGuide = useMemo(
|
||||
() =>
|
||||
(inputs.find((item) => item.key === SystemInputEnum.questionGuide)?.value as boolean) ||
|
||||
false,
|
||||
[inputs]
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'questionGuide'} mr={2} w={'16px'} />
|
||||
<Box>下一步指引</Box>
|
||||
<MyTooltip label={questionGuideTip} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
<Box flex={1} />
|
||||
<Switch
|
||||
isChecked={questionGuide}
|
||||
size={'lg'}
|
||||
onChange={(e) => {
|
||||
const value = e.target.checked;
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
key: SystemInputEnum.questionGuide,
|
||||
type: 'inputs',
|
||||
value: {
|
||||
...inputs.find((item) => item.key === SystemInputEnum.questionGuide),
|
||||
value
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
@@ -16,7 +16,8 @@ import {
|
||||
useDisclosure,
|
||||
Button,
|
||||
IconButton,
|
||||
Text
|
||||
Text,
|
||||
Switch
|
||||
} from '@chakra-ui/react';
|
||||
import { useUserStore } from '@/store/user';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
@@ -34,7 +35,8 @@ import { formatPrice } from '@fastgpt/common/bill/index';
|
||||
import {
|
||||
ChatModelSystemTip,
|
||||
ChatModelLimitTip,
|
||||
welcomeTextTip
|
||||
welcomeTextTip,
|
||||
questionGuideTip
|
||||
} from '@/constants/flow/ModuleTemplate';
|
||||
import { AppModuleItemType, VariableItemType } from '@/types/app';
|
||||
import { useRequest } from '@/hooks/useRequest';
|
||||
@@ -46,7 +48,7 @@ import { useToast } from '@/hooks/useToast';
|
||||
import { AppSchema } from '@/types/mongoSchema';
|
||||
import { delModelById } from '@/api/app';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getGuideModules } from '@/components/ChatBox/utils';
|
||||
import { getGuideModule } from '@/components/ChatBox/utils';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import MySelect from '@/components/Select';
|
||||
@@ -89,6 +91,7 @@ const Settings = ({ appId }: { appId: string }) => {
|
||||
const { register, setValue, getValues, reset, handleSubmit, control } = useForm<EditFormType>({
|
||||
defaultValues: getDefaultAppForm()
|
||||
});
|
||||
|
||||
const {
|
||||
fields: variables,
|
||||
append: appendVariable,
|
||||
@@ -157,7 +160,9 @@ const Settings = ({ appId }: { appId: string }) => {
|
||||
const appModule2Form = useCallback(() => {
|
||||
const formVal = appModules2Form(appDetail.modules);
|
||||
reset(formVal);
|
||||
setRefresh((state) => !state);
|
||||
setTimeout(() => {
|
||||
setRefresh((state) => !state);
|
||||
}, 100);
|
||||
}, [appDetail.modules, reset]);
|
||||
|
||||
const { mutate: onSubmitSave, isLoading: isSaving } = useRequest({
|
||||
@@ -536,6 +541,26 @@ const Settings = ({ appId }: { appId: string }) => {
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
<Box mt={5} {...BoxStyles}>
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'questionGuide'} mr={2} w={'16px'} />
|
||||
<Box>下一步指引</Box>
|
||||
<MyTooltip label={questionGuideTip} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
<Box flex={1} />
|
||||
<Switch
|
||||
isChecked={getValues('questionGuide')}
|
||||
size={'lg'}
|
||||
onChange={(e) => {
|
||||
const value = e.target.checked;
|
||||
setValue('questionGuide', value);
|
||||
setRefresh((state) => !state);
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
<ConfirmSaveModal />
|
||||
<ConfirmDelModal />
|
||||
{settingAppInfo && (
|
||||
@@ -678,7 +703,7 @@ const ChatTest = ({ appId }: { appId: string }) => {
|
||||
appAvatar={appDetail.avatar}
|
||||
userAvatar={userInfo?.avatar}
|
||||
showMarkIcon
|
||||
{...getGuideModules(modules)}
|
||||
userGuideModule={getGuideModule(modules)}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={() => {}}
|
||||
/>
|
||||
|
@@ -293,8 +293,7 @@ function DetailLogsModal({
|
||||
feedbackType={'admin'}
|
||||
showMarkIcon
|
||||
showVoiceIcon={false}
|
||||
variableModules={chat?.app.variableModules}
|
||||
welcomeText={chat?.app.welcomeText}
|
||||
userGuideModule={chat?.app?.userGuideModule}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
|
@@ -97,7 +97,7 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
<Th>金额限制(¥)</Th>
|
||||
<Th>IP限流(人/分钟)</Th>
|
||||
<Th>过期时间</Th>
|
||||
<Th>token校验</Th>
|
||||
<Th>身份校验</Th>
|
||||
</>
|
||||
)}
|
||||
<Th>最后使用时间</Th>
|
||||
|
@@ -361,9 +361,8 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
chatId={chatId}
|
||||
appAvatar={chatData.app.avatar}
|
||||
userAvatar={userInfo?.avatar}
|
||||
variableModules={chatData.app.variableModules}
|
||||
userGuideModule={chatData.app?.userGuideModule}
|
||||
feedbackType={'user'}
|
||||
welcomeText={chatData.app.welcomeText}
|
||||
onUpdateVariable={(e) => {}}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={delOneHistoryItem}
|
||||
|
@@ -245,8 +245,7 @@ const OutLink = ({
|
||||
ref={ChatBoxRef}
|
||||
appAvatar={shareChatData.app.avatar}
|
||||
userAvatar={shareChatData.userAvatar}
|
||||
variableModules={shareChatData.app.variableModules}
|
||||
welcomeText={shareChatData.app.welcomeText}
|
||||
userGuideModule={shareChatData.app?.userGuideModule}
|
||||
feedbackType={'user'}
|
||||
onUpdateVariable={(e) => {
|
||||
setShareChatData((state) => ({
|
||||
|
@@ -56,3 +56,5 @@ export const Prompt_CQJson = `我会给你几个问题类型,请参考额外
|
||||
{{text}}
|
||||
"""
|
||||
`;
|
||||
|
||||
export const Prompt_QuestionGuide = `我不太清楚问你什么问题,请帮我生成 3 个问题,引导我继续提问。问题的长度应小于20个字符,按 JSON 格式返回: ["问题1", "问题2", "问题3"]`;
|
||||
|
@@ -5,6 +5,7 @@ import { ChatHistoryItemResType } from '@/types/chat';
|
||||
import { formatPrice } from '@fastgpt/common/bill/index';
|
||||
import { addLog } from '@/service/utils/tools';
|
||||
import type { CreateBillType } from '@/types/common/bill';
|
||||
import { defaultQGModel } from '@/pages/api/system/getInitData';
|
||||
|
||||
async function createBill(data: CreateBillType) {
|
||||
try {
|
||||
@@ -170,3 +171,22 @@ export const countModelPrice = ({ model, tokens }: { model: string; tokens: numb
|
||||
if (!modelData) return 0;
|
||||
return modelData.price * tokens;
|
||||
};
|
||||
|
||||
export const pushQuestionGuideBill = ({ tokens, userId }: { tokens: number; userId: string }) => {
|
||||
const qgModel = global.qgModel || defaultQGModel;
|
||||
const total = qgModel.price * tokens;
|
||||
createBill({
|
||||
userId,
|
||||
appName: '问题指引',
|
||||
total,
|
||||
source: BillSourceEnum.fastgpt,
|
||||
list: [
|
||||
{
|
||||
moduleName: '问题指引',
|
||||
amount: total,
|
||||
model: qgModel.name,
|
||||
tokenLen: tokens
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
@@ -24,7 +24,7 @@ export const dispatchAnswer = (props: Record<string, any>): AnswerResponse => {
|
||||
res,
|
||||
event: detail ? sseResponseEventEnum.answer : undefined,
|
||||
data: textAdaptGptResponse({
|
||||
text: text.replace(/\\n/g, '\n')
|
||||
text: text.replace?.(/\\n/g, '\n') || ''
|
||||
})
|
||||
});
|
||||
}
|
||||
|
1
projects/app/src/types/index.d.ts
vendored
1
projects/app/src/types/index.d.ts
vendored
@@ -69,6 +69,7 @@ declare global {
|
||||
var qaModel: QAModelItemType;
|
||||
var extractModel: FunctionModelItemType;
|
||||
var cqModel: FunctionModelItemType;
|
||||
var qgModel: FunctionModelItemType;
|
||||
var vectorModels: VectorModelItemType[];
|
||||
var systemVersion: string;
|
||||
|
||||
|
@@ -10,7 +10,7 @@ import { SystemInputEnum } from '@/constants/app';
|
||||
import type { SelectedDatasetType } from '@/types/core/dataset';
|
||||
import { FlowInputItemType } from '@/types/flow';
|
||||
import type { AIChatProps } from '@/types/core/aiChat';
|
||||
import { getGuideModules } from '@/components/ChatBox/utils';
|
||||
import { getGuideModule, splitGuideModule } from '@/components/ChatBox/utils';
|
||||
|
||||
export type EditFormType = {
|
||||
chatModel: AIChatProps;
|
||||
@@ -26,6 +26,7 @@ export type EditFormType = {
|
||||
};
|
||||
};
|
||||
variables: VariableItemType[];
|
||||
questionGuide: boolean;
|
||||
};
|
||||
export const getDefaultAppForm = (): EditFormType => {
|
||||
const defaultChatModel = chatModelList[0];
|
||||
@@ -52,7 +53,8 @@ export const getDefaultAppForm = (): EditFormType => {
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
variables: []
|
||||
variables: [],
|
||||
questionGuide: false
|
||||
};
|
||||
};
|
||||
|
||||
@@ -137,13 +139,17 @@ export const appModules2Form = (modules: AppModuleItemType[]) => {
|
||||
target?.inputs?.find((item) => item.key === SpecialInputKeyEnum.answerText)?.value || '';
|
||||
}
|
||||
} else if (module.flowType === FlowModuleTypeEnum.userGuide) {
|
||||
const { welcomeText, variableModules } = getGuideModules(modules);
|
||||
const { welcomeText, variableModules, questionGuide } = splitGuideModule(
|
||||
getGuideModule(modules)
|
||||
);
|
||||
if (welcomeText) {
|
||||
defaultAppForm.guide.welcome = {
|
||||
text: welcomeText
|
||||
};
|
||||
}
|
||||
|
||||
defaultAppForm.variables = variableModules;
|
||||
defaultAppForm.questionGuide = !!questionGuide;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -225,15 +231,21 @@ const userGuideTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
||||
inputs: [
|
||||
{
|
||||
key: SystemInputEnum.welcomeText,
|
||||
type: FlowInputItemTypeEnum.input,
|
||||
type: FlowInputItemTypeEnum.hidden,
|
||||
label: '开场白',
|
||||
value: formData.guide.welcome.text
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.variables,
|
||||
type: FlowInputItemTypeEnum.systemInput,
|
||||
type: FlowInputItemTypeEnum.hidden,
|
||||
label: '对话框变量',
|
||||
value: formData.variables
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.questionGuide,
|
||||
type: FlowInputItemTypeEnum.hidden,
|
||||
label: '问题引导',
|
||||
value: formData.questionGuide
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
|
Reference in New Issue
Block a user