Commit bfac393a by Archer Committed by GitHub

Add question guide config (#3403)

* feat:Prompt task (#3337)

* feat:猜你想问自定义功能

* 修改用户输入框部分,去除冗余代码

* 删除不必要的属性

* 删除多余内容

* 修正了格式问题,并实现获取调试和app最新参数

* 修正了几行代码

* feat:Prompt task (#3337)

* feat:猜你想问自定义功能

* 修改用户输入框部分,去除冗余代码

* 删除不必要的属性

* 删除多余内容

* 修正了格式问题,并实现获取调试和app最新参数

* 修正了几行代码

* perf: question gudide code

* fix: i18n

* hunyuan logo

* fix: cq templates

* perf: create question guide code

* udpate svg

---------

Co-authored-by: Jiangween <145003935+Jiangween@users.noreply.github.com>
parent 76d20b2b
...@@ -201,7 +201,7 @@ weight: 708 ...@@ -201,7 +201,7 @@ weight: 708
- /imgs/model/qwen.svg - 通义千问 - /imgs/model/qwen.svg - 通义千问
- /imgs/model/sparkDesk.svg - 讯飞星火 - /imgs/model/sparkDesk.svg - 讯飞星火
- /imgs/model/yi.svg - 零一万物 - /imgs/model/yi.svg - 零一万物
- - /imgs/model/hunyuan.svg - 腾讯混元
## 特殊模型 ## 特殊模型
......
...@@ -1313,6 +1313,83 @@ curl --location --request POST 'http://localhost:3000/api/core/chat/feedback/upd ...@@ -1313,6 +1313,83 @@ curl --location --request POST 'http://localhost:3000/api/core/chat/feedback/upd
## 猜你想问 ## 猜你想问
**4.8.16 后新版接口**
新版猜你想问,必须包含 appId 和 chatId 的参数才可以进行使用。会自动根据 chatId 去拉取最近 6 轮对话记录作为上下文来引导回答。
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'http://localhost:3000/api/core/ai/agent/v2/createQuestionGuide' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "appId",
"chatId": "chatId",
"questionGuide": {
"open": true,
"model": "GPT-4o-mini",
"customPrompt": "你是一个智能助手,请根据用户的问题生成猜你想问。"
}
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
| 参数名 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| appId | string | ✅ | 应用 Id |
| chatId | string | ✅ | 对话 Id |
| questionGuide | object | | 自定义配置,不传的话,则会根据 appId,取最新发布版本的配置 |
```ts
type CreateQuestionGuideParams = OutLinkChatAuthProps & {
appId: string;
chatId: string;
questionGuide?: {
open: boolean;
model?: string;
customPrompt?: string;
};
};
```
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": [
"你对AI有什么看法?",
"想了解AI的应用吗?",
"你希望AI能做什么?"
]
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
---
**4.8.16 前旧版接口:**
{{< tabs tabTotal="3" >}} {{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}} {{< tab tabName="请求示例" >}}
{{< markdownify >}} {{< markdownify >}}
...@@ -1369,3 +1446,5 @@ curl --location --request POST 'http://localhost:3000/api/core/ai/agent/createQu ...@@ -1369,3 +1446,5 @@ curl --location --request POST 'http://localhost:3000/api/core/ai/agent/createQu
...@@ -12,9 +12,10 @@ weight: 808 ...@@ -12,9 +12,10 @@ weight: 808
1. 1.
2. 新增 - 商业版支持 API 知识库和链接集合定时同步。 2. 新增 - 商业版支持 API 知识库和链接集合定时同步。
3. 优化 - 工作流/简易模式变量初始化代码,去除监听初始化,避免因渲染顺序不一致导致的失败。 3. 新增 - 猜你想问支持选择模型和自定义提示词。
4. 修复 - 无法自动切换默认语言。增加分享链接,强制执行一次切换默认语言。 4. 优化 - 工作流/简易模式变量初始化代码,去除监听初始化,避免因渲染顺序不一致导致的失败。
5. 修复 - 数组选择器自动兼容 4.8.13 以前的数据。 5. 修复 - 无法自动切换默认语言。增加分享链接,强制执行一次切换默认语言。
6. 修复 - 站点同步知识库,链接同步时未使用选择器。 6. 修复 - 数组选择器自动兼容 4.8.13 以前的数据。
7. 修复 - 简易模式转工作流,没有把系统配置项转化。 7. 修复 - 站点同步知识库,链接同步时未使用选择器。
8. 修复 - 插件独立运行,变量初始值未赋上。 8. 修复 - 简易模式转工作流,没有把系统配置项转化。
\ No newline at end of file 9. 修复 - 插件独立运行,变量初始值未赋上。
\ No newline at end of file
...@@ -65,3 +65,13 @@ export const Prompt_CQJson = `请帮我执行一个“问题分类â€ä»»åŠ¡ï¼Œå° ...@@ -65,3 +65,13 @@ export const Prompt_CQJson = `请帮我执行一个“问题分类â€ä»»åŠ¡ï¼Œå°
问题:"{{question}}" 问题:"{{question}}"
类型ID= 类型ID=
`; `;
export const PROMPT_QUESTION_GUIDE = `You are an AI assistant tasked with predicting the user's next question based on the conversation history. Your goal is to generate 3 potential questions that will guide the user to continue the conversation. When generating these questions, adhere to the following rules:
1. Use the same language as the user's last question in the conversation history.
2. Keep each question under 20 characters in length.
Analyze the conversation history provided to you and use it as context to generate relevant and engaging follow-up questions. Your predictions should be logical extensions of the current topic or related areas that the user might be interested in exploring further.
Remember to maintain consistency in tone and style with the existing conversation while providing diverse options for the user to choose from. Your goal is to keep the conversation flowing naturally and help the user delve deeper into the subject matter or explore related topics.`;
export const PROMPT_QUESTION_GUIDE_FOOTER = `Please strictly follow the format rules: \nReturn questions in JSON format: ['Question 1', 'Question 2', 'Question 3']. Your output: `;
import { PROMPT_QUESTION_GUIDE } from '../ai/prompt/agent';
import { import {
AppTTSConfigType, AppTTSConfigType,
AppFileSelectConfigType, AppFileSelectConfigType,
AppWhisperConfigType, AppWhisperConfigType,
AppAutoExecuteConfigType AppAutoExecuteConfigType,
AppQGConfigType
} from './type'; } from './type';
export enum AppTypeEnum { export enum AppTypeEnum {
...@@ -28,6 +30,12 @@ export const defaultWhisperConfig: AppWhisperConfigType = { ...@@ -28,6 +30,12 @@ export const defaultWhisperConfig: AppWhisperConfigType = {
autoTTSResponse: false autoTTSResponse: false
}; };
export const defaultQGConfig: AppQGConfigType = {
open: false,
model: 'gpt-4o-mini',
customPrompt: PROMPT_QUESTION_GUIDE
};
export const defaultChatInputGuideConfig = { export const defaultChatInputGuideConfig = {
open: false, open: false,
textList: [], textList: [],
......
...@@ -97,7 +97,7 @@ export type AppChatConfigType = { ...@@ -97,7 +97,7 @@ export type AppChatConfigType = {
welcomeText?: string; welcomeText?: string;
variables?: VariableItemType[]; variables?: VariableItemType[];
autoExecute?: AppAutoExecuteConfigType; autoExecute?: AppAutoExecuteConfigType;
questionGuide?: boolean; questionGuide?: AppQGConfigType;
ttsConfig?: AppTTSConfigType; ttsConfig?: AppTTSConfigType;
whisperConfig?: AppWhisperConfigType; whisperConfig?: AppWhisperConfigType;
scheduledTriggerConfig?: AppScheduledTriggerConfigType; scheduledTriggerConfig?: AppScheduledTriggerConfigType;
...@@ -148,6 +148,14 @@ export type AppWhisperConfigType = { ...@@ -148,6 +148,14 @@ export type AppWhisperConfigType = {
autoSend: boolean; autoSend: boolean;
autoTTSResponse: boolean; autoTTSResponse: boolean;
}; };
// question guide
export type AppQGConfigType = {
open: boolean;
model?: string;
customPrompt?: string;
};
// question guide text // question guide text
export type ChatInputGuideConfigType = { export type ChatInputGuideConfigType = {
open: boolean; open: boolean;
......
...@@ -26,12 +26,14 @@ import type { ...@@ -26,12 +26,14 @@ import type {
AppScheduledTriggerConfigType, AppScheduledTriggerConfigType,
ChatInputGuideConfigType, ChatInputGuideConfigType,
AppChatConfigType, AppChatConfigType,
AppAutoExecuteConfigType AppAutoExecuteConfigType,
AppQGConfigType
} from '../app/type'; } from '../app/type';
import { EditorVariablePickerType } from '../../../web/components/common/Textarea/PromptEditor/type'; import { EditorVariablePickerType } from '../../../web/components/common/Textarea/PromptEditor/type';
import { import {
defaultAutoExecuteConfig, defaultAutoExecuteConfig,
defaultChatInputGuideConfig, defaultChatInputGuideConfig,
defaultQGConfig,
defaultTTSConfig, defaultTTSConfig,
defaultWhisperConfig defaultWhisperConfig
} from '../app/constants'; } from '../app/constants';
...@@ -76,9 +78,14 @@ export const splitGuideModule = (guideModules?: StoreNodeItemType) => { ...@@ -76,9 +78,14 @@ export const splitGuideModule = (guideModules?: StoreNodeItemType) => {
const variables: VariableItemType[] = const variables: VariableItemType[] =
guideModules?.inputs.find((item) => item.key === NodeInputKeyEnum.variables)?.value ?? []; guideModules?.inputs.find((item) => item.key === NodeInputKeyEnum.variables)?.value ?? [];
const questionGuide: boolean = // Adapt old version
!!guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.questionGuide)?.value ?? const questionGuideVal = guideModules?.inputs?.find(
false; (item) => item.key === NodeInputKeyEnum.questionGuide
)?.value;
const questionGuide: AppQGConfigType =
typeof questionGuideVal === 'boolean'
? { ...defaultQGConfig, open: questionGuideVal }
: questionGuideVal ?? defaultQGConfig;
const ttsConfig: AppTTSConfigType = const ttsConfig: AppTTSConfigType =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.tts)?.value ?? guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.tts)?.value ??
......
...@@ -439,7 +439,9 @@ ...@@ -439,7 +439,9 @@
} }
], ],
"chatConfig": { "chatConfig": {
"questionGuide": false, "questionGuide": {
"open": false
},
"ttsConfig": { "ttsConfig": {
"type": "web" "type": "web"
}, },
......
...@@ -489,7 +489,9 @@ ...@@ -489,7 +489,9 @@
"chatConfig": { "chatConfig": {
"welcomeText": "", "welcomeText": "",
"variables": [], "variables": [],
"questionGuide": false, "questionGuide": {
"open": false
},
"ttsConfig": { "ttsConfig": {
"type": "web" "type": "web"
}, },
......
...@@ -666,7 +666,9 @@ ...@@ -666,7 +666,9 @@
"chatConfig": { "chatConfig": {
"welcomeText": "", "welcomeText": "",
"variables": [], "variables": [],
"questionGuide": false, "questionGuide": {
"open": false
},
"ttsConfig": { "ttsConfig": {
"type": "web" "type": "web"
}, },
......
...@@ -502,7 +502,9 @@ ...@@ -502,7 +502,9 @@
"chatConfig": { "chatConfig": {
"welcomeText": "", "welcomeText": "",
"variables": [], "variables": [],
"questionGuide": false, "questionGuide": {
"open": false
},
"ttsConfig": { "ttsConfig": {
"type": "web" "type": "web"
}, },
......
...@@ -538,7 +538,9 @@ ...@@ -538,7 +538,9 @@
"chatConfig": { "chatConfig": {
"welcomeText": "", "welcomeText": "",
"variables": [], "variables": [],
"questionGuide": false, "questionGuide": {
"open": false
},
"ttsConfig": { "ttsConfig": {
"type": "web" "type": "web"
}, },
......
...@@ -320,7 +320,9 @@ ...@@ -320,7 +320,9 @@
"chatConfig": { "chatConfig": {
"welcomeText": "", "welcomeText": "",
"variables": [], "variables": [],
"questionGuide": false, "questionGuide": {
"open": false
},
"ttsConfig": { "ttsConfig": {
"type": "web" "type": "web"
}, },
......
...@@ -3,29 +3,30 @@ import { createChatCompletion } from '../config'; ...@@ -3,29 +3,30 @@ import { createChatCompletion } from '../config';
import { countGptMessagesTokens } from '../../../common/string/tiktoken/index'; import { countGptMessagesTokens } from '../../../common/string/tiktoken/index';
import { loadRequestMessages } from '../../chat/utils'; import { loadRequestMessages } from '../../chat/utils';
import { llmCompletionsBodyFormat } from '../utils'; import { llmCompletionsBodyFormat } from '../utils';
import {
export const Prompt_QuestionGuide = `You are an AI assistant tasked with predicting the user's next question based on the conversation history. Your goal is to generate 3 potential questions that will guide the user to continue the conversation. When generating these questions, adhere to the following rules: PROMPT_QUESTION_GUIDE,
PROMPT_QUESTION_GUIDE_FOOTER
1. Use the same language as the user's last question in the conversation history. } from '@fastgpt/global/core/ai/prompt/agent';
2. Keep each question under 20 characters in length. import { addLog } from '../../../common/system/log';
3. Return the questions in JSON format: ["question1", "question2", "question3"]. import json5 from 'json5';
Analyze the conversation history provided to you and use it as context to generate relevant and engaging follow-up questions. Your predictions should be logical extensions of the current topic or related areas that the user might be interested in exploring further.
Remember to maintain consistency in tone and style with the existing conversation while providing diverse options for the user to choose from. Your goal is to keep the conversation flowing naturally and help the user delve deeper into the subject matter or explore related topics.`;
export async function createQuestionGuide({ export async function createQuestionGuide({
messages, messages,
model model,
customPrompt
}: { }: {
messages: ChatCompletionMessageParam[]; messages: ChatCompletionMessageParam[];
model: string; model: string;
}) { customPrompt?: string;
}): Promise<{
result: string[];
tokens: number;
}> {
const concatMessages: ChatCompletionMessageParam[] = [ const concatMessages: ChatCompletionMessageParam[] = [
...messages, ...messages,
{ {
role: 'user', role: 'user',
content: Prompt_QuestionGuide content: `${customPrompt || PROMPT_QUESTION_GUIDE}\n${PROMPT_QUESTION_GUIDE_FOOTER}`
} }
]; ];
...@@ -53,6 +54,7 @@ export async function createQuestionGuide({ ...@@ -53,6 +54,7 @@ export async function createQuestionGuide({
const tokens = await countGptMessagesTokens(concatMessages); const tokens = await countGptMessagesTokens(concatMessages);
if (start === -1 || end === -1) { if (start === -1 || end === -1) {
addLog.warn('Create question guide error', { answer });
return { return {
result: [], result: [],
tokens: 0 tokens: 0
...@@ -66,10 +68,12 @@ export async function createQuestionGuide({ ...@@ -66,10 +68,12 @@ export async function createQuestionGuide({
try { try {
return { return {
result: JSON.parse(jsonStr), result: json5.parse(jsonStr),
tokens tokens
}; };
} catch (error) { } catch (error) {
console.log(error);
return { return {
result: [], result: [],
tokens: 0 tokens: 0
......
...@@ -11,7 +11,7 @@ export const AppCollectionName = 'apps'; ...@@ -11,7 +11,7 @@ export const AppCollectionName = 'apps';
export const chatConfigType = { export const chatConfigType = {
welcomeText: String, welcomeText: String,
variables: Array, variables: Array,
questionGuide: Boolean, questionGuide: Object,
ttsConfig: Object, ttsConfig: Object,
whisperConfig: Object, whisperConfig: Object,
scheduledTriggerConfig: Object, scheduledTriggerConfig: Object,
......
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1698504394130" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4081" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M928 448h-64a19.2 19.2 0 0 1 0-38.4h64a19.2 19.2 0 0 1 0 38.4zM797.1072 738.4064l-45.2608-45.2608a19.2 19.2 0 0 1 27.1488-27.1488l45.3248 45.2608a19.2 19.2 0 0 1-27.2128 27.1488zM779.008 204.4032a19.2 19.2 0 0 1-27.1488-27.1488l45.2608-45.2608a19.2 19.2 0 0 1 27.2 27.1488z m-121.216 472.0128a282.368 282.368 0 0 0-17.2032 77.5808v20.8A37.7856 37.7856 0 0 1 614.4 810.6752V819.2H409.6v-8.5248a37.7856 37.7856 0 0 1-26.1888-35.84v-23.9488a290.0352 290.0352 0 0 0-16.9344-74.24A279.04 279.04 0 0 1 243.2 443.5968C243.2 290.56 363.52 166.4 512 166.4s268.8 124.16 268.8 277.1968a279.04 279.04 0 0 1-123.008 232.8192zM505.6 691.2a19.2 19.2 0 1 0-19.2-19.2 19.2 19.2 0 0 0 19.2 19.2z m6.4-358.4a115.2 115.2 0 0 0-114.4448 102.4h6.5024a17.728 17.728 0 1 0 20.9024 0h8.6656A79.8848 79.8848 0 0 1 512 368.64a77.7216 77.7216 0 0 1 76.8 79.36c0.8064 45.6064-64 76.8-64 76.8a97.4976 97.4976 0 0 0-34.432 46.4768 18.7392 18.7392 0 0 0-3.968 11.1232v7.68a56.6784 56.6784 0 0 0 0 11.52v6.4a19.2 19.2 0 0 0 38.4 0v-14.4768a18.6496 18.6496 0 0 1 0.384-4.6336C533.3632 557.9904 588.8 524.8 588.8 524.8c36.2368-23.296 38.4-76.8 38.4-76.8a115.2 115.2 0 0 0-115.2-115.2z m6.4-230.4A19.2 19.2 0 0 1 499.2 83.2v-64a19.2 19.2 0 1 1 38.4 0v64A19.2 19.2 0 0 1 518.4 102.4z m-264.3456 92.9536l-45.2608-45.2608A19.2 19.2 0 1 1 235.9424 122.88l45.2608 45.248a19.2 19.2 0 0 1-27.1488 27.2256zM160 448h-64a19.2 19.2 0 0 1 0-38.4h64a19.2 19.2 0 0 1 0 38.4z m94.0544 227.0464a19.2 19.2 0 0 1 27.1488 27.1488L235.9424 747.52a19.2 19.2 0 0 1-27.1488-27.1488zM652.8 846.9376a8.384 8.384 0 0 1 0.384 1.9072V870.4a8.4096 8.4096 0 0 1-0.384 1.9072V883.2H371.2v-51.2h281.6v14.9376zM627.2 947.2H396.8v-51.2h230.4v51.2z m-183.6672 23.9104H579.84a8.5248 8.5248 0 0 1 4.8896 1.6896H601.6v38.4H422.4v-38.4h16.2432a8.5248 8.5248 0 0 1 4.8896-1.6896z" fill="#1296db" p-id="4082"></path></svg> <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
\ No newline at end of file <path d="M9.13063 2.05868C9.13063 1.57855 9.51985 1.18933 9.99998 1.18933C10.4801 1.18933 10.8693 1.57855 10.8693 2.05868V3.21982C10.8693 3.69994 10.4801 4.08916 9.99998 4.08916C9.51985 4.08916 9.13063 3.69994 9.13063 3.21982V2.05868Z" fill="#219BF4"/>
<path d="M3.38076 9.1859C3.86089 9.1859 4.25011 9.57512 4.25011 10.0552C4.25011 10.5354 3.86089 10.9246 3.38076 10.9246H2.22333C1.74321 10.9246 1.35399 10.5354 1.35399 10.0552C1.35399 9.57512 1.74321 9.1859 2.22333 9.1859H3.38076Z" fill="#219BF4"/>
<path d="M17.7767 9.1859C18.2568 9.1859 18.646 9.57512 18.646 10.0552C18.646 10.5354 18.2568 10.9246 17.7767 10.9246H16.6144C16.1342 10.9246 15.745 10.5354 15.745 10.0552C15.745 9.57512 16.1342 9.1859 16.6144 9.1859H17.7767Z" fill="#219BF4"/>
<path d="M11.9605 15.5135C12.3425 15.5135 12.6522 15.8231 12.6522 16.2051C12.6522 16.5871 12.3425 16.8968 11.9605 16.8968H8.01907C7.63707 16.8968 7.3274 16.5871 7.3274 16.2051C7.3274 15.8231 7.63707 15.5135 8.01907 15.5135H11.9605Z" fill="#219BF4"/>
<path d="M10.9742 17.5941C11.3102 17.5941 11.5825 17.8664 11.5825 18.2024C11.5825 18.5384 11.3102 18.8107 10.9742 18.8107H9.00533C8.66936 18.8107 8.397 18.5384 8.397 18.2024C8.397 17.8664 8.66936 17.5941 9.00533 17.5941H10.9742Z" fill="#219BF4"/>
<path d="M14.8373 9.83534C14.8373 12.5069 12.6715 14.6726 10 14.6726C7.32845 14.6726 5.16274 12.5069 5.16274 9.83534C5.16274 7.16379 7.32845 4.99808 10 4.99808C12.6715 4.99808 14.8373 7.16379 14.8373 9.83534Z" fill="#219BF4"/>
<path d="M15.3181 5.79775C14.9786 6.13725 14.4282 6.13725 14.0887 5.79775C13.7492 5.45825 13.7492 4.90781 14.0887 4.56831L14.9091 3.7479C15.2486 3.4084 15.799 3.4084 16.1385 3.7479C16.478 4.0874 16.478 4.63784 16.1385 4.97734L15.3181 5.79775Z" fill="#219BF4"/>
<path d="M4.68184 5.80161C5.02134 6.14111 5.57178 6.14111 5.91128 5.80161C6.25078 5.46211 6.25078 4.91167 5.91128 4.57217L5.09091 3.7518C4.75141 3.4123 4.20097 3.4123 3.86147 3.7518C3.52197 4.0913 3.52197 4.64174 3.86147 4.98124L4.68184 5.80161Z" fill="#219BF4"/>
</svg>
import {
Box,
Button,
Flex,
Textarea,
ModalFooter,
HStack,
Icon,
ModalBody
} from '@chakra-ui/react';
import MyIcon from '../../Icon/index';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'next-i18next';
import MyModal from '../../MyModal';
const CustomLightTip = () => {
const { t } = useTranslation();
return (
<HStack px="3" py="2" bgColor="primary.50" borderRadius="md" fontSize={'sm'}>
<Icon name="common/info" w="1rem" color={'primary.600'} />
<Box color="primary.600">
{t('common:core.app.QG.Custom prompt tip1')}
<Box as="span" color={'yellow.500'} fontWeight="500" display="inline">
{t('common:core.app.QG.Custom prompt tip2')}
</Box>
{t('common:core.app.QG.Custom prompt tip3')}
</Box>
</HStack>
);
};
const FixBox = ({ children }: { children: React.ReactNode }) => {
return (
<Box>
<Box
bg="yellow.100"
as="span" // 改为 inline 元素
display="inline" // 确保是行内显示
>
{children}
</Box>
</Box>
);
};
const CustomPromptEditor = ({
defaultValue = '',
defaultPrompt,
footerPrompt,
onChange,
onClose
}: {
defaultValue?: string;
defaultPrompt: string;
footerPrompt?: string;
onChange: (e: string) => void;
onClose: () => void;
}) => {
const ref = useRef<HTMLTextAreaElement>(null);
const { t } = useTranslation();
const [value, setValue] = useState(defaultValue || defaultPrompt);
const adjustHeight = useCallback(() => {
const textarea = ref.current;
if (!textarea) return;
textarea.style.height = '22px';
textarea.style.height = `${textarea.scrollHeight}px`;
}, []);
useEffect(() => {
adjustHeight();
const timer = setTimeout(adjustHeight, 0);
return () => clearTimeout(timer);
}, [value, adjustHeight]);
return (
<MyModal
isOpen
onClose={onClose}
iconSrc="modal/edit"
title={t('app:core.dataset.import.Custom prompt')}
w={'100%'}
h={'85vh'}
isCentered
>
<ModalBody flex={'1 0 0'} display={'flex'} flexDirection={'column'}>
<CustomLightTip />
<HStack my={3} justifyContent={'space-between'}>
<Box fontWeight={'bold'} color={'myGray.600'}>
{t('common:core.ai.Prompt')}
</Box>
<Button
variant={'grayGhost'}
size={'sm'}
leftIcon={<MyIcon name={'common/retryLight'} w={'14px'} />}
px={2}
onClick={() => setValue(defaultPrompt)}
>
{t('common:common.Reset')}
</Button>
</HStack>
<Box
flex={'1 0 0'}
overflow={'auto'}
border="1px solid"
borderColor="borderColor.base"
borderRadius="md"
bg={'myGray.50'}
whiteSpace="pre-wrap"
fontSize="sm"
p={3}
>
<Textarea
ref={ref}
value={value}
placeholder={t('common:prompt_input_placeholder')}
onChange={(e) => setValue(e.target.value)}
resize="none"
bg="transparent"
border="none"
p={0}
mb={2}
_focus={{
border: 'none',
boxShadow: 'none'
}}
/>
{footerPrompt && <FixBox>{footerPrompt}</FixBox>}
</Box>
</ModalBody>
<ModalFooter>
<Flex gap={3}>
<Button variant={'whiteBase'} fontWeight={'medium'} onClick={onClose} w={20}>
{t('common:common.Close')}
</Button>
<Button
fontWeight={'medium'}
onClick={() => {
onChange(value.replace(defaultValue, ''));
onClose();
}}
w={20}
>
{t('common:common.Confirm')}
</Button>
</Flex>
</ModalFooter>
</MyModal>
);
};
export default CustomPromptEditor;
...@@ -22,10 +22,13 @@ ...@@ -22,10 +22,13 @@
"chat_logs": "Conversation Logs", "chat_logs": "Conversation Logs",
"chat_logs_tips": "Logs will record the online, shared, and API (requires chatId) conversation records of this app.", "chat_logs_tips": "Logs will record the online, shared, and API (requires chatId) conversation records of this app.",
"config_file_upload": "Click to Configure File Upload Rules", "config_file_upload": "Click to Configure File Upload Rules",
"config_question_guide": "Configuration guess you want to ask",
"confirm_copy_app_tip": "The system will create an app with the same configuration for you, but permissions will not be copied. Please confirm!", "confirm_copy_app_tip": "The system will create an app with the same configuration for you, but permissions will not be copied. Please confirm!",
"confirm_del_app_tip": "Are you sure you want to delete 【{{name}}】 and all of its chat history?", "confirm_del_app_tip": "Are you sure you want to delete 【{{name}}】 and all of its chat history?",
"confirm_delete_folder_tip": "Confirm to delete this folder? All apps and corresponding conversation records under it will be deleted. Please confirm!", "confirm_delete_folder_tip": "Confirm to delete this folder? All apps and corresponding conversation records under it will be deleted. Please confirm!",
"copy_one_app": "Create Duplicate", "copy_one_app": "Create Duplicate",
"core.app.QG.Switch": "Enable guess what you want to ask",
"core.dataset.import.Custom prompt": "Custom Prompt",
"create_copy_success": "Duplicate Created Successfully", "create_copy_success": "Duplicate Created Successfully",
"create_empty_app": "Create Default App", "create_empty_app": "Create Default App",
"create_empty_plugin": "Create Default Plugin", "create_empty_plugin": "Create Default Plugin",
...@@ -94,6 +97,7 @@ ...@@ -94,6 +97,7 @@
"plugin_dispatch_tip": "Adds extra capabilities to the model. The specific plugins to be invoked will be autonomously decided by the model.\nIf a plugin is selected, the Dataset invocation will automatically be treated as a special plugin.", "plugin_dispatch_tip": "Adds extra capabilities to the model. The specific plugins to be invoked will be autonomously decided by the model.\nIf a plugin is selected, the Dataset invocation will automatically be treated as a special plugin.",
"publish_channel": "Publish Channel", "publish_channel": "Publish Channel",
"publish_success": "Publish Successful", "publish_success": "Publish Successful",
"question_guide_tip": "After the conversation, 3 guiding questions will be generated for you.",
"saved_success": "Save Successful", "saved_success": "Save Successful",
"search_app": "Search Application", "search_app": "Search Application",
"setting_app": "Application Settings", "setting_app": "Application Settings",
......
...@@ -168,6 +168,7 @@ ...@@ -168,6 +168,7 @@
"common.Rename": "Rename", "common.Rename": "Rename",
"common.Request Error": "Request Error", "common.Request Error": "Request Error",
"common.Require Input": "Required", "common.Require Input": "Required",
"common.Reset": "Reset",
"common.Restart": "Restart", "common.Restart": "Restart",
"common.Role": "Permission", "common.Role": "Permission",
"common.Root folder": "Root Folder", "common.Root folder": "Root Folder",
...@@ -289,8 +290,12 @@ ...@@ -289,8 +290,12 @@
"core.app.Publish": "Publish", "core.app.Publish": "Publish",
"core.app.Publish Confirm": "Confirm to Publish App? This Will Immediately Update the App Status on All Publishing Channels.", "core.app.Publish Confirm": "Confirm to Publish App? This Will Immediately Update the App Status on All Publishing Channels.",
"core.app.Publish app tip": "After Publishing the App, All Publishing Channels Will Immediately Use This Version", "core.app.Publish app tip": "After Publishing the App, All Publishing Channels Will Immediately Use This Version",
"core.app.QG.Custom prompt tip": "To ensure the generated content follows the correct format, [Yellow Prompt] cannot be modified",
"core.app.QG.Custom prompt tip1": "To ensure the generated content follows the correct format, ",
"core.app.QG.Custom prompt tip2": "[Yellow Prompt]",
"core.app.QG.Custom prompt tip3": " cannot be modified",
"core.app.QG.Fixed Prompt": "Please strictly follow the format rules: \nReturn questions in JSON format: ['Question 1', 'Question 2', 'Question 3'].",
"core.app.Question Guide": "Guess What You Want to Ask", "core.app.Question Guide": "Guess What You Want to Ask",
"core.app.Question Guide Tip": "After the conversation ends, 3 guiding questions will be generated.",
"core.app.Quote prompt": "Quote Template Prompt", "core.app.Quote prompt": "Quote Template Prompt",
"core.app.Quote templates": "Quote Content Templates", "core.app.Quote templates": "Quote Content Templates",
"core.app.Random": "Divergent", "core.app.Random": "Divergent",
...@@ -967,6 +972,7 @@ ...@@ -967,6 +972,7 @@
"plugin.contribute": "Contribute Plugin", "plugin.contribute": "Contribute Plugin",
"plugin.go to laf": "Go to Write", "plugin.go to laf": "Go to Write",
"plugin.path": "Path", "plugin.path": "Path",
"prompt_input_placeholder": "Please enter the prompt word",
"required": "Required", "required": "Required",
"resume_failed": "Resume Failed", "resume_failed": "Resume Failed",
"select_reference_variable": "Select Reference Variable", "select_reference_variable": "Select Reference Variable",
...@@ -1139,6 +1145,7 @@ ...@@ -1139,6 +1145,7 @@
"textarea_variable_picker_tip": "Enter \"/\" to select a variable", "textarea_variable_picker_tip": "Enter \"/\" to select a variable",
"unit.character": "Character", "unit.character": "Character",
"unit.minute": "Minute", "unit.minute": "Minute",
"unit.seconds": "Second",
"unusable_variable": "No Usable Variables", "unusable_variable": "No Usable Variables",
"upload_file_error": "File Upload Failed", "upload_file_error": "File Upload Failed",
"user.Account": "Account", "user.Account": "Account",
......
...@@ -22,10 +22,13 @@ ...@@ -22,10 +22,13 @@
"chat_logs": "对话日志", "chat_logs": "对话日志",
"chat_logs_tips": "日志会记录该应用的在线、分享和 API(需填写 chatId)对话记录", "chat_logs_tips": "日志会记录该应用的在线、分享和 API(需填写 chatId)对话记录",
"config_file_upload": "点击配置文件上传规则", "config_file_upload": "点击配置文件上传规则",
"config_question_guide": "配置猜你想问",
"confirm_copy_app_tip": "系统将为您创建一个相同配置应用,但权限不会进行复制,请确认!", "confirm_copy_app_tip": "系统将为您创建一个相同配置应用,但权限不会进行复制,请确认!",
"confirm_del_app_tip": "确认删除 【{{name}}】 及其所有聊天记录?", "confirm_del_app_tip": "确认删除 【{{name}}】 及其所有聊天记录?",
"confirm_delete_folder_tip": "确认删除该文件夹?将会删除它下面所有应用及对应的聊天记录,请确认!", "confirm_delete_folder_tip": "确认删除该文件夹?将会删除它下面所有应用及对应的聊天记录,请确认!",
"copy_one_app": "创建副本", "copy_one_app": "创建副本",
"core.app.QG.Switch": "启用猜你想问",
"core.dataset.import.Custom prompt": "自定义提示词",
"create_copy_success": "创建副本成功", "create_copy_success": "创建副本成功",
"create_empty_app": "创建空白应用", "create_empty_app": "创建空白应用",
"create_empty_plugin": "创建空白插件", "create_empty_plugin": "创建空白插件",
...@@ -94,6 +97,7 @@ ...@@ -94,6 +97,7 @@
"plugin_dispatch_tip": "给模型附加获取外部数据的能力,具体调用哪些插件,将由模型自主决定,所有插件都将以非流模式运行。\n若选择了插件,知识库调用将自动作为一个特殊的插件。", "plugin_dispatch_tip": "给模型附加获取外部数据的能力,具体调用哪些插件,将由模型自主决定,所有插件都将以非流模式运行。\n若选择了插件,知识库调用将自动作为一个特殊的插件。",
"publish_channel": "发布渠道", "publish_channel": "发布渠道",
"publish_success": "发布成功", "publish_success": "发布成功",
"question_guide_tip": "对话结束后,会为你生成 3 个引导性问题。",
"saved_success": "保存成功", "saved_success": "保存成功",
"search_app": "搜索应用", "search_app": "搜索应用",
"setting_app": "应用配置", "setting_app": "应用配置",
......
...@@ -168,6 +168,7 @@ ...@@ -168,6 +168,7 @@
"common.Rename": "重命名", "common.Rename": "重命名",
"common.Request Error": "请求异常", "common.Request Error": "请求异常",
"common.Require Input": "必填", "common.Require Input": "必填",
"common.Reset": "恢复默认",
"common.Restart": "重新开始", "common.Restart": "重新开始",
"common.Role": "权限", "common.Role": "权限",
"common.Root folder": "根目录", "common.Root folder": "根目录",
...@@ -288,8 +289,12 @@ ...@@ -288,8 +289,12 @@
"core.app.Publish": "发布", "core.app.Publish": "发布",
"core.app.Publish Confirm": "确认发布应用?会立即更新所有发布渠道的应用状态。", "core.app.Publish Confirm": "确认发布应用?会立即更新所有发布渠道的应用状态。",
"core.app.Publish app tip": "发布应用后,所有发布渠道将会立即使用该版本", "core.app.Publish app tip": "发布应用后,所有发布渠道将会立即使用该版本",
"core.app.QG.Custom prompt tip": "为保证生成的内容遵循正确格式,【黄色部分提示词】不允许修改",
"core.app.QG.Custom prompt tip1": "为保证生成的内容遵循正确格式,",
"core.app.QG.Custom prompt tip2": "【黄色部分提示词】",
"core.app.QG.Custom prompt tip3": "不允许修改",
"core.app.QG.Fixed Prompt": "请严格遵循格式规则:以 JSON 格式返回题目:\n['问题1','问题2','问题3']。",
"core.app.Question Guide": "猜你想问", "core.app.Question Guide": "猜你想问",
"core.app.Question Guide Tip": "对话结束后,会为生成 3 个引导性问题。",
"core.app.Quote prompt": "引用模板提示词", "core.app.Quote prompt": "引用模板提示词",
"core.app.Quote templates": "引用内容模板", "core.app.Quote templates": "引用内容模板",
"core.app.Random": "发散", "core.app.Random": "发散",
...@@ -966,6 +971,7 @@ ...@@ -966,6 +971,7 @@
"plugin.contribute": "贡献插件", "plugin.contribute": "贡献插件",
"plugin.go to laf": "去编写", "plugin.go to laf": "去编写",
"plugin.path": "路径", "plugin.path": "路径",
"prompt_input_placeholder": "请输入提示词",
"required": "必须", "required": "必须",
"resume_failed": "恢复失败", "resume_failed": "恢复失败",
"select_reference_variable": "选择引用变量", "select_reference_variable": "选择引用变量",
...@@ -1138,6 +1144,7 @@ ...@@ -1138,6 +1144,7 @@
"textarea_variable_picker_tip": "输入\"/\"可选择变量", "textarea_variable_picker_tip": "输入\"/\"可选择变量",
"unit.character": "字符", "unit.character": "字符",
"unit.minute": "分钟", "unit.minute": "分钟",
"unit.seconds": "秒",
"unusable_variable": "无可用变量", "unusable_variable": "无可用变量",
"upload_file_error": "上传文件失败", "upload_file_error": "上传文件失败",
"user.Account": "账号", "user.Account": "账号",
......
...@@ -22,10 +22,13 @@ ...@@ -22,10 +22,13 @@
"chat_logs": "對話紀錄", "chat_logs": "對話紀錄",
"chat_logs_tips": "紀錄會記錄此應用程式的線上、分享和 API(需填寫 chatId)對話紀錄", "chat_logs_tips": "紀錄會記錄此應用程式的線上、分享和 API(需填寫 chatId)對話紀錄",
"config_file_upload": "點選設定檔案上傳規則", "config_file_upload": "點選設定檔案上傳規則",
"config_question_guide": "配置猜你想問",
"confirm_copy_app_tip": "系統將為您建立一個相同設定的應用程式,但權限不會複製,請確認!", "confirm_copy_app_tip": "系統將為您建立一個相同設定的應用程式,但權限不會複製,請確認!",
"confirm_del_app_tip": "確認刪除【{{name}}】及其所有聊天紀錄?", "confirm_del_app_tip": "確認刪除【{{name}}】及其所有聊天紀錄?",
"confirm_delete_folder_tip": "確認刪除這個資料夾?將會刪除它底下所有應用程式及對應的對話紀錄,請確認!", "confirm_delete_folder_tip": "確認刪除這個資料夾?將會刪除它底下所有應用程式及對應的對話紀錄,請確認!",
"copy_one_app": "建立副本", "copy_one_app": "建立副本",
"core.app.QG.Switch": "啟用猜你想問",
"core.dataset.import.Custom prompt": "自訂提示詞",
"create_copy_success": "建立副本成功", "create_copy_success": "建立副本成功",
"create_empty_app": "建立空白應用程式", "create_empty_app": "建立空白應用程式",
"create_empty_plugin": "建立空白外掛", "create_empty_plugin": "建立空白外掛",
...@@ -94,6 +97,7 @@ ...@@ -94,6 +97,7 @@
"plugin_dispatch_tip": "賦予模型取得外部資料的能力,具體呼叫哪些外掛,將由模型自主決定,所有外掛都將以非串流模式執行。\n若選擇了外掛,知識庫呼叫將自動作為一個特殊的外掛。", "plugin_dispatch_tip": "賦予模型取得外部資料的能力,具體呼叫哪些外掛,將由模型自主決定,所有外掛都將以非串流模式執行。\n若選擇了外掛,知識庫呼叫將自動作為一個特殊的外掛。",
"publish_channel": "發布通道", "publish_channel": "發布通道",
"publish_success": "發布成功", "publish_success": "發布成功",
"question_guide_tip": "對話結束後,會為你產生 3 個引導性問題。",
"saved_success": "儲存成功", "saved_success": "儲存成功",
"search_app": "搜尋應用程式", "search_app": "搜尋應用程式",
"setting_app": "應用程式設定", "setting_app": "應用程式設定",
......
...@@ -168,6 +168,7 @@ ...@@ -168,6 +168,7 @@
"common.Rename": "重新命名", "common.Rename": "重新命名",
"common.Request Error": "請求錯誤", "common.Request Error": "請求錯誤",
"common.Require Input": "必填", "common.Require Input": "必填",
"common.Reset": "恢復預設",
"common.Restart": "重新開始", "common.Restart": "重新開始",
"common.Role": "權限", "common.Role": "權限",
"common.Root folder": "根目錄", "common.Root folder": "根目錄",
...@@ -289,8 +290,12 @@ ...@@ -289,8 +290,12 @@
"core.app.Publish": "發布", "core.app.Publish": "發布",
"core.app.Publish Confirm": "確認發布應用程式?這將立即更新所有發布管道的應用程式狀態。", "core.app.Publish Confirm": "確認發布應用程式?這將立即更新所有發布管道的應用程式狀態。",
"core.app.Publish app tip": "發布應用程式後,所有發布管道將立即使用此版本", "core.app.Publish app tip": "發布應用程式後,所有發布管道將立即使用此版本",
"core.app.QG.Custom prompt tip": "為確保生成的內容遵循正確格式,【黃色部分提示詞】不允許修改",
"core.app.QG.Custom prompt tip1": "為確保生成的內容遵循正確格式,",
"core.app.QG.Custom prompt tip2": "【黃色部分提示詞】",
"core.app.QG.Custom prompt tip3": "不允許修改",
"core.app.QG.Fixed Prompt": "請嚴格遵循格式規則:以 JSON 格式返回題目:\n['問題1','問題2','問題3']。",
"core.app.Question Guide": "猜你想問", "core.app.Question Guide": "猜你想問",
"core.app.Question Guide Tip": "對話結束後,系統會產生 3 個引導性問題。",
"core.app.Quote prompt": "引用範本提示詞", "core.app.Quote prompt": "引用範本提示詞",
"core.app.Quote templates": "引用內容範本", "core.app.Quote templates": "引用內容範本",
"core.app.Random": "發散", "core.app.Random": "發散",
...@@ -966,6 +971,7 @@ ...@@ -966,6 +971,7 @@
"plugin.contribute": "貢獻外掛程式", "plugin.contribute": "貢獻外掛程式",
"plugin.go to laf": "前往編寫", "plugin.go to laf": "前往編寫",
"plugin.path": "路徑", "plugin.path": "路徑",
"prompt_input_placeholder": "請輸入提示詞",
"required": "必填", "required": "必填",
"resume_failed": "恢復失敗", "resume_failed": "恢復失敗",
"select_reference_variable": "選擇引用變數", "select_reference_variable": "選擇引用變數",
...@@ -1138,6 +1144,7 @@ ...@@ -1138,6 +1144,7 @@
"textarea_variable_picker_tip": "輸入「/」以選擇變數", "textarea_variable_picker_tip": "輸入「/」以選擇變數",
"unit.character": "字元", "unit.character": "字元",
"unit.minute": "分鐘", "unit.minute": "分鐘",
"unit.seconds": "秒",
"unusable_variable": "無可用變數", "unusable_variable": "無可用變數",
"upload_file_error": "上傳檔案失敗", "upload_file_error": "上傳檔案失敗",
"user.Account": "帳戶", "user.Account": "帳戶",
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "any",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "any",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "any",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
...@@ -19,73 +19,7 @@ ...@@ -19,73 +19,7 @@
"y": -490.7611729549753 "y": -490.7611729549753
}, },
"version": "481", "version": "481",
"inputs": [ "inputs": [],
{
"key": "welcomeText",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "string",
"label": "core.app.Welcome Text",
"value": "你好,我可以为你翻译各种语言,请告诉我你需要翻译成什么语言?"
},
{
"key": "variables",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "any",
"label": "core.app.Chat Variable",
"value": [
{
"id": "myb3xk",
"key": "language",
"label": "目标语言",
"type": "select",
"required": true,
"maxLen": 50,
"enums": [
{
"value": "中文"
},
{
"value": "英文"
}
]
}
]
},
{
"key": "questionGuide",
"valueType": "boolean",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"label": "core.app.Question Guide",
"value": false
},
{
"key": "tts",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "any",
"label": "",
"value": {
"type": "web"
}
},
{
"key": "whisper",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "any",
"label": "",
"value": {
"open": false,
"autoSend": false,
"autoTTSResponse": false
}
},
{
"key": "scheduleTrigger",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "any",
"label": "",
"value": null
}
],
"outputs": [] "outputs": []
}, },
{ {
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "any",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "hidden",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "any",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "any",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
...@@ -18,56 +18,7 @@ ...@@ -18,56 +18,7 @@
"y": -486.7611729549753 "y": -486.7611729549753
}, },
"version": "481", "version": "481",
"inputs": [ "inputs": [],
{
"key": "welcomeText",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "string",
"label": "core.app.Welcome Text",
"value": "你好,我是知识库助手,请不要忘记选择知识库噢~\n[你是谁]\n[如何使用]"
},
{
"key": "variables",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "any",
"label": "core.app.Chat Variable",
"value": []
},
{
"key": "questionGuide",
"valueType": "boolean",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"label": "core.app.Question Guide",
"value": false
},
{
"key": "tts",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "any",
"label": "",
"value": {
"type": "web"
}
},
{
"key": "whisper",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "any",
"label": "",
"value": {
"open": false,
"autoSend": false,
"autoTTSResponse": false
}
},
{
"key": "scheduleTrigger",
"renderTypeList": ["FlowNodeInputTypeEnum.hidden"],
"valueType": "any",
"label": "",
"value": null
}
],
"outputs": [] "outputs": []
}, },
{ {
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "any",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
}, },
{ {
"key": "questionGuide", "key": "questionGuide",
"valueType": "boolean", "valueType": "any",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"label": "core.app.Question Guide", "label": "core.app.Question Guide",
"value": false "value": {
"open": false
}
}, },
{ {
"key": "tts", "key": "tts",
......
<svg viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="36" height="36" rx="6" fill="#FFF1F6"/> <rect width="36" height="36" rx="6" fill="#F0FBFF"/>
<path d="M16.9567 8.4704C16.9567 7.89425 17.4238 7.42719 17.9999 7.42719C18.5761 7.42719 19.0432 7.89425 19.0432 8.4704V9.86377C19.0432 10.4399 18.5761 10.907 17.9999 10.907C17.4238 10.907 16.9567 10.4399 16.9567 9.86377V8.4704Z" fill="#F9518E"/> <path d="M16.9568 8.4704C16.9568 7.89425 17.4238 7.42719 18 7.42719C18.5761 7.42719 19.0432 7.89425 19.0432 8.4704V9.86377C19.0432 10.4399 18.5761 10.907 18 10.907C17.4238 10.907 16.9568 10.4399 16.9568 9.86377V8.4704Z" fill="#219BF4"/>
<path d="M10.0569 17.0231C10.633 17.0231 11.1001 17.4901 11.1001 18.0663C11.1001 18.6424 10.633 19.1095 10.0569 19.1095H8.66797C8.09182 19.1095 7.62476 18.6424 7.62476 18.0663C7.62476 17.4901 8.09182 17.0231 8.66797 17.0231H10.0569Z" fill="#F9518E"/> <path d="M10.0569 17.0231C10.6331 17.0231 11.1001 17.4901 11.1001 18.0663C11.1001 18.6424 10.6331 19.1095 10.0569 19.1095H8.668C8.09185 19.1095 7.62479 18.6424 7.62479 18.0663C7.62479 17.4901 8.09185 17.0231 8.668 17.0231H10.0569Z" fill="#219BF4"/>
<path d="M27.332 17.0231C27.9081 17.0231 28.3752 17.4901 28.3752 18.0663C28.3752 18.6424 27.9081 19.1095 27.332 19.1095H25.9372C25.361 19.1095 24.894 18.6424 24.894 18.0663C24.894 17.4901 25.361 17.0231 25.9372 17.0231H27.332Z" fill="#F9518E"/> <path d="M27.332 17.0231C27.9082 17.0231 28.3752 17.4901 28.3752 18.0663C28.3752 18.6424 27.9082 19.1095 27.332 19.1095H25.9372C25.3611 19.1095 24.894 18.6424 24.894 18.0663C24.894 17.4901 25.3611 17.0231 25.9372 17.0231H27.332Z" fill="#219BF4"/>
<path d="M20.3526 24.6161C20.811 24.6161 21.1826 24.9878 21.1826 25.4461C21.1826 25.9045 20.811 26.2761 20.3526 26.2761H15.6229C15.1645 26.2761 14.7929 25.9045 14.7929 25.4461C14.7929 24.9878 15.1645 24.6161 15.6229 24.6161H20.3526Z" fill="#F9518E"/> <path d="M20.3526 24.6161C20.811 24.6161 21.1826 24.9878 21.1826 25.4461C21.1826 25.9045 20.811 26.2761 20.3526 26.2761H15.6229C15.1645 26.2761 14.7929 25.9045 14.7929 25.4461C14.7929 24.9878 15.1645 24.6161 15.6229 24.6161H20.3526Z" fill="#219BF4"/>
<path d="M19.169 27.1129C19.5722 27.1129 19.899 27.4397 19.899 27.8429C19.899 28.246 19.5722 28.5729 19.169 28.5729H16.8064C16.4032 28.5729 16.0764 28.246 16.0764 27.8429C16.0764 27.4397 16.4032 27.1129 16.8064 27.1129H19.169Z" fill="#F9518E"/> <path d="M19.169 27.1129C19.5722 27.1129 19.899 27.4397 19.899 27.8429C19.899 28.246 19.5722 28.5729 19.169 28.5729H16.8064C16.4032 28.5729 16.0764 28.246 16.0764 27.8429C16.0764 27.4397 16.4032 27.1129 16.8064 27.1129H19.169Z" fill="#219BF4"/>
<path d="M23.8047 17.8024C23.8047 21.0082 21.2058 23.6071 18 23.6071C14.7941 23.6071 12.1953 21.0082 12.1953 17.8024C12.1953 14.5965 14.7941 11.9977 18 11.9977C21.2058 11.9977 23.8047 14.5965 23.8047 17.8024Z" fill="#F9518E"/> <path d="M23.8047 17.8024C23.8047 21.0082 21.2058 23.6071 18 23.6071C14.7941 23.6071 12.1953 21.0082 12.1953 17.8024C12.1953 14.5965 14.7941 11.9977 18 11.9977C21.2058 11.9977 23.8047 14.5965 23.8047 17.8024Z" fill="#219BF4"/>
<path d="M24.3817 12.9573C23.9743 13.3647 23.3138 13.3647 22.9064 12.9573C22.499 12.5499 22.499 11.8894 22.9064 11.482L23.8909 10.4975C24.2983 10.0901 24.9588 10.0901 25.3662 10.4975C25.7736 10.9049 25.7736 11.5654 25.3662 11.9728L24.3817 12.9573Z" fill="#F9518E"/> <path d="M24.3817 12.9573C23.9743 13.3647 23.3138 13.3647 22.9064 12.9573C22.499 12.5499 22.499 11.8894 22.9064 11.482L23.8909 10.4975C24.2983 10.0901 24.9588 10.0901 25.3662 10.4975C25.7736 10.9049 25.7736 11.5654 25.3662 11.9728L24.3817 12.9573Z" fill="#219BF4"/>
<path d="M11.6182 12.9619C12.0256 13.3693 12.6861 13.3693 13.0935 12.9619C13.5009 12.5545 13.5009 11.894 13.0935 11.4866L12.1091 10.5022C11.7017 10.0948 11.0411 10.0948 10.6337 10.5022C10.2263 10.9096 10.2263 11.5701 10.6337 11.9775L11.6182 12.9619Z" fill="#F9518E"/> <path d="M11.6182 12.9619C12.0256 13.3693 12.6861 13.3693 13.0935 12.9619C13.5009 12.5545 13.5009 11.894 13.0935 11.4866L12.1091 10.5022C11.7017 10.0948 11.0412 10.0948 10.6338 10.5022C10.2264 10.9096 10.2264 11.5701 10.6338 11.9775L11.6182 12.9619Z" fill="#219BF4"/>
</svg> </svg>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_19_417)">
<path d="M8.69132 19.7708L8.43646 10.1106C7.92262 9.92227 9.99843 7.48009 10.8505 7.6956C13.3489 7.06769 16.0648 3.09118 11.1064 0.142151C-3.89673 0.142151 -2.25275 18.589 8.69132 19.7708Z" fill="#B3DDF2"/>
<path d="M8.64384 19.7663C4.17343 18.7386 -0.201612 12.4833 5.14972 6.86892C6.37883 5.78554 3.9237 2.58709 1.91253 4.3511C-3.43099 11.7411 3.5968 19.7863 8.64384 19.7663Z" fill="#0055E9"/>
<path d="M7.92307 10.4705C7.79974 10.5592 7.92307 10.4191 7.92307 10.4705V10.4705ZM7.92307 10.4705V11.2412C7.92307 11.344 7.77919 12.0274 7.71753 12.3203L8.48829 13.9646C8.48829 13.9646 9.00213 14.1187 9.05351 14.1701C9.1049 14.2215 9.35668 14.2575 9.46459 14.2729L10.5436 14.9409L12.3421 14.684L14.6544 13.9646L16.8125 12.1148L17.4805 10.9843L18.0457 8.1068L17.9429 6.77082V5.58898L16.7611 3.43086L16.1445 2.6601L15.0654 1.6838L14.1405 1.11858L13.8836 0.964424L13.5753 0.861657L13.0101 0.656121L11.2116 0.193665C15.1168 1.47826 15.4251 5.43483 14.2947 7.33604C13.1642 9.23725 10.715 10.3348 8.33414 10.1108L7.92307 10.4705Z" fill="#00BCFF"/>
<path d="M8.95026 19.7715C12.4444 20.6959 20.0974 17.3601 19.9978 10.2141C20.2549 7.02775 17.2808 0.68943 12.4444 0.451111C17.8362 1.54919 19.8961 11.4535 12.9079 13.9137C9.41293 14.7872 8.12863 12.1153 8.38607 10.2141C4.79042 10.3958 2.88305 18.1057 8.95026 19.7715Z" fill="#0055DF"/>
</g>
<defs>
<clipPath id="clip0_19_417">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>
<svg t="1719125004089" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2490" <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none">
width="200" height="200"> <path d="M8.33595 9.4104V14.8168C7.95355 16.6472 5.40635 16.1752 5.39515 14.8472C5.38315 13.1792 5.39515 11.5232 5.39515 9.8664V7.9472C5.39515 7.7072 5.34075 7.5176 5.11995 7.3664C4.69035 7.0608 4.17595 7.4208 4.16475 7.8624C4.14075 8.4544 4.15275 9.0344 4.14075 9.6192C4.14075 10.08 4.14075 10.5288 4.15275 10.9888C3.83515 13.0168 1.25835 12.68 1.19995 11.0008V9.596C1.19995 9.1352 2.14395 9.0272 2.09755 9.716C2.06715 10.0568 2.08635 10.4088 2.07435 10.7456C2.06315 11.3488 3.03035 11.7552 3.25835 10.7688C3.27035 9.956 3.27035 9.1432 3.27035 8.3224C3.27035 7.2936 3.57595 6.4576 4.71835 6.38C5.21355 6.3376 5.54235 6.5344 5.85915 6.876C5.97915 6.996 6.26555 7.3784 6.27755 7.796C6.27755 8.18 6.28875 8.5624 6.28875 8.9496C6.28875 9.716 6.27755 10.4856 6.27755 11.252C6.27755 11.748 6.28875 12.2392 6.28875 12.7232C6.28875 13.3384 6.28875 13.9616 6.27755 14.5768C6.26555 15.3776 7.28715 15.3664 7.45035 14.5648C7.45035 13.6208 7.46155 12.688 7.46155 11.744C7.46155 9.4176 7.45035 7.092 7.45035 4.7664C7.45035 4.5264 7.41515 3.8568 7.55035 3.6128C8.26235 1.9568 10.4264 2.68 10.4456 4.0504C10.488 6.86 10.4456 9.7008 10.4568 12.5176C10.4568 13.4936 9.62475 13.284 9.57835 12.9016C9.57835 9.9712 9.57835 7.0296 9.59035 4.104C9.54795 3.3688 8.40635 3.4696 8.33995 3.996C8.31675 4.6 8.32875 5.2152 8.31675 5.8184V9.4064H8.32875L8.33675 9.4104H8.33595Z" fill="#D4367A"/>
<path <path d="M11.68 9.36721V13.3376V3.96801C12.052 2.12561 14.5984 2.60561 14.6096 3.93361C14.6216 5.58961 14.6096 7.25761 14.6216 8.91361C14.6216 9.54881 14.6216 10.1872 14.6096 10.8216C14.6096 11.0736 14.6752 11.2512 14.896 11.4136C15.3144 11.712 15.8288 11.36 15.852 10.9112C15.8752 10.3304 15.8632 9.74961 15.8632 9.15361V7.79201C16.1808 5.76401 18.7512 6.10081 18.8048 7.78001V12.8688C18.8048 13.3296 17.872 13.4384 17.9144 12.7488C17.9384 12.3968 17.9144 8.37281 17.9264 8.02001C17.9496 7.42801 16.9704 7.00961 16.7424 8.00801V10.4424C16.7424 11.484 16.436 12.308 15.2832 12.3968C14.1952 12.4208 13.7584 11.704 13.7232 10.9808V6.06161C13.7232 5.43441 13.7232 4.82321 13.7352 4.20801C13.7464 3.40721 12.7248 3.40721 12.5512 4.22001V15.2336C12.5512 15.4736 12.5856 16.1432 12.4616 16.3872C11.7496 18.0432 9.57518 17.32 9.55518 15.9496V14.6456C9.60958 13.7672 10.3872 13.976 10.4224 14.3472V15.8952C10.4648 16.6312 11.6064 16.5416 11.6608 16.004C11.684 15.4 11.684 14.796 11.684 14.1808V9.36801H11.68V9.36721Z" fill="#ED6D48"/>
d="M415.185455 477.696v314.554182c-22.248727 106.496-170.449455 79.034182-171.101091 1.768727-0.698182-97.047273 0-193.396364 0-289.792V392.564364c0-13.963636-3.165091-24.994909-16.011637-33.792-24.994909-17.780364-54.923636 3.165091-55.575272 28.858181-1.396364 34.443636-0.698182 68.189091-1.396364 102.213819 0 26.810182 0 52.922182 0.698182 79.685818C153.320727 687.522909 3.397818 667.927273 0 570.228364v-81.733819c0-26.810182 54.923636-33.093818 52.224 6.981819-1.768727 19.828364-0.651636 40.308364-1.349818 59.904-0.651636 35.095273 55.621818 58.740364 68.887273 1.349818 0.698182-47.290182 0.698182-94.580364 0.698181-142.336 0-59.857455 17.780364-108.497455 84.247273-113.012364 28.811636-2.466909 47.941818 8.983273 66.373818 28.858182 6.981818 6.981818 23.645091 29.230545 24.343273 53.527273 0 22.341818 0.651636 44.590545 0.651636 67.118545 0 44.590545-0.651636 89.367273-0.651636 133.957818 0 28.858182 0.651636 57.437091 0.651636 85.597091 0 35.793455 0 72.052364-0.651636 107.845818-0.698182 46.592 58.740364 45.940364 68.235636-0.698181 0-54.923636 0.651636-109.195636 0.651637-164.119273 0-135.354182-0.651636-270.661818-0.651637-405.969455 0-13.963636-2.048-52.922182 5.818182-67.118545 41.425455-96.349091 167.330909-54.272 168.448 25.460364 2.466909 163.467636 0 328.750545 0.651637 492.63709 0 56.785455-48.407273 44.590545-51.10691 22.341819 0-170.496 0-341.643636 0.698182-511.860364-2.466909-42.775273-68.887273-36.910545-72.750545-6.283636-1.349818 35.141818-0.651636 70.935273-1.349818 106.030545v208.756364h0.698181l0.465455 0.232727z"
fill="#AE70FF" p-id="2491"></path>
<path
d="M609.745455 475.182545v231.005091V161.047273c21.643636-107.194182 169.797818-79.266909 170.449454-2.001455 0.698182 96.349091 0 193.396364 0.698182 289.745455 0 36.957091 0 74.100364-0.698182 111.010909 0 14.661818 3.816727 24.994909 16.663273 34.443636 24.343273 17.361455 54.272-3.118545 55.621818-29.230545 1.349818-33.792 0.651636-67.584 0.651636-102.260364V383.534545c18.478545-117.992727 168.029091-98.397091 171.147637-0.698181v296.075636c0 26.810182-54.272 33.140364-51.805091-6.981818 1.396364-20.48 0-254.603636 0.698182-275.130182 1.349818-34.443636-55.621818-58.786909-68.887273-0.698182v141.637818c0 60.602182-17.826909 108.544-84.898909 113.710546-63.301818 1.396364-88.715636-40.308364-90.763637-82.385455V282.856727c0-36.491636 0-72.052364 0.698182-107.845818 0.651636-46.592-58.786909-46.592-68.887272 0.698182v640.791273c0 13.963636 2.001455 52.922182-5.213091 67.118545-41.425455 96.349091-167.936 54.272-169.099637-25.460364v-75.86909c3.165091-51.106909 48.407273-38.958545 50.455273-17.361455v90.065455c2.466909 42.821818 68.887273 37.608727 72.052364 6.330181 1.349818-35.141818 1.349818-70.283636 1.349818-106.077091V475.229091H609.745455z"
fill="#AE70FF" p-id="2492"></path>
</svg> </svg>
\ No newline at end of file
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { Box, Button, Flex, ModalBody, useDisclosure, Switch, BoxProps } from '@chakra-ui/react';
import React from 'react';
import { useTranslation } from 'next-i18next';
import type { AppQGConfigType } from '@fastgpt/global/core/app/type.d';
import MyModal from '@fastgpt/web/components/common/MyModal';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import { defaultQGConfig } from '@fastgpt/global/core/app/constants';
import ChatFunctionTip from './Tip';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import AIModelSelector from '@/components/Select/AIModelSelector';
import CustomPromptEditor from '@fastgpt/web/components/common/Textarea/CustomPromptEditor';
import {
PROMPT_QUESTION_GUIDE,
PROMPT_QUESTION_GUIDE_FOOTER
} from '@fastgpt/global/core/ai/prompt/agent';
// question generator config
const QGConfig = ({
value = defaultQGConfig,
onChange
}: {
value?: AppQGConfigType;
onChange: (e: AppQGConfigType) => void;
}) => {
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
const isOpenQG = value.open;
const formLabel = isOpenQG
? t('common:core.app.whisper.Open')
: t('common:core.app.whisper.Close');
return (
<Flex alignItems={'center'}>
<MyIcon name={'core/chat/QGFill'} mr={2} w={'20px'} />
<FormLabel>{t('common:core.app.Question Guide')}</FormLabel>
<ChatFunctionTip type={'nextQuestion'} />
<Box flex={1} />
<MyTooltip label={t('app:config_question_guide')}>
<Button
variant={'transparentBase'}
size={'sm'}
mr={'-5px'}
color={'myGray.600'}
onClick={onOpen}
>
{formLabel}
</Button>
</MyTooltip>
{isOpen && <QGConfigModal value={value} onChange={onChange} onClose={onClose} />}
</Flex>
);
};
export default QGConfig;
const LabelStyles: BoxProps = {
display: 'flex',
alignItems: 'center',
fontSize: 'sm',
color: 'myGray.900',
width: ['6rem', '8rem']
};
const QGConfigModal = ({
value,
onClose,
onChange
}: {
value: AppQGConfigType;
onChange: (e: AppQGConfigType) => void;
onClose: () => void;
}) => {
const { t } = useTranslation();
const { llmModelList } = useSystemStore();
const customPrompt = value.customPrompt;
const isOpenQG = value.open;
const model = value?.model || llmModelList?.[0]?.model;
const {
isOpen: isOpenCustomPrompt,
onOpen: onOpenCustomPrompt,
onClose: onCloseCustomPrompt
} = useDisclosure();
return (
<>
<MyModal
title={t('common:core.chat.Question Guide')}
iconSrc="core/chat/QGFill"
isOpen
onClose={onClose}
width="500px"
>
<ModalBody px={[5, 10]} py={[4, 8]} pb={[4, 12]}>
<Flex justifyContent={'space-between'} alignItems={'center'}>
<FormLabel flex={'0 0 100px'}>{t('app:core.app.QG.Switch')}</FormLabel>
<Switch
isChecked={isOpenQG}
onChange={(e) => {
onChange({
...value,
open: e.target.checked
});
}}
/>
</Flex>
{isOpenQG && (
<>
<Flex alignItems={'center'} mt={4}>
<Box {...LabelStyles} mr={2}>
{t('common:core.ai.Model')}
</Box>
<Box flex={'1 0 0'}>
<AIModelSelector
width={'100%'}
value={model}
list={llmModelList.map((item) => ({
value: item.model,
label: item.name
}))}
onchange={(e) => {
onChange({
...value,
model: e
});
}}
/>
</Box>
</Flex>
<Box mt={4}>
<Flex alignItems={'center'} mb={1}>
<FormLabel>{t('app:core.dataset.import.Custom prompt')}</FormLabel>
<QuestionTip ml={1} label={t('common:core.app.QG.Custom prompt tip')} />
<Box flex={1} />
<Button
size="xs"
variant={'transparentBase'}
leftIcon={<MyIcon name={'edit'} w={'14px'} />}
onClick={onOpenCustomPrompt}
>
{t('common:common.Edit')}
</Button>
</Flex>
<Box
position={'relative'}
bg={'myGray.50'}
border={'1px'}
borderColor={'borderColor.base'}
borderRadius={'md'}
maxH={'200px'}
overflow={'auto'}
px={3}
py={2}
fontSize={'sm'}
textAlign={'justify'}
whiteSpace={'pre-wrap'}
_hover={{
'& .mask': {
display: 'block'
}
}}
>
{customPrompt || PROMPT_QUESTION_GUIDE}
</Box>
</Box>
</>
)}
</ModalBody>
</MyModal>
{isOpenCustomPrompt && (
<CustomPromptEditor
defaultValue={customPrompt}
defaultPrompt={PROMPT_QUESTION_GUIDE}
footerPrompt={PROMPT_QUESTION_GUIDE_FOOTER}
onChange={(e) => {
onChange({
...value,
customPrompt: e
});
}}
onClose={onCloseCustomPrompt}
/>
)}
</>
);
};
import MyIcon from '@fastgpt/web/components/common/Icon';
import { Box, Flex, Switch, type SwitchProps } from '@chakra-ui/react';
import React from 'react';
import { useTranslation } from 'next-i18next';
import ChatFunctionTip from './Tip';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
// question generator switch
const QGSwitch = (props: SwitchProps) => {
const { t } = useTranslation();
return (
<Flex alignItems={'center'}>
<MyIcon name={'core/chat/QGFill'} mr={2} w={'20px'} />
<FormLabel color={'myGray.600'}>{t('common:core.app.Question Guide')}</FormLabel>
<ChatFunctionTip type={'nextQuestion'} />
<Box flex={1} />
<Switch {...props} />
</Flex>
);
};
export default QGSwitch;
...@@ -29,7 +29,7 @@ const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => { ...@@ -29,7 +29,7 @@ const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => {
[FnTypeEnum.nextQuestion]: { [FnTypeEnum.nextQuestion]: {
icon: '/imgs/app/nextQuestion-icon.svg', icon: '/imgs/app/nextQuestion-icon.svg',
title: t('common:core.app.Question Guide'), title: t('common:core.app.Question Guide'),
desc: t('common:core.app.Question Guide Tip'), desc: t('app:question_guide_tip'),
imgUrl: '/imgs/app/nextQuestion.svg' imgUrl: '/imgs/app/nextQuestion.svg'
}, },
[FnTypeEnum.tts]: { [FnTypeEnum.tts]: {
......
...@@ -2,8 +2,8 @@ import React, { useState, useMemo, useCallback } from 'react'; ...@@ -2,8 +2,8 @@ import React, { useState, useMemo, useCallback } from 'react';
import { useAudioPlay } from '@/web/common/utils/voice'; import { useAudioPlay } from '@/web/common/utils/voice';
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { import {
AppAutoExecuteConfigType,
AppFileSelectConfigType, AppFileSelectConfigType,
AppQGConfigType,
AppTTSConfigType, AppTTSConfigType,
AppWhisperConfigType, AppWhisperConfigType,
ChatInputGuideConfigType, ChatInputGuideConfigType,
...@@ -12,8 +12,8 @@ import { ...@@ -12,8 +12,8 @@ import {
import { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type'; import { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type';
import { import {
defaultAppSelectFileConfig, defaultAppSelectFileConfig,
defaultAutoExecuteConfig,
defaultChatInputGuideConfig, defaultChatInputGuideConfig,
defaultQGConfig,
defaultTTSConfig, defaultTTSConfig,
defaultWhisperConfig defaultWhisperConfig
} from '@fastgpt/global/core/app/constants'; } from '@fastgpt/global/core/app/constants';
...@@ -37,7 +37,7 @@ type useChatStoreType = ChatProviderProps & { ...@@ -37,7 +37,7 @@ type useChatStoreType = ChatProviderProps & {
welcomeText: string; welcomeText: string;
variableList: VariableItemType[]; variableList: VariableItemType[];
allVariableList: VariableItemType[]; allVariableList: VariableItemType[];
questionGuide: boolean; questionGuide: AppQGConfigType;
ttsConfig: AppTTSConfigType; ttsConfig: AppTTSConfigType;
whisperConfig: AppWhisperConfigType; whisperConfig: AppWhisperConfigType;
autoTTSResponse: boolean; autoTTSResponse: boolean;
...@@ -72,7 +72,11 @@ type useChatStoreType = ChatProviderProps & { ...@@ -72,7 +72,11 @@ type useChatStoreType = ChatProviderProps & {
export const ChatBoxContext = createContext<useChatStoreType>({ export const ChatBoxContext = createContext<useChatStoreType>({
welcomeText: '', welcomeText: '',
variableList: [], variableList: [],
questionGuide: false, questionGuide: {
open: false,
model: undefined,
customPrompt: undefined
},
ttsConfig: { ttsConfig: {
type: 'none', type: 'none',
model: undefined, model: undefined,
...@@ -143,10 +147,16 @@ const Provider = ({ ...@@ -143,10 +147,16 @@ const Provider = ({
ChatItemContext, ChatItemContext,
(v) => v.chatBoxData?.app?.chatConfig?.variables ?? [] (v) => v.chatBoxData?.app?.chatConfig?.variables ?? []
); );
const questionGuide = useContextSelector( const questionGuide = useContextSelector(ChatItemContext, (v) => {
ChatItemContext, const val = v.chatBoxData?.app?.chatConfig?.questionGuide;
(v) => v.chatBoxData?.app?.chatConfig?.questionGuide ?? false if (typeof val === 'boolean') {
); return {
...defaultQGConfig,
open: val
};
}
return v.chatBoxData?.app?.chatConfig?.questionGuide ?? defaultQGConfig;
});
const ttsConfig = useContextSelector( const ttsConfig = useContextSelector(
ChatItemContext, ChatItemContext,
(v) => v.chatBoxData?.app?.chatConfig?.ttsConfig ?? defaultTTSConfig (v) => v.chatBoxData?.app?.chatConfig?.ttsConfig ?? defaultTTSConfig
......
...@@ -335,7 +335,7 @@ const ChatBox = ({ ...@@ -335,7 +335,7 @@ const ChatBox = ({
// create question guide // create question guide
const createQuestionGuide = useCallback(async () => { const createQuestionGuide = useCallback(async () => {
if (!questionGuide || chatController.current?.signal?.aborted) return; if (!questionGuide.open || chatController.current?.signal?.aborted) return;
try { try {
const abortSignal = new AbortController(); const abortSignal = new AbortController();
questionGuideController.current = abortSignal; questionGuideController.current = abortSignal;
...@@ -344,6 +344,7 @@ const ChatBox = ({ ...@@ -344,6 +344,7 @@ const ChatBox = ({
{ {
appId, appId,
chatId, chatId,
questionGuide,
...outLinkAuthData ...outLinkAuthData
}, },
abortSignal abortSignal
...@@ -355,7 +356,7 @@ const ChatBox = ({ ...@@ -355,7 +356,7 @@ const ChatBox = ({
}, 100); }, 100);
} }
} catch (error) {} } catch (error) {}
}, [questionGuide, appId, outLinkAuthData, scrollToBottom]); }, [questionGuide, appId, chatId, outLinkAuthData, scrollToBottom]);
/* Abort chat completions, questionGuide */ /* Abort chat completions, questionGuide */
const abortRequest = useMemoizedFn((signal: string = 'stop') => { const abortRequest = useMemoizedFn((signal: string = 'stop') => {
......
...@@ -8,15 +8,20 @@ import { NextAPI } from '@/service/middleware/entry'; ...@@ -8,15 +8,20 @@ import { NextAPI } from '@/service/middleware/entry';
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { getChatItems } from '@fastgpt/service/core/chat/controller'; import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt'; import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt';
import { getAppLatestVersion } from '@fastgpt/service/core/app/version/controller';
export type CreateQuestionGuideParams = OutLinkChatAuthProps & { export type CreateQuestionGuideParams = OutLinkChatAuthProps & {
appId: string; appId: string;
chatId: string; chatId: string;
questionGuide?: {
open: boolean;
model?: string;
customPrompt?: string;
};
}; };
async function handler(req: ApiRequestProps<CreateQuestionGuideParams>, res: NextApiResponse<any>) { async function handler(req: ApiRequestProps<CreateQuestionGuideParams>, res: NextApiResponse<any>) {
const { appId, chatId } = req.body; const { appId, chatId, questionGuide: inputQuestionGuide } = req.body;
const [{ tmbId, teamId }] = await Promise.all([ const [{ tmbId, teamId }] = await Promise.all([
authChatCrud({ authChatCrud({
req, req,
...@@ -27,6 +32,13 @@ async function handler(req: ApiRequestProps<CreateQuestionGuideParams>, res: Nex ...@@ -27,6 +32,13 @@ async function handler(req: ApiRequestProps<CreateQuestionGuideParams>, res: Nex
]); ]);
// Auth app and get questionGuide config // Auth app and get questionGuide config
const questionGuide = await (async () => {
if (inputQuestionGuide) {
return inputQuestionGuide;
}
const { chatConfig } = await getAppLatestVersion(appId);
return chatConfig.questionGuide;
})();
// Get histories // Get histories
const { histories } = await getChatItems({ const { histories } = await getChatItems({
...@@ -38,15 +50,12 @@ async function handler(req: ApiRequestProps<CreateQuestionGuideParams>, res: Nex ...@@ -38,15 +50,12 @@ async function handler(req: ApiRequestProps<CreateQuestionGuideParams>, res: Nex
}); });
const messages = chats2GPTMessages({ messages: histories, reserveId: false }); const messages = chats2GPTMessages({ messages: histories, reserveId: false });
const qgModel = global.llmModels[0]; const qgModel = questionGuide?.model || global.llmModels[0].model;
const { result, tokens } = await createQuestionGuide({ const { result, tokens } = await createQuestionGuide({
messages, messages,
model: qgModel.model model: qgModel,
}); customPrompt: questionGuide?.customPrompt
jsonRes(res, {
data: result
}); });
pushQuestionGuideUsage({ pushQuestionGuideUsage({
...@@ -54,6 +63,8 @@ async function handler(req: ApiRequestProps<CreateQuestionGuideParams>, res: Nex ...@@ -54,6 +63,8 @@ async function handler(req: ApiRequestProps<CreateQuestionGuideParams>, res: Nex
teamId, teamId,
tmbId tmbId
}); });
return result;
} }
export default NextAPI(handler); export default NextAPI(handler);
...@@ -40,7 +40,7 @@ const DatasetSelectModal = dynamic(() => import('@/components/core/app/DatasetSe ...@@ -40,7 +40,7 @@ const DatasetSelectModal = dynamic(() => import('@/components/core/app/DatasetSe
const DatasetParamsModal = dynamic(() => import('@/components/core/app/DatasetParamsModal')); const DatasetParamsModal = dynamic(() => import('@/components/core/app/DatasetParamsModal'));
const ToolSelectModal = dynamic(() => import('./components/ToolSelectModal')); const ToolSelectModal = dynamic(() => import('./components/ToolSelectModal'));
const TTSSelect = dynamic(() => import('@/components/core/app/TTSSelect')); const TTSSelect = dynamic(() => import('@/components/core/app/TTSSelect'));
const QGSwitch = dynamic(() => import('@/components/core/app/QGSwitch')); const QGConfig = dynamic(() => import('@/components/core/app/QGConfig'));
const WhisperConfig = dynamic(() => import('@/components/core/app/WhisperConfig')); const WhisperConfig = dynamic(() => import('@/components/core/app/WhisperConfig'));
const InputGuideConfig = dynamic(() => import('@/components/core/app/InputGuideConfig')); const InputGuideConfig = dynamic(() => import('@/components/core/app/InputGuideConfig'));
const WelcomeTextConfig = dynamic(() => import('@/components/core/app/WelcomeTextConfig')); const WelcomeTextConfig = dynamic(() => import('@/components/core/app/WelcomeTextConfig'));
...@@ -425,14 +425,14 @@ const EditForm = ({ ...@@ -425,14 +425,14 @@ const EditForm = ({
{/* question guide */} {/* question guide */}
<Box {...BoxStyles}> <Box {...BoxStyles}>
<QGSwitch <QGConfig
isChecked={appForm.chatConfig.questionGuide} value={appForm.chatConfig.questionGuide}
onChange={(e) => { onChange={(e) => {
setAppForm((state) => ({ setAppForm((state) => ({
...state, ...state,
chatConfig: { chatConfig: {
...state.chatConfig, ...state.chatConfig,
questionGuide: e.target.checked questionGuide: e
} }
})); }));
}} }}
......
...@@ -30,7 +30,7 @@ export const compareSimpleAppSnapshot = ( ...@@ -30,7 +30,7 @@ export const compareSimpleAppSnapshot = (
{ {
welcomeText: appForm1.chatConfig?.welcomeText || '', welcomeText: appForm1.chatConfig?.welcomeText || '',
variables: appForm1.chatConfig?.variables || [], variables: appForm1.chatConfig?.variables || [],
questionGuide: appForm1.chatConfig?.questionGuide || false, questionGuide: appForm1.chatConfig?.questionGuide || undefined,
ttsConfig: appForm1.chatConfig?.ttsConfig || undefined, ttsConfig: appForm1.chatConfig?.ttsConfig || undefined,
whisperConfig: appForm1.chatConfig?.whisperConfig || undefined, whisperConfig: appForm1.chatConfig?.whisperConfig || undefined,
chatInputGuide: appForm1.chatConfig?.chatInputGuide || undefined, chatInputGuide: appForm1.chatConfig?.chatInputGuide || undefined,
...@@ -39,7 +39,7 @@ export const compareSimpleAppSnapshot = ( ...@@ -39,7 +39,7 @@ export const compareSimpleAppSnapshot = (
{ {
welcomeText: appForm2.chatConfig?.welcomeText || '', welcomeText: appForm2.chatConfig?.welcomeText || '',
variables: appForm2.chatConfig?.variables || [], variables: appForm2.chatConfig?.variables || [],
questionGuide: appForm2.chatConfig?.questionGuide || false, questionGuide: appForm2.chatConfig?.questionGuide || undefined,
ttsConfig: appForm2.chatConfig?.ttsConfig || undefined, ttsConfig: appForm2.chatConfig?.ttsConfig || undefined,
whisperConfig: appForm2.chatConfig?.whisperConfig || undefined, whisperConfig: appForm2.chatConfig?.whisperConfig || undefined,
chatInputGuide: appForm2.chatConfig?.chatInputGuide || undefined, chatInputGuide: appForm2.chatConfig?.chatInputGuide || undefined,
......
...@@ -3,7 +3,7 @@ import { NodeProps } from 'reactflow'; ...@@ -3,7 +3,7 @@ import { NodeProps } from 'reactflow';
import { Box } from '@chakra-ui/react'; import { Box } from '@chakra-ui/react';
import { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node.d'; import { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node.d';
import QGSwitch from '@/components/core/app/QGSwitch'; import QGConfig from '@/components/core/app/QGConfig';
import TTSSelect from '@/components/core/app/TTSSelect'; import TTSSelect from '@/components/core/app/TTSSelect';
import WhisperConfig from '@/components/core/app/WhisperConfig'; import WhisperConfig from '@/components/core/app/WhisperConfig';
import InputGuideConfig from '@/components/core/app/InputGuideConfig'; import InputGuideConfig from '@/components/core/app/InputGuideConfig';
...@@ -13,7 +13,12 @@ import NodeCard from './render/NodeCard'; ...@@ -13,7 +13,12 @@ import NodeCard from './render/NodeCard';
import ScheduledTriggerConfig from '@/components/core/app/ScheduledTriggerConfig'; import ScheduledTriggerConfig from '@/components/core/app/ScheduledTriggerConfig';
import { useContextSelector } from 'use-context-selector'; import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '../../context'; import { WorkflowContext } from '../../context';
import { AppChatConfigType, AppDetailType, VariableItemType } from '@fastgpt/global/core/app/type'; import {
AppChatConfigType,
AppDetailType,
AppQGConfigType,
VariableItemType
} from '@fastgpt/global/core/app/type';
import { useMemoizedFn } from 'ahooks'; import { useMemoizedFn } from 'ahooks';
import VariableEdit from '@/components/core/app/VariableEdit'; import VariableEdit from '@/components/core/app/VariableEdit';
import { AppContext } from '@/pages/app/detail/components/context'; import { AppContext } from '@/pages/app/detail/components/context';
...@@ -149,17 +154,16 @@ function AutoExecute({ chatConfig: { autoExecute }, setAppDetail }: ComponentPro ...@@ -149,17 +154,16 @@ function AutoExecute({ chatConfig: { autoExecute }, setAppDetail }: ComponentPro
); );
} }
function QuestionGuide({ chatConfig: { questionGuide = false }, setAppDetail }: ComponentProps) { function QuestionGuide({ chatConfig: { questionGuide }, setAppDetail }: ComponentProps) {
return ( return (
<QGSwitch <QGConfig
isChecked={questionGuide} value={questionGuide}
onChange={(e) => { onChange={(e) => {
const value = e.target.checked;
setAppDetail((state) => ({ setAppDetail((state) => ({
...state, ...state,
chatConfig: { chatConfig: {
...state.chatConfig, ...state.chatConfig,
questionGuide: value questionGuide: e
} }
})); }));
}} }}
......
...@@ -142,7 +142,7 @@ export const AiPointsTable = () => { ...@@ -142,7 +142,7 @@ export const AiPointsTable = () => {
{whisperModel?.charsPointsPrice + {whisperModel?.charsPointsPrice +
t('common:support.wallet.subscription.point') + t('common:support.wallet.subscription.point') +
' / 60' + ' / 60' +
t('common:unit.minute')} t('common:unit.seconds')}
</Box> </Box>
</Flex> </Flex>
</Box> </Box>
......
...@@ -58,10 +58,12 @@ export const emptyTemplates: Record< ...@@ -58,10 +58,12 @@ export const emptyTemplates: Record<
}, },
{ {
key: 'questionGuide', key: 'questionGuide',
valueType: WorkflowIOValueTypeEnum.boolean, valueType: WorkflowIOValueTypeEnum.object,
renderTypeList: [FlowNodeInputTypeEnum.hidden], renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: 'core.app.Question Guide', label: 'core.app.Question Guide',
value: false value: {
open: false
}
}, },
{ {
key: 'tts', key: 'tts',
...@@ -285,10 +287,12 @@ export const emptyTemplates: Record< ...@@ -285,10 +287,12 @@ export const emptyTemplates: Record<
}, },
{ {
key: 'questionGuide', key: 'questionGuide',
valueType: 'boolean', valueType: 'any',
renderTypeList: ['hidden'], renderTypeList: ['hidden'],
label: 'core.app.Question Guide', label: 'core.app.Question Guide',
value: false value: {
open: false
}
}, },
{ {
key: 'tts', key: 'tts',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment