mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
v4.6.4-Outlink (#589)
This commit is contained in:
@@ -28,14 +28,16 @@ curl --location --request POST 'https://{{host}}/api/admin/initv464' \
|
||||
|
||||
1. 重写 - 分享链接身份逻辑,采用 localID 记录用户的ID。
|
||||
2. 商业版新增 - 分享链接 SSO 方案,通过`身份鉴权`地址,仅需`3个接口`即可完全接入已有用户系统。具体参考[分享链接身份鉴权](/docs/development/openapi/share/)
|
||||
3. 调整 - 知识库搜索模块 topk 逻辑,采用 MaxToken 计算,兼容不同长度的文本块
|
||||
4. 调整鉴权顺序,提高 apikey 的优先级,避免cookie抢占 apikey 的鉴权。
|
||||
5. 链接读取支持多选择器。参考[Web 站点同步用法](/docs/course/webSync)
|
||||
6. 修复 - 分享链接图片上传鉴权问题
|
||||
7. 修复 - Mongo 连接池未释放问题。
|
||||
8. 修复 - Dataset Intro 无法更新
|
||||
9. 修复 - md 代码块问题
|
||||
10. 修复 - root 权限问题
|
||||
11. 优化 docker file
|
||||
3. 新增 - 分享链接更多嵌入方式提示,更多DIY方式。
|
||||
4. 优化 - 历史记录模块。弃用旧的历史记录模块,直接在对应地方填写数值即可。
|
||||
5. 调整 - 知识库搜索模块 topk 逻辑,采用 MaxToken 计算,兼容不同长度的文本块
|
||||
6. 调整鉴权顺序,提高 apikey 的优先级,避免cookie抢占 apikey 的鉴权。
|
||||
7. 链接读取支持多选择器。参考[Web 站点同步用法](/docs/course/webSync)
|
||||
8. 修复 - 分享链接图片上传鉴权问题
|
||||
9. 修复 - Mongo 连接池未释放问题。
|
||||
10. 修复 - Dataset Intro 无法更新
|
||||
11. 修复 - md 代码块问题
|
||||
12. 修复 - root 权限问题
|
||||
13. 优化 docker file
|
||||
|
||||
|
||||
|
1
packages/global/core/chat/api.d.ts
vendored
1
packages/global/core/chat/api.d.ts
vendored
@@ -1,4 +1,5 @@
|
||||
export type UpdateChatFeedbackProps = {
|
||||
appId: string;
|
||||
chatId: string;
|
||||
chatItemId: string;
|
||||
shareId?: string;
|
||||
|
@@ -12,8 +12,11 @@ export enum FlowNodeInputTypeEnum {
|
||||
selectApp = 'selectApp',
|
||||
// chat special input
|
||||
aiSettings = 'aiSettings',
|
||||
// maxToken = 'maxToken',
|
||||
|
||||
// model select
|
||||
selectChatModel = 'selectChatModel',
|
||||
selectCQModel = 'selectCQModel',
|
||||
|
||||
// dataset special input
|
||||
selectDataset = 'selectDataset',
|
||||
selectDatasetParamsModal = 'selectDatasetParamsModal',
|
||||
|
@@ -14,9 +14,13 @@ export const Input_Template_TFSwitch: FlowNodeInputItemType = {
|
||||
|
||||
export const Input_Template_History: FlowNodeInputItemType = {
|
||||
key: ModuleInputKeyEnum.history,
|
||||
type: FlowNodeInputTypeEnum.target,
|
||||
type: FlowNodeInputTypeEnum.numberInput,
|
||||
label: 'core.module.input.label.chat history',
|
||||
required: true,
|
||||
min: 0,
|
||||
max: 30,
|
||||
valueType: ModuleDataTypeEnum.chatHistory,
|
||||
value: 6,
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true
|
||||
};
|
||||
|
@@ -87,7 +87,6 @@ export const AiChatModule: FlowModuleTemplateType = {
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '引用内容模板',
|
||||
valueType: ModuleDataTypeEnum.string,
|
||||
value: '',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false
|
||||
},
|
||||
@@ -96,7 +95,6 @@ export const AiChatModule: FlowModuleTemplateType = {
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '引用内容提示词',
|
||||
valueType: ModuleDataTypeEnum.string,
|
||||
value: '',
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false
|
||||
},
|
||||
@@ -104,7 +102,6 @@ export const AiChatModule: FlowModuleTemplateType = {
|
||||
key: ModuleInputKeyEnum.aiChatSettingModal,
|
||||
type: FlowNodeInputTypeEnum.aiSettings,
|
||||
label: '',
|
||||
connected: false,
|
||||
valueType: ModuleDataTypeEnum.any,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false
|
||||
@@ -118,21 +115,19 @@ export const AiChatModule: FlowModuleTemplateType = {
|
||||
valueType: ModuleDataTypeEnum.string,
|
||||
description: chatNodeSystemPromptTip,
|
||||
placeholder: chatNodeSystemPromptTip,
|
||||
value: '',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true
|
||||
},
|
||||
Input_Template_History,
|
||||
{
|
||||
key: ModuleInputKeyEnum.aiChatDatasetQuote,
|
||||
type: FlowNodeInputTypeEnum.target,
|
||||
label: '引用内容',
|
||||
description: "对象数组格式,结构:\n [{q:'问题',a:'回答'}]",
|
||||
valueType: ModuleDataTypeEnum.datasetQuote,
|
||||
connected: false,
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true
|
||||
},
|
||||
Input_Template_History,
|
||||
Input_Template_UserChatInput
|
||||
],
|
||||
outputs: [
|
||||
|
@@ -17,7 +17,6 @@ export const AssignedAnswerModule: FlowModuleTemplateType = {
|
||||
key: ModuleInputKeyEnum.answerText,
|
||||
type: FlowNodeInputTypeEnum.textarea,
|
||||
valueType: ModuleDataTypeEnum.any,
|
||||
value: '',
|
||||
label: '回复的内容',
|
||||
description:
|
||||
'可以使用 \\n 来实现连续换行。\n\n可以通过外部模块输入实现回复,外部模块输入时会覆盖当前填写的内容。\n\n如传入非字符串类型数据将会自动转成字符串',
|
||||
|
@@ -27,7 +27,7 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = {
|
||||
Input_Template_TFSwitch,
|
||||
{
|
||||
key: ModuleInputKeyEnum.aiModel,
|
||||
type: FlowNodeInputTypeEnum.selectChatModel,
|
||||
type: FlowNodeInputTypeEnum.selectCQModel,
|
||||
valueType: ModuleDataTypeEnum.string,
|
||||
label: '分类模型',
|
||||
required: true,
|
||||
@@ -38,7 +38,6 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = {
|
||||
key: ModuleInputKeyEnum.aiSystemPrompt,
|
||||
type: FlowNodeInputTypeEnum.textarea,
|
||||
valueType: ModuleDataTypeEnum.string,
|
||||
value: '',
|
||||
label: '背景知识',
|
||||
description:
|
||||
'你可以添加一些特定内容的介绍,从而更好的识别用户的问题类型。这个内容通常是给模型介绍一个它不知道的内容。',
|
||||
@@ -57,15 +56,15 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = {
|
||||
value: [
|
||||
{
|
||||
value: '打招呼',
|
||||
key: 'fasw'
|
||||
key: 'wqre'
|
||||
},
|
||||
{
|
||||
value: '关于 xxx 的问题',
|
||||
key: 'fqsw'
|
||||
key: 'sdfa'
|
||||
},
|
||||
{
|
||||
value: '其他问题',
|
||||
key: 'fesw'
|
||||
key: 'agex'
|
||||
}
|
||||
],
|
||||
showTargetInApp: false,
|
||||
@@ -75,19 +74,19 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = {
|
||||
outputs: [
|
||||
// custom output
|
||||
{
|
||||
key: 'fasw',
|
||||
key: 'wqre',
|
||||
label: '',
|
||||
type: FlowNodeOutputTypeEnum.hidden,
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'fqsw',
|
||||
key: 'sdfa',
|
||||
label: '',
|
||||
type: FlowNodeOutputTypeEnum.hidden,
|
||||
targets: []
|
||||
},
|
||||
{
|
||||
key: 'fesw',
|
||||
key: 'agex',
|
||||
label: '',
|
||||
type: FlowNodeOutputTypeEnum.hidden,
|
||||
targets: []
|
||||
|
@@ -26,12 +26,11 @@ export const ContextExtractModule: FlowModuleTemplateType = {
|
||||
key: ModuleInputKeyEnum.description,
|
||||
type: FlowNodeInputTypeEnum.textarea,
|
||||
valueType: ModuleDataTypeEnum.string,
|
||||
value: '',
|
||||
label: '提取要求描述',
|
||||
description: '写一段提取要求,告诉 AI 需要提取哪些内容',
|
||||
description: '给AI一些对应的背景知识或要求描述,引导AI更好的完成任务',
|
||||
required: true,
|
||||
placeholder:
|
||||
'例如: \n1. 你是一个实验室预约助手。根据用户问题,提取出姓名、实验室号和预约时间',
|
||||
'例如: \n1. 你是一个实验室预约助手,你的任务是帮助用户预约实验室。\n2. 你是谷歌搜索助手,需要从文本中提取出合适的搜索词。',
|
||||
showTargetInApp: true,
|
||||
showTargetInPlugin: true
|
||||
},
|
||||
|
@@ -74,7 +74,6 @@ export const DatasetSearchModule: FlowModuleTemplateType = {
|
||||
key: ModuleInputKeyEnum.datasetParamsModal,
|
||||
type: FlowNodeInputTypeEnum.selectDatasetParamsModal,
|
||||
label: '',
|
||||
connected: false,
|
||||
valueType: ModuleDataTypeEnum.any,
|
||||
showTargetInApp: false,
|
||||
showTargetInPlugin: false
|
||||
|
@@ -11,7 +11,7 @@ export const HistoryModule: FlowModuleTemplateType = {
|
||||
templateType: ModuleTemplateTypeEnum.systemInput,
|
||||
flowType: FlowNodeTypeEnum.historyNode,
|
||||
avatar: '/imgs/module/history.png',
|
||||
name: '聊天记录',
|
||||
name: '聊天记录(弃用)',
|
||||
intro: '用户输入的内容。该模块通常作为应用的入口,用户在发送消息后会首先执行该模块。',
|
||||
inputs: [
|
||||
{
|
||||
|
@@ -16,7 +16,6 @@ export const HttpModule: FlowModuleTemplateType = {
|
||||
Input_Template_TFSwitch,
|
||||
{
|
||||
key: ModuleInputKeyEnum.httpUrl,
|
||||
value: '',
|
||||
type: FlowNodeInputTypeEnum.input,
|
||||
valueType: ModuleDataTypeEnum.string,
|
||||
label: '请求地址',
|
||||
|
@@ -8,7 +8,7 @@
|
||||
"encoding": "^0.1.13",
|
||||
"js-tiktoken": "^1.0.7",
|
||||
"node-html-markdown": "^1.3.0",
|
||||
"openai": "^4.16.1",
|
||||
"openai": "^4.20.1",
|
||||
"timezones-list": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@@ -70,8 +70,9 @@ instance.interceptors.request.use(requestStart, (err) => Promise.reject(err));
|
||||
instance.interceptors.response.use(responseSuccess, (err) => Promise.reject(err));
|
||||
|
||||
export function request(url: string, data: any, config: ConfigType, method: Method): any {
|
||||
if (global.systemEnv && !global.systemEnv?.pluginBaseUrl) {
|
||||
return Promise.reject('该功能为商业版特有...');
|
||||
if (!global.systemEnv || !global.systemEnv?.pluginBaseUrl) {
|
||||
console.log('未部署商业版接口');
|
||||
return Promise.reject('The The request was denied...');
|
||||
}
|
||||
|
||||
/* 去空 */
|
||||
|
@@ -14,7 +14,7 @@ export async function getChatItems({
|
||||
return { history: [] };
|
||||
}
|
||||
|
||||
const history = await MongoChatItem.find({ chatId }, field).sort({ _id: -1 }).limit(limit);
|
||||
const history = await MongoChatItem.find({ chatId }, field).sort({ _id: -1 }).limit(limit).lean();
|
||||
|
||||
history.reverse();
|
||||
|
||||
|
@@ -30,7 +30,7 @@ export const pushResult2Remote = async ({
|
||||
shareId?: string;
|
||||
responseData?: any[];
|
||||
}) => {
|
||||
if (!shareId || !outLinkUid || !global.systemEnv.pluginBaseUrl) return;
|
||||
if (!shareId || !outLinkUid || !global.systemEnv?.pluginBaseUrl) return;
|
||||
try {
|
||||
const outLink = await MongoOutLink.findOne({
|
||||
shareId
|
||||
|
29
pnpm-lock.yaml
generated
29
pnpm-lock.yaml
generated
@@ -13,7 +13,7 @@ importers:
|
||||
version: registry.npmmirror.com/multer@1.4.5-lts.1
|
||||
openai:
|
||||
specifier: 4.16.1
|
||||
version: registry.npmmirror.com/openai@4.16.1(encoding@0.1.13)
|
||||
version: registry.npmmirror.com/openai@4.16.1
|
||||
devDependencies:
|
||||
'@types/multer':
|
||||
specifier: ^1.4.10
|
||||
@@ -61,8 +61,8 @@ importers:
|
||||
specifier: ^1.3.0
|
||||
version: registry.npmmirror.com/node-html-markdown@1.3.0
|
||||
openai:
|
||||
specifier: ^4.16.1
|
||||
version: registry.npmmirror.com/openai@4.16.1(encoding@0.1.13)
|
||||
specifier: ^4.20.1
|
||||
version: registry.npmmirror.com/openai@4.20.1(encoding@0.1.13)
|
||||
timezones-list:
|
||||
specifier: ^3.0.2
|
||||
version: registry.npmmirror.com/timezones-list@3.0.2
|
||||
@@ -10320,9 +10320,8 @@ packages:
|
||||
mimic-fn: registry.npmmirror.com/mimic-fn@4.0.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/openai@4.16.1(encoding@0.1.13):
|
||||
registry.npmmirror.com/openai@4.16.1:
|
||||
resolution: {integrity: sha512-Gr+uqUN1ICSk6VhrX64E+zL7skjI1TgPr/XUN+ZQuNLLOvx15+XZulx/lSW4wFEAQzgjBDlMBbBeikguGIjiMg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/openai/-/openai-4.16.1.tgz}
|
||||
id: registry.npmmirror.com/openai/4.16.1
|
||||
name: openai
|
||||
version: 4.16.1
|
||||
hasBin: true
|
||||
@@ -10340,6 +10339,26 @@ packages:
|
||||
- encoding
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/openai@4.20.1(encoding@0.1.13):
|
||||
resolution: {integrity: sha512-Dd3q8EvINfganZFtg6V36HjrMaihqRgIcKiHua4Nq9aw/PxOP48dhbsk8x5klrxajt5Lpnc1KTOG5i1S6BKAJA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/openai/-/openai-4.20.1.tgz}
|
||||
id: registry.npmmirror.com/openai/4.20.1
|
||||
name: openai
|
||||
version: 4.20.1
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@types/node': registry.npmmirror.com/@types/node@18.18.6
|
||||
'@types/node-fetch': registry.npmmirror.com/@types/node-fetch@2.6.7
|
||||
abort-controller: registry.npmmirror.com/abort-controller@3.0.0
|
||||
agentkeepalive: registry.npmmirror.com/agentkeepalive@4.5.0
|
||||
digest-fetch: registry.npmmirror.com/digest-fetch@1.3.0
|
||||
form-data-encoder: registry.npmmirror.com/form-data-encoder@1.7.2
|
||||
formdata-node: registry.npmmirror.com/formdata-node@4.4.1
|
||||
node-fetch: registry.npmmirror.com/node-fetch@2.7.0(encoding@0.1.13)
|
||||
web-streams-polyfill: registry.npmmirror.com/web-streams-polyfill@3.2.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/option@0.2.4:
|
||||
resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/option/-/option-0.2.4.tgz}
|
||||
name: option
|
||||
|
@@ -66,9 +66,9 @@
|
||||
],
|
||||
"CQModels": [
|
||||
{
|
||||
"model": "gpt-3.5-turbo-1106",
|
||||
"name": "GPT35-1106",
|
||||
"maxContext": 16000,
|
||||
"model": "gpt-3.5-turbo",
|
||||
"name": "GPT35",
|
||||
"maxContext": 4000,
|
||||
"maxResponse": 4000,
|
||||
"price": 0,
|
||||
"functionCall": true,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "4.6.3",
|
||||
"version": "4.6.4",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
@@ -2,17 +2,12 @@
|
||||
|
||||
1. 重写 - 分享链接身份逻辑,采用 localID 记录用户的ID。
|
||||
2. 商业版新增 - 分享链接 SSO 方案,通过`身份鉴权`地址,仅需`3个接口`即可完全接入已有用户系统。具体参考[分享链接身份鉴权](https://doc.fastgpt.in/docs/development/openapi/share/)
|
||||
3. 调整 - 知识库搜索模块 topk 逻辑,采用 MaxToken 计算,兼容不同长度的文本块
|
||||
4. 调整鉴权顺序,提高 apikey 的优先级,避免cookie抢占 apikey 的鉴权。
|
||||
5. 链接读取支持多选择器。参考[Web 站点同步用法](https://doc.fastgpt.in/docs/course/webSync)
|
||||
6. 修复 - 分享链接图片上传鉴权问题
|
||||
7. 修复 - Mongo 连接池未释放问题。
|
||||
8. 修复 - Dataset Intro 无法更新
|
||||
9. 修复 - md 代码块问题
|
||||
10. 修复 - root 权限问题
|
||||
11. 优化 docker file
|
||||
12. [知识库结构详解](https://doc.fastgpt.in/docs/use-cases/datasetengine/)
|
||||
13. [知识库提示词详解](https://doc.fastgpt.in/docs/use-cases/ai_settings/#引用模板--引用提示词)
|
||||
14. [使用文档](https://doc.fastgpt.in/docs/intro/)
|
||||
15. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow)
|
||||
16. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/)
|
||||
3. 新增 - 分享链接更多嵌入方式提示,更多DIY方式。
|
||||
4. 优化 - 历史记录模块。弃用旧的历史记录模块,直接在对应地方填写数值即可。
|
||||
5. 调整 - 知识库搜索模块 topk 逻辑,采用 MaxToken 计算,兼容不同长度的文本块
|
||||
6. 链接读取支持多选择器。参考[Web 站点同步用法](https://doc.fastgpt.in/docs/course/webSync)
|
||||
7. [知识库结构详解](https://doc.fastgpt.in/docs/use-cases/datasetengine/)
|
||||
8. [知识库提示词详解](https://doc.fastgpt.in/docs/use-cases/ai_settings/#引用模板--引用提示词)
|
||||
9. [使用文档](https://doc.fastgpt.in/docs/intro/)
|
||||
10. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow)
|
||||
11. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/)
|
||||
|
1
projects/app/public/imgs/modal/usingWay.svg
Normal file
1
projects/app/public/imgs/modal/usingWay.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?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="1702278024550" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4455" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M347.637 435.935l37.455-62.447c-43.588-26.142-69.609-72.043-69.609-122.782 0-78.882 64.173-143.055 143.053-143.055 78.881 0 143.057 64.173 143.057 143.055 0 51.318-27.746 98.994-72.412 124.422l36.028 63.281c67.358-38.347 109.201-110.271 109.201-187.703 0-119.033-96.84-215.872-215.874-215.872-119.032 0-215.87 96.839-215.87 215.872 0 37.964 10.006 75.315 28.935 108.013 18.34 31.68 44.633 58.38 76.036 77.216z" fill="#3260A6" p-id="4456"></path><path d="M793.562 490.761c-30.832 0-55.827 24.995-55.827 55.827V513.82c0-30.832-24.995-55.827-55.827-55.827s-55.827 24.995-55.827 55.827c0-30.832-24.995-55.827-55.827-55.827s-55.827 24.995-55.827 55.827V240.754c0-30.832-24.994-55.827-55.827-55.827s-55.827 24.995-55.827 55.827V637.13l-70.76-65.956c-22.553-21.022-57.877-19.783-78.9 2.77-21.025 22.556-19.784 57.881 2.77 78.905L383.722 772.01s179.657 348.826 394.062 164.762c0 0 70.436-54.944 69.59-200.56a55.87 55.87 0 0 0 2.014-14.86V546.59c0.001-30.834-24.994-55.829-55.826-55.829z" fill="#3260A6" p-id="4457"></path></svg>
|
After Width: | Height: | Size: 1.3 KiB |
124
projects/app/public/imgs/outlink/iframe.svg
Normal file
124
projects/app/public/imgs/outlink/iframe.svg
Normal file
@@ -0,0 +1,124 @@
|
||||
<svg width="236" height="134" viewBox="0 0 236 134" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_528_985)">
|
||||
<rect x="0.5" width="235" height="134" rx="8" fill="#F4F4F7" />
|
||||
<mask id="path-2-inside-1_528_985" fill="white">
|
||||
<path d="M0.5 9.73413H235.5V22.5H0.5V9.73413Z" />
|
||||
</mask>
|
||||
<path d="M0.5 9.73413H235.5V22.5H0.5V9.73413Z" fill="white" />
|
||||
<path d="M0.5 9.93413H235.5V9.53413H0.5V9.93413ZM235.5 22.3H0.5V22.7H235.5V22.3Z" fill="#DFE2EA"
|
||||
mask="url(#path-2-inside-1_528_985)" />
|
||||
<rect x="19.0779" y="14.5801" width="24.7145" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="171.534" y="14.5801" width="10.8445" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="185.956" y="14.5801" width="10.8445" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="200.377" y="14.5801" width="10.8445" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="214.799" y="14.5801" width="10.8445" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="7.50122" y="12.0801" width="8" height="8" rx="4" fill="#E8EBF0" />
|
||||
<path
|
||||
d="M0.5 7.71924C0.5 3.30096 4.08172 -0.280762 8.5 -0.280762H227.5C231.918 -0.280762 235.5 3.30096 235.5 7.71924V9.71924H0.5V7.71924Z"
|
||||
fill="#F0F1F6" />
|
||||
<circle cx="9.5" cy="4.71924" r="2" fill="#C4CBD7" />
|
||||
<circle cx="17.5" cy="4.71924" r="2" fill="#C4CBD7" />
|
||||
<circle cx="25.5" cy="4.71924" r="2" fill="#C4CBD7" />
|
||||
<g filter="url(#filter0_dd_528_985)">
|
||||
<rect x="44.8657" y="28.0518" width="146.269" height="97.8965" rx="4.60689" fill="white" />
|
||||
<rect x="44.2899" y="27.4759" width="147.421" height="99.0482" rx="5.18275" stroke="#94B5FF"
|
||||
stroke-width="1.15172" />
|
||||
<rect x="49.3128" y="32.815" width="10.9442" height="10.9442" rx="2.34518" fill="#FBFBFC" />
|
||||
<rect x="49.3128" y="32.815" width="10.9442" height="10.9442" rx="2.34518" stroke="#E8EBF0"
|
||||
stroke-width="0.31269" />
|
||||
<g clip-path="url(#clip1_528_985)">
|
||||
<path
|
||||
d="M54.0296 35.4534L55.4606 35.4534V35.4539C55.473 35.4535 55.4855 35.4534 55.498 35.4534C55.6914 35.4534 55.883 35.4924 56.0617 35.5684C56.2404 35.6443 56.4028 35.7555 56.5396 35.8958C56.6764 36.036 56.7849 36.2026 56.8589 36.3858C56.9329 36.5691 56.971 36.7655 56.971 36.9639L54.0296 36.9639L54.0296 41.1209C53.8417 41.1209 53.6556 41.0818 53.482 41.0058C53.3084 40.9299 53.1506 40.8185 53.0178 40.6782C52.8849 40.5378 52.7795 40.3712 52.7076 40.1878C52.644 40.0256 52.6077 39.8531 52.6001 39.6781H52.5986L52.5986 37.0001H52.599C52.5965 36.8897 52.6055 36.7787 52.6261 36.6692C52.6813 36.3762 52.8176 36.107 53.0178 35.8958C53.2179 35.6845 53.4728 35.5407 53.7504 35.4824C53.8428 35.463 53.9363 35.4534 54.0296 35.4534Z"
|
||||
fill="url(#paint0_linear_528_985)" />
|
||||
<path
|
||||
d="M55.2611 39.2568H54.7538V37.8761H55.2686V37.8761C55.4483 37.8771 55.6262 37.9128 55.7923 37.9813C55.9608 38.0507 56.1138 38.1524 56.2427 38.2807C56.3716 38.4089 56.4739 38.5612 56.5436 38.7288C56.6134 38.8964 56.6493 39.076 56.6493 39.2574H55.2611V39.2568Z"
|
||||
fill="url(#paint1_linear_528_985)" />
|
||||
</g>
|
||||
<path
|
||||
d="M49.4727 46.4792H184.697C185.708 46.4792 186.528 47.299 186.528 48.3103V63.0758C186.528 64.087 185.708 64.9068 184.697 64.9068H51.3037C50.2925 64.9068 49.4727 64.087 49.4727 63.0758V46.4792Z"
|
||||
fill="#F7F8FA" />
|
||||
<rect x="52.7708" y="50.1025" width="129.783" height="2.6" rx="1.3" fill="#DFE2EA" />
|
||||
<rect x="52.7708" y="56.0198" width="51.5588" height="2.6" rx="1.3" fill="#DFE2EA" />
|
||||
<g filter="url(#filter1_dd_528_985)">
|
||||
<rect x="49.4727" y="108.672" width="137.055" height="12.669" rx="1.83106" fill="white" />
|
||||
<rect x="49.5871" y="108.787" width="136.826" height="12.4401" rx="1.71662" stroke="#DFE2EA"
|
||||
stroke-width="0.228883" />
|
||||
<g clip-path="url(#clip2_528_985)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M56.1104 113.098C55.9757 113.098 55.8464 113.151 55.7512 113.247L54.196 114.802C54.0373 114.96 53.9481 115.176 53.9481 115.4C53.9481 115.625 54.0373 115.84 54.196 115.999C54.3548 116.158 54.5702 116.247 54.7947 116.247C55.0193 116.247 55.2346 116.158 55.3934 115.999L56.9485 114.444C57.0146 114.378 57.1218 114.378 57.1878 114.444C57.2539 114.51 57.2539 114.617 57.1878 114.683L55.6327 116.238C55.4105 116.461 55.109 116.585 54.7947 116.585C54.4804 116.585 54.179 116.461 53.9567 116.238C53.7345 116.016 53.6096 115.715 53.6096 115.4C53.6096 115.086 53.7345 114.785 53.9567 114.562L55.5119 113.007C55.6706 112.848 55.8859 112.759 56.1104 112.759C56.3349 112.759 56.5502 112.848 56.7089 113.007C56.8677 113.166 56.9569 113.381 56.9569 113.606C56.9569 113.83 56.8677 114.046 56.7089 114.204L55.1521 115.759C55.0569 115.855 54.9277 115.908 54.793 115.908C54.6583 115.908 54.5292 115.855 54.4339 115.759C54.3387 115.664 54.2852 115.535 54.2852 115.4C54.2852 115.266 54.3387 115.136 54.4339 115.041L55.8707 113.606C55.9368 113.54 56.0439 113.54 56.11 113.606C56.176 113.672 56.176 113.78 56.1098 113.846L54.6732 115.281C54.6415 115.312 54.6236 115.355 54.6236 115.4C54.6236 115.445 54.6415 115.488 54.6732 115.52C54.705 115.552 54.7481 115.57 54.793 115.57C54.838 115.57 54.881 115.552 54.9128 115.52L56.4696 113.965C56.5649 113.87 56.6184 113.74 56.6184 113.606C56.6184 113.471 56.5649 113.342 56.4696 113.247C56.3744 113.151 56.2451 113.098 56.1104 113.098Z"
|
||||
fill="#485264" />
|
||||
</g>
|
||||
<g clip-path="url(#clip3_528_985)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M169.058 112.846C169.185 112.72 169.356 112.649 169.535 112.649C169.714 112.649 169.886 112.72 170.012 112.846C170.139 112.973 170.21 113.145 170.21 113.323V114.672C170.21 114.851 170.139 115.023 170.012 115.149C169.886 115.276 169.714 115.347 169.535 115.347C169.356 115.347 169.185 115.276 169.058 115.149C168.932 115.023 168.861 114.851 168.861 114.672V113.323C168.861 113.145 168.932 112.973 169.058 112.846ZM169.535 112.986C169.446 112.986 169.36 113.022 169.297 113.085C169.233 113.148 169.198 113.234 169.198 113.323V114.672C169.198 114.762 169.233 114.848 169.297 114.911C169.36 114.974 169.446 115.01 169.535 115.01C169.625 115.01 169.71 114.974 169.774 114.911C169.837 114.848 169.872 114.762 169.872 114.672V113.323C169.872 113.234 169.837 113.148 169.774 113.085C169.71 113.022 169.625 112.986 169.535 112.986ZM168.355 114.166C168.448 114.166 168.524 114.242 168.524 114.335V114.672C168.524 114.941 168.63 115.198 168.82 115.388C169.01 115.577 169.267 115.684 169.535 115.684C169.804 115.684 170.061 115.577 170.251 115.388C170.44 115.198 170.547 114.941 170.547 114.672V114.335C170.547 114.242 170.622 114.166 170.715 114.166C170.809 114.166 170.884 114.242 170.884 114.335V114.672C170.884 115.03 170.742 115.373 170.489 115.626C170.276 115.839 169.999 115.973 169.704 116.011V116.358H170.21C170.303 116.358 170.378 116.434 170.378 116.527C170.378 116.62 170.303 116.696 170.21 116.696H168.861C168.768 116.696 168.692 116.62 168.692 116.527C168.692 116.434 168.768 116.358 168.861 116.358H169.367V116.011C169.071 115.973 168.794 115.839 168.581 115.626C168.328 115.373 168.186 115.03 168.186 114.672V114.335C168.186 114.242 168.262 114.166 168.355 114.166Z"
|
||||
fill="#485264" />
|
||||
</g>
|
||||
<rect x="175.486" y="111.01" width="7.32425" height="7.32425" rx="0.915532" fill="#171717"
|
||||
fill-opacity="0.1" />
|
||||
<path
|
||||
d="M181.033 114.566C180.994 114.488 180.871 114.431 180.625 114.316L177.953 113.07C177.671 112.938 177.529 112.872 177.434 112.894C177.352 112.912 177.284 112.966 177.251 113.039C177.213 113.123 177.26 113.264 177.355 113.545L177.639 114.397L178.538 114.502C178.831 114.536 178.978 114.553 179.007 114.575C179.078 114.626 179.078 114.726 179.007 114.777C178.978 114.799 178.831 114.816 178.538 114.85L177.637 114.956L177.355 115.799C177.26 116.081 177.213 116.221 177.251 116.305C177.284 116.378 177.352 116.432 177.434 116.451C177.529 116.472 177.671 116.406 177.953 116.274L180.625 115.029C180.871 114.914 180.994 114.857 181.033 114.779C181.067 114.711 181.067 114.633 181.033 114.566Z"
|
||||
fill="white" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_dd_528_985" x="33.7141" y="20.9001" width="168.572" height="120.2"
|
||||
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset />
|
||||
<feGaussianBlur stdDeviation="0.5" />
|
||||
<feComposite in2="hardAlpha" operator="out" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_528_985" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset dy="4" />
|
||||
<feGaussianBlur stdDeviation="5" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="effect1_dropShadow_528_985" result="effect2_dropShadow_528_985" />
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_528_985" result="shape" />
|
||||
</filter>
|
||||
<filter id="filter1_dd_528_985" x="47.1838" y="107.299" width="141.633" height="17.2466"
|
||||
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset />
|
||||
<feGaussianBlur stdDeviation="0.114441" />
|
||||
<feComposite in2="hardAlpha" operator="out" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_528_985" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset dy="0.915532" />
|
||||
<feGaussianBlur stdDeviation="1.14441" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="effect1_dropShadow_528_985" result="effect2_dropShadow_528_985" />
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_528_985" result="shape" />
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_528_985" x1="54.7848" y1="35.4534" x2="54.7848" y2="41.1209"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#326DFF" />
|
||||
<stop offset="1" stop-color="#8EAEFF" />
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_528_985" x1="55.7016" y1="37.8761" x2="55.7016" y2="39.2574"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#326DFF" />
|
||||
<stop offset="1" stop-color="#8EAEFF" />
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_528_985">
|
||||
<rect x="0.5" width="235" height="134" rx="8" fill="white" />
|
||||
</clipPath>
|
||||
<clipPath id="clip1_528_985">
|
||||
<rect width="6.25381" height="6.25381" fill="white" transform="translate(51.658 35.1602)" />
|
||||
</clipPath>
|
||||
<clipPath id="clip2_528_985">
|
||||
<rect width="4.57766" height="4.57766" fill="white" transform="translate(53.1348 112.384)" />
|
||||
</clipPath>
|
||||
<clipPath id="clip3_528_985">
|
||||
<rect width="4.57766" height="4.57766" fill="white" transform="translate(167.247 112.384)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
36
projects/app/public/imgs/outlink/link.svg
Normal file
36
projects/app/public/imgs/outlink/link.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 31 KiB |
147
projects/app/public/imgs/outlink/script.svg
Normal file
147
projects/app/public/imgs/outlink/script.svg
Normal file
@@ -0,0 +1,147 @@
|
||||
<svg width="236" height="134" viewBox="0 0 236 134" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_528_1010)">
|
||||
<rect x="0.5" width="235" height="134" rx="8" fill="#F4F4F7" />
|
||||
<path
|
||||
d="M0.5 7.71924C0.5 3.30096 4.08172 -0.280762 8.5 -0.280762H227.5C231.918 -0.280762 235.5 3.30096 235.5 7.71924V9.71924H0.5V7.71924Z"
|
||||
fill="#F0F1F6" />
|
||||
<circle cx="9.5" cy="4.71924" r="2" fill="#C4CBD7" />
|
||||
<circle cx="17.5" cy="4.71924" r="2" fill="#C4CBD7" />
|
||||
<circle cx="25.5" cy="4.71924" r="2" fill="#C4CBD7" />
|
||||
<g filter="url(#filter0_dd_528_1010)">
|
||||
<rect x="168.5" y="27.5801" width="57" height="81" rx="4" fill="white" />
|
||||
<rect x="168" y="27.0801" width="58" height="82" rx="4.5" stroke="#94B5FF" />
|
||||
<rect x="172.361" y="31.7158" width="9.50242" height="9.50242" rx="2.03623" fill="#FBFBFC" />
|
||||
<rect x="172.361" y="31.7158" width="9.50242" height="9.50242" rx="2.03623" stroke="#E8EBF0"
|
||||
stroke-width="0.271498" />
|
||||
<g clip-path="url(#clip1_528_1010)">
|
||||
<path
|
||||
d="M176.457 34.0066L177.699 34.0066V34.007C177.71 34.0067 177.721 34.0066 177.732 34.0066C177.899 34.0066 178.066 34.0405 178.221 34.1064C178.376 34.1723 178.517 34.2689 178.636 34.3907C178.755 34.5125 178.849 34.6571 178.913 34.8162C178.977 34.9753 179.011 35.1459 179.011 35.3181L176.457 35.3181L176.457 38.9275C176.293 38.9275 176.132 38.8935 175.981 38.8276C175.83 38.7616 175.693 38.665 175.578 38.5431C175.463 38.4212 175.371 38.2765 175.309 38.1173C175.253 37.9765 175.222 37.8267 175.215 37.6748H175.214L175.214 35.3496H175.214C175.212 35.2537 175.22 35.1573 175.238 35.0622C175.286 34.8078 175.404 34.5741 175.578 34.3907C175.752 34.2073 175.973 34.0824 176.214 34.0318C176.294 34.015 176.376 34.0066 176.457 34.0066Z"
|
||||
fill="url(#paint0_linear_528_1010)" />
|
||||
<path
|
||||
d="M177.526 37.309H177.085V36.1102H177.532V36.1102C177.688 36.111 177.843 36.142 177.987 36.2015C178.133 36.2617 178.266 36.3501 178.378 36.4614C178.49 36.5728 178.579 36.705 178.639 36.8505C178.7 36.996 178.731 37.152 178.731 37.3095H177.526V37.309Z"
|
||||
fill="url(#paint1_linear_528_1010)" />
|
||||
</g>
|
||||
<path
|
||||
d="M172.5 43.5801H219.91C220.788 43.5801 221.5 44.2919 221.5 45.1699V57.9902C221.5 58.8683 220.788 59.5801 219.91 59.5801H174.09C173.212 59.5801 172.5 58.8683 172.5 57.9902V43.5801Z"
|
||||
fill="#F7F8FA" />
|
||||
<rect x="175.167" y="46.2725" width="43.0222" height="2.6" rx="1.3" fill="#DFE2EA" />
|
||||
<rect x="175.167" y="52.1897" width="19.9498" height="2.6" rx="1.3" fill="#DFE2EA" />
|
||||
<g filter="url(#filter1_dd_528_1010)">
|
||||
<rect x="172.5" y="93.5801" width="49" height="11" rx="1.58985" fill="white" />
|
||||
<rect x="172.599" y="93.6794" width="48.8013" height="10.8013" rx="1.49048" stroke="#DFE2EA"
|
||||
stroke-width="0.198731" />
|
||||
<g clip-path="url(#clip2_528_1010)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M178.263 97.2128C178.146 97.2128 178.034 97.2593 177.951 97.342L176.601 98.6923C176.463 98.8301 176.386 99.0171 176.386 99.2121C176.386 99.407 176.463 99.594 176.601 99.7319C176.739 99.8697 176.926 99.9472 177.121 99.9472C177.316 99.9472 177.503 99.8697 177.641 99.7319L178.991 98.3816C179.048 98.3242 179.142 98.3242 179.199 98.3816C179.256 98.439 179.256 98.532 179.199 98.5894L177.849 99.9397C177.656 100.133 177.394 100.241 177.121 100.241C176.848 100.241 176.586 100.133 176.393 99.9397C176.2 99.7467 176.092 99.485 176.092 99.2121C176.092 98.9392 176.2 98.6774 176.393 98.4845L177.744 97.1342C177.882 96.9964 178.068 96.9189 178.263 96.9189C178.458 96.9189 178.645 96.9964 178.783 97.1342C178.921 97.272 178.998 97.459 178.998 97.6539C178.998 97.8488 178.921 98.0358 178.783 98.1736L177.431 99.5239C177.349 99.6066 177.236 99.653 177.12 99.653C177.003 99.653 176.89 99.6066 176.808 99.5239C176.725 99.4412 176.679 99.329 176.679 99.2121C176.679 99.0951 176.725 98.983 176.808 98.9003L178.055 97.6543C178.113 97.5969 178.206 97.597 178.263 97.6544C178.32 97.7118 178.32 97.8048 178.263 97.8622L177.016 99.1081C176.988 99.1356 176.972 99.1731 176.972 99.2121C176.972 99.2511 176.988 99.2885 177.016 99.3161C177.043 99.3437 177.081 99.3592 177.12 99.3592C177.159 99.3592 177.196 99.3437 177.224 99.3161L178.575 97.9658C178.658 97.8831 178.704 97.7709 178.704 97.6539C178.704 97.5369 178.658 97.4247 178.575 97.342C178.493 97.2593 178.38 97.2128 178.263 97.2128Z"
|
||||
fill="#485264" />
|
||||
</g>
|
||||
<g clip-path="url(#clip3_528_1010)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M206.38 96.9948C206.49 96.8849 206.639 96.8232 206.794 96.8232C206.949 96.8232 207.098 96.8849 207.208 96.9948C207.318 97.1046 207.38 97.2535 207.38 97.4088V98.5801C207.38 98.7354 207.318 98.8843 207.208 98.9941C207.098 99.104 206.949 99.1657 206.794 99.1657C206.639 99.1657 206.49 99.104 206.38 98.9941C206.27 98.8843 206.208 98.7354 206.208 98.5801V97.4088C206.208 97.2535 206.27 97.1046 206.38 96.9948ZM206.794 97.116C206.716 97.116 206.642 97.1469 206.587 97.2018C206.532 97.2567 206.501 97.3312 206.501 97.4088V98.5801C206.501 98.6577 206.532 98.7322 206.587 98.7871C206.642 98.842 206.716 98.8729 206.794 98.8729C206.872 98.8729 206.946 98.842 207.001 98.7871C207.056 98.7322 207.087 98.6577 207.087 98.5801V97.4088C207.087 97.3312 207.056 97.2567 207.001 97.2018C206.946 97.1469 206.872 97.116 206.794 97.116ZM205.769 98.1409C205.85 98.1409 205.916 98.2064 205.916 98.2873V98.5801C205.916 98.813 206.008 99.0365 206.173 99.2012C206.338 99.3659 206.561 99.4585 206.794 99.4585C207.027 99.4585 207.25 99.3659 207.415 99.2012C207.58 99.0365 207.672 98.813 207.672 98.5801V98.2873C207.672 98.2064 207.738 98.1409 207.819 98.1409C207.9 98.1409 207.965 98.2064 207.965 98.2873V98.5801C207.965 98.8907 207.842 99.1886 207.622 99.4082C207.437 99.5931 207.197 99.7098 206.94 99.7421V100.044H207.38C207.46 100.044 207.526 100.11 207.526 100.19C207.526 100.271 207.46 100.337 207.38 100.337H206.208C206.128 100.337 206.062 100.271 206.062 100.19C206.062 100.11 206.128 100.044 206.208 100.044H206.648V99.7421C206.391 99.7098 206.151 99.5931 205.966 99.4082C205.746 99.1886 205.623 98.8907 205.623 98.5801V98.2873C205.623 98.2064 205.688 98.1409 205.769 98.1409Z"
|
||||
fill="#485264" />
|
||||
</g>
|
||||
<rect x="211.961" y="95.4004" width="6.35939" height="6.35939" rx="0.794923" fill="#171717"
|
||||
fill-opacity="0.1" />
|
||||
<path
|
||||
d="M216.777 98.4874C216.743 98.4199 216.636 98.3701 216.422 98.2705L214.103 97.189C213.858 97.0746 213.735 97.0173 213.652 97.0359C213.581 97.0521 213.522 97.099 213.493 97.1622C213.46 97.2351 213.501 97.3573 213.583 97.6017L213.83 98.341L214.611 98.4322C214.865 98.462 214.992 98.4768 215.018 98.4955C215.08 98.5401 215.08 98.6268 215.018 98.6713C214.992 98.69 214.865 98.7049 214.611 98.7346L213.828 98.8261L213.583 99.5584C213.501 99.8028 213.46 99.925 213.493 99.9979C213.522 100.061 213.581 100.108 213.652 100.124C213.735 100.143 213.858 100.086 214.103 99.9711L216.422 98.8896C216.636 98.79 216.743 98.7402 216.777 98.6728C216.807 98.6141 216.807 98.546 216.777 98.4874Z"
|
||||
fill="white" />
|
||||
</g>
|
||||
</g>
|
||||
<g filter="url(#filter2_dd_528_1010)">
|
||||
<rect x="212.5" y="113" width="13" height="13" rx="6.5" fill="#3370FF" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M216.764 121.736C216.634 121.605 216.634 121.394 216.764 121.264L218.529 119.5L216.764 117.736C216.634 117.605 216.634 117.394 216.764 117.264C216.895 117.134 217.106 117.134 217.236 117.264L219 119.029L220.764 117.264C220.895 117.134 221.106 117.134 221.236 117.264C221.366 117.394 221.366 117.605 221.236 117.736L219.471 119.5L221.236 121.264C221.366 121.394 221.366 121.605 221.236 121.736C221.106 121.866 220.895 121.866 220.764 121.736L219 119.971L217.236 121.736C217.106 121.866 216.895 121.866 216.764 121.736Z"
|
||||
fill="white" />
|
||||
</g>
|
||||
<mask id="path-23-inside-1_528_1010" fill="white">
|
||||
<path d="M0.5 9.73413H235.5V22.5H0.5V9.73413Z" />
|
||||
</mask>
|
||||
<path d="M0.5 9.73413H235.5V22.5H0.5V9.73413Z" fill="white" />
|
||||
<path d="M0.5 9.93413H235.5V9.53413H0.5V9.93413ZM235.5 22.3H0.5V22.7H235.5V22.3Z" fill="#DFE2EA"
|
||||
mask="url(#path-23-inside-1_528_1010)" />
|
||||
<rect x="19.0779" y="14.5801" width="24.7145" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="171.534" y="14.5801" width="10.8445" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="185.956" y="14.5801" width="10.8445" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="200.377" y="14.5801" width="10.8445" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="214.799" y="14.5801" width="10.8445" height="3" rx="1.5" fill="#E8EBF0" />
|
||||
<rect x="7.50122" y="12.0801" width="8" height="8" rx="4" fill="#E8EBF0" />
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_dd_528_1010" x="157.5" y="20.5801" width="79" height="103" filterUnits="userSpaceOnUse"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset />
|
||||
<feGaussianBlur stdDeviation="0.5" />
|
||||
<feComposite in2="hardAlpha" operator="out" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_528_1010" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset dy="4" />
|
||||
<feGaussianBlur stdDeviation="5" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="effect1_dropShadow_528_1010" result="effect2_dropShadow_528_1010" />
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_528_1010" result="shape" />
|
||||
</filter>
|
||||
<filter id="filter1_dd_528_1010" x="170.513" y="92.3877" width="52.9746" height="14.9746"
|
||||
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset />
|
||||
<feGaussianBlur stdDeviation="0.0993654" />
|
||||
<feComposite in2="hardAlpha" operator="out" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_528_1010" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset dy="0.794923" />
|
||||
<feGaussianBlur stdDeviation="0.993654" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="effect1_dropShadow_528_1010" result="effect2_dropShadow_528_1010" />
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_528_1010" result="shape" />
|
||||
</filter>
|
||||
<filter id="filter2_dd_528_1010" x="210.5" y="112" width="17" height="17" filterUnits="userSpaceOnUse"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset />
|
||||
<feGaussianBlur stdDeviation="0.5" />
|
||||
<feComposite in2="hardAlpha" operator="out" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_528_1010" />
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha" />
|
||||
<feOffset dy="1" />
|
||||
<feGaussianBlur stdDeviation="1" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0745098 0 0 0 0 0.2 0 0 0 0 0.419608 0 0 0 0.08 0" />
|
||||
<feBlend mode="normal" in2="effect1_dropShadow_528_1010" result="effect2_dropShadow_528_1010" />
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_528_1010" result="shape" />
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_528_1010" x1="177.112" y1="34.0066" x2="177.112" y2="38.9275"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#326DFF" />
|
||||
<stop offset="1" stop-color="#8EAEFF" />
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_528_1010" x1="177.908" y1="36.1102" x2="177.908" y2="37.3095"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#326DFF" />
|
||||
<stop offset="1" stop-color="#8EAEFF" />
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_528_1010">
|
||||
<rect x="0.5" width="235" height="134" rx="8" fill="white" />
|
||||
</clipPath>
|
||||
<clipPath id="clip1_528_1010">
|
||||
<rect width="5.42996" height="5.42996" fill="white" transform="translate(174.397 33.752)" />
|
||||
</clipPath>
|
||||
<clipPath id="clip2_528_1010">
|
||||
<rect width="3.97462" height="3.97462" fill="white" transform="translate(175.68 96.5928)" />
|
||||
</clipPath>
|
||||
<clipPath id="clip3_528_1010">
|
||||
<rect width="3.97462" height="3.97462" fill="white" transform="translate(204.807 96.5928)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 14 KiB |
@@ -1,10 +1,16 @@
|
||||
async function embedChatbot() {
|
||||
function embedChatbot() {
|
||||
const chatBtnId = 'fastgpt-chatbot-button';
|
||||
const chatWindowId = 'fastgpt-chatbot-window';
|
||||
const script = document.getElementById('fastgpt-iframe');
|
||||
const botSrc = script?.getAttribute('data-src');
|
||||
const primaryColor = script?.getAttribute('data-color') || '#4e83fd';
|
||||
const script = document.getElementById('chatbot-iframe');
|
||||
const botSrc = script?.getAttribute('data-bot-src');
|
||||
const defaultOpen = script?.getAttribute('data-default-open') === 'true';
|
||||
const canDrag = script?.getAttribute('data-drag') === 'true';
|
||||
const MessageIcon =
|
||||
script?.getAttribute('data-open-icon') ||
|
||||
`data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTMyNzg1NjY0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQxMzIiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDMyQzI0Ny4wNCAzMiAzMiAyMjQgMzIgNDY0QTQxMC4yNCA0MTAuMjQgMCAwIDAgMTcyLjQ4IDc2OEwxNjAgOTY1LjEyYTI1LjI4IDI1LjI4IDAgMCAwIDM5LjA0IDIyLjRsMTY4LTExMkE1MjguNjQgNTI4LjY0IDAgMCAwIDUxMiA4OTZjMjY0Ljk2IDAgNDgwLTE5MiA0ODAtNDMyUzc3Ni45NiAzMiA1MTIgMzJ6IG0yNDQuOCA0MTZsLTM2MS42IDMwMS43NmExMi40OCAxMi40OCAwIDAgMS0xOS44NC0xMi40OGw1OS4yLTIzMy45MmgtMTYwYTEyLjQ4IDEyLjQ4IDAgMCAxLTcuMzYtMjMuMzZsMzYxLjYtMzAxLjc2YTEyLjQ4IDEyLjQ4IDAgMCAxIDE5Ljg0IDEyLjQ4bC01OS4yIDIzMy45MmgxNjBhMTIuNDggMTIuNDggMCAwIDEgOCAyMi4wOHoiIGZpbGw9IiM0ZTgzZmQiIHAtaWQ9IjQxMzMiPjwvcGF0aD48L3N2Zz4=`;
|
||||
const CloseIcon =
|
||||
script?.getAttribute('data-close-icon') ||
|
||||
'data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTM1NDQxNTI2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjYzNjciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDEwMjRBNTEyIDUxMiAwIDEgMSA1MTIgMGE1MTIgNTEyIDAgMCAxIDAgMTAyNHpNMzA1Ljk1NjU3MSAzNzAuMzk1NDI5TDQ0Ny40ODggNTEyIDMwNS45NTY1NzEgNjUzLjYwNDU3MWE0NS41NjggNDUuNTY4IDAgMSAwIDY0LjQzODg1OCA2NC40Mzg4NThMNTEyIDU3Ni41MTJsMTQxLjYwNDU3MSAxNDEuNTMxNDI5YTQ1LjU2OCA0NS41NjggMCAwIDAgNjQuNDM4ODU4LTY0LjQzODg1OEw1NzYuNTEyIDUxMmwxNDEuNTMxNDI5LTE0MS42MDQ1NzFhNDUuNTY4IDQ1LjU2OCAwIDEgMC02NC40Mzg4NTgtNjQuNDM4ODU4TDUxMiA0NDcuNDg4IDM3MC4zOTU0MjkgMzA1Ljk1NjU3MWE0NS41NjggNDUuNTY4IDAgMCAwLTY0LjQzODg1OCA2NC40Mzg4NTh6IiBmaWxsPSIjNGU4M2ZkIiBwLWlkPSI2MzY4Ij48L3BhdGg+PC9zdmc+';
|
||||
|
||||
if (!botSrc) {
|
||||
console.error(`Can't find appid`);
|
||||
@@ -14,17 +20,17 @@ async function embedChatbot() {
|
||||
return;
|
||||
}
|
||||
|
||||
const MessageIcon = `<?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="1690532785664" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4132" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M512 32C247.04 32 32 224 32 464A410.24 410.24 0 0 0 172.48 768L160 965.12a25.28 25.28 0 0 0 39.04 22.4l168-112A528.64 528.64 0 0 0 512 896c264.96 0 480-192 480-432S776.96 32 512 32z m244.8 416l-361.6 301.76a12.48 12.48 0 0 1-19.84-12.48l59.2-233.92h-160a12.48 12.48 0 0 1-7.36-23.36l361.6-301.76a12.48 12.48 0 0 1 19.84 12.48l-59.2 233.92h160a12.48 12.48 0 0 1 8 22.08z" fill=${primaryColor} p-id="4133"></path></svg>`;
|
||||
|
||||
const CloseIcon = `<?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="1690535441526" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6367" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 1024A512 512 0 1 1 512 0a512 512 0 0 1 0 1024zM305.956571 370.395429L447.488 512 305.956571 653.604571a45.568 45.568 0 1 0 64.438858 64.438858L512 576.512l141.604571 141.531429a45.568 45.568 0 0 0 64.438858-64.438858L576.512 512l141.531429-141.604571a45.568 45.568 0 1 0-64.438858-64.438858L512 447.488 370.395429 305.956571a45.568 45.568 0 0 0-64.438858 64.438858z" fill=${primaryColor} p-id="6368"></path></svg>`;
|
||||
|
||||
const ChatBtn = document.createElement('div');
|
||||
ChatBtn.id = chatBtnId;
|
||||
ChatBtn.style.cssText =
|
||||
'position: fixed; bottom: 1rem; right: 1rem; width: 40px; height: 40px; cursor: pointer; z-index: 2147483647; transition: 0;';
|
||||
|
||||
const ChatBtnDiv = document.createElement('div');
|
||||
ChatBtnDiv.innerHTML = MessageIcon;
|
||||
// btn icon
|
||||
const ChatBtnDiv = document.createElement('img');
|
||||
ChatBtnDiv.src = defaultOpen ? CloseIcon : MessageIcon;
|
||||
ChatBtnDiv.setAttribute('width', '100%');
|
||||
ChatBtnDiv.setAttribute('height', '100%');
|
||||
ChatBtnDiv.draggable = false;
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.allow = 'fullscreen;microphone';
|
||||
@@ -52,14 +58,16 @@ async function embedChatbot() {
|
||||
const visibilityVal = chatWindow.style.visibility;
|
||||
if (visibilityVal === 'hidden') {
|
||||
chatWindow.style.visibility = 'unset';
|
||||
ChatBtnDiv.innerHTML = CloseIcon;
|
||||
ChatBtnDiv.src = CloseIcon;
|
||||
} else {
|
||||
chatWindow.style.visibility = 'hidden';
|
||||
ChatBtnDiv.innerHTML = MessageIcon;
|
||||
ChatBtnDiv.src = MessageIcon;
|
||||
}
|
||||
});
|
||||
|
||||
ChatBtn.addEventListener('mousedown', (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
if (!chatBtnMouseX && !chatBtnMouseY) {
|
||||
chatBtnMouseX = e.clientX;
|
||||
chatBtnMouseY = e.clientY;
|
||||
@@ -68,19 +76,21 @@ async function embedChatbot() {
|
||||
chatBtnDown = true;
|
||||
});
|
||||
ChatBtn.addEventListener('mousemove', (e) => {
|
||||
if (!chatBtnDown) return;
|
||||
e.stopPropagation();
|
||||
if (!canDrag || !chatBtnDown) return;
|
||||
|
||||
chatBtnDragged = true;
|
||||
const transformX = e.clientX - chatBtnMouseX;
|
||||
const transformY = e.clientY - chatBtnMouseY;
|
||||
|
||||
ChatBtn.style.transform = `translate3d(${transformX}px, ${transformY}px, 0)`;
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
ChatBtn.addEventListener('mouseup', (e) => {
|
||||
chatBtnDragged = false;
|
||||
chatBtnDown = false;
|
||||
});
|
||||
ChatBtn.addEventListener('mouseleave', (e) => {
|
||||
window.addEventListener('mouseup', (e) => {
|
||||
chatBtnDragged = false;
|
||||
chatBtnDown = false;
|
||||
});
|
||||
|
||||
|
@@ -265,6 +265,20 @@
|
||||
"logs": {
|
||||
"Source And Time": "Source & Time"
|
||||
},
|
||||
"outLink": {
|
||||
"Can Drag": "Icon Drag",
|
||||
"Default open": "Default Open",
|
||||
"Iframe block title": "Copy the Iframe below and add it to your web page",
|
||||
"Link block title": "Copy the link below to your browser to open",
|
||||
"Script Close Icon": "Close Icon",
|
||||
"Script Icon": "Icon",
|
||||
"Script Open Icon": "Open Script",
|
||||
"Script block title": "Add the following code to your website",
|
||||
"Select Mode": "Select Mode",
|
||||
"Select Using Way": "Select use mode",
|
||||
"Show History": "Show History",
|
||||
"Web Link": "Web Link"
|
||||
},
|
||||
"setting": "App Setting",
|
||||
"simple": {
|
||||
"mode template select": "Template"
|
||||
@@ -297,9 +311,9 @@
|
||||
"feedback": {
|
||||
"Close User Good Feedback": "",
|
||||
"Close User Like": "The user like\nClick to close the tag",
|
||||
"Feedback Close": "Close Feedback",
|
||||
"No Content": "The user did not fill in the specific feedback content",
|
||||
"Read User dislike": "User dislike\nClick to view content",
|
||||
"Feedback Close": "Close Feedback"
|
||||
"Read User dislike": "User dislike\nClick to view content"
|
||||
},
|
||||
"markdown": {
|
||||
"Edit Question": "Edit Question",
|
||||
|
@@ -265,6 +265,20 @@
|
||||
"logs": {
|
||||
"Source And Time": "来源 & 时间"
|
||||
},
|
||||
"outLink": {
|
||||
"Can Drag": "图标可拖拽",
|
||||
"Default open": "默认打开",
|
||||
"Iframe block title": "复制下面 Iframe 加入到你的网站中",
|
||||
"Link block title": "将下面链接复制到浏览器打开",
|
||||
"Script Close Icon": "关闭图标",
|
||||
"Script Icon": "图标",
|
||||
"Script Open Icon": "打开图标",
|
||||
"Script block title": "将下面代码加入到你的网站中",
|
||||
"Select Mode": "开始使用",
|
||||
"Select Using Way": "选择使用方式",
|
||||
"Show History": "展示历史对话",
|
||||
"Web Link": "网络链接"
|
||||
},
|
||||
"setting": "应用信息设置",
|
||||
"simple": {
|
||||
"mode template select": "简易模板"
|
||||
@@ -297,9 +311,9 @@
|
||||
"feedback": {
|
||||
"Close User Good Feedback": "",
|
||||
"Close User Like": "用户表示赞同\n点击关闭该标记",
|
||||
"Feedback Close": "关闭反馈",
|
||||
"No Content": "用户没有填写具体反馈内容",
|
||||
"Read User dislike": "用户表示反对\n点击查看内容",
|
||||
"Feedback Close": "关闭反馈"
|
||||
"Read User dislike": "用户表示反对\n点击查看内容"
|
||||
},
|
||||
"markdown": {
|
||||
"Edit Question": "编辑问题",
|
||||
|
@@ -6,11 +6,13 @@ import { useTranslation } from 'next-i18next';
|
||||
import { updateChatUserFeedback } from '@/web/core/chat/api';
|
||||
|
||||
const FeedbackModal = ({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId,
|
||||
onSuccess,
|
||||
onClose
|
||||
}: {
|
||||
appId: string;
|
||||
chatId: string;
|
||||
chatItemId: string;
|
||||
onSuccess: (e: string) => void;
|
||||
@@ -23,6 +25,7 @@ const FeedbackModal = ({
|
||||
mutationFn: async () => {
|
||||
const val = ref.current?.value || t('core.chat.feedback.No Content');
|
||||
return updateChatUserFeedback({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId,
|
||||
userBadFeedback: val
|
||||
|
@@ -429,7 +429,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
|
||||
>
|
||||
{isChatting ? (
|
||||
<MyIcon
|
||||
className={styles.stopIcon}
|
||||
animation={'zoomStopIcon 0.4s infinite alternate'}
|
||||
width={['22px', '25px']}
|
||||
height={['22px', '25px']}
|
||||
cursor={'pointer'}
|
||||
|
@@ -1,7 +1,3 @@
|
||||
.stopIcon {
|
||||
animation: zoomStopIcon 0.4s infinite alternate;
|
||||
}
|
||||
|
||||
.statusAnimation {
|
||||
animation: statusBox 0.8s linear infinite alternate;
|
||||
}
|
||||
|
@@ -102,9 +102,13 @@ type Props = {
|
||||
userGuideModule?: ModuleItemType;
|
||||
showFileSelector?: boolean;
|
||||
active?: boolean; // can use
|
||||
|
||||
// not chat test params
|
||||
appId?: string;
|
||||
chatId?: string;
|
||||
shareId?: string;
|
||||
outLinkUid?: string;
|
||||
|
||||
onUpdateVariable?: (e: Record<string, any>) => void;
|
||||
onStartChat?: (e: StartChatFnProps) => Promise<{
|
||||
responseText: string;
|
||||
@@ -125,6 +129,7 @@ const ChatBox = (
|
||||
userGuideModule,
|
||||
showFileSelector,
|
||||
active = true,
|
||||
appId,
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
@@ -711,7 +716,7 @@ const ChatBox = (
|
||||
return;
|
||||
}
|
||||
return () => {
|
||||
if (!item.dataId || !chatId) return;
|
||||
if (!item.dataId || !chatId || !appId) return;
|
||||
|
||||
const isGoodFeedback = !!item.userGoodFeedback;
|
||||
setChatHistory((state) =>
|
||||
@@ -726,6 +731,7 @@ const ChatBox = (
|
||||
);
|
||||
try {
|
||||
updateChatUserFeedback({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId: item.dataId,
|
||||
shareId,
|
||||
@@ -738,7 +744,7 @@ const ChatBox = (
|
||||
onCloseUserLike={
|
||||
feedbackType === FeedbackTypeEnum.admin
|
||||
? () => {
|
||||
if (!item.dataId || !chatId) return;
|
||||
if (!item.dataId || !chatId || !appId) return;
|
||||
setChatHistory((state) =>
|
||||
state.map((chatItem) =>
|
||||
chatItem.dataId === item.dataId
|
||||
@@ -747,6 +753,7 @@ const ChatBox = (
|
||||
)
|
||||
);
|
||||
updateChatUserFeedback({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId: item.dataId,
|
||||
userGoodFeedback: undefined
|
||||
@@ -760,7 +767,7 @@ const ChatBox = (
|
||||
}
|
||||
if (item.userBadFeedback) {
|
||||
return () => {
|
||||
if (!item.dataId || !chatId) return;
|
||||
if (!item.dataId || !chatId || !appId) return;
|
||||
setChatHistory((state) =>
|
||||
state.map((chatItem) =>
|
||||
chatItem.dataId === item.dataId
|
||||
@@ -770,6 +777,7 @@ const ChatBox = (
|
||||
);
|
||||
try {
|
||||
updateChatUserFeedback({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId: item.dataId,
|
||||
shareId,
|
||||
@@ -886,8 +894,9 @@ const ChatBox = (
|
||||
/>
|
||||
) : null}
|
||||
{/* user feedback modal */}
|
||||
{!!feedbackId && chatId && (
|
||||
{!!feedbackId && chatId && appId && (
|
||||
<FeedbackModal
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
chatItemId={feedbackId}
|
||||
onClose={() => setFeedbackId(undefined)}
|
||||
@@ -915,8 +924,9 @@ const ChatBox = (
|
||||
)
|
||||
);
|
||||
try {
|
||||
if (!chatId) return;
|
||||
if (!chatId || !appId) return;
|
||||
updateChatUserFeedback({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId: readFeedbackData.chatItemId
|
||||
});
|
||||
@@ -948,8 +958,9 @@ const ChatBox = (
|
||||
)
|
||||
);
|
||||
|
||||
if (readFeedbackData && chatId) {
|
||||
if (readFeedbackData && chatId && appId) {
|
||||
updateChatUserFeedback({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId: readFeedbackData.chatItemId,
|
||||
userBadFeedback: undefined
|
||||
|
@@ -10,6 +10,7 @@ import {
|
||||
Image
|
||||
} from '@chakra-ui/react';
|
||||
import MyIcon from '../Icon';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
|
||||
export interface MyModalProps extends ModalContentProps {
|
||||
iconSrc?: string;
|
||||
@@ -30,12 +31,13 @@ const MyModal = ({
|
||||
maxW = ['90vw', '600px'],
|
||||
...props
|
||||
}: MyModalProps) => {
|
||||
const { isPc } = useSystemStore();
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={() => onClose && onClose()}
|
||||
autoFocus={false}
|
||||
isCentered={isCentered}
|
||||
isCentered={isPc ? isCentered : true}
|
||||
>
|
||||
<ModalOverlay />
|
||||
<ModalContent
|
||||
|
@@ -5,11 +5,12 @@ import { useTranslation } from 'next-i18next';
|
||||
|
||||
// @ts-ignore
|
||||
interface Props extends GridProps {
|
||||
list: { icon?: string; title: string; desc?: string; value: string | number }[];
|
||||
list: { icon?: string; title: string | React.ReactNode; desc?: string; value: any }[];
|
||||
iconSize?: string;
|
||||
align?: 'top' | 'center';
|
||||
value: string | number;
|
||||
onChange: (e: string | number) => void;
|
||||
value: any;
|
||||
hiddenCircle?: boolean;
|
||||
onChange: (e: any) => void;
|
||||
}
|
||||
|
||||
const MyRadio = ({
|
||||
@@ -17,6 +18,8 @@ const MyRadio = ({
|
||||
value,
|
||||
align = 'center',
|
||||
iconSize = '18px',
|
||||
hiddenCircle = false,
|
||||
p,
|
||||
onChange,
|
||||
...props
|
||||
}: Props) => {
|
||||
@@ -32,7 +35,8 @@ const MyRadio = ({
|
||||
userSelect={'none'}
|
||||
py={3}
|
||||
pl={'14px'}
|
||||
pr={'36px'}
|
||||
pr={hiddenCircle ? '14px' : '36px'}
|
||||
p={p !== undefined ? `${p} !important` : undefined}
|
||||
border={theme.borders.sm}
|
||||
borderWidth={'1.5px'}
|
||||
borderRadius={'md'}
|
||||
@@ -50,6 +54,7 @@ const MyRadio = ({
|
||||
})}
|
||||
_after={{
|
||||
content: '""',
|
||||
display: hiddenCircle ? 'none' : 'block',
|
||||
position: 'absolute',
|
||||
right: '14px',
|
||||
w: '16px',
|
||||
@@ -79,8 +84,8 @@ const MyRadio = ({
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<Box pr={2}>
|
||||
<Box>{t(item.title)}</Box>
|
||||
<Box pr={hiddenCircle ? 0 : 2} color={'myGray.800'}>
|
||||
<Box>{typeof item.title === 'string' ? t(item.title) : item.title}</Box>
|
||||
{!!item.desc && (
|
||||
<Box fontSize={['xs', 'sm']} color={'myGray.500'}>
|
||||
{t(item.desc)}
|
||||
|
@@ -10,13 +10,13 @@ import React, {
|
||||
} from 'react';
|
||||
import { Box, Flex, IconButton } from '@chakra-ui/react';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { streamFetch } from '@/web/common/api/fetch';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
|
||||
import { getGuideModule } from '@fastgpt/global/core/module/utils';
|
||||
import { checkChatSupportSelectFileByModules } from '@/web/core/chat/utils';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
|
||||
export type ChatTestComponentRef = {
|
||||
resetChatTest: () => void;
|
||||
@@ -40,10 +40,18 @@ const ChatTest = (
|
||||
|
||||
const startChat = useCallback(
|
||||
async ({ chatList, controller, generatingMessage, variables }: StartChatFnProps) => {
|
||||
const historyMaxLen =
|
||||
modules
|
||||
?.find((item) => item.flowType === FlowNodeTypeEnum.historyNode)
|
||||
?.inputs?.find((item) => item.key === 'maxContext')?.value || 0;
|
||||
let historyMaxLen = 6;
|
||||
modules.forEach((module) => {
|
||||
module.inputs.forEach((input) => {
|
||||
if (
|
||||
(input.key === ModuleInputKeyEnum.history ||
|
||||
input.key === ModuleInputKeyEnum.historyMaxAmount) &&
|
||||
typeof input.value === 'number'
|
||||
) {
|
||||
historyMaxLen = Math.max(historyMaxLen, input.value);
|
||||
}
|
||||
});
|
||||
});
|
||||
const history = chatList.slice(-historyMaxLen - 2, -2);
|
||||
|
||||
// 流请求,获取数据
|
||||
|
@@ -28,7 +28,7 @@ import React, {
|
||||
import { customAlphabet } from 'nanoid';
|
||||
import { appModule2FlowEdge, appModule2FlowNode } from '@/utils/adapt';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleDataTypeEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { ModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||
@@ -449,9 +449,9 @@ export function flowNode2Modules({
|
||||
flowType: item.data.flowType,
|
||||
showStatus: item.data.showStatus,
|
||||
position: item.position,
|
||||
inputs: item.data.inputs.map((item) => ({
|
||||
...item,
|
||||
connected: Boolean(item.value ?? item.connected ?? item.type !== FlowNodeInputTypeEnum.target)
|
||||
inputs: item.data.inputs.map((input) => ({
|
||||
...input,
|
||||
connected: false
|
||||
})),
|
||||
outputs: item.data.outputs.map((item) => ({
|
||||
...item,
|
||||
@@ -462,10 +462,11 @@ export function flowNode2Modules({
|
||||
// update inputs and outputs
|
||||
modules.forEach((module) => {
|
||||
module.inputs.forEach((input) => {
|
||||
input.connected =
|
||||
input.connected ||
|
||||
!!edges.find((edge) => edge.target === module.moduleId && edge.targetHandle === input.key);
|
||||
input.connected = !!edges.find(
|
||||
(edge) => edge.target === module.moduleId && edge.targetHandle === input.key
|
||||
);
|
||||
});
|
||||
|
||||
module.outputs.forEach((output) => {
|
||||
output.targets = edges
|
||||
.filter(
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -12,9 +12,7 @@ import {
|
||||
Flex,
|
||||
Switch,
|
||||
Input,
|
||||
Grid,
|
||||
FormControl,
|
||||
useTheme,
|
||||
Image,
|
||||
Table,
|
||||
Thead,
|
||||
@@ -39,6 +37,7 @@ import MyTooltip from '@/components/MyTooltip';
|
||||
import { variableTip } from '@fastgpt/global/core/module/template/tip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import MyRadio from '@/components/common/MyRadio';
|
||||
|
||||
const VariableEdit = ({
|
||||
variables,
|
||||
@@ -49,26 +48,28 @@ const VariableEdit = ({
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const theme = useTheme();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
|
||||
const VariableTypeList = [
|
||||
const VariableTypeList = useMemo(
|
||||
() => [
|
||||
{
|
||||
label: t('core.module.variable.input type'),
|
||||
title: t('core.module.variable.input type'),
|
||||
icon: 'core/app/variable/input',
|
||||
key: VariableInputEnum.input
|
||||
value: VariableInputEnum.input
|
||||
},
|
||||
{
|
||||
label: t('core.module.variable.textarea type'),
|
||||
title: t('core.module.variable.textarea type'),
|
||||
icon: 'core/app/variable/textarea',
|
||||
key: VariableInputEnum.textarea
|
||||
value: VariableInputEnum.textarea
|
||||
},
|
||||
{
|
||||
label: t('core.module.variable.select type'),
|
||||
title: t('core.module.variable.select type'),
|
||||
icon: 'core/app/variable/select',
|
||||
key: VariableInputEnum.select
|
||||
value: VariableInputEnum.select
|
||||
}
|
||||
];
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
const { isOpen: isOpenEdit, onOpen: onOpenEdit, onClose: onCloseEdit } = useDisclosure();
|
||||
const {
|
||||
@@ -102,9 +103,9 @@ const VariableEdit = ({
|
||||
const formatVariables = useMemo(() => {
|
||||
return variables.map((item) => ({
|
||||
...item,
|
||||
icon: VariableTypeList.find((type) => type.key === item.type)?.icon
|
||||
icon: VariableTypeList.find((type) => type.value === item.type)?.icon
|
||||
}));
|
||||
}, [variables]);
|
||||
}, [VariableTypeList, variables]);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
@@ -206,38 +207,18 @@ const VariableEdit = ({
|
||||
<Box mt={5} mb={2}>
|
||||
{t('core.module.Field Type')}
|
||||
</Box>
|
||||
<Grid gridTemplateColumns={'repeat(3,1fr)'} gridGap={4}>
|
||||
{VariableTypeList.map((item) => (
|
||||
<Flex
|
||||
key={item.key}
|
||||
px={3}
|
||||
py={3}
|
||||
border={theme.borders.base}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
{...(item.key === getValuesEdit('variable.type')
|
||||
? {
|
||||
bg: 'myBlue.100',
|
||||
borderColor: 'myBlue.600',
|
||||
color: 'myBlue.600',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
: {
|
||||
color: 'myGray.600',
|
||||
_hover: {
|
||||
boxShadow: 'md'
|
||||
},
|
||||
onClick: () => {
|
||||
setValuesEdit('variable.type', item.key);
|
||||
<MyRadio
|
||||
gridGap={4}
|
||||
gridTemplateColumns={'repeat(3,1fr)'}
|
||||
value={getValuesEdit('variable.type')}
|
||||
list={VariableTypeList}
|
||||
color={'myGray.600'}
|
||||
hiddenCircle
|
||||
onChange={(e) => {
|
||||
setValuesEdit('variable.type', e as any);
|
||||
setRefresh(!refresh);
|
||||
}
|
||||
})}
|
||||
>
|
||||
<MyIcon name={item.icon as any} w={'16px'} />
|
||||
<Box ml={2}>{item.label}</Box>
|
||||
</Flex>
|
||||
))}
|
||||
</Grid>
|
||||
}}
|
||||
/>
|
||||
|
||||
{getValuesEdit('variable.type') === VariableInputEnum.input && (
|
||||
<>
|
||||
|
@@ -97,7 +97,7 @@ const NodeCQNode = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<SourceHandle handleKey={item.key} valueType={ModuleDataTypeEnum.boolean} />
|
||||
<SourceHandle handleKey={item.key} valueType={ModuleDataTypeEnum.string} />
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
|
@@ -29,7 +29,7 @@ import TargetHandle from './TargetHandle';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import type { AIChatModuleProps } from '@fastgpt/global/core/module/node/type.d';
|
||||
import { chatModelList } from '@/web/common/system/staticData';
|
||||
import { chatModelList, cqModelList } from '@/web/common/system/staticData';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d';
|
||||
@@ -229,8 +229,11 @@ const RenderInput = ({
|
||||
{item.type === FlowNodeInputTypeEnum.aiSettings && (
|
||||
<AISetting inputs={sortInputs} item={item} moduleId={moduleId} />
|
||||
)}
|
||||
{item.type === FlowNodeInputTypeEnum.selectChatModel && (
|
||||
<SelectChatModelRender inputs={sortInputs} item={item} moduleId={moduleId} />
|
||||
{[
|
||||
FlowNodeInputTypeEnum.selectChatModel,
|
||||
FlowNodeInputTypeEnum.selectCQModel
|
||||
].includes(item.type as any) && (
|
||||
<SelectAIModelRender inputs={sortInputs} item={item} moduleId={moduleId} />
|
||||
)}
|
||||
{item.type === FlowNodeInputTypeEnum.selectDataset && (
|
||||
<SelectDatasetRender item={item} moduleId={moduleId} />
|
||||
@@ -446,12 +449,21 @@ const AISetting = React.memo(function AISetting({ inputs = [], moduleId }: Rende
|
||||
);
|
||||
});
|
||||
|
||||
const SelectChatModelRender = React.memo(function SelectChatModelRender({
|
||||
const SelectAIModelRender = React.memo(function SelectAIModelRender({
|
||||
inputs = [],
|
||||
item,
|
||||
moduleId
|
||||
}: RenderProps) {
|
||||
const modelList = chatModelList || [];
|
||||
const modelList = (() => {
|
||||
if (item.type === FlowNodeInputTypeEnum.selectChatModel) return chatModelList;
|
||||
if (item.type === FlowNodeInputTypeEnum.selectCQModel) return cqModelList;
|
||||
return [];
|
||||
})().map((item) => ({
|
||||
model: item.model,
|
||||
name: item.name,
|
||||
maxResponse: item.maxResponse,
|
||||
price: item.price
|
||||
}));
|
||||
|
||||
const onChangeModel = useCallback(
|
||||
(e: string) => {
|
||||
|
3
projects/app/src/global/core/chat/api.d.ts
vendored
3
projects/app/src/global/core/chat/api.d.ts
vendored
@@ -44,6 +44,7 @@ export type getHistoriesProps = {
|
||||
};
|
||||
|
||||
export type UpdateHistoryProps = {
|
||||
appId: string;
|
||||
chatId: string;
|
||||
customTitle?: string;
|
||||
top?: boolean;
|
||||
@@ -52,6 +53,7 @@ export type UpdateHistoryProps = {
|
||||
};
|
||||
|
||||
export type DelHistoryProps = {
|
||||
appId: string;
|
||||
chatId: string;
|
||||
shareId?: string;
|
||||
outLinkUid?: string;
|
||||
@@ -64,6 +66,7 @@ export type ClearHistoriesProps = {
|
||||
|
||||
/* -------- chat item ---------- */
|
||||
export type DeleteChatItemProps = {
|
||||
appId: string;
|
||||
chatId: string;
|
||||
contentId?: string;
|
||||
shareId?: string;
|
||||
|
@@ -18,46 +18,40 @@ A2:
|
||||
`
|
||||
};
|
||||
|
||||
export const Prompt_ExtractJson = `你可以从 "对话记录" 中提取指定信息,并返回一个 JSON 对象,JSON 对象要求:
|
||||
1. JSON 对象仅包含字段说明中的值。
|
||||
2. 字段说明中的 required 决定 JSON 对象是否必须存在该字段。
|
||||
3. 必须存在的字段,值可以为空字符串或根据提取要求来设置,不能随机生成值。
|
||||
|
||||
提取要求:
|
||||
"""
|
||||
export const Prompt_ExtractJson = `你可以从 <对话记录></对话记录> 中提取指定 JSON 信息,你仅需返回 JSON 字符串,无需回答问题。
|
||||
<提取要求>
|
||||
{{description}}
|
||||
"""
|
||||
</提取要求>
|
||||
|
||||
<字段说明>
|
||||
1. 下面的 JSON 字符串均按照 JSON Schema 的规则描述。
|
||||
2. key 代表字段名,description 代表字段的描述,required 代表字段是否必须。
|
||||
3. 如果字段内容为空,你可以返回空字符串。
|
||||
|
||||
字段说明:
|
||||
"""
|
||||
{{json}}
|
||||
"""
|
||||
</字段说明>
|
||||
|
||||
对话记录:
|
||||
"""
|
||||
<对话记录>
|
||||
{{text}}
|
||||
"""
|
||||
</对话记录>
|
||||
`;
|
||||
|
||||
export const Prompt_CQJson = `我会给你几个问题类型,请参考额外的背景知识(可能为空)和对话内容,判断我本次的问题类型,并返回对应类型的 ID,格式为 JSON 字符串:
|
||||
"""
|
||||
'{"type":"问题类型的 ID"}'
|
||||
'{"问题类型":"类型的 ID"}'
|
||||
"""
|
||||
|
||||
问题类型:
|
||||
"""
|
||||
<问题类型>
|
||||
{{typeList}}
|
||||
"""
|
||||
</问题类型>
|
||||
|
||||
额外背景知识:
|
||||
"""
|
||||
<背景知识>
|
||||
{{systemPrompt}}
|
||||
"""
|
||||
</背景知识>
|
||||
|
||||
对话内容:
|
||||
"""
|
||||
<对话内容>
|
||||
{{text}}
|
||||
"""
|
||||
</对话内容>
|
||||
`;
|
||||
|
||||
export const Prompt_QuestionGuide = `我不太清楚问你什么问题,请帮我生成 3 个问题,引导我继续提问。问题的长度应小于20个字符,按 JSON 格式返回: ["问题1", "问题2", "问题3"]`;
|
||||
|
@@ -71,47 +71,6 @@ function simpleChatTemplate({
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'history',
|
||||
name: '聊天记录',
|
||||
avatar: '/imgs/module/history.png',
|
||||
flowType: 'historyNode',
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
type: 'numberInput',
|
||||
label: '最长记录数',
|
||||
value: 10,
|
||||
min: 0,
|
||||
max: 50,
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
name: 'AI 对话',
|
||||
@@ -191,7 +150,6 @@ function simpleChatTemplate({
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
valueType: 'string',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -199,7 +157,6 @@ function simpleChatTemplate({
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
valueType: 'string',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -234,7 +191,8 @@ function simpleChatTemplate({
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.chat history',
|
||||
valueType: 'chatHistory',
|
||||
connected: true
|
||||
connected: true,
|
||||
value: 8
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
@@ -318,47 +276,6 @@ function datasetTemplate({
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'history',
|
||||
name: '聊天记录',
|
||||
avatar: '/imgs/module/history.png',
|
||||
flowType: 'historyNode',
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
type: 'numberInput',
|
||||
label: '最长记录数',
|
||||
value: 6,
|
||||
min: 0,
|
||||
max: 50,
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'datasetSearch',
|
||||
name: '知识库搜索',
|
||||
@@ -541,7 +458,6 @@ function datasetTemplate({
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
valueType: 'string',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -549,7 +465,6 @@ function datasetTemplate({
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
valueType: 'string',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -584,7 +499,8 @@ function datasetTemplate({
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.chat history',
|
||||
valueType: 'chatHistory',
|
||||
connected: true
|
||||
connected: true,
|
||||
value: 8
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
|
@@ -89,18 +89,19 @@ function chatModelInput(formData: AppSimpleEditFormType): FlowNodeInputItemType[
|
||||
label: '触发器',
|
||||
connected: formData.dataset.datasets.length > 0 && !!formData.dataset.searchEmptyText
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.chat history',
|
||||
connected: true,
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
type: 'target',
|
||||
label: '引用内容',
|
||||
connected: formData.dataset.datasets.length > 0
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'target',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
type: 'target',
|
||||
@@ -139,41 +140,6 @@ function simpleChatTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
},
|
||||
moduleId: 'userChatInput'
|
||||
},
|
||||
{
|
||||
name: '聊天记录',
|
||||
flowType: FlowNodeTypeEnum.historyNode,
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
value: 6,
|
||||
connected: true,
|
||||
type: 'numberInput',
|
||||
label: '最长记录数'
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
moduleId: 'history'
|
||||
},
|
||||
{
|
||||
name: 'AI 对话',
|
||||
flowType: FlowNodeTypeEnum.chatNode,
|
||||
@@ -238,41 +204,6 @@ function datasetTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
},
|
||||
moduleId: 'userChatInput'
|
||||
},
|
||||
{
|
||||
name: '聊天记录',
|
||||
flowType: FlowNodeTypeEnum.historyNode,
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
value: 6,
|
||||
connected: true,
|
||||
type: 'numberInput',
|
||||
label: '最长记录数'
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
moduleId: 'history'
|
||||
},
|
||||
{
|
||||
name: '知识库搜索',
|
||||
flowType: FlowNodeTypeEnum.datasetSearchNode,
|
||||
|
@@ -64,8 +64,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
appId,
|
||||
modules,
|
||||
variables,
|
||||
params: {
|
||||
history,
|
||||
histories: history,
|
||||
startParams: {
|
||||
userChatInput: prompt
|
||||
},
|
||||
stream: true,
|
||||
|
@@ -10,11 +10,12 @@ import { autChatCrud } from '@/service/support/permission/auth/chat';
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { chatId, shareId, outLinkUid } = req.query as DelHistoryProps;
|
||||
const { appId, chatId, shareId, outLinkUid } = req.query as DelHistoryProps;
|
||||
|
||||
await autChatCrud({
|
||||
req,
|
||||
authToken: true,
|
||||
appId,
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
|
@@ -7,7 +7,7 @@ import { autChatCrud } from '@/service/support/permission/auth/chat';
|
||||
|
||||
/* 初始化我的聊天框,需要身份验证 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { chatId, chatItemId, shareId, outLinkUid, userBadFeedback, userGoodFeedback } =
|
||||
const { appId, chatId, chatItemId, shareId, outLinkUid, userBadFeedback, userGoodFeedback } =
|
||||
req.body as UpdateChatFeedbackProps;
|
||||
|
||||
try {
|
||||
@@ -16,6 +16,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
await autChatCrud({
|
||||
req,
|
||||
authToken: true,
|
||||
appId,
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
|
@@ -8,7 +8,7 @@ import type { DeleteChatItemProps } from '@/global/core/chat/api.d';
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { chatId, contentId, shareId, outLinkUid } = req.query as DeleteChatItemProps;
|
||||
const { appId, chatId, contentId, shareId, outLinkUid } = req.query as DeleteChatItemProps;
|
||||
|
||||
if (!contentId || !chatId) {
|
||||
return jsonRes(res);
|
||||
@@ -17,6 +17,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
await autChatCrud({
|
||||
req,
|
||||
authToken: true,
|
||||
appId,
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
|
@@ -9,11 +9,12 @@ import { autChatCrud } from '@/service/support/permission/auth/chat';
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { chatId, shareId, outLinkUid, customTitle, top } = req.body as UpdateHistoryProps;
|
||||
const { appId, chatId, shareId, outLinkUid, customTitle, top } = req.body as UpdateHistoryProps;
|
||||
|
||||
await autChatCrud({
|
||||
req,
|
||||
authToken: true,
|
||||
appId,
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
|
@@ -16,7 +16,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
|
||||
const [userPlugins, plusPlugins] = await Promise.all([
|
||||
MongoPlugin.find({ teamId }).lean(),
|
||||
global.systemEnv.pluginBaseUrl ? GET<PluginTemplateType[]>('/core/plugin/getTemplates') : []
|
||||
global.systemEnv?.pluginBaseUrl ? GET<PluginTemplateType[]>('/core/plugin/getTemplates') : []
|
||||
]);
|
||||
|
||||
const data: FlowModuleTemplateType[] = [
|
||||
|
@@ -21,6 +21,7 @@ import { SimpleModeTemplate_FastGPT_Universal } from '@/global/core/app/constant
|
||||
import { getSimpleTemplatesFromPlus } from '@/service/core/app/utils';
|
||||
import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants';
|
||||
import { getFastGPTFeConfig } from '@fastgpt/service/common/system/config/controller';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
await getInitConfig();
|
||||
@@ -68,6 +69,7 @@ const defaultFeConfigs: FeConfigsType = {
|
||||
export async function getInitConfig() {
|
||||
try {
|
||||
if (global.feConfigs) return;
|
||||
await connectToDatabase();
|
||||
initGlobal();
|
||||
|
||||
const filename =
|
||||
|
@@ -180,6 +180,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
req,
|
||||
authToken: true,
|
||||
authApiKey: true,
|
||||
appId: app._id,
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
@@ -188,7 +189,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
|
||||
// get and concat history
|
||||
const { history } = await getChatItems({ chatId, limit: 30, field: `dataId obj value` });
|
||||
const concatHistory = history.concat(chatMessages);
|
||||
const concatHistories = history.concat(chatMessages);
|
||||
|
||||
/* start flow controller */
|
||||
const { responseData, answerText } = await dispatchModules({
|
||||
@@ -200,8 +201,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
teamId: user.team.teamId,
|
||||
tmbId: user.team.tmbId,
|
||||
variables,
|
||||
params: {
|
||||
history: concatHistory,
|
||||
histories: concatHistories,
|
||||
startParams: {
|
||||
userChatInput: question.value
|
||||
},
|
||||
stream,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { useRef, useState } from 'react';
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import { Box, Flex, IconButton, useTheme, useDisclosure } from '@chakra-ui/react';
|
||||
import { SmallCloseIcon } from '@chakra-ui/icons';
|
||||
import { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
@@ -14,6 +14,7 @@ import MyTooltip from '@/components/MyTooltip';
|
||||
import ChatTest, { type ChatTestComponentRef } from '@/components/core/module/Flow/ChatTest';
|
||||
import { flowNode2Modules, useFlowProviderStore } from '@/components/core/module/Flow/FlowProvider';
|
||||
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
|
||||
const ImportSettings = dynamic(() => import('@/components/core/module/Flow/ImportSettings'));
|
||||
|
||||
@@ -31,6 +32,7 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
|
||||
setTestModules: React.Dispatch<ModuleItemType[] | undefined>;
|
||||
}) {
|
||||
const theme = useTheme();
|
||||
const { toast } = useToast();
|
||||
const { t } = useTranslation();
|
||||
const { copyData } = useCopyData();
|
||||
const { isOpen: isOpenImport, onOpen: onOpenImport, onClose: onCloseImport } = useDisclosure();
|
||||
@@ -38,8 +40,8 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
|
||||
|
||||
const { nodes, edges, onFixView } = useFlowProviderStore();
|
||||
|
||||
const { mutate: onclickSave, isLoading } = useRequest({
|
||||
mutationFn: () => {
|
||||
const flow2ModulesAndCheck = useCallback(
|
||||
(tip = false) => {
|
||||
const modules = flowNode2Modules({ nodes, edges });
|
||||
// check required connect
|
||||
for (let i = 0; i < modules.length; i++) {
|
||||
@@ -51,12 +53,24 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
|
||||
return false;
|
||||
})
|
||||
) {
|
||||
return Promise.reject(`【${item.name}】存在未填或未连接参数`);
|
||||
const msg = `【${item.name}】存在未填或未连接参数`;
|
||||
tip &&
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: msg
|
||||
});
|
||||
return Promise.reject(msg);
|
||||
}
|
||||
}
|
||||
return modules;
|
||||
},
|
||||
[edges, nodes, toast]
|
||||
);
|
||||
|
||||
const { mutate: onclickSave, isLoading } = useRequest({
|
||||
mutationFn: async () => {
|
||||
return updateAppDetail(app._id, {
|
||||
modules,
|
||||
modules: await flow2ModulesAndCheck(),
|
||||
type: AppTypeEnum.advanced,
|
||||
permission: undefined
|
||||
});
|
||||
@@ -139,8 +153,8 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
|
||||
borderRadius={'lg'}
|
||||
aria-label={'save'}
|
||||
variant={'base'}
|
||||
onClick={() => {
|
||||
setTestModules(flowNode2Modules({ nodes, edges }));
|
||||
onClick={async () => {
|
||||
setTestModules(await flow2ModulesAndCheck(true));
|
||||
}}
|
||||
/>
|
||||
</MyTooltip>
|
||||
|
@@ -321,6 +321,7 @@ function DetailLogsModal({
|
||||
showMarkIcon
|
||||
showVoiceIcon={false}
|
||||
userGuideModule={chat?.app?.userGuideModule}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
/>
|
||||
</Box>
|
||||
|
@@ -1,9 +0,0 @@
|
||||
import { OutLinkSchema } from '@fastgpt/global/support/outLink/type';
|
||||
import React from 'react';
|
||||
import MyModal from '@/components/MyModal';
|
||||
|
||||
const EmbModal = ({ share }: { share: OutLinkSchema }) => {
|
||||
return <MyModal isOpen>EmbModal</MyModal>;
|
||||
};
|
||||
|
||||
export default EmbModal;
|
@@ -0,0 +1,209 @@
|
||||
import { OutLinkSchema } from '@fastgpt/global/support/outLink/type';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { Box, Flex, FlexProps, Grid, Image, ModalBody, Switch, useTheme } from '@chakra-ui/react';
|
||||
import MyRadio from '@/components/common/MyRadio';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { fileToBase64 } from '@/web/common/file/utils';
|
||||
|
||||
enum UsingWayEnum {
|
||||
link = 'link',
|
||||
iframe = 'iframe',
|
||||
script = 'script'
|
||||
}
|
||||
|
||||
const SelectUsingWayModal = ({ share, onClose }: { share: OutLinkSchema; onClose: () => void }) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { copyData } = useCopyData();
|
||||
const { File, onOpen } = useSelectFile({
|
||||
multiple: false,
|
||||
fileType: 'image/*'
|
||||
});
|
||||
|
||||
const VariableTypeList = [
|
||||
{
|
||||
title: <Image src={'/imgs/outlink/link.svg'} alt={''} />,
|
||||
value: UsingWayEnum.link
|
||||
},
|
||||
{
|
||||
title: <Image src={'/imgs/outlink/iframe.svg'} alt={''} />,
|
||||
value: UsingWayEnum.iframe
|
||||
},
|
||||
{
|
||||
title: <Image src={'/imgs/outlink/script.svg'} alt={''} />,
|
||||
value: UsingWayEnum.script
|
||||
}
|
||||
];
|
||||
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
|
||||
const { getValues, setValue, register, watch } = useForm({
|
||||
defaultValues: {
|
||||
usingWay: UsingWayEnum.link,
|
||||
showHistory: true,
|
||||
scriptIconCanDrag: true,
|
||||
scriptDefaultOpen: true,
|
||||
scriptOpenIcon:
|
||||
'data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTMyNzg1NjY0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQxMzIiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDMyQzI0Ny4wNCAzMiAzMiAyMjQgMzIgNDY0QTQxMC4yNCA0MTAuMjQgMCAwIDAgMTcyLjQ4IDc2OEwxNjAgOTY1LjEyYTI1LjI4IDI1LjI4IDAgMCAwIDM5LjA0IDIyLjRsMTY4LTExMkE1MjguNjQgNTI4LjY0IDAgMCAwIDUxMiA4OTZjMjY0Ljk2IDAgNDgwLTE5MiA0ODAtNDMyUzc3Ni45NiAzMiA1MTIgMzJ6IG0yNDQuOCA0MTZsLTM2MS42IDMwMS43NmExMi40OCAxMi40OCAwIDAgMS0xOS44NC0xMi40OGw1OS4yLTIzMy45MmgtMTYwYTEyLjQ4IDEyLjQ4IDAgMCAxLTcuMzYtMjMuMzZsMzYxLjYtMzAxLjc2YTEyLjQ4IDEyLjQ4IDAgMCAxIDE5Ljg0IDEyLjQ4bC01OS4yIDIzMy45MmgxNjBhMTIuNDggMTIuNDggMCAwIDEgOCAyMi4wOHoiIGZpbGw9IiM0ZTgzZmQiIHAtaWQ9IjQxMzMiPjwvcGF0aD48L3N2Zz4=',
|
||||
scriptCloseIcon:
|
||||
'data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTM1NDQxNTI2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjYzNjciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDEwMjRBNTEyIDUxMiAwIDEgMSA1MTIgMGE1MTIgNTEyIDAgMCAxIDAgMTAyNHpNMzA1Ljk1NjU3MSAzNzAuMzk1NDI5TDQ0Ny40ODggNTEyIDMwNS45NTY1NzEgNjUzLjYwNDU3MWE0NS41NjggNDUuNTY4IDAgMSAwIDY0LjQzODg1OCA2NC40Mzg4NThMNTEyIDU3Ni41MTJsMTQxLjYwNDU3MSAxNDEuNTMxNDI5YTQ1LjU2OCA0NS41NjggMCAwIDAgNjQuNDM4ODU4LTY0LjQzODg1OEw1NzYuNTEyIDUxMmwxNDEuNTMxNDI5LTE0MS42MDQ1NzFhNDUuNTY4IDQ1LjU2OCAwIDEgMC02NC40Mzg4NTgtNjQuNDM4ODU4TDUxMiA0NDcuNDg4IDM3MC4zOTU0MjkgMzA1Ljk1NjU3MWE0NS41NjggNDUuNTY4IDAgMCAwLTY0LjQzODg1OCA2NC40Mzg4NTh6IiBmaWxsPSIjNGU4M2ZkIiBwLWlkPSI2MzY4Ij48L3BhdGg+PC9zdmc+'
|
||||
}
|
||||
});
|
||||
|
||||
const selectFile = useCallback(
|
||||
async (files: File[], key: 'scriptOpenIcon' | 'scriptCloseIcon') => {
|
||||
const file = files[0];
|
||||
if (!file) return;
|
||||
// image to base64
|
||||
const base64 = await fileToBase64(file);
|
||||
setValue(key, base64);
|
||||
},
|
||||
[setValue]
|
||||
);
|
||||
|
||||
watch(() => {
|
||||
setRefresh(!refresh);
|
||||
});
|
||||
|
||||
const linkUrl = `${location?.origin}/chat/share?shareId=${share?.shareId}${
|
||||
getValues('showHistory') ? '' : '&showHistory=0'
|
||||
}`;
|
||||
|
||||
const wayMap = {
|
||||
[UsingWayEnum.link]: {
|
||||
blockTitle: t('core.app.outLink.Link block title'),
|
||||
code: linkUrl
|
||||
},
|
||||
[UsingWayEnum.iframe]: {
|
||||
blockTitle: t('core.app.outLink.Iframe block title'),
|
||||
code: `<iframe
|
||||
src="${linkUrl}"
|
||||
style="width: 100%; height: 100%;"
|
||||
frameborder="0"
|
||||
allow="microphone"
|
||||
/>`
|
||||
},
|
||||
[UsingWayEnum.script]: {
|
||||
blockTitle: t('core.app.outLink.Script block title'),
|
||||
code: `<script
|
||||
src="${location?.origin}/js/iframe.js"
|
||||
id="chatbot-iframe"
|
||||
data-bot-src="${linkUrl}"
|
||||
data-default-open="${getValues('scriptDefaultOpen') ? 'true' : 'false'}"
|
||||
data-drag="${getValues('scriptIconCanDrag') ? 'true' : 'false'}"
|
||||
data-open-icon="${getValues('scriptOpenIcon')}"
|
||||
data-close-icon="${getValues('scriptCloseIcon')}"
|
||||
defer
|
||||
/>`
|
||||
}
|
||||
};
|
||||
|
||||
const gridItemStyle: FlexProps = {
|
||||
alignItems: 'center',
|
||||
bg: 'myWhite.600',
|
||||
p: 2,
|
||||
borderRadius: 'md',
|
||||
border: theme.borders.sm
|
||||
};
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
isOpen
|
||||
iconSrc="/imgs/modal/usingWay.svg"
|
||||
title={t('core.app.outLink.Select Using Way')}
|
||||
onClose={onClose}
|
||||
maxW={['90vw', '700px']}
|
||||
>
|
||||
<ModalBody py={4}>
|
||||
<MyRadio
|
||||
gridGap={2}
|
||||
gridTemplateColumns={['repeat(1,1fr)', 'repeat(3,1fr)']}
|
||||
value={getValues('usingWay')}
|
||||
list={VariableTypeList}
|
||||
hiddenCircle
|
||||
p={0}
|
||||
onChange={(e) => {
|
||||
setValue('usingWay', e);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* config */}
|
||||
<Grid gridTemplateColumns={['repeat(3,1fr)']} gridGap={4} my={5}>
|
||||
<Flex {...gridItemStyle}>
|
||||
<Box flex={1}>{t('core.app.outLink.Show History')}</Box>
|
||||
<Switch {...register('showHistory')} />
|
||||
</Flex>
|
||||
{getValues('usingWay') === UsingWayEnum.script && (
|
||||
<>
|
||||
<Flex {...gridItemStyle}>
|
||||
<Box flex={1}>{t('core.app.outLink.Can Drag')}</Box>
|
||||
<Switch {...register('scriptIconCanDrag')} />
|
||||
</Flex>
|
||||
<Flex {...gridItemStyle}>
|
||||
<Box flex={1}>{t('core.app.outLink.Default open')}</Box>
|
||||
<Switch {...register('scriptDefaultOpen')} />
|
||||
</Flex>
|
||||
<Flex {...gridItemStyle}>
|
||||
<Box flex={1}>{t('core.app.outLink.Script Open Icon')}</Box>
|
||||
<Image
|
||||
src={getValues('scriptOpenIcon')}
|
||||
alt={''}
|
||||
w={'20px'}
|
||||
h={'20px'}
|
||||
cursor={'pointer'}
|
||||
onClick={() => onOpen('scriptOpenIcon')}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex {...gridItemStyle}>
|
||||
<Box flex={1}>{t('core.app.outLink.Script Close Icon')}</Box>
|
||||
<Image
|
||||
src={getValues('scriptCloseIcon')}
|
||||
alt={''}
|
||||
w={'20px'}
|
||||
h={'20px'}
|
||||
cursor={'pointer'}
|
||||
onClick={() => onOpen('scriptCloseIcon')}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
{/* code */}
|
||||
<Box borderRadius={'md'} bg={'myGray.100'} overflow={'hidden'}>
|
||||
<Flex
|
||||
p={3}
|
||||
bg={'myWhite.500'}
|
||||
border={theme.borders.base}
|
||||
borderTopLeftRadius={'md'}
|
||||
borderTopRightRadius={'md'}
|
||||
>
|
||||
<Box flex={1}>{wayMap[getValues('usingWay')].blockTitle}</Box>
|
||||
<MyIcon
|
||||
name={'copy'}
|
||||
w={'16px'}
|
||||
color={'myGray.600'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
onClick={() => {
|
||||
copyData(wayMap[getValues('usingWay')].code);
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Box whiteSpace={'pre'} p={3} overflowX={'auto'}>
|
||||
{wayMap[getValues('usingWay')].code}
|
||||
</Box>
|
||||
</Box>
|
||||
</ModalBody>
|
||||
|
||||
<File onSelect={selectFile} />
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectUsingWayModal;
|
@@ -34,7 +34,7 @@ import { formatTimeToChatTime } from '@/utils/tools';
|
||||
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { defaultOutLinkForm } from '@/constants/app';
|
||||
import type { OutLinkEditType } from '@fastgpt/global/support/outLink/type.d';
|
||||
import type { OutLinkEditType, OutLinkSchema } from '@fastgpt/global/support/outLink/type.d';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { OutLinkTypeEnum } from '@fastgpt/global/support/outLink/constant';
|
||||
@@ -45,12 +45,16 @@ import MyTooltip from '@/components/MyTooltip';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import dayjs from 'dayjs';
|
||||
import { getDocPath } from '@/web/common/system/doc';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const SelectUsingWayModal = dynamic(() => import('./SelectUsingWayModal'));
|
||||
|
||||
const Share = ({ appId }: { appId: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const { Loading, setIsLoading } = useLoading();
|
||||
const { copyData } = useCopyData();
|
||||
const [editLinkData, setEditLinkData] = useState<OutLinkEditType>();
|
||||
const [selectedLinkData, setSelectedLinkData] = useState<OutLinkSchema>();
|
||||
const { toast } = useToast();
|
||||
|
||||
const {
|
||||
@@ -141,6 +145,15 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
<MyIcon name={'more'} w={'14px'} p={2} />
|
||||
</MenuButton>
|
||||
<MenuList color={'myGray.700'} minW={`120px !important`} zIndex={10}>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setSelectedLinkData(item);
|
||||
}}
|
||||
py={[2, 3]}
|
||||
>
|
||||
<MyIcon name={'copy'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('core.app.outLink.Select Mode')}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
setEditLinkData({
|
||||
@@ -155,28 +168,6 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
<MyIcon name={'edit'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('common.Edit')}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
const url = `${location.origin}/chat/share?shareId=${item.shareId}`;
|
||||
copyData(url, '已复制分享链接,可直接分享使用');
|
||||
}}
|
||||
py={[2, 3]}
|
||||
>
|
||||
<MyIcon name={'copy'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('common.Copy')}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
const url = `${location.origin}/chat/share?shareId=${item.shareId}`;
|
||||
const src = `${location.origin}/js/iframe.js`;
|
||||
const script = `<script src="${src}" id="fastgpt-iframe" data-src="${url}" data-color="#4e83fd"></script>`;
|
||||
copyData(script, '已复制嵌入 Script,可在应用 HTML 底部嵌入', 3000);
|
||||
}}
|
||||
py={[2, 3]}
|
||||
>
|
||||
<MyIcon name={'apiLight'} w={['14px', '16px']} />
|
||||
<Box ml={[1, 2]}>{t('outlink.Copy IFrame')}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={async () => {
|
||||
setIsLoading(true);
|
||||
@@ -232,6 +223,12 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
onClose={() => setEditLinkData(undefined)}
|
||||
/>
|
||||
)}
|
||||
{!!selectedLinkData && (
|
||||
<SelectUsingWayModal
|
||||
share={selectedLinkData}
|
||||
onClose={() => setSelectedLinkData(undefined)}
|
||||
/>
|
||||
)}
|
||||
<Loading loading={isFetching} fixed={false} />
|
||||
</Box>
|
||||
);
|
||||
@@ -290,7 +287,7 @@ function EditLinkModal({
|
||||
>
|
||||
<ModalBody>
|
||||
<Flex alignItems={'center'}>
|
||||
<Box flex={'0 0 90px'}>{t('Name')}:</Box>
|
||||
<Box flex={'0 0 90px'}>{t('Name')}</Box>
|
||||
<Input
|
||||
placeholder={t('outlink.Link Name') || 'Link Name'}
|
||||
maxLength={20}
|
||||
@@ -303,7 +300,7 @@ function EditLinkModal({
|
||||
<>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
QPM:
|
||||
QPM
|
||||
<MyTooltip label={t('outlink.QPM Tips' || '')}>
|
||||
<QuestionOutlineIcon ml={1} />
|
||||
</MyTooltip>
|
||||
@@ -320,7 +317,7 @@ function EditLinkModal({
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
{t('common.Max credit')}:
|
||||
{t('common.Max credit')}
|
||||
<MyTooltip label={t('common.Max credit tips' || '')}>
|
||||
<QuestionOutlineIcon ml={1} />
|
||||
</MyTooltip>
|
||||
@@ -336,7 +333,7 @@ function EditLinkModal({
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
{t('common.Expired Time')}:
|
||||
{t('common.Expired Time')}
|
||||
</Flex>
|
||||
<Input
|
||||
type="datetime-local"
|
||||
@@ -351,7 +348,7 @@ function EditLinkModal({
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
{t('outlink.token auth')}
|
||||
<MyTooltip label={t('outlink.token auth Tips') || ''}>
|
||||
<QuestionOutlineIcon ml={1} />
|
||||
@@ -359,6 +356,7 @@ function EditLinkModal({
|
||||
</Flex>
|
||||
<Input
|
||||
placeholder={t('outlink.token auth Tips') || ''}
|
||||
fontSize={'sm'}
|
||||
{...register('limit.hookUrl')}
|
||||
/>
|
||||
</Flex>
|
||||
@@ -375,7 +373,7 @@ function EditLinkModal({
|
||||
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
{t('outlink.Response Detail')}:
|
||||
{t('outlink.Response Detail')}
|
||||
<MyTooltip label={t('outlink.Response Detail tips' || '')}>
|
||||
<QuestionOutlineIcon ml={1} />
|
||||
</MyTooltip>
|
||||
|
@@ -51,6 +51,7 @@ import { SimpleModeTemplate_FastGPT_Universal } from '@/global/core/app/constant
|
||||
import QGSwitch from '@/components/core/module/Flow/components/modules/QGSwitch';
|
||||
import TTSSelect from '@/components/core/module/Flow/components/modules/TTSSelect';
|
||||
import VariableEdit from '@/components/core/module/Flow/components/modules/VariableEdit';
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
|
||||
const InfoModal = dynamic(() => import('../InfoModal'));
|
||||
const DatasetSelectModal = dynamic(() => import('@/components/core/module/DatasetSelectModal'));
|
||||
@@ -635,10 +636,19 @@ function ChatTest({ appId }: { appId: string }) {
|
||||
|
||||
const startChat = useCallback(
|
||||
async ({ chatList, controller, generatingMessage, variables }: StartChatFnProps) => {
|
||||
const historyMaxLen =
|
||||
modules
|
||||
?.find((item) => item.flowType === FlowNodeTypeEnum.historyNode)
|
||||
?.inputs?.find((item) => item.key === 'maxContext')?.value || 0;
|
||||
let historyMaxLen = 0;
|
||||
|
||||
modules.forEach((module) => {
|
||||
module.inputs.forEach((input) => {
|
||||
if (
|
||||
(input.key === ModuleInputKeyEnum.history ||
|
||||
input.key === ModuleInputKeyEnum.historyMaxAmount) &&
|
||||
typeof input.value === 'number'
|
||||
) {
|
||||
historyMaxLen = Math.max(historyMaxLen, input.value);
|
||||
}
|
||||
});
|
||||
});
|
||||
const history = chatList.slice(-historyMaxLen - 2, -2);
|
||||
|
||||
// 流请求,获取数据
|
||||
|
@@ -15,6 +15,7 @@ const ChatHeader = ({
|
||||
appAvatar,
|
||||
chatModels,
|
||||
appId,
|
||||
showHistory,
|
||||
onOpenSlider
|
||||
}: {
|
||||
history: ChatItemType[];
|
||||
@@ -22,6 +23,7 @@ const ChatHeader = ({
|
||||
appAvatar: string;
|
||||
chatModels?: string[];
|
||||
appId?: string;
|
||||
showHistory?: boolean;
|
||||
onOpenSlider: () => void;
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
@@ -63,7 +65,16 @@ const ChatHeader = ({
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<MyIcon name={'menu'} w={'20px'} h={'20px'} color={'myGray.900'} onClick={onOpenSlider} />
|
||||
{showHistory && (
|
||||
<MyIcon
|
||||
name={'menu'}
|
||||
w={'20px'}
|
||||
h={'20px'}
|
||||
color={'myGray.900'}
|
||||
onClick={onOpenSlider}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Flex px={3} alignItems={'center'} flex={'1 0 0'} w={0} justifyContent={'center'}>
|
||||
<Avatar src={appAvatar} w={'16px'} />
|
||||
<Box
|
||||
|
@@ -1,15 +1,3 @@
|
||||
.stopIcon {
|
||||
animation: zoomStopIcon 0.4s infinite alternate;
|
||||
}
|
||||
@keyframes zoomStopIcon {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
.newChat {
|
||||
.modelListContainer {
|
||||
height: 0;
|
||||
|
@@ -297,7 +297,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
onCloseSlider();
|
||||
}
|
||||
}}
|
||||
onDelHistory={delOneHistory}
|
||||
onDelHistory={(e) => delOneHistory({ ...e, appId })}
|
||||
onClearHistory={() => {
|
||||
clearHistories({ appId });
|
||||
router.replace({
|
||||
@@ -307,10 +307,11 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
});
|
||||
}}
|
||||
onSetHistoryTop={(e) => {
|
||||
updateHistory(e);
|
||||
updateHistory({ ...e, appId });
|
||||
}}
|
||||
onSetCustomTitle={async (e) => {
|
||||
updateHistory({
|
||||
appId,
|
||||
chatId: e.chatId,
|
||||
title: e.title,
|
||||
customTitle: e.title
|
||||
@@ -334,6 +335,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
history={chatData.history}
|
||||
chatModels={chatData.app.chatModels}
|
||||
onOpenSlider={onOpenSlider}
|
||||
showHistory
|
||||
/>
|
||||
|
||||
{/* chat box */}
|
||||
@@ -348,7 +350,8 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
feedbackType={'user'}
|
||||
onUpdateVariable={(e) => {}}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={(e) => delOneHistoryItem({ ...e, chatId })}
|
||||
onDelMessage={(e) => delOneHistoryItem({ ...e, appId, chatId })}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
/>
|
||||
</Box>
|
||||
|
@@ -300,7 +300,9 @@ const OutLink = ({
|
||||
onCloseSlider();
|
||||
}
|
||||
}}
|
||||
onDelHistory={({ chatId }) => delOneHistory({ chatId, shareId, outLinkUid })}
|
||||
onDelHistory={({ chatId }) =>
|
||||
delOneHistory({ appId: chatData.appId, chatId, shareId, outLinkUid })
|
||||
}
|
||||
onClearHistory={() => {
|
||||
clearHistories({ shareId, outLinkUid });
|
||||
router.replace({
|
||||
@@ -313,12 +315,14 @@ const OutLink = ({
|
||||
onSetHistoryTop={(e) => {
|
||||
updateHistory({
|
||||
...e,
|
||||
appId: chatData.appId,
|
||||
shareId,
|
||||
outLinkUid
|
||||
});
|
||||
}}
|
||||
onSetCustomTitle={async (e) => {
|
||||
updateHistory({
|
||||
appId: chatData.appId,
|
||||
chatId: e.chatId,
|
||||
title: e.title,
|
||||
customTitle: e.title,
|
||||
@@ -343,6 +347,7 @@ const OutLink = ({
|
||||
appAvatar={chatData.app.avatar}
|
||||
appName={chatData.app.name}
|
||||
history={chatData.history}
|
||||
showHistory={showHistory === '1'}
|
||||
onOpenSlider={onOpenSlider}
|
||||
/>
|
||||
{/* chat box */}
|
||||
@@ -357,7 +362,10 @@ const OutLink = ({
|
||||
feedbackType={'user'}
|
||||
onUpdateVariable={(e) => {}}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={(e) => delOneHistoryItem({ ...e, chatId, shareId, outLinkUid })}
|
||||
onDelMessage={(e) =>
|
||||
delOneHistoryItem({ ...e, appId: chatData.appId, chatId, shareId, outLinkUid })
|
||||
}
|
||||
appId={chatData.appId}
|
||||
chatId={chatId}
|
||||
shareId={shareId}
|
||||
outLinkUid={outLinkUid}
|
||||
|
@@ -3,7 +3,7 @@ import { GET } from '@fastgpt/service/common/api/plusRequest';
|
||||
|
||||
export async function getSimpleTemplatesFromPlus(): Promise<AppSimpleEditConfigTemplateType[]> {
|
||||
try {
|
||||
if (!global.systemEnv.pluginBaseUrl) return [];
|
||||
if (!global.systemEnv?.pluginBaseUrl) return [];
|
||||
|
||||
return GET<AppSimpleEditConfigTemplateType[]>('/core/app/getSimpleTemplates');
|
||||
} catch (error) {
|
||||
|
@@ -112,7 +112,7 @@ export async function searchDatasetData(props: SearchProps) {
|
||||
limit: maxTokens,
|
||||
searchMode = DatasetSearchModeEnum.embedding
|
||||
} = props;
|
||||
searchMode = global.systemEnv.pluginBaseUrl ? searchMode : DatasetSearchModeEnum.embedding;
|
||||
searchMode = global.systemEnv?.pluginBaseUrl ? searchMode : DatasetSearchModeEnum.embedding;
|
||||
|
||||
// Compatible with topk limit
|
||||
if (maxTokens < 50) {
|
||||
|
@@ -10,11 +10,12 @@ import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||||
import { Prompt_CQJson } from '@/global/core/prompt/agent';
|
||||
import { FunctionModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||
import { getCQModel } from '@/service/core/ai/model';
|
||||
import { getHistories } from '../utils';
|
||||
|
||||
type Props = ModuleDispatchProps<{
|
||||
[ModuleInputKeyEnum.aiModel]: string;
|
||||
[ModuleInputKeyEnum.aiSystemPrompt]?: string;
|
||||
[ModuleInputKeyEnum.history]?: ChatItemType[];
|
||||
[ModuleInputKeyEnum.history]?: ChatItemType[] | number;
|
||||
[ModuleInputKeyEnum.userChatInput]: string;
|
||||
[ModuleInputKeyEnum.agents]: ClassifyQuestionAgentItemType[];
|
||||
}>;
|
||||
@@ -23,13 +24,14 @@ type CQResponse = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
const agentFunName = 'agent_user_question';
|
||||
const agentFunName = 'classify_question';
|
||||
|
||||
/* request openai chat */
|
||||
export const dispatchClassifyQuestion = async (props: Props): Promise<CQResponse> => {
|
||||
const {
|
||||
user,
|
||||
inputs: { model, agents, userChatInput }
|
||||
histories,
|
||||
inputs: { model, history = 6, agents, userChatInput }
|
||||
} = props as Props;
|
||||
|
||||
if (!userChatInput) {
|
||||
@@ -42,11 +44,13 @@ export const dispatchClassifyQuestion = async (props: Props): Promise<CQResponse
|
||||
if (cqModel.functionCall) {
|
||||
return functionCall({
|
||||
...props,
|
||||
histories: getHistories(history, histories),
|
||||
cqModel
|
||||
});
|
||||
}
|
||||
return completions({
|
||||
...props,
|
||||
histories: getHistories(history, histories),
|
||||
cqModel
|
||||
});
|
||||
})();
|
||||
@@ -54,7 +58,7 @@ export const dispatchClassifyQuestion = async (props: Props): Promise<CQResponse
|
||||
const result = agents.find((item) => item.key === arg?.type) || agents[agents.length - 1];
|
||||
|
||||
return {
|
||||
[result.key]: 1,
|
||||
[result.key]: result.value,
|
||||
[ModuleOutputKeyEnum.responseData]: {
|
||||
price: user.openaiAccount?.key ? 0 : cqModel.price * tokens,
|
||||
model: cqModel.name || '',
|
||||
@@ -69,18 +73,19 @@ export const dispatchClassifyQuestion = async (props: Props): Promise<CQResponse
|
||||
async function functionCall({
|
||||
user,
|
||||
cqModel,
|
||||
inputs: { agents, systemPrompt, history = [], userChatInput }
|
||||
histories,
|
||||
inputs: { agents, systemPrompt, userChatInput }
|
||||
}: Props & { cqModel: FunctionModelItemType }) {
|
||||
const messages: ChatItemType[] = [
|
||||
...history,
|
||||
...histories,
|
||||
{
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: systemPrompt
|
||||
? `补充的背景知识:
|
||||
"""
|
||||
? `<背景知识>
|
||||
${systemPrompt}
|
||||
"""
|
||||
我的问题: ${userChatInput}
|
||||
</背景知识>
|
||||
|
||||
问题: "${userChatInput}"
|
||||
`
|
||||
: userChatInput
|
||||
}
|
||||
@@ -95,18 +100,19 @@ ${systemPrompt}
|
||||
// function body
|
||||
const agentFunction = {
|
||||
name: agentFunName,
|
||||
description: '请根据对话记录及补充的背景知识,判断用户的问题类型,并返回对应的字段',
|
||||
description: '根据对话记录及补充的背景知识,对问题进行分类,并返回对应的类型字段',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
type: {
|
||||
type: 'string',
|
||||
description: `判断用户的问题类型,并返回对应的字段。下面是几种问题类型: ${agents
|
||||
description: `问题类型。下面是几种可选的问题类型: ${agents
|
||||
.map((item) => `${item.value},返回:'${item.key}'`)
|
||||
.join(';')}`,
|
||||
enum: agents.map((item) => item.key)
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['type']
|
||||
}
|
||||
};
|
||||
const ai = getAIApi(user.openaiAccount, 48000);
|
||||
@@ -115,12 +121,19 @@ ${systemPrompt}
|
||||
model: cqModel.model,
|
||||
temperature: 0,
|
||||
messages: [...adaptMessages],
|
||||
function_call: { name: agentFunName },
|
||||
functions: [agentFunction]
|
||||
tools: [
|
||||
{
|
||||
type: 'function',
|
||||
function: agentFunction
|
||||
}
|
||||
],
|
||||
tool_choice: { type: 'function', function: { name: agentFunName } }
|
||||
});
|
||||
|
||||
try {
|
||||
const arg = JSON.parse(response.choices?.[0]?.message?.function_call?.arguments || '');
|
||||
const arg = JSON.parse(
|
||||
response?.choices?.[0]?.message?.tool_calls?.[0]?.function?.arguments || ''
|
||||
);
|
||||
|
||||
return {
|
||||
arg,
|
||||
@@ -130,7 +143,7 @@ ${systemPrompt}
|
||||
console.log(agentFunction.parameters);
|
||||
console.log(response.choices?.[0]?.message);
|
||||
|
||||
console.log('Your model may not support function_call', error);
|
||||
console.log('Your model may not support toll_call', error);
|
||||
|
||||
return {
|
||||
arg: {},
|
||||
@@ -142,15 +155,16 @@ ${systemPrompt}
|
||||
async function completions({
|
||||
cqModel,
|
||||
user,
|
||||
inputs: { agents, systemPrompt = '', history = [], userChatInput }
|
||||
histories,
|
||||
inputs: { agents, systemPrompt = '', userChatInput }
|
||||
}: Props & { cqModel: FunctionModelItemType }) {
|
||||
const messages: ChatItemType[] = [
|
||||
{
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: replaceVariable(cqModel.functionPrompt || Prompt_CQJson, {
|
||||
systemPrompt,
|
||||
typeList: agents.map((item) => `ID: "${item.key}", 问题类型:${item.value}`).join('\n'),
|
||||
text: `${history.map((item) => `${item.obj}:${item.value}`).join('\n')}
|
||||
typeList: agents.map((item) => `{"${item.value}": ${item.key}}`).join('\n'),
|
||||
text: `${histories.map((item) => `${item.obj}:${item.value}`).join('\n')}
|
||||
Human:${userChatInput}`
|
||||
})
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ import type { ModuleDispatchProps } from '@/types/core/chat/type';
|
||||
import { Prompt_ExtractJson } from '@/global/core/prompt/agent';
|
||||
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||||
import { FunctionModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||
import { getHistories } from '../utils';
|
||||
|
||||
type Props = ModuleDispatchProps<{
|
||||
[ModuleInputKeyEnum.history]?: ChatItemType[];
|
||||
@@ -23,12 +24,13 @@ type Response = {
|
||||
[ModuleOutputKeyEnum.responseData]: moduleDispatchResType;
|
||||
};
|
||||
|
||||
const agentFunName = 'agent_extract_data';
|
||||
const agentFunName = 'extract_json_data';
|
||||
|
||||
export async function dispatchContentExtract(props: Props): Promise<Response> {
|
||||
const {
|
||||
user,
|
||||
inputs: { content, description, extractKeys }
|
||||
histories,
|
||||
inputs: { content, history = 6, description, extractKeys }
|
||||
} = props;
|
||||
|
||||
if (!content) {
|
||||
@@ -41,11 +43,13 @@ export async function dispatchContentExtract(props: Props): Promise<Response> {
|
||||
if (extractModel.functionCall) {
|
||||
return functionCall({
|
||||
...props,
|
||||
histories: getHistories(history, histories),
|
||||
extractModel
|
||||
});
|
||||
}
|
||||
return completions({
|
||||
...props,
|
||||
histories: getHistories(history, histories),
|
||||
extractModel
|
||||
});
|
||||
})();
|
||||
@@ -88,13 +92,24 @@ export async function dispatchContentExtract(props: Props): Promise<Response> {
|
||||
async function functionCall({
|
||||
extractModel,
|
||||
user,
|
||||
inputs: { history = [], content, extractKeys, description }
|
||||
histories,
|
||||
inputs: { content, extractKeys, description }
|
||||
}: Props & { extractModel: FunctionModelItemType }) {
|
||||
const messages: ChatItemType[] = [
|
||||
...history,
|
||||
...histories,
|
||||
{
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: content
|
||||
value: `<任务描述>
|
||||
${description || '根据用户要求提取适当的 JSON 字符串。'}
|
||||
|
||||
- 如果字段为空,你返回空字符串。
|
||||
- 不要换行。
|
||||
- 结合历史记录和文本进行提取。
|
||||
</任务描述>
|
||||
|
||||
<文本>
|
||||
${content}
|
||||
</文本>`
|
||||
}
|
||||
];
|
||||
const filterMessages = ChatContextFilter({
|
||||
@@ -120,7 +135,7 @@ async function functionCall({
|
||||
// function body
|
||||
const agentFunction = {
|
||||
name: agentFunName,
|
||||
description: `${description}\n如果内容不存在,返回空字符串。`,
|
||||
description,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties,
|
||||
@@ -134,17 +149,24 @@ async function functionCall({
|
||||
model: extractModel.model,
|
||||
temperature: 0,
|
||||
messages: [...adaptMessages],
|
||||
function_call: { name: agentFunName },
|
||||
functions: [agentFunction]
|
||||
tools: [
|
||||
{
|
||||
type: 'function',
|
||||
function: agentFunction
|
||||
}
|
||||
],
|
||||
tool_choice: { type: 'function', function: { name: agentFunName } }
|
||||
});
|
||||
|
||||
const arg: Record<string, any> = (() => {
|
||||
try {
|
||||
return JSON.parse(response.choices?.[0]?.message?.function_call?.arguments || '{}');
|
||||
return JSON.parse(
|
||||
response?.choices?.[0]?.message?.tool_calls?.[0]?.function?.arguments || '{}'
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(agentFunction.parameters);
|
||||
console.log(response.choices?.[0]?.message);
|
||||
console.log('Your model may not support function_call', error);
|
||||
console.log(response.choices?.[0]?.message?.tool_calls?.[0]?.function);
|
||||
console.log('Your model may not support tool_call', error);
|
||||
return {};
|
||||
}
|
||||
})();
|
||||
@@ -159,7 +181,8 @@ async function functionCall({
|
||||
async function completions({
|
||||
extractModel,
|
||||
user,
|
||||
inputs: { history = [], content, extractKeys, description }
|
||||
histories,
|
||||
inputs: { content, extractKeys, description }
|
||||
}: Props & { extractModel: FunctionModelItemType }) {
|
||||
const messages: ChatItemType[] = [
|
||||
{
|
||||
@@ -169,12 +192,10 @@ async function completions({
|
||||
json: extractKeys
|
||||
.map(
|
||||
(item) =>
|
||||
`key="${item.key}",描述="${item.desc}",required="${
|
||||
item.required ? 'true' : 'false'
|
||||
}"`
|
||||
`{"key":"${item.key}", "description":"${item.required}", "required":${item.required}}}`
|
||||
)
|
||||
.join('\n'),
|
||||
text: `${history.map((item) => `${item.obj}:${item.value}`).join('\n')}
|
||||
text: `${histories.map((item) => `${item.obj}:${item.value}`).join('\n')}
|
||||
Human: ${content}`
|
||||
})
|
||||
}
|
||||
|
@@ -22,11 +22,12 @@ import { getChatModel, ModelTypeEnum } from '@/service/core/ai/model';
|
||||
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
||||
import { formatStr2ChatContent } from '@fastgpt/service/core/chat/utils';
|
||||
import { ModuleInputKeyEnum, ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { getHistories } from '../utils';
|
||||
|
||||
export type ChatProps = ModuleDispatchProps<
|
||||
AIChatModuleProps & {
|
||||
[ModuleInputKeyEnum.userChatInput]: string;
|
||||
[ModuleInputKeyEnum.history]?: ChatItemType[];
|
||||
[ModuleInputKeyEnum.history]?: ChatItemType[] | number;
|
||||
[ModuleInputKeyEnum.aiChatDatasetQuote]?: SearchDataResponseItemType[];
|
||||
}
|
||||
>;
|
||||
@@ -43,12 +44,13 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
|
||||
stream = false,
|
||||
detail = false,
|
||||
user,
|
||||
histories,
|
||||
outputs,
|
||||
inputs: {
|
||||
model,
|
||||
temperature = 0,
|
||||
maxToken = 4000,
|
||||
history = [],
|
||||
history = 6,
|
||||
quoteQA = [],
|
||||
userChatInput,
|
||||
isResponseAnswerText = true,
|
||||
@@ -63,6 +65,8 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
|
||||
|
||||
stream = stream && isResponseAnswerText;
|
||||
|
||||
const chatHistories = getHistories(history, histories);
|
||||
|
||||
// temperature adapt
|
||||
const modelConstantsData = getChatModel(model);
|
||||
|
||||
@@ -88,7 +92,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
|
||||
|
||||
const { messages, filterMessages } = getChatMessages({
|
||||
model: modelConstantsData,
|
||||
history,
|
||||
histories: chatHistories,
|
||||
quoteText,
|
||||
quotePrompt,
|
||||
userChatInput,
|
||||
@@ -265,14 +269,14 @@ function filterQuote({
|
||||
function getChatMessages({
|
||||
quotePrompt,
|
||||
quoteText,
|
||||
history = [],
|
||||
histories = [],
|
||||
systemPrompt,
|
||||
userChatInput,
|
||||
model
|
||||
}: {
|
||||
quotePrompt?: string;
|
||||
quoteText: string;
|
||||
history: ChatProps['inputs']['history'];
|
||||
histories: ChatItemType[];
|
||||
systemPrompt: string;
|
||||
userChatInput: string;
|
||||
model: ChatModelItemType;
|
||||
@@ -293,7 +297,7 @@ function getChatMessages({
|
||||
}
|
||||
]
|
||||
: []),
|
||||
...history,
|
||||
...histories,
|
||||
{
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: question
|
||||
@@ -319,7 +323,7 @@ function getMaxTokens({
|
||||
}: {
|
||||
maxToken: number;
|
||||
model: ChatModelItemType;
|
||||
filterMessages: ChatProps['inputs']['history'];
|
||||
filterMessages: ChatItemType[];
|
||||
}) {
|
||||
const tokensLimit = model.maxContext;
|
||||
|
||||
|
@@ -3,8 +3,8 @@ import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { RunningModuleItemType } from '@/types/app';
|
||||
import { ModuleDispatchProps } from '@/types/core/chat/type';
|
||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import type { ChatHistoryItemResType, ChatItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { UserType } from '@fastgpt/global/support/user/type';
|
||||
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||||
@@ -25,7 +25,6 @@ import { dispatchAppRequest } from './tools/runApp';
|
||||
import { dispatchRunPlugin } from './plugin/run';
|
||||
import { dispatchPluginInput } from './plugin/runInput';
|
||||
import { dispatchPluginOutput } from './plugin/runOutput';
|
||||
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
|
||||
/* running */
|
||||
export async function dispatchModules({
|
||||
@@ -36,7 +35,8 @@ export async function dispatchModules({
|
||||
appId,
|
||||
modules,
|
||||
chatId,
|
||||
params = {},
|
||||
histories = [],
|
||||
startParams = {},
|
||||
variables = {},
|
||||
stream = false,
|
||||
detail = false
|
||||
@@ -48,7 +48,8 @@ export async function dispatchModules({
|
||||
appId: string;
|
||||
modules: ModuleItemType[];
|
||||
chatId?: string;
|
||||
params?: Record<string, any>;
|
||||
histories: ChatItemType[];
|
||||
startParams?: Record<string, any>;
|
||||
variables?: Record<string, any>;
|
||||
stream?: boolean;
|
||||
detail?: boolean;
|
||||
@@ -185,6 +186,7 @@ export async function dispatchModules({
|
||||
stream,
|
||||
detail,
|
||||
variables,
|
||||
histories,
|
||||
outputs: module.outputs,
|
||||
inputs: params
|
||||
};
|
||||
@@ -230,7 +232,12 @@ export async function dispatchModules({
|
||||
|
||||
// start process width initInput
|
||||
const initModules = runningModules.filter((item) => initRunningModuleType[item.flowType]);
|
||||
initModules.map((module) => moduleInput(module, params));
|
||||
initModules.map((module) =>
|
||||
moduleInput(module, {
|
||||
...startParams,
|
||||
history: [] // abandon history field. History module will get histories from other fields.
|
||||
})
|
||||
);
|
||||
await checkModulesCanRun(initModules);
|
||||
|
||||
// focus try to run pluginOutput
|
||||
@@ -252,14 +259,23 @@ function loadModules(
|
||||
modules: ModuleItemType[],
|
||||
variables: Record<string, any>
|
||||
): RunningModuleItemType[] {
|
||||
return modules.map((module) => {
|
||||
return modules
|
||||
.filter((item) => {
|
||||
return ![FlowNodeTypeEnum.userGuide].includes(item.moduleId as any);
|
||||
})
|
||||
.map((module) => {
|
||||
return {
|
||||
moduleId: module.moduleId,
|
||||
name: module.name,
|
||||
flowType: module.flowType,
|
||||
showStatus: module.showStatus,
|
||||
inputs: module.inputs
|
||||
.filter((item) => item.connected || item.value !== undefined) // filter unconnected target input
|
||||
.filter(
|
||||
(item) =>
|
||||
item.type === FlowNodeInputTypeEnum.systemInput ||
|
||||
item.connected ||
|
||||
item.value !== undefined
|
||||
) // filter unconnected target input
|
||||
.map((item) => {
|
||||
if (typeof item.value !== 'string') {
|
||||
return {
|
||||
|
@@ -1,17 +1,19 @@
|
||||
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
import type { ModuleDispatchProps } from '@/types/core/chat/type';
|
||||
import { getHistories } from '../utils';
|
||||
export type HistoryProps = ModuleDispatchProps<{
|
||||
maxContext: number;
|
||||
maxContext?: number;
|
||||
[ModuleInputKeyEnum.history]: ChatItemType[];
|
||||
}>;
|
||||
|
||||
export const dispatchHistory = (props: Record<string, any>) => {
|
||||
const {
|
||||
inputs: { maxContext = 5, history = [] }
|
||||
histories,
|
||||
inputs: { maxContext }
|
||||
} = props as HistoryProps;
|
||||
|
||||
return {
|
||||
history: maxContext > 0 ? history.slice(-maxContext) : []
|
||||
history: getHistories(maxContext, histories)
|
||||
};
|
||||
};
|
||||
|
@@ -35,7 +35,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
...module,
|
||||
showStatus: false
|
||||
})),
|
||||
params: data
|
||||
startParams: data
|
||||
});
|
||||
|
||||
const output = responseData.find((item) => item.moduleType === FlowNodeTypeEnum.pluginOutput);
|
||||
|
@@ -56,8 +56,8 @@ export const dispatchAppRequest = async (props: Props): Promise<Response> => {
|
||||
...props,
|
||||
appId: app.id,
|
||||
modules: appData.modules,
|
||||
params: {
|
||||
history,
|
||||
histories: history,
|
||||
startParams: {
|
||||
userChatInput
|
||||
}
|
||||
});
|
||||
|
9
projects/app/src/service/moduleDispatch/utils.ts
Normal file
9
projects/app/src/service/moduleDispatch/utils.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
|
||||
export const getHistories = (history?: ChatItemType[] | number, histories: ChatItemType[] = []) => {
|
||||
if (!history) return [];
|
||||
if (typeof history === 'number') return histories.slice(-history);
|
||||
if (Array.isArray(history)) return history;
|
||||
|
||||
return [];
|
||||
};
|
@@ -1,7 +1,7 @@
|
||||
import { GET } from '@fastgpt/service/common/api/plusRequest';
|
||||
|
||||
export const authTeamBalance = async (teamId: string) => {
|
||||
if (global.systemEnv.pluginBaseUrl) {
|
||||
if (global.systemEnv?.pluginBaseUrl) {
|
||||
return GET('/support/permission/authBalance', { teamId });
|
||||
}
|
||||
return true;
|
||||
|
@@ -11,12 +11,14 @@ import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
token: team owner and chat owner have all permissions
|
||||
*/
|
||||
export async function autChatCrud({
|
||||
appId,
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
per = 'owner',
|
||||
...props
|
||||
}: AuthModeType & {
|
||||
appId: string;
|
||||
chatId?: string;
|
||||
shareId?: string;
|
||||
outLinkUid?: string;
|
||||
@@ -28,7 +30,7 @@ export async function autChatCrud({
|
||||
const isOutLink = Boolean(shareId && outLinkUid);
|
||||
if (!chatId) return { isOutLink, uid: outLinkUid };
|
||||
|
||||
const chat = await MongoChat.findOne({ chatId }).lean();
|
||||
const chat = await MongoChat.findOne({ appId, chatId }).lean();
|
||||
|
||||
if (!chat) return { isOutLink, uid: outLinkUid };
|
||||
|
||||
|
@@ -2,6 +2,6 @@ import { POST } from '@fastgpt/service/common/api/plusRequest';
|
||||
import { SendInformProps } from '@fastgpt/global/support/user/inform/type';
|
||||
|
||||
export function sendOneInform(data: SendInformProps) {
|
||||
if (!global.systemEnv.pluginBaseUrl) return;
|
||||
if (!global.systemEnv?.pluginBaseUrl) return;
|
||||
return POST('/support/user/inform/create', data);
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ import { defaultQGModels } from '@fastgpt/global/core/ai/model';
|
||||
import { POST } from '@fastgpt/service/common/api/plusRequest';
|
||||
|
||||
export function createBill(data: CreateBillProps) {
|
||||
if (!global.systemEnv.pluginBaseUrl) return;
|
||||
if (!global.systemEnv?.pluginBaseUrl) return;
|
||||
if (data.total === 0) {
|
||||
addLog.info('0 Bill', data);
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export function createBill(data: CreateBillProps) {
|
||||
} catch (error) {}
|
||||
}
|
||||
export function concatBill(data: ConcatBillProps) {
|
||||
if (!global.systemEnv.pluginBaseUrl) return;
|
||||
if (!global.systemEnv?.pluginBaseUrl) return;
|
||||
if (data.total === 0) {
|
||||
addLog.info('0 Bill', data);
|
||||
}
|
||||
|
2
projects/app/src/types/core/chat/type.d.ts
vendored
2
projects/app/src/types/core/chat/type.d.ts
vendored
@@ -2,6 +2,7 @@ import type { NextApiResponse } from 'next';
|
||||
import { RunningModuleItemType } from '@/types/app';
|
||||
import type { UserType } from '@fastgpt/global/support/user/type';
|
||||
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||
import { ChatItemType } from '@fastgpt/global/core/chat/type';
|
||||
|
||||
// module dispatch props type
|
||||
export type ModuleDispatchProps<T> = {
|
||||
@@ -14,6 +15,7 @@ export type ModuleDispatchProps<T> = {
|
||||
stream: boolean;
|
||||
detail: boolean; // response detail
|
||||
variables: Record<string, any>;
|
||||
histories: ChatItemType[];
|
||||
outputs: RunningModuleItemType['outputs'];
|
||||
inputs: T;
|
||||
};
|
||||
|
@@ -12,9 +12,10 @@ export const useSelectFile = (props?: {
|
||||
const { fileType = '*', multiple = false, maxCount = 10 } = props || {};
|
||||
const { toast } = useToast();
|
||||
const SelectFileDom = useRef<HTMLInputElement>(null);
|
||||
const openSign = useRef<any>();
|
||||
|
||||
const File = useCallback(
|
||||
({ onSelect }: { onSelect: (e: File[]) => void }) => (
|
||||
({ onSelect }: { onSelect: (e: File[], sign?: any) => void }) => (
|
||||
<Box position={'absolute'} w={0} h={0} overflow={'hidden'}>
|
||||
<input
|
||||
ref={SelectFileDom}
|
||||
@@ -29,7 +30,7 @@ export const useSelectFile = (props?: {
|
||||
title: t('file.Select a maximum of 10 files')
|
||||
});
|
||||
}
|
||||
onSelect(Array.from(e.target.files));
|
||||
onSelect(Array.from(e.target.files), openSign.current);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@@ -37,7 +38,8 @@ export const useSelectFile = (props?: {
|
||||
[fileType, maxCount, multiple]
|
||||
);
|
||||
|
||||
const onOpen = useCallback(() => {
|
||||
const onOpen = useCallback((sign?: any) => {
|
||||
openSign.current = sign;
|
||||
SelectFileDom.current && SelectFileDom.current.click();
|
||||
}, []);
|
||||
|
||||
|
@@ -233,10 +233,10 @@ export const fileDownload = ({
|
||||
};
|
||||
|
||||
export const fileToBase64 = (file: File) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => resolve(reader.result);
|
||||
reader.onload = () => resolve(reader.result as string);
|
||||
reader.onerror = (error) => reject(error);
|
||||
});
|
||||
};
|
||||
|
@@ -27,7 +27,6 @@ export const appTemplates: (AppItemType & {
|
||||
key: 'welcomeText',
|
||||
type: 'input',
|
||||
label: '开场白',
|
||||
value: '',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
@@ -64,46 +63,6 @@ export const appTemplates: (AppItemType & {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'history',
|
||||
name: '聊天记录',
|
||||
flowType: 'historyNode',
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
type: 'numberInput',
|
||||
label: '最长记录数',
|
||||
value: 6,
|
||||
min: 0,
|
||||
max: 50,
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
name: 'AI 对话',
|
||||
@@ -171,7 +130,6 @@ export const appTemplates: (AppItemType & {
|
||||
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}',
|
||||
placeholder:
|
||||
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -193,7 +151,8 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'target',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
connected: true
|
||||
connected: true,
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
@@ -285,46 +244,6 @@ export const appTemplates: (AppItemType & {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'history',
|
||||
name: '聊天记录',
|
||||
flowType: 'historyNode',
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
type: 'numberInput',
|
||||
label: '最长记录数',
|
||||
value: 6,
|
||||
min: 0,
|
||||
max: 50,
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'datasetSearch',
|
||||
name: '知识库搜索',
|
||||
@@ -495,7 +414,6 @@ export const appTemplates: (AppItemType & {
|
||||
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}',
|
||||
placeholder:
|
||||
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -517,7 +435,8 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'target',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
connected: true
|
||||
connected: true,
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
@@ -678,46 +597,6 @@ export const appTemplates: (AppItemType & {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'history',
|
||||
name: '聊天记录',
|
||||
flowType: 'historyNode',
|
||||
position: {
|
||||
x: 452.5466249541586,
|
||||
y: 1276.3930310334215
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
type: 'numberInput',
|
||||
label: '最长记录数',
|
||||
value: 2,
|
||||
min: 0,
|
||||
max: 50,
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
name: 'AI 对话',
|
||||
@@ -793,7 +672,6 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
valueType: 'string',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -801,7 +679,6 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
valueType: 'string',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -824,7 +701,8 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'target',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
connected: true
|
||||
connected: true,
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
@@ -906,46 +784,6 @@ export const appTemplates: (AppItemType & {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'xj0c9p',
|
||||
name: '聊天记录',
|
||||
flowType: 'historyNode',
|
||||
position: {
|
||||
x: 1770.497690708367,
|
||||
y: 1820.2355054321215
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
type: 'numberInput',
|
||||
label: '最长记录数',
|
||||
value: 6,
|
||||
min: 0,
|
||||
max: 50,
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'nlfwkc',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'remuj3',
|
||||
name: '问题分类',
|
||||
@@ -980,7 +818,8 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'target',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
connected: true
|
||||
connected: true,
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
@@ -997,15 +836,15 @@ export const appTemplates: (AppItemType & {
|
||||
value: [
|
||||
{
|
||||
value: '打招呼、问候等问题',
|
||||
key: 'fasw'
|
||||
key: 'wqre'
|
||||
},
|
||||
{
|
||||
value: '“laf” 的问题',
|
||||
key: 'fqsw'
|
||||
value: '关于 xxx 的问题',
|
||||
key: 'sdfa'
|
||||
},
|
||||
{
|
||||
value: '商务问题',
|
||||
key: 'fesw'
|
||||
key: 'agex'
|
||||
},
|
||||
{
|
||||
value: '其他问题',
|
||||
@@ -1017,7 +856,7 @@ export const appTemplates: (AppItemType & {
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'fasw',
|
||||
key: 'wqre',
|
||||
label: '',
|
||||
type: 'hidden',
|
||||
targets: [
|
||||
@@ -1028,7 +867,7 @@ export const appTemplates: (AppItemType & {
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'fqsw',
|
||||
key: 'sdfa',
|
||||
label: '',
|
||||
type: 'hidden',
|
||||
targets: [
|
||||
@@ -1039,7 +878,7 @@ export const appTemplates: (AppItemType & {
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'fesw',
|
||||
key: 'agex',
|
||||
label: '',
|
||||
type: 'hidden',
|
||||
targets: [
|
||||
@@ -1255,7 +1094,6 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
valueType: 'string',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -1263,7 +1101,6 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
valueType: 'string',
|
||||
value: '',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
@@ -1286,7 +1123,8 @@ export const appTemplates: (AppItemType & {
|
||||
type: 'target',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
connected: true
|
||||
connected: true,
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
key: 'userChatInput',
|
||||
@@ -1324,46 +1162,6 @@ export const appTemplates: (AppItemType & {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 's4v9su',
|
||||
name: '聊天记录',
|
||||
flowType: 'historyNode',
|
||||
position: {
|
||||
x: 193.3803955457983,
|
||||
y: 1316.251200765746
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: 'maxContext',
|
||||
type: 'numberInput',
|
||||
label: '最长记录数',
|
||||
value: 2,
|
||||
min: 0,
|
||||
max: 50,
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
type: 'hidden',
|
||||
label: '聊天记录',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
key: 'history',
|
||||
label: '聊天记录',
|
||||
valueType: 'chatHistory',
|
||||
type: 'source',
|
||||
targets: [
|
||||
{
|
||||
moduleId: 'remuj3',
|
||||
key: 'history'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
moduleId: 'fljhzy',
|
||||
name: '知识库搜索',
|
||||
|
@@ -21,7 +21,6 @@ import { ModuleTemplateTypeEnum } from '@fastgpt/global/core/module/constants';
|
||||
export const appSystemModuleTemplates: FlowModuleTemplateType[] = [
|
||||
UserGuideModule,
|
||||
UserInputModule,
|
||||
HistoryModule,
|
||||
AiChatModule,
|
||||
AssignedAnswerModule,
|
||||
DatasetSearchModule,
|
||||
@@ -33,7 +32,6 @@ export const appSystemModuleTemplates: FlowModuleTemplateType[] = [
|
||||
export const pluginSystemModuleTemplates: FlowModuleTemplateType[] = [
|
||||
PluginInputModule,
|
||||
PluginOutputModule,
|
||||
HistoryModule,
|
||||
AiChatModule,
|
||||
AssignedAnswerModule,
|
||||
DatasetSearchModule,
|
||||
|
Reference in New Issue
Block a user