4.7-alpha2 (#1027)

* feat: stop toolCall and rename some field. (#46)

* perf: node delete tip;pay tip

* fix: toolCall cannot save child answer

* feat: stop tool

* fix: team modal

* fix feckbackMoal  auth bug (#47)

* 简单的支持提示词运行tool。优化workflow模板 (#49)

* remove templates

* fix: request body undefined

* feat: prompt tool run

* feat: workflow tamplates modal

* perf: plugin start

* 4.7 (#50)

* fix docker-compose download url (#994)

original code is a bad url with '404 NOT FOUND' return.
fix docker-compose download url, add 'v' before docker-compose version

* Update ai_settings.md (#1000)

* Update configuration.md

* Update configuration.md

* Fix history in classifyQuestion and extract modules (#1012)

* Fix history in classifyQuestion and extract modules

* Add chatValue2RuntimePrompt import and update text formatting

* flow controller to packages

* fix: rerank select

* modal ui

* perf: modal code path

* point not sufficient

* feat: http url support variable

* fix http key

* perf: prompt

* perf: ai setting modal

* simple edit ui

---------

Co-authored-by: entorick <entorick11@qq.com>
Co-authored-by: liujianglc <liujianglc@163.com>
Co-authored-by: Fengrui Liu <liufengrui.work@bytedance.com>

* fix team share redirect to login (#51)

* feat: support openapi import plugins (#48)

* feat: support openapi import plugins

* feat: import from url

* fix: add body params parse

* fix build

* fix

* fix

* fix

* tool box ui (#52)

* fix: training queue

* feat: simple edit tool select

* perf: simple edit dataset prompt

* fix: chatbox tool ux

* feat: quote prompt module

* perf: plugin tools sign

* perf: model avatar

* tool selector ui

* feat: max histories

* perf: http plugin import (#53)

* perf: plugin http import

* chatBox ui

* perf: name

* fix: Node template card (#54)

* fix: ts

* setting modal

* package

* package

* feat: add plugins search (#57)

* feat: add plugins search

* perf: change http plugin header input

* Yjl (#56)

* perf: prompt tool call

* perf: chat box ux

* doc

* doc

* price tip

* perf: tool selector

* ui'

* fix: vector queue

* fix: empty tool and empty response

* fix: empty msg

* perf: pg index

* perf: ui tip

* doc

* tool tip

---------

Co-authored-by: yst <77910600+yu-and-liu@users.noreply.github.com>
Co-authored-by: entorick <entorick11@qq.com>
Co-authored-by: liujianglc <liujianglc@163.com>
Co-authored-by: Fengrui Liu <liufengrui.work@bytedance.com>
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
Archer
2024-03-21 13:32:31 +08:00
committed by GitHub
parent 6d4b331db9
commit 9d27de154b
322 changed files with 9282 additions and 6498 deletions

View File

@@ -10,41 +10,20 @@
"model": "gpt-3.5-turbo",
"name": "gpt-3.5-turbo",
"maxContext": 16000,
"avatar": "/imgs/model/openai.svg",
"maxResponse": 4000,
"quoteMaxToken": 13000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": false,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {}
},
{
"model": "gpt-3.5-turbo-16k",
"name": "gpt-3.5-turbo-16k",
"maxContext": 16000,
"maxResponse": 16000,
"quoteMaxToken": 13000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": true,
"functionCall": false,
"functionCall": true,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
@@ -53,6 +32,7 @@
{
"model": "gpt-4-0125-preview",
"name": "gpt-4-turbo",
"avatar": "/imgs/model/openai.svg",
"maxContext": 125000,
"maxResponse": 4000,
"quoteMaxToken": 100000,
@@ -75,6 +55,7 @@
{
"model": "gpt-4-vision-preview",
"name": "gpt-4-vision",
"avatar": "/imgs/model/openai.svg",
"maxContext": 128000,
"maxResponse": 4000,
"quoteMaxToken": 100000,
@@ -99,6 +80,7 @@
{
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"avatar": "/imgs/model/openai.svg",
"charsPointsPrice": 0,
"defaultToken": 700,
"maxToken": 3000,

View File

@@ -14,7 +14,7 @@ type TemplateType =
type pluginType = {
author: string; // 填写作者信息
templateType: FlowModuleTemplateType['templateType'];
templateType: FlowNodeTemplateType['templateType'];
name: string;
avatar: string;
intro: string;

View File

@@ -5,6 +5,7 @@
"avatar": "/imgs/module/customFeedback.svg",
"intro": "该模块被触发时,会给当前的对话记录增加一条反馈。可用于自动记录对话效果等。",
"showStatus": false,
"isTool": false,
"modules": [
{
"moduleId": "w90mfp",

View File

@@ -1,10 +1,11 @@
{
"author": "FastGPT Team",
"templateType": "tools",
"name": "core.module.template.textEditor",
"name": "文本加工",
"avatar": "/imgs/module/textEditor.svg",
"intro": "core.module.template.textEditor intro",
"intro": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。",
"showStatus": false,
"isTool": false,
"modules": [
{
"moduleId": "w90mfp",

View File

@@ -1,10 +1,11 @@
{
"author": "FastGPT Team",
"templateType": "tools",
"name": "core.module.template.TFSwitch",
"name": "判断器",
"avatar": "/imgs/module/tfSwitch.svg",
"intro": "core.module.template.TFSwitch intro",
"intro": "根据传入的内容进行 True False 输出。默认情况下,当传入的内容为 false, undefined, null, 0, none 时,会输出 false。你也可以增加一些自定义的字符串来补充输出 false 的内容。非字符、非数字、非布尔类型,直接输出 True。",
"showStatus": false,
"isTool": false,
"modules": [
{
"moduleId": "w90mfp",

View File

@@ -1,28 +0,0 @@
{
"name": "core.app.template.Simple template",
"desc": "core.app.template.Simple template tip",
"systemForm": {
"aiSettings": {
"model": true,
"systemPrompt": true,
"temperature": false,
"maxToken": false,
"quoteTemplate": false,
"quotePrompt": false
},
"dataset": {
"datasets": true,
"similarity": false,
"limit": false,
"searchMode": false,
"usingReRank": false,
"searchEmptyText": false
},
"userGuide": {
"welcomeText": true,
"variables": false,
"questionGuide": false,
"tts": true
}
}
}

View File

@@ -9,12 +9,13 @@
"lint": "next lint"
},
"dependencies": {
"@chakra-ui/anatomy": "^2.2.1",
"@chakra-ui/icons": "^2.1.1",
"@chakra-ui/next-js": "^2.1.5",
"@chakra-ui/react": "^2.8.1",
"@chakra-ui/styled-system": "^2.9.1",
"@chakra-ui/system": "^2.6.1",
"@apidevtools/swagger-parser": "^10.1.0",
"@chakra-ui/anatomy": "2.2.1",
"@chakra-ui/icons": "2.1.1",
"@chakra-ui/next-js": "2.1.5",
"@chakra-ui/react": "2.8.1",
"@chakra-ui/styled-system": "2.9.1",
"@chakra-ui/system": "2.6.1",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@fastgpt/global": "workspace:*",
@@ -22,14 +23,13 @@
"@fastgpt/service": "workspace:*",
"@fastgpt/web": "workspace:*",
"@fortaine/fetch-event-source": "^3.0.6",
"@node-rs/jieba": "^1.7.2",
"@tanstack/react-query": "^4.24.10",
"@types/nprogress": "^0.2.0",
"axios": "^1.5.1",
"date-fns": "2.30.0",
"dayjs": "^1.11.7",
"echarts": "^5.4.1",
"echarts-gl": "^2.0.9",
"echarts": "5.4.1",
"echarts-gl": "2.0.9",
"formidable": "^2.1.1",
"framer-motion": "^9.0.6",
"hyperdown": "^2.4.29",
@@ -37,10 +37,10 @@
"immer": "^9.0.19",
"js-yaml": "^4.1.0",
"jschardet": "^3.0.0",
"json5": "^2.2.3",
"jsonwebtoken": "^9.0.2",
"lodash": "^4.17.21",
"mermaid": "^10.2.3",
"@node-rs/jieba": "1.10.0",
"nanoid": "^4.0.1",
"next": "13.5.2",
"next-i18next": "15.2.0",

View File

@@ -9,6 +9,6 @@
- [计费规则](https://doc.fastgpt.in/docs/pricing/)
**其他问题**
| 添加小助手进入交流群 |
| 扫码进入交流群 |
| ----------------------- |
| ![](https://otnvvf-imgs.oss.laf.run/wx300.jpg) |
| ![](https://oss.laf.run/htr4n1-images/fastgpt-qr-code.jpg) |

View File

@@ -1 +0,0 @@
<?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="1700745458924" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="30191" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M0 512a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#EFF2FF" p-id="30192"></path><path d="M682.666667 682.666667c9.898667 9.841778-9.841778-9.841778 0 0zM338.488889 685.511111l5.688889-5.688889c-1.080889 0.682667-2.161778 2.104889-2.844445 2.844445a10.752 10.752 0 0 0-2.844444 2.844444z" fill="#000000" p-id="30193"></path><path d="M784.896 740.693333c23.324444-40.504889 10.410667-71.68-30.947556-102.798222-48.696889-36.579556-96.199111-61.212444-130.389333-21.788444 0 0-36.295111 43.064889-143.075555-57.685334C356.352 440.490667 408.462222 398.677333 408.462222 398.677333c43.178667-43.235556 15.701333-75.548444-20.48-124.416-36.238222-48.924444-72.817778-64.341333-125.326222-22.300444-101.262222 81.009778 41.528889 271.189333 113.607111 345.144889 0 0 109.738667 113.095111 178.801778 150.755555l36.920889 20.593778c52.906667 27.079111 112.469333 39.480889 154.339555 14.336 0 0 20.195556-10.353778 38.570667-42.097778z" fill="#4D4DEE" p-id="30194"></path></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,6 @@
<svg t="1710841200339" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1550"
width="128" height="128">
<path
d="M441.08001533 510.85997782V108.53819562c0-20.25527787 0-20.30830215 20.57342359-20.33481431H649.86314777c16.91474774 0 17.5510392 0.42419429 17.55103921 17.07382061 0 178.50626422-0.05302429 357.03904059-0.13256073 535.6513534 0 90.06175249 0.47721859 180.12350499 0.66280361 270.15874534 0 20.52039931 0 20.62644787-21.60739721 20.65296002h-188.20970885c-16.57008987 0-16.88823559-0.29163359-16.88823562-16.17240772V510.80695353l-0.15907285 0.05302429zM34.78141155 936.19430083c8.56342244-16.96777203 15.05889769-30.3829168 22.00507936-43.63898869 21.95205507-42.63152723 44.38132873-85.1039816 65.77662877-128.00063028 3.60565156-7.26432739 4.2949673-16.33148058 4.32147945-24.57675731 0.26512144-147.03634954 0.26512144-294.01967477 0-440.94997572-0.15907286-16.11938343 3.44657869-32.07969399 10.49880894-46.68788524a10636.14185068 10636.14185068 0 0 0 71.2381304-152.33877828c3.92379728-8.56342244 9.17320175-12.32814687 18.98269496-12.11604972 33.45832548 0.39768215 66.91665095 0.13256073 100.37497644 0.21209715 17.20638133 0 17.57755134 0.34465787 17.57755134 16.96777204v468.81423886c0 56.12620844 0.45070644 112.25241685-0.23860931 168.37862529-0.21209715 10.79044253-2.65121438 21.44832433-7.2113031 31.28432968-22.58834652 49.04746604-46.39625165 97.59120133-69.35576818 146.50610666-5.30242877 11.26766112-12.30163473 15.85426198-25.87585235 15.69518912-61.45514934-0.53024288-122.96332295 0.21209715-184.39196015 0.47721859L34.78141155 936.19430083zM762.14207678 633.13398503V350.99175069c0-18.66454924 0-18.92967068 19.56596212-18.95618283 62.72773223-0.10604857 125.45546447-0.10604857 188.236221 0 18.31989136 0 18.87664639 0.79536432 18.87664639 18.55850067L989.21858845 913.73851504c0 4.02984586-0.26512144 8.05969171-0.42419431 12.11604971-0.26512144 6.8401331-3.60565156 10.02159036-11.02905181 10.02159035-68.13620958 0-136.27241915 0.10604857-204.35560443 0.31814573-7.34386383 0-10.92300324-2.78377509-10.73741824-9.96856606V633.13398503h-0.53024288zM874.68612722 260.82394962c-32.98110689 0-66.01523807-0.39768215-98.99634496 0.21209715-10.63136967 0.185585-13.65375406-3.44657869-13.60072977-13.25607191 0.31814573-47.58929812 0-95.20510839 0-142.82091866 0-15.85426198 0.90141289-16.6496263 16.83521131-16.70265059 65.59104377-0.13256073 131.18208753 0 196.79964344-0.34465788 9.80949321 0 13.09699904 3.15494512 13.04397477 12.61978046-0.185585 47.64232241 0.26512144 95.25813268 0.34465786 142.84743081 0 16.09287129-0.90141289 16.78218703-17.97523349 16.80869917h-96.50420346l0.07953644 0.63629145z"
fill="#E06639" p-id="1551"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,9 @@
<svg t="1710841195972" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1400"
width="128" height="128">
<path
d="M164.864 616.704c0-57.856 34.56-115.925333 102.186667-161.706667 67.413333-45.653333 163.285333-75.52 271.786666-75.52 108.416 0 204.373333 29.866667 271.701334 75.52 34.133333 23.04 59.818667 49.322667 76.928 77.056 20.778667-37.973333 29.738667-78.293333 24.917333-118.485333a18.346667 18.346667 0 0 1 0.725333-7.765333 412.714667 412.714667 0 0 0-44.586666-34.773334C781.952 312.32 665.173333 277.76 538.794667 277.76S295.68 312.32 209.109333 371.029333c-86.314667 58.453333-146.944 144.426667-146.944 245.674667s60.586667 187.264 146.944 245.76c86.528 58.581333 203.264 93.226667 329.685334 93.226667s243.2-34.645333 329.728-93.269334c86.314667-58.453333 146.901333-144.469333 146.901333-245.717333 0-64.384-24.490667-122.581333-64.512-171.477333-2.133333 45.098667-18.133333 88.405333-44.757333 127.786666 4.394667 14.464 6.613333 29.098667 6.613333 43.690667 0 57.898667-34.602667 115.968-102.229333 161.749333-67.370667 45.653333-163.285333 75.52-271.744 75.52s-204.373333-29.866667-271.744-75.52c-67.626667-45.781333-102.186667-103.850667-102.186667-161.706666z"
fill="#3762FF" p-id="1401"></path>
<path
d="M164.010667 498.517333c-27.392 77.013333-20.906667 146.432 14.72 196.266667 35.626667 49.834667 99.584 78.933333 182.016 78.933333 82.261333-0.042667 178.133333-29.610667 266.197333-91.392s148.053333-141.525333 175.402667-218.368c27.392-77.013333 20.906667-146.432-14.677334-196.266666-35.626667-49.834667-99.584-78.933333-182.016-78.933334-82.261333 0-178.133333 29.610667-266.24 91.392-88.021333 61.738667-148.053333 141.525333-175.36 218.368z m-98.474667-34.389333C100.864 364.8 175.488 268.373333 279.04 195.669333 382.72 123.008 499.328 85.333333 605.610667 85.333333c106.197333 0 206.890667 38.058667 267.306666 122.624 60.416 84.522667 63.232 191.274667 27.946667 290.432-35.328 99.328-109.952 195.754667-213.589333 268.416-103.594667 72.704-220.202667 110.378667-326.528 110.378667-106.154667 0-206.848-38.058667-267.264-122.581333-60.458667-84.522667-63.232-191.274667-27.946667-290.432z"
fill="#1041F3" p-id="1402"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,7 @@
<svg t="1710840533172" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1458"
width="128" height="128">
<path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#F3DFBC" p-id="1459"></path>
<path
d="M653.443072 286.424064h-97.913856l178.556928 451.150848H832L653.443072 286.424064z m-282.886144 0L192 737.575936h99.84512l36.514816-94.741504h186.805248l36.514816 94.741504h99.84512L472.968192 286.424064H370.556928z m-9.89696 272.622592l61.103104-158.55104 61.103104 158.55104H360.659968z"
fill="#20201C" p-id="1460"></path>
</svg>

After

Width:  |  Height:  |  Size: 619 B

View File

@@ -0,0 +1,11 @@
<svg t="1710923402682" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1121"
width="128" height="128">
<path
d="M68.48129212 644.59999627c-0.15710901-120.97393023-0.31421799-241.94786048-0.314218-362.92179071 0-15.86800901 8.16966803-28.27962006 21.83815104-36.29217909 48.5466811-28.43672906 97.09336219-56.87345811 145.9542613-84.83886017 75.88364715-43.67630209 151.9244033-87.03838618 227.96515945-130.55757925 7.85545002-4.39905201 15.55379103-8.95521301 22.93791404-14.13981003 20.73838803-14.29691903 41.63388507-17.12488105 64.10047214-3.77061602 29.22227406 17.43909904 58.60165712 34.40687107 87.98104017 51.37464313 93.95118219 54.3597141 188.05947338 108.56231921 282.01065555 162.7649243 10.52630302 6.127251 21.20971504 11.94028402 31.57890906 18.22464405 15.08246403 9.11232202 22.93791404 22.46658704 22.93791406 40.21990407 0 157.58032731 0.31421799 315.16065462-0.15710901 472.74098195 0 16.49644503-7.69834101 30.47914606-23.25213205 39.43435907-37.07772405 21.52393302-75.25521114 41.47677609-111.54739022 63.94336312-52.1601881 32.20734506-106.67701121 59.85852912-158.68009031 92.38009218-30.95047306 19.32440705-63.47203613 36.29217908-95.05094519 54.35971411-13.98270102 8.01255901-27.80829306 16.18222702-41.63388508 24.50900405-14.76824603 8.95521301-29.69360106 9.42654002-44.77606509 0.78554499-60.17274713-34.72108908-120.34549424-69.44217814-180.67535037-104.1632672-65.98578013-38.02037807-131.97156027-75.88364715-197.80023136-113.90402523-11.94028402-6.91279601-23.72345905-13.66848304-35.1924161-21.20971504-12.25450203-8.16966803-18.22464404-20.42417004-18.22464403-34.87819806-0.15710901-37.07772405 0.15710901-74.15544815 0.314218-111.23317222 1.72819901-0.628436 1.72819901-1.72819901-0.314218-2.827962z m380.36088975-240.53387947c2.35663501-1.885308 4.71327001-3.92772502 7.22701402-5.49881501 73.52701215-42.26232108 147.05402429-84.52464218 220.73814544-126.78696327 2.98507101-1.72819901 6.91279601-1.72819901 7.06990501-6.59857801 0.15710901-5.18459701-4.39905201-5.02748801-7.22701402-6.598578-43.36208409-25.13744005-87.03838618-49.96066209-130.24336125-75.56942917-17.91042605-10.68341202-35.03530708-9.11232202-51.6888611 0.62843601-49.01800811 28.27962006-97.56468919 57.18767612-146.4255883 85.78151417-34.09265308 19.95284304-68.49952413 39.59146809-102.74928619 59.38720211-19.63862503 11.31184801-29.37938307 27.02274804-29.06516507 50.90331611 0.94265401 95.52227219 0.628436 191.04454438 0.157109 286.56681656-0.15710901 21.52393302 9.89786702 35.82085206 27.02274805 46.0329371 33.46421707 19.95284304 67.39976113 39.59146809 101.4924142 58.60165712 11.62606602 6.441469 22.46658704 14.92535503 38.17748709 19.63862503V505.08720399c6.91279601 20.89549705 19.79573404 36.29217908 39.12014107 47.60402709 29.69360106 17.28199003 67.39976113 13.35426503 92.06587419-11.15473903 28.75094705-28.43672906 30.63625506-67.08554313 13.66848301-96.15070819-17.43909904-30.32203706-46.50426407-40.06279507-79.34004515-41.31966706z m87.98104018 458.2869539c15.23957303-4.08483399 27.65118406-14.92535503 41.47677608-22.78080505 43.67630209-24.82322205 86.72416817-50.90331611 130.71468825-75.25521115 28.75094705-16.02511803 56.40213111-33.77843506 86.09573217-48.2324631 17.91042605-8.64099502 31.57890905-24.03767705 31.57890908-46.34715509 0.15710901-99.1357792 0.31421799-198.1144494 0.157109-297.25022859 0-11.94028402-5.49881501-14.92535503-14.76824605-7.54123201-28.27962006 22.15236905-61.11540111 36.76350606-91.90876517 54.67393211-58.13033011 33.93554407-116.41776923 67.55687014-174.70520834 101.33530519-9.11232202 5.18459701-12.56872002 11.15473903-12.41161104 21.83815106 0.31421799 102.59217721 0.15710901 205.3414634 0.15710901 307.9336406-0.31421799 3.770616-1.57108999 8.16966803 3.61350701 11.62606603z"
fill="#066AF3" p-id="1122"></path>
<path d="M68.48129212 644.59999627c2.042417 1.09976302 2.042417 2.19952601 0 3.29928901v-3.29928901z" fill="#4372E0"
p-id="1123"></path>
<path
d="M383.32772875 504.93009499c-5.81303301-47.28980909 14.76824603-79.02582716 65.51445312-100.86397819 32.99289006 1.25687199 61.90094612 10.99763002 79.34004515 41.16255808 16.81066303 29.22227406 15.08246403 67.71397913-13.66848301 96.15070819-24.82322205 24.50900404-62.37227313 28.43672906-92.06587419 11.15473902-19.32440705-11.31184801-32.36445406-26.70853004-39.12014107-47.6040271z"
fill="#002A9A" p-id="1124"></path>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1,15 @@
<svg t="1710841272884" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2684"
width="128" height="128">
<path
d="M511.968 959.936c298.688 0 447.968-200.576 447.968-448 0-247.36-149.28-447.936-448-447.936C213.28 64 64 264.576 64 511.968c0 247.392 149.248 447.968 447.968 447.968z"
fill="#FFB02E" p-id="2685"></path>
<path
d="M103.936 586.912a31.936 31.936 0 0 0-7.584 25.568 32 32 0 0 0-37.152 51.84l9.344 8a32 32 0 0 0-24.992 56.256l63.52 52.928-4.032-1.984a35.712 35.712 0 0 0-36.672 60.896C107.712 869.76 163.008 908.64 192 928c48 32 102.72 42.944 160 0 32-24 72.48-97.984 29.92-171.712-8.064-13.952-15.296-28.64-18.304-44.48-13.152-69.76-32.8-141.216-75.616-119.808-23.2 11.584-21.184 31.584-18.304 60 1.088 10.784 2.304 22.784 2.304 36l-2.56 1.28-120.384-105.376a32 32 0 0 0-45.12 3.04zM920.096 586.912c6.368 7.296 8.832 16.64 7.584 25.568a32 32 0 0 1 37.12 51.84l-9.344 8a32 32 0 0 1 25.024 56.256l-63.52 52.928 4.032-1.984a35.712 35.712 0 0 1 36.672 60.896C916.32 869.76 861.024 908.64 832 928c-48 32-102.752 42.944-160 0-32-24-72.48-97.984-29.92-171.712 8.064-13.952 15.296-28.64 18.304-44.48 13.152-69.76 32.8-141.216 75.616-119.808 23.2 11.584 21.184 31.584 18.304 60-1.088 10.784-2.304 22.784-2.304 36l2.56 1.28 120.384-105.376a32 32 0 0 1 45.12 3.04z"
fill="#FF822D" p-id="2686"></path>
<path
d="M224 464c0 44.16-28.64 80-64 80s-64-35.84-64-80 28.64-80 64-80 64 35.84 64 80zM928 464c0 44.16-28.64 80-64 80s-64-35.84-64-80 28.64-80 64-80 64 35.84 64 80z"
fill="#FF6723" p-id="2687"></path>
<path
d="M299.168 333.184c-6.72 7.296-10.24 17.024-11.744 24.928a32 32 0 0 1-62.848-12.224c2.848-14.592 9.92-36.896 27.456-55.968C270.496 269.792 298.112 256 336 256c38.24 0 65.984 14.464 84.352 34.624 17.408 19.104 24.64 41.344 27.2 55.904a32 32 0 0 1-63.072 10.944 49.472 49.472 0 0 0-11.456-23.744C367.04 327.104 356.544 320 336 320c-20.896 0-31.104 6.944-36.832 13.184zM651.2 333.184c-6.72 7.296-10.24 17.024-11.776 24.928a32 32 0 0 1-62.816-12.224c2.816-14.592 9.92-36.896 27.424-55.968C622.496 269.792 650.112 256 688 256c38.272 0 65.984 14.464 84.352 34.624 17.408 19.104 24.64 41.344 27.2 55.904a32 32 0 0 1-63.072 10.944 49.44 49.44 0 0 0-11.456-23.744C719.04 327.104 708.544 320 688 320c-20.896 0-31.072 6.944-36.8 13.184zM313.6 492.8a32 32 0 1 0-51.2 38.4c22.464 29.952 96.256 92.8 249.6 92.8s227.136-62.848 249.6-92.8a32 32 0 0 0-51.2-38.4c-9.536 12.704-63.744 67.2-198.4 67.2s-188.864-54.496-198.4-67.2z"
fill="#402A32" p-id="2688"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,31 @@
<svg t="1710840553956" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2078"
width="128" height="128">
<path d="M0.143417 0h1011.952942v1011.952941h-1011.952942v-1011.952941z" fill="#1A1D22" p-id="2079"></path>
<path
d="M554.308123 289.129412a1898.375529 1898.375529 0 0 0-289.129412-96.376471c175.911153-130.710588 352.617412-126.686871 530.070589 12.047059 46.116141 34.044988 78.2336 78.2336 96.37647 132.517647l-60.235294 24.094118a1077.320282 1077.320282 0 0 0-277.082353-72.282353z"
fill="#EDEDEE" p-id="2080"></path>
<path
d="M265.178711 216.847059c86.690635 52.814306 183.067106 76.908424 289.129412 72.282353 14.215529 15.709365 30.286306 31.756047 48.188236 48.188235-27.467294 22.287059-27.467294 42.381553 0 60.235294l337.317647 84.329412v96.376471a2918.207247 2918.207247 0 0 0-409.6-96.376471c-122.398118-52.043294-250.916141-92.184094-385.505883-120.470588-18.432-86.738824 21.7088-134.927059 120.470588-144.564706z"
fill="#EFEFF0" p-id="2081"></path>
<path
d="M265.178711 192.752941a1898.375529 1898.375529 0 0 1 289.129412 96.376471c-106.062306 4.626071-202.438776-19.468047-289.129412-72.282353v-24.094118z"
fill="#626568" p-id="2082"></path>
<path
d="M144.708123 385.505882a2590.021271 2590.021271 0 0 0 313.22353 96.376471c29.226165 5.951247 45.296941 22.022024 48.188235 48.188235 2.891294 26.166212 18.962071 42.236988 48.188235 48.188236a6047.623529 6047.623529 0 0 1 361.411765 108.423529c-17.492329 33.659482-45.586071 53.729882-84.329412 60.235294a2021.7856 2021.7856 0 0 1-301.17647-72.282353 3182.302871 3182.302871 0 0 0-457.788236-120.470588v-72.282353c-9.926776-59.584753 14.167341-91.702212 72.282353-96.376471z"
fill="#EEEEEF" p-id="2083"></path>
<path
d="M144.708123 361.411765c134.589741 28.286494 263.107765 68.427294 385.505883 120.470588 4.144188 23.901365-3.903247 39.948047-24.094118 48.188235-2.891294-26.166212-18.962071-42.236988-48.188235-48.188235a2590.021271 2590.021271 0 0 1-313.22353-96.376471v-24.094117z"
fill="#5C5E62" p-id="2084"></path>
<path
d="M72.42577 481.882353v72.282353a3182.302871 3182.302871 0 0 1 457.788236 120.470588c-16.070776 0-24.094118 8.023341-24.094118 24.094118a6126.772706 6126.772706 0 0 1-397.552941-120.470588 118.832188 118.832188 0 0 0-12.047059 72.282352c-49.007435-51.922824-57.030776-108.1344-24.094118-168.658823z"
fill="#4F5155" p-id="2085"></path>
<path
d="M506.119888 698.729412v72.282353c94.930824 9.637647 183.283953 37.755482 265.035294 84.329411-44.092235 66.499765-100.303812 78.546824-168.658823 36.141177a4261.285647 4261.285647 0 0 0-433.694118-120.470588c-42.164706-27.949176-66.258824-68.089976-72.282353-120.470589a118.832188 118.832188 0 0 1 12.047059-72.282352 6126.772706 6126.772706 0 0 0 397.552941 120.470588z"
fill="#F2F2F3" p-id="2086"></path>
<path
d="M168.802241 771.011765a4261.285647 4261.285647 0 0 1 433.694118 120.470588v24.094118a2109.391812 2109.391812 0 0 1-397.552942-120.470589c-9.613553 5.493459-13.613176 13.540894-12.047058 24.094118-20.190871-8.240188-28.238306-24.286871-24.094118-48.188235z"
fill="#5D5F62" p-id="2087"></path>
<path
d="M602.496359 915.576471c10.553224-1.566118 18.600659 2.433506 24.094117 12.047058-169.285271 59.994353-313.825882 23.853176-433.694117-108.423529-1.566118-10.553224 2.433506-18.600659 12.047058-24.094118a2109.391812 2109.391812 0 0 0 397.552942 120.470589z"
fill="#E7E7E8" p-id="2088"></path>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,27 @@
<svg t="1710841166479" class="icon" viewBox="0 0 1040 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1089"
width="128" height="128">
<path
d="M373.508197 8.393443L411.278689 16.786885l37.770491 50.360656 12.590164-4.196721q-19.304918 10.911475 4.196722 20.983606l12.590164-4.196721-4.196722 12.590164q21.822951-5.87541 12.590164 16.786885h16.786885v12.590164l67.147541 109.114754-4.196721 12.590164 12.590164 4.196721-4.196721 12.590164 12.590164 4.196722-193.049181 4.196721 58.754099-104.918033v-25.180328L390.295082 33.57377q-18.465574-5.87541-12.590164 12.590164L251.803279 268.590164H104.918033l-4.196722 12.590164 276.983607 461.639344-130.098361 4.196721-20.983606 20.983607-58.754099 100.721311 117.508197 8.393443-54.557377 20.983607q-79.737705 16.786885-96.52459-29.37705l-58.754098-100.721311v-25.180328l58.754098-109.114754-134.295082-235.016393 67.147541-125.90164 29.377049-29.377049h134.295082l12.590164-12.590164L373.508197 8.393443z"
fill="#4644B0" opacity=".992" p-id="1090"></path>
<path
d="M365.114754 419.672131h235.016394l4.196721 12.590164-8.393443 25.180328q3.357377 95.685246-33.57377 151.081967l4.196721 12.590164q-18.465574-5.87541-12.590164 12.590164v16.786885L516.196721 688.262295 386.098361 474.229508 365.114754 419.672131z"
fill="#4644B0" opacity=".992" p-id="1091"></path>
<path
d="M919.081967 176.262295l8.393443 16.786885-8.393443-16.786885zM944.262295 318.95082l-8.393443 16.786885 8.393443-16.786885zM910.688525 327.344262l-8.393443 16.786886 8.393443-16.786886zM902.295082 386.098361l12.590164 20.983606-16.786885-8.393442 4.196721-12.590164zM927.47541 486.819672l8.393442 16.786885-8.393442-16.786885zM961.04918 495.213115l8.393443 16.786885-8.393443-16.786885zM961.04918 545.57377l8.393443 16.786886-8.393443-16.786886zM1036.590164 621.114754l4.196721 20.983607h-8.393442l4.196721-20.983607zM809.967213 805.770492l-8.393443 16.786885 8.393443-16.786885zM146.885246 881.311475l8.393443 16.786886-8.393443-16.786886zM751.213115 906.491803l-8.393443 16.786886 8.393443-16.786886zM717.639344 965.245902l-8.393442 16.786885 8.393442-16.786885zM516.196721 982.032787l8.393443 16.786885-8.393443-16.786885zM642.098361 1015.606557l37.770491 4.196722-37.770491 4.196721v-8.393443z"
fill="#6C6CEF" opacity=".843" p-id="1092"></path>
<path
d="M373.508197 0l-8.393443 16.786885 8.393443-16.786885zM239.213115 226.622951l-8.393443 16.786885 8.393443-16.786885zM88.131148 243.409836l-16.786886 25.180328 16.786886-25.180328zM100.721311 268.590164l142.688525 4.196721-134.295082 8.393443 4.196721 12.590164-12.590164-25.180328zM46.163934 310.557377l-8.393442 16.786885 8.393442-16.786885zM130.098361 318.95082l8.393442 16.786885-8.393442-16.786885zM12.590164 369.311475L8.393443 381.901639 4.196721 394.491803 0 381.901639 12.590164 369.311475zM163.672131 377.704918l8.393443 16.786885-8.393443-16.786885zM4.196721 402.885246L16.786885 423.868852l-16.786885-8.393442L4.196721 402.885246zM188.852459 419.672131l8.393443 16.786885-8.393443-16.786885zM37.770492 470.032787l8.393442 16.786885-8.393442-16.786885zM222.42623 478.42623l8.393442 16.786885-8.393442-16.786885zM62.95082 512l8.393442 16.786885-8.393442-16.786885zM96.52459 570.754098l8.393443 16.786886-8.393443-16.786886zM247.606557 747.016393l130.098361 4.196722-130.098361 4.196721v-8.393443z"
fill="#413FA6" opacity=".588" p-id="1093"></path>
<path
d="M348.327869 33.57377l-8.393443 16.786886 8.393443-16.786886zM390.295082 33.57377l-16.786885 25.180328 16.786885-25.180328zM323.147541 75.540984l-8.393443 16.786885 8.393443-16.786885zM348.327869 100.721311l-8.393443 16.786886 8.393443-16.786886zM440.655738 125.901639l8.393442 16.786886-8.393442-16.786886zM289.57377 134.295082l-8.393442 16.786885 8.393442-16.786885zM314.754098 159.47541l-8.393442 16.786885 8.393442-16.786885zM432.262295 184.655738l-8.393443 16.786885 8.393443-16.786885zM289.57377 201.442623l-8.393442 16.786885 8.393442-16.786885zM104.918033 235.016393l121.704918 4.196722-121.704918 4.196721v-8.393443zM256 260.196721l-8.393443 16.786886 8.393443-16.786886zM390.295082 268.590164l222.426229 4.196721-222.426229 4.196722v-8.393443zM352.52459 411.278689l201.442623 4.196721-188.852459 4.196721-8.393443 8.393443-4.196721-16.786885zM650.491803 486.819672l-8.393442 16.786885 8.393442-16.786885zM407.081967 512l8.393443 16.786885-8.393443-16.786885zM289.57377 587.540984l8.393443 16.786885-8.393443-16.786885zM591.737705 587.540984l-8.393443 16.786885 8.393443-16.786885zM465.836066 612.721311l8.393442 16.786886-8.393442-16.786886zM323.147541 646.295082l8.393443 16.786885-8.393443-16.786885zM558.163934 646.295082l-8.393442 16.786885 8.393442-16.786885zM88.131148 713.442623l-8.393443 16.786885 8.393443-16.786885zM71.344262 738.622951l4.196722 29.377049H67.147541l4.196721-29.377049zM205.639344 814.163934l-8.393442 16.786886 8.393442-16.786886zM104.918033 822.557377l8.393442 16.786885-8.393442-16.786885zM180.459016 864.52459l264.393443 4.196721-264.393443 4.196722v-8.393443z"
fill="#4847B2" opacity=".176" p-id="1094"></path>
<path
d="M365.114754 0L360.918033 12.590164 348.327869 33.57377l4.196721-12.590163L365.114754 0zM541.377049 0l8.393443 16.786885-8.393443-16.786885zM558.163934 25.180328l8.393443 16.786885-8.393443-16.786885zM390.295082 41.967213l8.393443 16.786885-8.393443-16.786885zM583.344262 67.147541l12.590164 20.983607h-8.393442L583.344262 67.147541zM415.47541 83.934426l8.393442 16.786885-8.393442-16.786885zM608.52459 109.114754h268.590164l29.377049 29.377049-29.377049-20.983606h-268.590164v-8.393443zM910.688525 151.081967l20.983606 29.377049-16.786885-8.393442-4.196721-20.983607zM944.262295 209.836066l20.983607 29.377049-16.786886-8.393443-4.196721-20.983606zM616.918033 268.590164h318.950819l4.196722 12.590164-16.786885 8.393442-4.196722-12.590163h-302.163934v-8.393443zM969.442623 276.983607l4.196721 12.590163-16.786885 8.393443 12.590164-20.983606zM919.081967 302.163934l-4.196721 12.590164-12.590164 20.983607 4.196721-12.590164 12.590164-20.983607zM944.262295 327.344262l-4.196721 12.590164-12.590164 20.983607 4.196721-12.590164 12.590164-20.983607zM885.508197 360.918033l-4.196722 12.590164-8.393442 25.180328 16.786885 25.180327-16.786885-8.393442-8.393443-25.180328 20.983607-29.377049zM919.081967 369.311475l-4.196721 12.590164-4.196721 20.983607-4.196722-20.983607 12.590164-12.590164zM558.163934 411.278689l130.098361 4.196721-130.098361 4.196721v-8.393442zM927.47541 428.065574l20.983606 29.377049-16.786885-8.393443-4.196721-20.983606zM893.901639 436.459016l29.37705 46.163935-25.180328-16.786885-4.196722-29.37705zM952.655738 470.032787l20.983606 29.377049-16.786885-8.393443-4.196721-20.983606zM927.47541 495.213115l20.983606 29.377049-16.786885-8.393443-4.196721-20.983606zM642.098361 503.606557l-8.393443 16.786886 8.393443-16.786886zM788.983607 512l33.57377 20.983607 8.393443 16.786885-16.786886-8.393443-12.590164-20.983606-25.180327 33.57377 4.196721-12.590164 8.393443-29.377049zM986.229508 528.786885l20.983607 29.377049-16.786885-8.393442-4.196722-20.983607zM616.918033 545.57377l-8.393443 16.786886 8.393443-16.786886zM961.04918 553.967213l20.983607 29.377049-16.786885-8.393442-4.196722-20.983607zM768 562.360656l-4.196721 12.590164-4.196722 12.590164-4.196721-12.590164 12.590164-12.590164zM843.540984 579.147541l20.983606 29.377049-16.786885-8.393442-4.196721-20.983607zM1019.803279 587.540984l20.983606 29.377049-16.786885-8.393443-4.196721-20.983606zM986.229508 595.934426l20.983607 41.967213h-130.098361l-12.590164-12.590164 12.590164 4.196722 121.704918-4.196722-12.590164-29.377049zM734.42623 621.114754l-4.196722 12.590164-12.590164 20.983607 4.196722-12.590164 12.590164-20.983607zM1036.590164 646.295082l4.196721 12.590164-20.983606 29.377049 4.196721-12.590164 12.590164-29.377049zM549.770492 663.081967l-8.393443 16.786885 8.393443-16.786885zM700.852459 679.868852l-4.196721 12.590164-12.590164 20.983607-4.196722-12.590164 20.983607-20.983607zM1011.409836 696.655738l-4.196721 12.590164-20.983607 37.770491 4.196722-12.590163 20.983606-37.770492zM675.672131 721.836066l-4.196721 12.590164-4.196721 12.590163-4.196722-12.590163 12.590164-12.590164zM977.836066 755.409836l-25.180328 33.573771-130.098361-4.196722 130.098361-4.196721 25.180328-25.180328zM642.098361 780.590164l-4.196722 12.590164-12.590164 20.983606 4.196722-12.590164 12.590164-20.983606zM809.967213 814.163934l-4.196721 12.590164-12.590164 20.983607 4.196721-12.590164 12.590164-20.983607zM608.52459 839.344262l-4.196721 12.590164-12.590164 20.983607 4.196721-12.590164 12.590164-20.983607zM784.786885 856.131148l-4.196721 12.590163-12.590164 20.983607 4.196721-12.590164 12.590164-20.983606zM449.04918 864.52459l8.393443 16.786885-8.393443-16.786885zM583.344262 881.311475l-4.196721 12.590164-4.196721 12.590164-4.196722-12.590164 12.590164-12.590164zM146.885246 889.704918l20.983606 12.590164-12.590163 4.196721-8.393443-16.786885zM465.836066 889.704918l20.983606 29.377049-16.786885-8.393442-4.196721-20.983607zM180.459016 898.098361l256 4.196721-256 4.196721v-8.393442zM440.655738 914.885246l20.983606 29.377049-16.786885-8.393443-4.196721-20.983606zM751.213115 914.885246l-4.196722 12.590164-12.590163 20.983606 4.196721-12.590164 12.590164-20.983606zM549.770492 940.065574l-4.196722 12.590164-12.590163 20.983606 4.196721-12.590164 12.590164-20.983606zM499.409836 948.459016l29.377049 37.770492-25.180328-16.786885-4.196721-20.983607zM717.639344 973.639344l-4.196721 12.590164-12.590164 20.983607 4.196721-12.590164 12.590164-20.983607zM482.622951 982.032787l12.590164 20.983606-16.786885-8.393442 4.196721-12.590164z"
fill="#6F6FEA" opacity=".227" p-id="1095"></path>
<path
d="M386.098361 0h138.491803L545.57377 8.393443l62.95082 109.114754h260.196721l29.37705 20.983606 67.147541 117.508197v25.180328l-67.147541 117.508197 134.295082 218.229508v33.57377L952.655738 780.590164h-125.90164L814.163934 793.180328 684.065574 1015.606557l-159.47541 8.393443-29.377049-20.983607-62.95082-104.918032-180.459016-4.196722 37.770491-20.983606h159.47541l4.196722 12.590164 71.344262 113.311475 276.983606-478.426229 62.95082 117.508196 151.081967-4.196721-142.688524-243.409836q47.842623-51.2 67.147541-121.704918H591.737705L570.754098 256l4.196722-12.590164-12.590164-4.196721v-16.786885L503.606557 109.114754h-16.786885q9.232787-22.662295-12.590164-16.786885L411.278689 16.786885q-34.413115 10.911475-25.180328-16.786885z"
fill="#6867ED" opacity=".996" p-id="1096"></path>
<path
d="M604.327869 419.672131h71.344262l4.196721 12.590164L566.557377 612.721311l4.196721-12.590163 33.573771-151.081968V419.672131zM558.163934 621.114754l4.196722 12.590164-16.786886 8.393443 12.590164-20.983607zM532.983607 671.47541l-4.196722 12.590164-4.196721 12.590164-4.196721-12.590164 12.590164-12.590164z"
fill="#6867ED" opacity=".996" p-id="1097"></path>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,12 @@
<svg t="1710840542445" class="icon" viewBox="0 0 1090 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1764"
width="128" height="128">
<path
d="M851.79730973 887.73599356c-22.09345317 31.07812413-50.66765259 55.38092261-81.15661796 77.32708609-89.84670956 64.80746262-190.74014569 91.17231675-300.6182528 82.48222515-178.6623913-13.99252034-341.71207568-148.32071561-387.96103764-322.26983687-46.39625165-174.09641097-5.89158752-326.68852752 121.66128212-454.8305559 62.89269668-63.18727606 126.96371088-125.04894493 190.59285601-187.49977256 3.24037312-3.24037312 5.89158752-7.51177407 12.07775439-9.27925034 2.79850407 8.10093283-1.17831749 15.75999659-2.06205562 23.12448099-10.31027814 90.4358683 16.49644503 171.29790689 63.33456575 246.85751673 33.87662819 54.79176385 76.0014789 102.95549177 125.93268306 143.16557653 61.71437919 49.78391447 68.48970482 131.23511182 32.551021 187.20519319-41.24111259 64.21830387-129.32034589 82.77680453-192.06575288 39.47363633-3.24037312-2.20934532-7.95364315-3.5349525-8.83738126-9.86840908 8.54280189 0.29457937 16.79102442 2.79850407 25.03924691 0.88373812 19.73681815-4.71327001 33.28746944-16.49644503 38.44260852-36.2332632 5.15513907-19.88410785-0.88373813-36.96971163-16.64373473-49.78391447-45.51251353-37.11700133-88.0792333-77.32708608-123.13417898-124.90165524-13.2560719-17.96934191-25.18653662-36.96971163-36.96971164-57.73755762-17.67476253 19.88410785-29.75251694 41.68298165-38.88447757 64.95475232-45.80709291 116.9480121-7.2171947 240.81863954 97.06390426 313.87432469 7.65906378 5.30242877 15.75999659 10.16298847 22.68261191 16.49644504 1.62018657 1.62018657 3.09308345 3.5349525 5.00784938 4.86055968 59.94690292 40.21008477 124.60707587 68.93157389 196.33715382 80.12559017 50.96223197 7.95364315 102.07175363 8.69009158 153.4758547 3.68224218 37.26429101-3.5349525 71.73007796-14.13981003 104.13380925-32.10915193z"
fill="#3EC7F8" p-id="1765"></path>
<path
d="M514.06205563-27.96399545c65.54391107 64.36559357 130.204084 127.84744899 194.71696726 191.18201476 38.73718787 38.00073946 77.76895517 76.0014789 116.21156367 114.29679774 70.84633982 70.55176044 112.82390085 155.83248969 128.28931806 254.3692908 0.58915875 3.82953187 0.88373813 7.51177407 1.03102783 11.34130596 0 1.17831749-0.58915875 2.35663501-0.88373814 3.53495249-3.5349525 0.29457937-4.27140094-2.35663501-5.15513907-4.41869062-24.45008817-50.52036291-64.95475232-82.18764578-116.94801211-100.59885675-27.39588193-9.72111939-55.97008134-15.31812754-83.95512203-22.82990161-70.10989139-18.55850066-133.29716746-49.04746604-179.39883976-107.3741824-37.4115807-47.42727948-57.44297824-101.48259488-57.14839883-162.46052565 0.29457937-53.90802574 0-107.66876177 0.14728966-161.5767875-0.1472897-4.56598032-2.35663501-10.16298847 3.09308346-15.46541722z"
fill="#E90302" p-id="1766"></path>
<path
d="M851.79730973 887.73599356c-32.40373131 17.96934191-66.86951826 28.42690974-103.83922989 32.10915193-51.40410106 5.0078494-102.5136227 4.27140094-153.47585469-3.68224218-71.73007796-11.19401627-136.39025089-39.9155054-196.33715381-80.12559017-1.91476594-1.3256072-3.38766283-3.24037312-5.00784939-4.86055968 5.74429781-1.91476594 10.01569877 1.91476594 14.72896877 3.97682157 161.13491844 70.25718107 343.18497255-38.44260851 358.06123104-213.717337 3.97682157-46.24896197-3.68224221-90.14128893-22.82990161-132.11884996-1.17831749-2.65121438-2.35663501-5.15513907-3.38766282-7.80635344-0.29457937-0.73644845 0.1472897-1.76747625 0.14728968-2.79850407 4.12411126-3.5349525 8.24822251-0.44186907 12.07775441 0.44186905 49.78391447 10.89943689 94.55997955 32.10915193 132.70800869 66.13306983 51.55139072 46.10167228 72.4665264 103.8392299 56.70652979 171.29790689-14.72896878 64.0710142-44.7760651 121.8085718-89.55213017 171.15061723z"
fill="#1753D7" p-id="1767"></path>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,10 @@
<svg width="600" height="600" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="300" cy="300" r="300" fill="white" />
<rect x="409.733" y="340.032" width="42.3862" height="151.648" rx="21.1931" fill="#003425" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M422.005 133.354C413.089 125.771 399.714 126.851 392.131 135.768L273.699 275.021C270.643 278.614 268.994 282.932 268.698 287.302C268.532 288.371 268.446 289.466 268.446 290.581V468.603C268.446 480.308 277.934 489.796 289.639 489.796C301.344 489.796 310.832 480.308 310.832 468.603V296.784L424.419 163.228C432.002 154.312 430.921 140.937 422.005 133.354Z"
fill="#003425" />
<rect x="113.972" y="134.25" width="42.3862" height="174.745" rx="21.1931"
transform="rotate(-39.3441 113.972 134.25)" fill="#003425" />
<circle cx="460.126" cy="279.278" r="25.9027" fill="#00DD20" />
</svg>

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -0,0 +1,7 @@
<svg t="1710325242339" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1009"
width="128" height="128">
<path
d="M500.7739264 502.10725974m-474.22577813 0a474.22577813 474.22577813 0 1 0 948.4515552 0 474.22577813 474.22577813 0 1 0-948.4515552 0Z"
fill="#DD6A5E" p-id="1010"></path>
<path d="M350.16248853 351.49582186h300.2519712v300.2519712H350.16248853z" fill="#FFFFFF" p-id="1011"></path>
</svg>

After

Width:  |  Height:  |  Size: 471 B

View File

@@ -62,6 +62,7 @@
"Back": "Back",
"Beta": "Beta",
"Business edition features": "This is the commercial version function ~",
"Cancel": "Cancel",
"Choose": "Choose",
"Close": "Close",
"Collect": "Collect",
@@ -113,6 +114,7 @@
"Not open": "Close",
"Number of words": "{{amount}} words",
"OK": "OK",
"Open": "Open",
"Opened": "Opened",
"Other": "Other",
"Output": "Output",
@@ -122,6 +124,7 @@
"Price used": "Usage",
"Read document": "Read document",
"Read intro": "Read intro",
"Remove": "Remove",
"Rename": "Rename",
"Rename Failed": "Rename Failed",
"Rename Success": "Rename Success",
@@ -159,6 +162,7 @@
"Upload File Failed": "Upload File Failed",
"Username": "UserName",
"Waiting": "Waiting",
"Warning": "",
"Website": "Website",
"avatar": {
"Select Avatar": "Select Avatar",
@@ -244,8 +248,12 @@
"Total chars": "Total chars: {{total}}",
"Total tokens": "Tokens: {{total}}",
"ai": {
"AI settings": "AI settings",
"Ai point price": "AI points",
"Max context": "Max context",
"Model": "Model",
"Prompt": "Prompt",
"Support tool": "Function call",
"model": {
"Dataset Agent Model": "Agent Model",
"Vector Model": "Vector Model"
@@ -260,6 +268,7 @@
"Chat Variable": "",
"External using": "External use",
"Make a brief introduction of your app": "Make a brief introduction of your app",
"Max histories": "Dialog round",
"Max tokens": "Max tokens",
"Name and avatar": "Avatar & Name",
"Next Step Guide": "Next step guide",
@@ -282,6 +291,15 @@
"TTS Tip": "After this function is enabled, the voice playback function can be used after each conversation. Use of this feature may incur additional charges.",
"Team tags": "Team tags",
"Temperature": "Temperature",
"Tool call": "Tool call",
"Tool call tip": "The AI model automatically selects one or more tools to use. If this feature is enabled, the knowledge base call is also called as a tool. Please try to choose the AI model that supports \"function call\", the effect is better.",
"ToolCall": {
"No plugin": "No plugins",
"Setting tool": "Setting tool",
"System": "System",
"Team": "Team",
"This plugin cannot be called as a tool": "This tool cannot be used in easy mode"
},
"Welcome Text": "Welcome Text",
"create app": "Create App",
"deterministic": "Deterministic",
@@ -692,6 +710,7 @@
"Search type": "Type",
"Source id": "Source ID",
"Source name": "Source",
"Tool description": "Description",
"Top K": "Top K",
"Using cfr": "Open query extension",
"Using query extension": "Open query extension",
@@ -770,6 +789,7 @@
"module": {
"Add question type": "Add type",
"Can not connect self": "Cannot connect itself",
"Confirm Delete Node": "",
"Data Type": "Data Type",
"Dataset quote": {
"Add quote": "Add quote",
@@ -792,6 +812,9 @@
"placeholder": "Questions about python introduction and usage, etc. The current conversation is related to the game GTA5.",
"tip": "Describes the scope of the current conversation, making it easier for the AI to complete first or vague questions, thereby enhancing the knowledge base's ability to continue conversations.If \n is empty, the question completion function is not used in the first conversation. "
},
"Quote prompt setting": "Quote prompt setting",
"Qupte prompt setting": "",
"Setting quote prompt": "Setting quote prompt",
"Unlink tip": "[{{name}}] An unfilled or unconnected parameter exists",
"Variable": "Variables",
"Variable Setting": "Variable Setting",
@@ -900,10 +923,13 @@
}
},
"template": {
"AI response switch tip": "If you want the current node not to output content, you can turn this switch off. AI output content will not be shown to the user, you can manually use the \"AI reply content\" for special processing.",
"AI support tool tip": "A model that supports function calls allows better use of tool calls.",
"Ai chat": "LLM Chat",
"Ai chat intro": "Request LLM chat",
"Assigned reply": "Assigned reply",
"Assigned reply intro": "The module can respond directly to a specified piece of content. Often used to guide and prompt. When non-string content is passed in, it is converted to a string for output.",
"Basic Node": "Basic Node",
"Chat entrance": "Chat entrance",
"Chat entrance intro": "When the user sends a content, the flow will start from this module.",
"Classify question": "Classify question",
@@ -924,9 +950,11 @@
"Response module": "Text output",
"Running app": "Running app",
"Running app intro": "You can select a different app to run",
"System Plugin": "System Plugin",
"System input module": "System input",
"TFSwitch": "TF Switch",
"TFSwitch intro": "Output True False based on what is passed in. By default, false is printed when the content passed in is false, undefined, null, 0, none. You can also add some custom strings to supplement the output of false.",
"Team Plugin": "Team Plugin",
"Tool module": "Tools",
"UnKnow Module": "UnKnow Module",
"User guide": "User guide",
@@ -934,6 +962,9 @@
"textEditor": "Text Editor",
"textEditor intro": "Output of fixed or incoming text after edit"
},
"templates": {
"Load plugin error": "Load plugin error"
},
"textEditor": {
"Text Edit": "Text Edit"
},
@@ -971,7 +1002,10 @@
"variable add option": "Add Option"
},
"plugin": {
"Get Plugin Module Detail Failed": "Load plugin failed"
"Custom headers": "Custom Headers",
"Delete http plugin": "Are you sure to delete this group of HTTP plug-ins? All plug-ins in the directory are deleted.",
"Get Plugin Module Detail Failed": "Load plugin failed",
"Intro placeholder": "If the plug-in is called as a tool, the introduction is used as the prompt word."
},
"shareChat": {
"Init Error": "Init Chat Error",
@@ -1178,18 +1212,38 @@
"Set Public": "Set to public"
},
"plugin": {
"Auth Header Prefix": "Auth header prefix",
"Auth Method": "Auth method",
"Auth Type": "Auth Type",
"Confirm Delete": "Confirm to delete the plugin?",
"Create Your Plugin": "Create Plugin",
"Custom Plugin": "Custom plugin",
"Description": "Description",
"Edit Http Plugin": "Edit HTTP plugin",
"Get Plugin Module Detail Failed": "Get plugin detail failed",
"HTTP Plugin": "HTTP plugin",
"Import Plugin": "Import HTTP plugin",
"Import from URL": "Import from URL",
"Intro": "Plugin Intro",
"Invalid Schema": "Invalid Schema",
"Invalid URL": "Invalid URL",
"Key": "Key",
"Load Plugin Failed": "Load Plugin Failed",
"Method": "Method",
"My Plugins": "My Plugins",
"No Intro": "This plugin is not introduced",
"None": "None",
"Path": "Path",
"Plugin List": "Plugin list",
"Plugin Module": "Plugin",
"Privacy Agreement": "privacy agreement",
"Search plugin": "Search plugins",
"Set Name": "Plugin Name",
"Synchronous version": "Sync Version",
"To Edit Plugin": "To Edit",
"Update Your Plugin": "Update Plugin"
"Update Your Plugin": "Update Plugin",
"Value": "Value",
"path": ""
},
"support": {
"account": {
@@ -1229,6 +1283,7 @@
}
},
"user": {
"AI point standard": "AI points price",
"Avatar": "Avatar",
"Need to login": "Please log in first",
"Price": "Price",
@@ -1267,15 +1322,20 @@
}
},
"wallet": {
"Ai point every thoundsand tokens": "",
"Ai point every thounsand tokens": "{{points}}Points/1K Tokens",
"Ai point every thousand tokens": "{{points}}Points/1K Tokens",
"Amount": "Amount",
"Balance not enough tip": "The balance is insufficient, please go to the account page first",
"Bills": "Bill",
"Buy": "Buy",
"Buy more": "Buy more",
"Confirm pay": "Confirm pay",
"Not sufficient": "Your AI points are insufficient, please upgrade the package or purchase additional AI points before continuing to use.",
"Pay error": "Pay error",
"Pay success": "Pay success",
"Standard Plan Detail": "Standard Plan Detail",
"To read plan": "Read plan",
"bill": {
"AI Model": "AI Model",
"AI Type": "AI Type",
@@ -1302,6 +1362,10 @@
"noBill": "Not Bills",
"subscription": {
"AI points": "AI points",
"AI points click to read tip": "Each time an AI model is invoked, a certain amount of AI credits (similar to Tokens) are consumed. Click to view the detailed calculation rules.",
"AI points tip": "",
"AI points usage": "AI point usage",
"AI points usage tip": "Each time the AI model is invoked, a certain amount of AI credits are consumed. Please refer to the \"Charging Standard\" above for specific calculation standards.",
"Ai points": "AI Points Standard",
"Buy now": "Buy now",
"Change will take effect after the current subscription expires": "Change will take effect after the current subscription expires",
@@ -1395,7 +1459,7 @@
"Help Document": "Document"
},
"template": {
"Quote Content Tip": "This configuration takes effect only when reference content is passed in (knowledge base search).\nYou can customize the structure of the reference content to better suit different scenarios. Some variables can be used for template configuration:\n{{q}} - retrieve content, {{a}} - expected content, {{source}} - source, {{sourceId}} - source file name, {{index}} - the first n references, {{with}} - the reference points (0-1), they are optional, Here are the default values:\n{{default}}",
"Quote Content Tip": "This configuration takes effect only when reference content is passed in (knowledge base search).\nYou can customize the structure of the reference content to better suit different scenarios. Some variables can be used for template configuration:\n{{q}} - retrieve content, {{a}} - expected content, {{source}} - source, {{sourceId}} - source file name, {{index}} - the first n references, they are optional, Here are the default values:\n{{default}}",
"Quote Prompt Tip": "This configuration takes effect only when the knowledge base is searched.\nYou can use {{quote}} to insert the reference content template and {{question}} to insert the question. Here are the default values:\n{{default}}"
},
"user": {

View File

@@ -62,6 +62,7 @@
"Back": "返回",
"Beta": "实验版",
"Business edition features": "这是商业版功能~",
"Cancel": "取消",
"Choose": "选择",
"Close": "关闭",
"Collect": "收藏",
@@ -113,6 +114,7 @@
"Not open": "未开启",
"Number of words": "{{amount}}字",
"OK": "好的",
"Open": "打开",
"Opened": "已开启",
"Other": "其他",
"Output": "输出",
@@ -122,6 +124,7 @@
"Price used": "金额消耗",
"Read document": "查看文档",
"Read intro": "查看说明",
"Remove": "移除",
"Rename": "重命名",
"Rename Failed": "重命名失败",
"Rename Success": "重命名成功",
@@ -159,6 +162,7 @@
"Upload File Failed": "上传文件失败",
"Username": "用户名",
"Waiting": "等待中",
"Warning": "警告",
"Website": "网站",
"avatar": {
"Select Avatar": "点击选择头像",
@@ -244,8 +248,12 @@
"Total chars": "总字数: {{total}}",
"Total tokens": "总 Tokens: {{total}}",
"ai": {
"AI settings": "AI 配置",
"Ai point price": "AI积分消耗",
"Max context": "最大上下文",
"Model": "AI 模型",
"Prompt": "提示词",
"Support tool": "函数调用",
"model": {
"Dataset Agent Model": "文件处理模型",
"Vector Model": "索引模型"
@@ -260,6 +268,7 @@
"Chat Variable": "对话框变量",
"External using": "外部使用途径",
"Make a brief introduction of your app": "给你的 AI 应用一个介绍",
"Max histories": "聊天记录数量",
"Max tokens": "回复上限",
"Name and avatar": "头像 & 名称",
"Next Step Guide": "下一步指引",
@@ -282,6 +291,15 @@
"TTS Tip": "开启后,每次对话后可使用语音播放功能。使用该功能可能产生额外费用。",
"Team tags": "团队标签",
"Temperature": "温度",
"Tool call": "工具调用",
"Tool call tip": "通过AI模型自动选择一个或多个工具进行使用。如果启动该功能知识库调用也会被当做一个工具调用。请尽量选择支持“函数调用”的AI模型效果更好。",
"ToolCall": {
"No plugin": "没有可用的插件",
"Setting tool": "配置工具",
"System": "系统",
"Team": "团队",
"This plugin cannot be called as a tool": "该工具无法在简易模式中使用"
},
"Welcome Text": "对话开场白",
"create app": "创建属于你的 AI 应用",
"deterministic": "严谨",
@@ -355,7 +373,7 @@
},
"tip": {
"Add a intro to app": "快来给应用一个介绍~",
"chatNodeSystemPromptTip": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"chatNodeSystemPromptTip": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}\n如果关联了知识库你还可以通过适当的描述来引导模型何时去调用知识库搜索。例如\n你是电影《星际穿越》的助手当用户询问与《星际穿越》相关的内容时请搜索知识库并结合搜索结果进行回答。",
"userGuideTip": "可以在对话前设置引导语,设置全局变量,设置下一步指引",
"variableTip": "可以在对话开始前,要求用户填写一些内容作为本轮对话的特定变量。该模块位于开场引导之后。\n变量可以通过 {{变量key}} 的形式注入到其他模块 string 类型的输入中,例如:提示词、限定词等",
"welcomeTextTip": "每次对话开始前,发送一个初始内容。支持标准 Markdown 语法,可使用的额外标记:\n[快捷按键]: 用户点击后可以直接发送该问题"
@@ -694,6 +712,7 @@
"Search type": "类型",
"Source id": "来源ID",
"Source name": "引用来源名",
"Tool description": "调用时机",
"Top K": "单次搜索上限",
"Using cfr": "",
"Using query extension": "使用问题优化",
@@ -772,6 +791,7 @@
"module": {
"Add question type": "添加问题类型",
"Can not connect self": "不能连接自身",
"Confirm Delete Node": "确认删除该节点?",
"Data Type": "数据类型",
"Dataset quote": {
"Add quote": "添加引用",
@@ -794,6 +814,9 @@
"placeholder": "例如:\n关于 python 的介绍和使用等问题。\n当前对话与游戏《GTA5》有关。",
"tip": "描述当前对话的范围便于AI补全首次问题或模糊的问题从而增强知识库连续对话的能力。建议开启该功能后都简单的描述在对话的背景否则容易造成补全对象不准确。"
},
"Quote prompt setting": "引用提示词配置",
"Qupte prompt setting": "",
"Setting quote prompt": "配置引用提示词",
"Unlink tip": "【{{name}}】存在未填或未连接参数",
"Variable": "全局变量",
"Variable Setting": "变量设置",
@@ -902,10 +925,13 @@
}
},
"template": {
"AI response switch tip": "如果你希望当前节点不输出内容可以关闭该开关。AI输出的内容不会展示给用户你可以手动的使用“AI回复内容”进行特殊处理。",
"AI support tool tip": "支持函数调用的模型,可以更好的使用工具调用。",
"Ai chat": "AI 对话",
"Ai chat intro": "AI 大模型对话",
"Assigned reply": "指定回复",
"Assigned reply intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。",
"Basic Node": "基础功能",
"Chat entrance": "对话入口",
"Chat entrance intro": "当用户发送一个内容后,流程将会从这个模块开始执行。",
"Classify question": "问题分类",
@@ -926,9 +952,11 @@
"Response module": "文本输出",
"Running app": "应用调用",
"Running app intro": "可以选择一个其他应用进行调用",
"System Plugin": "系统插件",
"System input module": "系统输入",
"TFSwitch": "判断器",
"TFSwitch intro": "根据传入的内容进行 True False 输出。默认情况下,当传入的内容为 false, undefined, null, 0, none 时,会输出 false。你也可以增加一些自定义的字符串来补充输出 false 的内容。非字符、非数字、非布尔类型,直接输出 True。",
"Team Plugin": "团队插件",
"Tool module": "工具",
"UnKnow Module": "未知模块",
"User guide": "用户引导",
@@ -936,6 +964,9 @@
"textEditor": "文本加工",
"textEditor intro": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。"
},
"templates": {
"Load plugin error": "加载插件失败"
},
"textEditor": {
"Text Edit": "文本加工"
},
@@ -973,7 +1004,10 @@
"variable add option": "添加选项"
},
"plugin": {
"Get Plugin Module Detail Failed": "加载插件异常"
"Custom headers": "自定义请求头",
"Delete http plugin": "确认删除该组HTTP插件会删除该目录下所有插件。",
"Get Plugin Module Detail Failed": "加载插件异常",
"Intro placeholder": "如果该插件作为工具被调用,则会使用该介绍作为提示词。"
},
"shareChat": {
"Init Error": "初始化对话框失败",
@@ -1180,18 +1214,38 @@
"Set Public": "设为团队可用"
},
"plugin": {
"Auth Header Prefix": "鉴权头部前缀",
"Auth Method": "鉴权方法",
"Auth Type": "鉴权类型",
"Confirm Delete": "确认删除该插件?",
"Create Your Plugin": "创建你的插件",
"Custom Plugin": "自定义插件",
"Description": "描述",
"Edit Http Plugin": "编辑 HTTP 插件",
"Get Plugin Module Detail Failed": "获取插件信息异常",
"HTTP Plugin": "HTTP 插件",
"Import Plugin": "导入 HTTP 插件",
"Import from URL": "URL 导入",
"Intro": "插件介绍",
"Invalid Schema": "Schema 无效",
"Invalid URL": "URL 无效",
"Key": "键",
"Load Plugin Failed": "加载插件异常",
"Method": "方法",
"My Plugins": "我的插件",
"No Intro": "这个插件没有介绍~",
"None": "无",
"Path": "路径",
"Plugin List": "插件列表",
"Plugin Module": "插件模块",
"Privacy Agreement": "隐私协议",
"Search plugin": "搜索插件",
"Set Name": "给插件取个名字",
"Synchronous version": "同步版本",
"To Edit Plugin": "去编辑",
"Update Your Plugin": "更新插件"
"Update Your Plugin": "更新插件",
"Value": "值",
"path": ""
},
"support": {
"account": {
@@ -1231,6 +1285,7 @@
}
},
"user": {
"AI point standard": "AI积分标准",
"Avatar": "头像",
"Need to login": "请先登录",
"Price": "计费标准",
@@ -1269,15 +1324,20 @@
}
},
"wallet": {
"Ai point every thoundsand tokens": "{{points}}积分/1K tokens",
"Ai point every thounsand tokens": "{{points}}积分/1K tokens",
"Ai point every thousand tokens": "{{points}}积分/1K tokens",
"Amount": "金额",
"Balance not enough tip": "余额不足,请先到账号页充值",
"Bills": "账单",
"Buy": "购买",
"Buy more": "扩容",
"Confirm pay": "支付确认",
"Not sufficient": "您的 AI 积分不足,请先升级套餐或购买额外 AI 积分后继续使用。",
"Pay error": "支付失败",
"Pay success": "支付成功",
"Standard Plan Detail": "套餐详情",
"To read plan": "查看套餐",
"bill": {
"AI Model": "AI 模型",
"AI Type": "AI 类型",
@@ -1304,6 +1364,10 @@
"noBill": "无账单记录~",
"subscription": {
"AI points": "AI积分",
"AI points click to read tip": "每次调用AI模型时都会消耗一定的AI积分(类似于 Tokens)。点击可查看详细计算规则。",
"AI points tip": "每次调用AI模型时都会消耗一定的AI积分。具体的计算标准可参考下方的“计费标准”",
"AI points usage": "AI积分使用量",
"AI points usage tip": "每次调用AI模型时都会消耗一定的AI积分。具体的计算标准可参考上方的“计费标准”",
"Ai points": "AI 积分计算标准",
"Buy now": "切换套餐",
"Change will take effect after the current subscription expires": "更新成功。将会再下个订阅周期生效。",
@@ -1337,7 +1401,7 @@
"Upgrade plan": "升级套餐",
"function": {
"History store": "{{amount}} 天对话记录保留",
"Max app": "{{amount}} 个应用与插件",
"Max app": "{{amount}} 个应用",
"Max dataset": "{{amount}} 个知识库",
"Max dataset size": "{{amount}} 组知识库索引",
"Max members": "{{amount}} 个团队成员",
@@ -1354,7 +1418,7 @@
"experience": "体验版",
"experience desc": "",
"free": "免费版",
"free desc": "每月均可免费使用基础功能15天不活跃时,将会清除知识库",
"free desc": "每月均可免费使用基础功能15天无使用记录时,将会清除知识库",
"team": "团队版"
},
"type": {
@@ -1397,8 +1461,8 @@
"Help Document": "帮助文档"
},
"template": {
"Quote Content Tip": "该配置只有传入引用内容(知识库搜索)时生效。\n可以自定义引用内容的结构,以更好的适配不同场景。可以使用一些变量来进行模板配置:\n{{q}} - 检索内容, {{a}} - 预期内容, {{source}} - 来源,{{sourceId}} - 来源文件名,{{index}} - 第n个引用{{score}} - 该引用的得分(0-1)他们都是可选的,下面是默认值:\n{{default}}",
"Quote Prompt Tip": "该配置只在知识库搜索时生效。\n可以用 {{quote}} 来插入引用内容模板,使用 {{question}} 来插入问题。下面是默认值:\n{{default}}"
"Quote Content Tip": "可以自定义引用内容的结构,以更好的适配不同场景。可以使用一些变量来进行模板配置:\n{{q}} - 检索内容, {{a}} - 预期内容, {{source}} - 来源,{{sourceId}} - 来源文件名,{{index}} - 第n个引用他们都是可选的下面是默认值\n{{default}}",
"Quote Prompt Tip": "可以用 {{quote}} 来插入引用内容模板,使用 {{question}} 来插入问题。下面是默认值:\n{{default}}"
},
"user": {
"Account": "账号",

View File

@@ -14,7 +14,7 @@ const Avatar = ({ w = '30px', src, ...props }: ImageProps) => {
w={w}
h={w}
p={'1px'}
src={src || LOGO_ICON}
src={src}
{...props}
/>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { ModalBody, Box, useTheme } from '@chakra-ui/react';
import MyModal from '../MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { DispatchNodeResponseType } from '@fastgpt/global/core/module/runtime/type.d';
const ContextModal = ({

View File

@@ -1,6 +1,6 @@
import React, { useRef } from 'react';
import { ModalBody, Textarea, ModalFooter, Button } from '@chakra-ui/react';
import MyModal from '../MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useRequest } from '@/web/common/hooks/useRequest';
import { useTranslation } from 'next-i18next';
import { updateChatUserFeedback } from '@/web/core/chat/api';
@@ -9,6 +9,8 @@ const FeedbackModal = ({
appId,
chatId,
chatItemId,
teamId,
teamToken,
shareId,
outLinkUid,
onSuccess,
@@ -18,6 +20,8 @@ const FeedbackModal = ({
chatId: string;
chatItemId: string;
shareId?: string;
teamId?: string;
teamToken?: string;
outLinkUid?: string;
onSuccess: (e: string) => void;
onClose: () => void;
@@ -33,6 +37,8 @@ const FeedbackModal = ({
chatId,
chatItemId,
shareId,
teamId,
teamToken,
outLinkUid,
userBadFeedback: val
});

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { ModalBody, Box, useTheme } from '@chakra-ui/react';
import MyModal from '../MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
import QuoteItem from '../core/dataset/QuoteItem';

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { ModalBody, ModalFooter, Button } from '@chakra-ui/react';
import MyModal from '../MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
const ReadFeedbackModal = ({

View File

@@ -5,7 +5,7 @@ import { useTranslation } from 'next-i18next';
import { moduleTemplatesFlat } from '@fastgpt/global/core/module/template/constants';
import Tabs from '../Tabs';
import MyModal from '../MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import MyTooltip from '../MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import Markdown from '../Markdown';

View File

@@ -9,9 +9,7 @@ import {
AccordionButton,
AccordionPanel,
AccordionIcon,
Button,
Image,
Grid
Image
} from '@chakra-ui/react';
import React, { useMemo } from 'react';
import ChatController, { type ChatControllerProps } from './ChatController';
@@ -88,7 +86,7 @@ const ChatItem = ({
return (
<>
{files.length > 0 && <FilesBlock files={files} />}
<Markdown source={text} isChatting={false} />
<Markdown source={text} />
</>
);
}
@@ -100,13 +98,26 @@ const ChatItem = ({
if (value.text) {
let source = value.text?.content || '';
if (isLastChild && !isChatting && questionGuides.length > 0) {
if (!source && chat.value.length > 1) return <></>;
if (
isLastChild &&
!isChatting &&
questionGuides.length > 0 &&
i === chat.value.length - 1
) {
source = `${source}
\`\`\`${CodeClassName.questionGuide}
${JSON.stringify(questionGuides)}`;
}
return <Markdown key={key} source={source} isChatting={isLastChild && isChatting} />;
return (
<Markdown
key={key}
source={source}
showAnimation={isLastChild && isChatting && i === chat.value.length - 1}
/>
);
}
if (value.type === ChatItemValueTypeEnum.tool && value.tools) {
return (
@@ -233,4 +244,4 @@ ${toolResponse}`}
);
};
export default ChatItem;
export default React.memo(ChatItem);

View File

@@ -18,7 +18,7 @@ const WelcomeBox = ({ appAvatar, welcomeText }: { appAvatar?: string; welcomeTex
bg={'white'}
boxShadow={'0 0 8px rgba(0,0,0,0.15)'}
>
<Markdown source={`~~~guide \n${welcomeText}`} isChatting={false} />
<Markdown source={`~~~guide \n${welcomeText}`} />
</Card>
</Box>
</Box>

View File

@@ -257,10 +257,7 @@ const ChatBox = (
};
return {
...item,
value:
lastValue && lastValue.text
? item.value.slice(0, -1).concat(val)
: item.value.concat(val)
value: item.value.concat(val)
};
} else if (
event === SseResponseEventEnum.toolParams &&
@@ -441,6 +438,7 @@ const ChatBox = (
chatController.current = abortSignal;
const messages = chats2GPTMessages({ messages: newChatList, reserveId: true });
const {
responseData,
responseText,
@@ -537,10 +535,9 @@ const ChatBox = (
setLoading(true);
const index = chatHistories.findIndex((item) => item.dataId === dataId);
const delHistory = chatHistories.slice(index);
try {
await Promise.all(
delHistory.map(async (item) => {
delHistory.map((item) => {
if (item.dataId) {
return onDelMessage({ contentId: item.dataId });
}
@@ -563,14 +560,29 @@ const ChatBox = (
},
[chatHistories, onDelMessage, sendPrompt, setLoading, toast]
);
// delete one message
// delete one message(One human and the ai response)
const delOneMessage = useCallback(
(dataId?: string) => {
if (!dataId || !onDelMessage) return;
return () => {
setChatHistories((state) => state.filter((chat) => chat.dataId !== dataId));
onDelMessage({
contentId: dataId
setChatHistories((state) => {
let aiIndex = -1;
return state.filter((chat, i) => {
if (chat.dataId === dataId) {
aiIndex = i + 1;
onDelMessage({
contentId: dataId
});
return false;
} else if (aiIndex === i && chat.obj === ChatRoleEnum.AI && chat.dataId) {
onDelMessage({
contentId: chat.dataId
});
return false;
}
return true;
});
});
};
},
@@ -630,6 +642,8 @@ const ChatBox = (
updateChatUserFeedback({
appId,
chatId,
teamId,
teamToken,
chatItemId: chat.dataId,
shareId,
outLinkUid,
@@ -654,6 +668,8 @@ const ChatBox = (
);
updateChatUserFeedback({
appId,
teamId,
teamToken,
chatId,
chatItemId: chat.dataId,
userGoodFeedback: undefined
@@ -687,6 +703,8 @@ const ChatBox = (
chatId,
chatItemId: chat.dataId,
shareId,
teamId,
teamToken,
outLinkUid
});
} catch (error) {}
@@ -869,7 +887,6 @@ const ChatBox = (
avatar={appAvatar}
chat={item}
isChatting={isChatting}
onDelete={delOneMessage(item.dataId)}
{...(item.obj === 'AI' && {
setChatHistories,
showVoiceIcon,
@@ -955,6 +972,8 @@ const ChatBox = (
{!!feedbackId && chatId && appId && (
<FeedbackModal
appId={appId}
teamId={teamId}
teamToken={teamToken}
chatId={chatId}
chatItemId={feedbackId}
shareId={shareId}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Button, ModalFooter, ModalBody } from '@chakra-ui/react';
import MyModal from '../MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import Markdown from '../Markdown';
import { useSystemStore } from '@/web/common/system/useSystemStore';
@@ -10,12 +10,7 @@ const CommunityModal = ({ onClose }: { onClose: () => void }) => {
const { feConfigs } = useSystemStore();
return (
<MyModal
isOpen={true}
onClose={onClose}
iconSrc="/imgs/modal/concat.svg"
title={t('home.Community')}
>
<MyModal isOpen={true} onClose={onClose} iconSrc="modal/concat" title={t('home.Community')}>
<ModalBody textAlign={'center'}>
<Markdown source={feConfigs?.concatMd || ''} />
</ModalBody>

View File

@@ -12,10 +12,8 @@ import dynamic from 'next/dynamic';
import Auth from './auth';
import Navbar from './navbar';
import NavbarPhone from './navbarPhone';
const UpdateInviteModal = dynamic(
() => import('@/components/support/user/team/UpdateInviteModal'),
{ ssr: false }
);
const UpdateInviteModal = dynamic(() => import('@/components/support/user/team/UpdateInviteModal'));
const NotSufficientModal = dynamic(() => import('@/components/support/wallet/NotSufficientModal'));
const pcUnShowLayoutRoute: Record<string, boolean> = {
'/': true,
@@ -44,7 +42,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
const router = useRouter();
const { colorMode, setColorMode } = useColorMode();
const { Loading } = useLoading();
const { loading, setScreenWidth, isPc, feConfigs } = useSystemStore();
const { loading, setScreenWidth, isPc, feConfigs, isNotSufficientModal } = useSystemStore();
const { userInfo } = useUserStore();
const isChatPage = useMemo(
@@ -118,6 +116,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
)}
{!!userInfo && <UpdateInviteModal />}
{isNotSufficientModal && !isHideNavbar && <NotSufficientModal />}
</Box>
<Loading loading={loading} zIndex={999999} />
</>

View File

@@ -36,10 +36,10 @@ export enum CodeClassName {
const Markdown = ({
source = '',
isChatting = false
showAnimation = false
}: {
source?: string;
isChatting?: boolean;
showAnimation?: boolean;
}) => {
const components = useMemo<any>(
() => ({
@@ -60,7 +60,7 @@ const Markdown = ({
return (
<ReactMarkdown
className={`markdown ${styles.markdown}
${isChatting ? `${formatSource ? styles.waitingAnimation : styles.animation}` : ''}
${showAnimation ? `${formatSource ? styles.waitingAnimation : styles.animation}` : ''}
`}
remarkPlugins={[RemarkMath, [RemarkGfm, { singleTilde: false }], RemarkBreaks]}
rehypePlugins={[RehypeKatex]}

View File

@@ -1,42 +0,0 @@
import React from 'react';
import { ModalContentProps } from '@chakra-ui/react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import CustomModal from '@fastgpt/web/components/common/CustomModal';
export interface MyModalProps extends ModalContentProps {
iconSrc?: string;
title?: any;
isCentered?: boolean;
isOpen: boolean;
onClose?: () => void;
}
const MyModal = ({
isOpen,
onClose,
iconSrc,
title,
children,
isCentered,
w = 'auto',
maxW = ['90vw', '600px'],
...props
}: MyModalProps) => {
const { isPc } = useSystemStore();
return (
<CustomModal
isOpen={isOpen}
onClose={onClose}
iconSrc={iconSrc}
title={title}
isCentered={isPc ? isCentered : true}
w={w}
maxW={maxW}
{...props}
>
{children}
</CustomModal>
);
};
export default MyModal;

View File

@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import MyModal from '../MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { Box, Button, Flex, Grid, useTheme } from '@chakra-ui/react';
import { PromptTemplateItem } from '@fastgpt/global/core/ai/type.d';
import { ModalBody, ModalFooter } from '@chakra-ui/react';

View File

@@ -0,0 +1,70 @@
import React, { useMemo } from 'react';
import { useTranslation } from 'next-i18next';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useRouter } from 'next/router';
import { AI_POINT_USAGE_CARD_ROUTE } from '@/web/support/wallet/sub/constants';
import MySelect, { SelectProps } from '@fastgpt/web/components/common/MySelect';
import { HUGGING_FACE_ICON, LOGO_ICON } from '@fastgpt/global/common/system/constants';
import { Box, Flex } from '@chakra-ui/react';
import Avatar from '../Avatar';
const AIModelSelector = ({ list, ...props }: SelectProps) => {
const { t } = useTranslation();
const { feConfigs, llmModelList, vectorModelList } = useSystemStore();
const router = useRouter();
const avatarList = list.map((item) => {
const modelData =
llmModelList.find((model) => model.model === item.value) ||
vectorModelList.find((model) => model.model === item.value);
return {
value: item.value,
label: (
<Flex alignItems={'center'} py={1}>
<Avatar
borderRadius={'0'}
mr={2}
src={modelData?.avatar || HUGGING_FACE_ICON}
fallbackSrc={HUGGING_FACE_ICON}
w={'18px'}
/>
<Box>{item.label}</Box>
</Flex>
)
};
});
const expandList = useMemo(() => {
return feConfigs.show_pay
? avatarList.concat({
label: (
<Flex alignItems={'center'}>
<Avatar borderRadius={'0'} mr={2} src={LOGO_ICON} w={'18px'} />
<Box>{t('support.user.Price')}</Box>
</Flex>
),
value: 'price'
})
: avatarList;
}, [feConfigs.show_pay, avatarList, t]);
return (
<>
<MySelect
list={expandList}
{...props}
onchange={(e) => {
if (e === 'price') {
router.push(AI_POINT_USAGE_CARD_ROUTE);
return;
}
props.onchange?.(e);
}}
/>
</>
);
};
export default AIModelSelector;

View File

@@ -1,40 +0,0 @@
import React, { useMemo } from 'react';
import { useTranslation } from 'next-i18next';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useRouter } from 'next/router';
import { AI_POINT_USAGE_CARD_ROUTE } from '@/web/support/wallet/sub/constants';
import MySelect, { SelectProps } from '@fastgpt/web/components/common/MySelect';
const SelectAiModel = ({ list, ...props }: SelectProps) => {
const { t } = useTranslation();
const { feConfigs } = useSystemStore();
const router = useRouter();
const expandList = useMemo(() => {
return feConfigs.show_pay
? list.concat({
label: t('support.user.Price'),
value: 'price'
})
: list;
}, [feConfigs.show_pay, list, t]);
return (
<>
<MySelect
list={expandList}
{...props}
onchange={(e) => {
if (e === 'price') {
router.push(AI_POINT_USAGE_CARD_ROUTE);
return;
}
props.onchange?.(e);
}}
/>
</>
);
};
export default SelectAiModel;

View File

@@ -10,8 +10,8 @@ type Props = BoxProps & {
const MyBox = ({ text, isLoading, children, ...props }: Props) => {
return (
<Box position={'relative'} {...props}>
{children}
{isLoading && <Loading fixed={false} text={text} />}
{children}
</Box>
);
};

View File

@@ -9,9 +9,16 @@ const ParentPaths = (props: {
rootName?: string;
FirstPathDom?: React.ReactNode;
onClick: (parentId: string) => void;
fontSize?: string;
}) => {
const { t } = useTranslation();
const { paths = [], rootName = t('common.folder.Root Path'), FirstPathDom, onClick } = props;
const {
paths = [],
rootName = t('common.folder.Root Path'),
FirstPathDom,
onClick,
fontSize
} = props;
const concatPaths = useMemo(
() => [
{
@@ -30,7 +37,7 @@ const ParentPaths = (props: {
{concatPaths.map((item, i) => (
<Flex key={item.parentId || i} alignItems={'center'}>
<Box
fontSize={['sm', 'lg']}
fontSize={['sm', fontSize || 'lg']}
py={1}
px={[1, 2]}
borderRadius={'md'}

View File

@@ -12,7 +12,7 @@ import {
import MyTooltip from '@/components/MyTooltip';
import { useTranslation } from 'next-i18next';
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
type Props = TextareaProps & {
title?: string;

View File

@@ -0,0 +1,242 @@
import React, { useMemo, useState } from 'react';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { useForm } from 'react-hook-form';
import {
Box,
BoxProps,
Button,
Flex,
Link,
ModalBody,
ModalFooter,
Switch
} from '@chakra-ui/react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import MySlider from '@/components/Slider';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
import type { SettingAIDataType } from '@fastgpt/global/core/module/node/type.d';
import { getDocPath } from '@/web/common/system/doc';
import AIModelSelector from '@/components/Select/AIModelSelector';
import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
const AIChatSettingsModal = ({
onClose,
onSuccess,
defaultData,
llmModels = []
}: {
onClose: () => void;
onSuccess: (e: SettingAIDataType) => void;
defaultData: SettingAIDataType;
llmModels?: LLMModelItemType[];
}) => {
const { t } = useTranslation();
const [refresh, setRefresh] = useState(false);
const { feConfigs, llmModelList } = useSystemStore();
const { handleSubmit, getValues, setValue, watch } = useForm({
defaultValues: defaultData
});
const model = watch('model');
const showResponseAnswerText = watch(ModuleInputKeyEnum.aiChatIsResponseText) !== undefined;
const showMaxHistoriesSlider = watch('maxHistories') !== undefined;
const selectedModel = llmModelList.find((item) => item.model === model) || llmModelList[0];
const tokenLimit = useMemo(() => {
return llmModelList.find((item) => item.model === model)?.maxResponse || 4096;
}, [llmModelList, model]);
const onChangeModel = (e: string) => {
setValue('model', e);
// update max tokens
const modelData = llmModelList.find((item) => item.model === e);
if (modelData) {
setValue('maxToken', modelData.maxResponse / 2);
}
setRefresh(!refresh);
};
const LabelStyles: BoxProps = {
display: 'flex',
alignItems: 'center',
fontSize: ['sm', 'md'],
width: ['80px', '90px']
};
return (
<MyModal
isOpen
iconSrc="/imgs/module/AI.png"
onClose={onClose}
title={
<>
{t('core.ai.AI settings')}
{feConfigs?.docUrl && (
<Link
href={getDocPath('/docs/course/ai_settings/')}
target={'_blank'}
ml={1}
textDecoration={'underline'}
fontWeight={'normal'}
fontSize={'md'}
>
{t('common.Read intro')}
</Link>
)}
</>
}
w={'500px'}
>
<ModalBody overflowY={'auto'}>
<Flex alignItems={'center'}>
<Box {...LabelStyles} mr={2}>
{t('core.ai.Model')}
</Box>
<Box flex={'1 0 0'}>
<AIModelSelector
width={'100%'}
value={model}
list={llmModels.map((item) => ({
value: item.model,
label: item.name
}))}
onchange={onChangeModel}
/>
</Box>
</Flex>
{feConfigs && (
<Flex mt={8}>
<Box {...LabelStyles} mr={2}>
{t('core.ai.Ai point price')}
</Box>
<Box flex={1} ml={'10px'}>
{t('support.wallet.Ai point every thousand tokens', {
points: selectedModel?.charsPointsPrice || 0
})}
</Box>
</Flex>
)}
<Flex mt={8}>
<Box {...LabelStyles} mr={2}>
{t('core.ai.Max context')}
</Box>
<Box flex={1} ml={'10px'}>
{selectedModel?.maxContext || 4096}Tokens
</Box>
</Flex>
<Flex mt={8}>
<Box {...LabelStyles} mr={2}>
{t('core.ai.Support tool')}
<QuestionTip ml={1} label={t('core.module.template.AI support tool tip')} />
</Box>
<Box flex={1} ml={'10px'}>
{selectedModel?.usedInToolCall ? '支持' : '不支持'}
</Box>
</Flex>
<Flex mt={8}>
<Box {...LabelStyles} mr={2}>
{t('core.app.Temperature')}
</Box>
<Box flex={1} ml={'10px'}>
<MySlider
markList={[
{ label: t('core.app.deterministic'), value: 0 },
{ label: t('core.app.Random'), value: 10 }
]}
width={'95%'}
min={0}
max={10}
value={getValues(ModuleInputKeyEnum.aiChatTemperature)}
onChange={(e) => {
setValue(ModuleInputKeyEnum.aiChatTemperature, e);
setRefresh(!refresh);
}}
/>
</Box>
</Flex>
<Flex mt={8}>
<Box {...LabelStyles} mr={2}>
{t('core.app.Max tokens')}
</Box>
<Box flex={1} ml={'10px'}>
<MySlider
markList={[
{ label: '100', value: 100 },
{ label: `${tokenLimit}`, value: tokenLimit }
]}
width={'95%'}
min={100}
max={tokenLimit}
step={50}
value={getValues(ModuleInputKeyEnum.aiChatMaxToken)}
onChange={(val) => {
setValue(ModuleInputKeyEnum.aiChatMaxToken, val);
setRefresh(!refresh);
}}
/>
</Box>
</Flex>
{showMaxHistoriesSlider && (
<Flex mt={8}>
<Box {...LabelStyles} mr={2}>
{t('core.app.Max histories')}
</Box>
<Box flex={1} ml={'10px'}>
<MySlider
markList={[
{ label: 0, value: 0 },
{ label: 30, value: 30 }
]}
width={'95%'}
min={0}
max={30}
value={getValues('maxHistories') ?? 6}
onChange={(e) => {
setValue('maxHistories', e);
setRefresh(!refresh);
}}
/>
</Box>
</Flex>
)}
{showResponseAnswerText && (
<Flex mt={8} alignItems={'center'}>
<Box {...LabelStyles}>
{t('core.app.Ai response')}
<MyTooltip label={t('core.module.template.AI response switch tip')}>
<QuestionOutlineIcon ml={1} />
</MyTooltip>
</Box>
<Box flex={1} ml={'10px'}>
<Switch
isChecked={getValues(ModuleInputKeyEnum.aiChatIsResponseText)}
size={'lg'}
onChange={(e) => {
const value = e.target.checked;
setValue(ModuleInputKeyEnum.aiChatIsResponseText, value);
setRefresh((state) => !state);
}}
/>
</Box>
</Flex>
)}
</ModalBody>
<ModalFooter>
<Button variant={'whiteBase'} onClick={onClose}>
{t('common.Close')}
</Button>
<Button ml={4} onClick={handleSubmit(onSuccess)}>
{t('common.Confirm')}
</Button>
</ModalFooter>
</MyModal>
);
};
export default AIChatSettingsModal;

View File

@@ -0,0 +1,83 @@
import React, { useEffect } from 'react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { LLMModelTypeEnum, llmModelTypeFilterMap } from '@fastgpt/global/core/ai/constants';
import { Box, Button, useDisclosure } from '@chakra-ui/react';
import { SettingAIDataType } from '@fastgpt/global/core/module/node/type';
import AISettingModal from '@/components/core/ai/AISettingModal';
import Avatar from '@/components/Avatar';
import { HUGGING_FACE_ICON } from '@fastgpt/global/common/system/constants';
type Props = {
llmModelType?: `${LLMModelTypeEnum}`;
defaultData: SettingAIDataType;
onChange: (e: SettingAIDataType) => void;
};
const SettingLLMModel = ({ llmModelType = LLMModelTypeEnum.all, defaultData, onChange }: Props) => {
const { llmModelList } = useSystemStore();
const model = defaultData.model;
const modelList = llmModelList.filter((model) => {
if (!llmModelType) return true;
const filterField = llmModelTypeFilterMap[llmModelType];
if (!filterField) return true;
//@ts-ignore
return !!model[filterField];
});
const selectedModel = modelList.find((item) => item.model === model) || modelList[0];
const {
isOpen: isOpenAIChatSetting,
onOpen: onOpenAIChatSetting,
onClose: onCloseAIChatSetting
} = useDisclosure();
useEffect(() => {
if (!model && modelList.length > 0) {
onChange({
...defaultData,
model: modelList[0].model
});
}
}, [defaultData, model, modelList, onChange]);
return (
<Box position={'relative'}>
<Button
w={'100%'}
justifyContent={'flex-start'}
variant={'whitePrimary'}
_active={{
transform: 'none'
}}
leftIcon={
<Avatar
borderRadius={'0'}
src={selectedModel.avatar || HUGGING_FACE_ICON}
fallbackSrc={HUGGING_FACE_ICON}
w={'18px'}
/>
}
pl={4}
onClick={onOpenAIChatSetting}
>
{selectedModel?.name}
</Button>
{isOpenAIChatSetting && (
<AISettingModal
onClose={onCloseAIChatSetting}
onSuccess={(e) => {
onChange(e);
onCloseAIChatSetting();
}}
defaultData={defaultData}
llmModels={modelList}
/>
)}
</Box>
);
};
export default React.memo(SettingLLMModel);

View File

@@ -50,7 +50,7 @@ const SearchParamsTip = ({
</Thead>
<Tbody>
<Tr color={'myGray.800'}>
<Td pt={0} pb={1}>
<Td pt={0} pb={2}>
<Flex alignItems={'center'}>
<MyIcon
name={DatasetSearchModeMap[searchMode]?.icon as any}
@@ -60,18 +60,18 @@ const SearchParamsTip = ({
{t(DatasetSearchModeMap[searchMode]?.title)}
</Flex>
</Td>
<Td pt={0} pb={1}>
<Td pt={0} pb={2}>
{limit}
</Td>
<Td pt={0} pb={1}>
<Td pt={0} pb={2}>
{hasSimilarityMode ? similarity : t('core.dataset.search.Nonsupport')}
</Td>
{hasReRankModel && (
<Td pt={0} pb={1}>
<Td pt={0} pb={2}>
{usingReRank ? '✅' : '❌'}
</Td>
)}
<Td pt={0} pb={1}>
<Td pt={0} pb={2}>
{usingQueryExtension ? '✅' : '❌'}
</Td>
{hasEmptyResponseMode && <Th>{responseEmptyText !== '' ? '✅' : '❌'}</Th>}

View File

@@ -1,5 +1,5 @@
import { getDatasets, getDatasetPaths } from '@/web/core/dataset/api';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useQuery } from '@tanstack/react-query';
import React, { Dispatch, useMemo, useState } from 'react';
import { useTranslation } from 'next-i18next';

View File

@@ -1,293 +0,0 @@
import React, { useMemo, useState } from 'react';
import MyModal from '@/components/MyModal';
import { useTranslation } from 'next-i18next';
import { useForm } from 'react-hook-form';
import {
Box,
BoxProps,
Button,
Flex,
Link,
ModalBody,
ModalFooter,
Switch
} from '@chakra-ui/react';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { Prompt_QuotePromptList, Prompt_QuoteTemplateList } from '@/global/core/prompt/AIChat';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import MySlider from '@/components/Slider';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
import dynamic from 'next/dynamic';
import { PromptTemplateItem } from '@fastgpt/global/core/ai/type.d';
import type { AIChatModuleProps } from '@fastgpt/global/core/module/node/type.d';
import type { AppSimpleEditConfigTemplateType } from '@fastgpt/global/core/app/type.d';
import { SimpleModeTemplate_FastGPT_Universal } from '@/global/core/app/constants';
import { getDocPath } from '@/web/common/system/doc';
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
import { EditorVariablePickerType } from '@fastgpt/web/components/common/Textarea/PromptEditor/type';
const PromptTemplate = dynamic(() => import('@/components/PromptTemplate'));
const AIChatSettingsModal = ({
isAdEdit,
onClose,
onSuccess,
defaultData,
pickerMenu = []
}: {
isAdEdit?: boolean;
onClose: () => void;
onSuccess: (e: AIChatModuleProps) => void;
defaultData: AIChatModuleProps;
pickerMenu?: EditorVariablePickerType[];
}) => {
const { t } = useTranslation();
const [refresh, setRefresh] = useState(false);
const { feConfigs, llmModelList } = useSystemStore();
const { handleSubmit, getValues, setValue, watch } = useForm({
defaultValues: defaultData
});
const aiChatQuoteTemplate = watch(ModuleInputKeyEnum.aiChatQuoteTemplate);
const aiChatQuotePrompt = watch(ModuleInputKeyEnum.aiChatQuotePrompt);
const [selectTemplateData, setSelectTemplateData] = useState<{
title: string;
templates: PromptTemplateItem[];
}>();
const tokenLimit = useMemo(() => {
return (
llmModelList.find((item) => item.model === getValues(ModuleInputKeyEnum.aiModel))
?.maxResponse || 4000
);
}, [getValues, llmModelList]);
const quoteTemplateVariables = (() => [
{
key: 'q',
label: 'q',
icon: 'core/app/simpleMode/variable'
},
{
key: 'a',
label: 'a',
icon: 'core/app/simpleMode/variable'
},
{
key: 'source',
label: t('core.dataset.search.Source name'),
icon: 'core/app/simpleMode/variable'
},
{
key: 'sourceId',
label: t('core.dataset.search.Source id'),
icon: 'core/app/simpleMode/variable'
},
{
key: 'index',
label: t('core.dataset.search.Quote index'),
icon: 'core/app/simpleMode/variable'
},
...pickerMenu
])();
const quotePromptVariables = (() => [
{
key: 'quote',
label: t('core.app.Quote templates'),
icon: 'core/app/simpleMode/variable'
},
{
key: 'question',
label: t('core.module.input.label.user question'),
icon: 'core/app/simpleMode/variable'
},
...pickerMenu
])();
const LabelStyles: BoxProps = {
fontSize: ['sm', 'md']
};
const selectTemplateBtn: BoxProps = {
color: 'primary.500',
cursor: 'pointer'
};
return (
<MyModal
isOpen
iconSrc="/imgs/module/AI.png"
title={
<>
{t('common.More settings')}
{feConfigs?.docUrl && (
<Link
href={getDocPath('/docs/use-cases/ai_settings/')}
target={'_blank'}
ml={1}
textDecoration={'underline'}
fontWeight={'normal'}
fontSize={'md'}
>
{t('common.Read intro')}
</Link>
)}
</>
}
isCentered
w={'700px'}
h={['90vh', 'auto']}
>
<ModalBody flex={['1 0 0', 'auto']} overflowY={'auto'} minH={'40vh'}>
{isAdEdit && (
<Flex alignItems={'center'}>
<Box {...LabelStyles} w={'80px'}>
{t('core.app.Ai response')}
</Box>
<Box flex={1} ml={'10px'}>
<Switch
isChecked={getValues(ModuleInputKeyEnum.aiChatIsResponseText)}
size={'lg'}
onChange={(e) => {
const value = e.target.checked;
setValue(ModuleInputKeyEnum.aiChatIsResponseText, value);
setRefresh((state) => !state);
}}
/>
</Box>
</Flex>
)}
<Flex mb={10} mt={isAdEdit ? 8 : 6}>
<Box {...LabelStyles} mr={2} w={'80px'}>
{t('core.app.Temperature')}
</Box>
<Box flex={1} ml={'10px'}>
<MySlider
markList={[
{ label: t('core.app.deterministic'), value: 0 },
{ label: t('core.app.Random'), value: 10 }
]}
width={'95%'}
min={0}
max={10}
value={getValues(ModuleInputKeyEnum.aiChatTemperature)}
onChange={(e) => {
setValue(ModuleInputKeyEnum.aiChatTemperature, e);
setRefresh(!refresh);
}}
/>
</Box>
</Flex>
<Flex mt={5} mb={5}>
<Box {...LabelStyles} mr={2} w={'80px'}>
{t('core.app.Max tokens')}
</Box>
<Box flex={1} ml={'10px'}>
<MySlider
markList={[
{ label: '100', value: 100 },
{ label: `${tokenLimit}`, value: tokenLimit }
]}
width={'95%'}
min={100}
max={tokenLimit}
step={50}
value={getValues(ModuleInputKeyEnum.aiChatMaxToken)}
onChange={(val) => {
setValue(ModuleInputKeyEnum.aiChatMaxToken, val);
setRefresh(!refresh);
}}
/>
</Box>
</Flex>
<Box>
<Flex {...LabelStyles} mb={1}>
{t('core.app.Quote templates')}
<MyTooltip
label={t('template.Quote Content Tip', {
default: Prompt_QuoteTemplateList[0].value
})}
forceShow
>
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</MyTooltip>
<Box flex={1} />
<Box
{...selectTemplateBtn}
onClick={() =>
setSelectTemplateData({
title: t('core.app.Select quote template'),
templates: Prompt_QuoteTemplateList
})
}
>
{t('common.Select template')}
</Box>
</Flex>
<PromptEditor
variables={quoteTemplateVariables}
h={160}
title={t('core.app.Quote templates')}
placeholder={t('template.Quote Content Tip', {
default: Prompt_QuoteTemplateList[0].value
})}
value={aiChatQuoteTemplate}
onChange={(e) => {
setValue(ModuleInputKeyEnum.aiChatQuoteTemplate, e);
// setRefresh(!refresh);
}}
/>
</Box>
<Box mt={4}>
<Flex {...LabelStyles} mb={1}>
{t('core.app.Quote prompt')}
<MyTooltip
label={t('template.Quote Prompt Tip', { default: Prompt_QuotePromptList[0].value })}
forceShow
>
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</MyTooltip>
</Flex>
<PromptEditor
variables={quotePromptVariables}
title={t('core.app.Quote prompt')}
h={230}
placeholder={t('template.Quote Prompt Tip', {
default: Prompt_QuotePromptList[0].value
})}
value={aiChatQuotePrompt}
onChange={(e) => {
setValue(ModuleInputKeyEnum.aiChatQuotePrompt, e);
}}
/>
</Box>
</ModalBody>
<ModalFooter>
<Button variant={'whiteBase'} onClick={onClose}>
{t('common.Close')}
</Button>
<Button ml={4} onClick={handleSubmit(onSuccess)}>
{t('common.Confirm')}
</Button>
</ModalFooter>
{!!selectTemplateData && (
<PromptTemplate
title={selectTemplateData.title}
templates={selectTemplateData.templates}
onClose={() => setSelectTemplateData(undefined)}
onSuccess={(e) => {
const quoteVal = e.value;
const promptVal = Prompt_QuotePromptList.find((item) => item.title === e.title)?.value;
setValue(ModuleInputKeyEnum.aiChatQuoteTemplate, quoteVal);
setValue(ModuleInputKeyEnum.aiChatQuotePrompt, promptVal);
}}
/>
)}
</MyModal>
);
};
export default AIChatSettingsModal;

View File

@@ -15,7 +15,7 @@ import { useForm } from 'react-hook-form';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import MySlider from '@/components/Slider';
import MyTooltip from '@/components/MyTooltip';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
import { useTranslation } from 'next-i18next';
import { useSystemStore } from '@/web/common/system/useSystemStore';
@@ -28,7 +28,7 @@ import Tabs from '@/components/Tabs';
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
import { useUserStore } from '@/web/support/user/useUserStore';
import { useToast } from '@fastgpt/web/hooks/useToast';
import SelectAiModel from '@/components/Select/SelectAiModel';
import SelectAiModel from '@/components/Select/AIModelSelector';
export type DatasetParamsProps = {
searchMode: `${DatasetSearchModeEnum}`;
@@ -40,7 +40,6 @@ export type DatasetParamsProps = {
datasetSearchExtensionBg?: string;
maxTokens?: number; // limit max tokens
searchEmptyText?: string;
};
enum SearchSettingTabEnum {
searchMode = 'searchMode',
@@ -50,7 +49,6 @@ enum SearchSettingTabEnum {
const DatasetParamsModal = ({
searchMode = DatasetSearchModeEnum.embedding,
searchEmptyText,
limit,
similarity,
usingReRank,
@@ -71,11 +69,10 @@ const DatasetParamsModal = ({
const { register, setValue, getValues, handleSubmit, watch } = useForm<DatasetParamsProps>({
defaultValues: {
searchEmptyText,
limit,
similarity,
searchMode,
usingReRank: !!usingReRank && !!teamPlanStatus?.standardConstants?.permissionReRank,
usingReRank: !!usingReRank && teamPlanStatus?.standardConstants?.permissionReRank !== false,
datasetSearchUsingExtensionQuery,
datasetSearchExtensionModel: datasetSearchExtensionModel ?? llmModelList[0]?.model,
datasetSearchExtensionBg
@@ -272,21 +269,6 @@ const DatasetParamsModal = ({
</Box>
</Box>
)}
{searchEmptyText !== undefined && (
<Box display={['block', 'flex']} pt={3}>
<Box flex={'0 0 120px'} mb={[2, 0]}>
{t('core.dataset.search.Empty result response')}
</Box>
<Box flex={1}>
<Textarea
rows={5}
maxLength={500}
placeholder={t('core.dataset.search.Empty result response Tips')}
{...register('searchEmptyText')}
></Textarea>
</Box>
</Box>
)}
</Box>
)}
{currentTabType === SearchSettingTabEnum.queryExtension && (

View File

@@ -8,10 +8,7 @@ import {
Connection,
addEdge
} from 'reactflow';
import type {
FlowModuleItemType,
FlowModuleTemplateType
} from '@fastgpt/global/core/module/type.d';
import type { FlowModuleItemType, FlowNodeTemplateType } from '@fastgpt/global/core/module/type.d';
import type {
FlowNodeChangeProps,
FlowNodeInputItemType
@@ -64,7 +61,7 @@ export type useFlowProviderStoreType = {
onDelNode: (nodeId: string) => void;
onChangeNode: (e: FlowNodeChangeProps) => void;
onCopyNode: (nodeId: string) => void;
onResetNode: (e: { id: string; module: FlowModuleTemplateType }) => void;
onResetNode: (e: { id: string; module: FlowNodeTemplateType }) => void;
onDelEdge: (e: {
moduleId: string;
sourceHandle?: string | undefined;
@@ -417,7 +414,7 @@ export const FlowProvider = ({
// reset a node data. delete edge and replace it
const onResetNode = useCallback(
({ id, module }: { id: string; module: FlowModuleTemplateType }) => {
({ id, module }: { id: string; module: FlowNodeTemplateType }) => {
setNodes((state) =>
state.map((node) => {
if (node.id === id) {
@@ -549,12 +546,6 @@ export const onResetNode = (e: Parameters<useFlowProviderStoreType['onResetNode'
data: e
});
};
export const onDelNode = (nodeId: string) => {
eventBus.emit(EventNameEnum.requestFlowEvent, {
type: 'onDelNode',
data: nodeId
});
};
export const onDelConnect = (e: Parameters<useFlowProviderStoreType['onDelConnect']>[0]) => {
eventBus.emit(EventNameEnum.requestFlowEvent, {
type: 'onDelConnect',

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { Textarea, Button, ModalBody, ModalFooter } from '@chakra-ui/react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useFlowProviderStore } from './FlowProvider';

View File

@@ -1,13 +1,13 @@
import React, { useCallback, useMemo } from 'react';
import { Box, Flex } from '@chakra-ui/react';
import React, { useCallback, useMemo, useState } from 'react';
import { Box, Flex, IconButton, Input, InputGroup, InputLeftElement } from '@chakra-ui/react';
import type {
FlowModuleTemplateType,
FlowNodeTemplateType,
moduleTemplateListType
} from '@fastgpt/global/core/module/type.d';
import { useViewport, XYPosition } from 'reactflow';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import Avatar from '@/components/Avatar';
import { getFlowStore, onSetNodes } from './FlowProvider';
import { onSetNodes, useFlowProviderStore } from './FlowProvider';
import { customAlphabet } from 'nanoid';
import { appModule2FlowNode } from '@/utils/adapt';
import { useTranslation } from 'next-i18next';
@@ -18,22 +18,83 @@ import { getPreviewPluginModule } from '@/web/core/plugin/api';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { moduleTemplatesList } from '@fastgpt/global/core/module/template/constants';
import RowTabs from '@fastgpt/web/components/common/Tabs/RowTabs';
import { useWorkflowStore } from '@/web/core/workflow/store/workflow';
import { useRequest } from '@/web/common/hooks/useRequest';
import ParentPaths from '@/components/common/ParentPaths';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useRouter } from 'next/router';
import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants';
import { useQuery } from '@tanstack/react-query';
import { debounce } from 'lodash';
export type ModuleTemplateProps = {
templates: FlowModuleTemplateType[];
};
type ModuleTemplateListProps = ModuleTemplateProps & {
type ModuleTemplateListProps = {
isOpen: boolean;
onClose: () => void;
};
type RenderListProps = {
templates: FlowModuleTemplateType[];
templates: FlowNodeTemplateType[];
onClose: () => void;
currentParent?: { parentId: string; parentName: string };
setCurrentParent: (e: { parentId: string; parentName: string }) => void;
};
const ModuleTemplateList = ({ templates, isOpen, onClose }: ModuleTemplateListProps) => {
enum TemplateTypeEnum {
'basic' = 'basic',
'systemPlugin' = 'systemPlugin',
'teamPlugin' = 'teamPlugin'
}
const sliderWidth = 380;
const ModuleTemplateList = ({ isOpen, onClose }: ModuleTemplateListProps) => {
const { t } = useTranslation();
const router = useRouter();
const [currentParent, setCurrentParent] = useState<RenderListProps['currentParent']>();
const [searchKey, setSearchKey] = useState('');
const {
basicNodeTemplates,
systemNodeTemplates,
loadSystemNodeTemplates,
teamPluginNodeTemplates,
loadTeamPluginNodeTemplates
} = useWorkflowStore();
const [templateType, setTemplateType] = useState(TemplateTypeEnum.basic);
const templates = useMemo(() => {
const map = {
[TemplateTypeEnum.basic]: basicNodeTemplates,
[TemplateTypeEnum.systemPlugin]: systemNodeTemplates,
[TemplateTypeEnum.teamPlugin]: teamPluginNodeTemplates.filter((item) =>
searchKey ? item.pluginType !== PluginTypeEnum.folder : true
)
};
return map[templateType];
}, [basicNodeTemplates, searchKey, systemNodeTemplates, teamPluginNodeTemplates, templateType]);
const { mutate: onChangeTab } = useRequest({
mutationFn: async (e: any) => {
const val = e as TemplateTypeEnum;
if (val === TemplateTypeEnum.systemPlugin) {
await loadSystemNodeTemplates();
} else if (val === TemplateTypeEnum.teamPlugin) {
await loadTeamPluginNodeTemplates({
parentId: currentParent?.parentId
});
}
setTemplateType(val);
},
errorToast: t('core.module.templates.Load plugin error')
});
useQuery(['teamNodeTemplate', currentParent?.parentId, searchKey], () =>
loadTeamPluginNodeTemplates({
parentId: currentParent?.parentId,
searchKey,
init: true
})
);
return (
<>
@@ -44,27 +105,108 @@ const ModuleTemplateList = ({ templates, isOpen, onClose }: ModuleTemplateListPr
top={0}
left={0}
bottom={0}
w={'360px'}
w={`${sliderWidth}px`}
onClick={onClose}
/>
<Flex
zIndex={3}
flexDirection={'column'}
position={'absolute'}
top={'65px'}
top={'10px'}
left={0}
pt={2}
pt={'20px'}
pb={4}
h={isOpen ? 'calc(100% - 100px)' : '0'}
w={isOpen ? ['100%', '360px'] : '0'}
h={isOpen ? 'calc(100% - 20px)' : '0'}
w={isOpen ? ['100%', `${sliderWidth}px`] : '0'}
bg={'white'}
boxShadow={'3px 0 20px rgba(0,0,0,0.2)'}
borderRadius={'20px'}
overflow={'hidden'}
borderRadius={'0 20px 20px 0'}
transition={'.2s ease'}
userSelect={'none'}
overflow={isOpen ? 'none' : 'hidden'}
>
<RenderList templates={templates} onClose={onClose} />
<Box mb={2} pl={'20px'} pr={'10px'} whiteSpace={'nowrap'} overflow={'hidden'}>
<Flex flex={'1 0 0'} alignItems={'center'} gap={3}>
<RowTabs
list={[
{
icon: 'core/modules/basicNode',
label: t('core.module.template.Basic Node'),
value: TemplateTypeEnum.basic
},
{
icon: 'core/modules/systemPlugin',
label: t('core.module.template.System Plugin'),
value: TemplateTypeEnum.systemPlugin
},
{
icon: 'core/modules/teamPlugin',
label: t('core.module.template.Team Plugin'),
value: TemplateTypeEnum.teamPlugin
}
]}
py={'5px'}
value={templateType}
onChange={onChangeTab}
/>
{/* close icon */}
<IconButton
size={'sm'}
icon={<MyIcon name={'common/backFill'} w={'14px'} color={'myGray.700'} />}
w={'26px'}
h={'26px'}
borderColor={'myGray.300'}
variant={'grayBase'}
aria-label={''}
onClick={onClose}
/>
</Flex>
{templateType === TemplateTypeEnum.teamPlugin && (
<Flex mt={2} alignItems={'center'} h={10}>
<InputGroup mr={4} h={'full'}>
<InputLeftElement h={'full'} alignItems={'center'} display={'flex'}>
<MyIcon name={'common/searchLight'} w={'16px'} color={'myGray.500'} ml={3} />
</InputLeftElement>
<Input
h={'full'}
bg={'myGray.50'}
placeholder={t('plugin.Search plugin')}
onChange={debounce((e) => setSearchKey(e.target.value), 200)}
/>
</InputGroup>
<Box flex={1} />
<Flex
alignItems={'center'}
cursor={'pointer'}
_hover={{
color: 'primary.600'
}}
onClick={() => router.push('/plugin/list')}
>
<Box></Box>
<MyIcon name={'common/rightArrowLight'} w={'14px'} />
</Flex>
</Flex>
)}
{templateType === TemplateTypeEnum.teamPlugin && !searchKey && currentParent && (
<Flex alignItems={'center'} mt={2}>
<ParentPaths
paths={[currentParent]}
FirstPathDom={null}
onClick={() => {
setCurrentParent(undefined);
}}
fontSize="md"
/>
</Flex>
)}
</Box>
<RenderList
templates={templates}
onClose={onClose}
currentParent={currentParent}
setCurrentParent={setCurrentParent}
/>
</Flex>
</>
);
@@ -72,12 +214,18 @@ const ModuleTemplateList = ({ templates, isOpen, onClose }: ModuleTemplateListPr
export default React.memo(ModuleTemplateList);
const RenderList = React.memo(function RenderList({ templates, onClose }: RenderListProps) {
const RenderList = React.memo(function RenderList({
templates,
onClose,
currentParent,
setCurrentParent
}: RenderListProps) {
const { t } = useTranslation();
const { isPc } = useSystemStore();
const { x, y, zoom } = useViewport();
const { setLoading } = useSystemStore();
const { toast } = useToast();
const { reactFlowWrapper, nodes } = useFlowProviderStore();
const formatTemplates = useMemo<moduleTemplateListType>(() => {
const copy: moduleTemplateListType = JSON.parse(JSON.stringify(moduleTemplatesList));
@@ -87,11 +235,11 @@ const RenderList = React.memo(function RenderList({ templates, onClose }: Render
copy[index].list.push(item);
});
return copy.filter((item) => item.list.length > 0);
}, [templates]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [templates, currentParent]);
const onAddNode = useCallback(
async ({ template, position }: { template: FlowModuleTemplateType; position: XYPosition }) => {
const { reactFlowWrapper, nodes } = await getFlowStore();
async ({ template, position }: { template: FlowNodeTemplateType; position: XYPosition }) => {
if (!reactFlowWrapper?.current) return;
const templateModule = await (async () => {
@@ -131,34 +279,24 @@ const RenderList = React.memo(function RenderList({ templates, onClose }: Render
)
);
},
[setLoading, t, toast, x, y, zoom]
[nodes, reactFlowWrapper, setLoading, t, toast, x, y, zoom]
);
return templates.length === 0 ? (
<EmptyTip text={t('app.module.No Modules')} />
) : (
<Box flex={'1 0 0'} overflow={'overlay'}>
<Box w={['100%', '330px']} mx={'auto'}>
<Box flex={'1 0 0'} overflow={'overlay'} px={'20px'}>
<Box mx={'auto'}>
{formatTemplates.map((item, i) => (
<Box key={item.type}>
<Flex>
<Box fontWeight={'bold'} flex={1}>
{t(item.label)}
</Box>
{/* {isPlugin && item.type === ModuleTemplateTypeEnum.personalPlugin && (
<Flex
alignItems={'center'}
_hover={{ textDecoration: 'underline' }}
cursor={'pointer'}
onClick={() => router.push('/plugin/list')}
>
<Box fontSize={'sm'} transform={'translateY(-1px)'}>
{t('plugin.To Edit Plugin')}
</Box>
<MyIcon name={'common/rightArrowLight'} w={'12px'} />
</Flex>
)} */}
</Flex>
{item.label && (
<Flex>
<Box fontWeight={'bold'} flex={1}>
{t(item.label)}
</Box>
</Flex>
)}
<>
{item.list.map((template) => (
<Flex
@@ -168,21 +306,32 @@ const RenderList = React.memo(function RenderList({ templates, onClose }: Render
cursor={'pointer'}
_hover={{ bg: 'myWhite.600' }}
borderRadius={'sm'}
draggable
draggable={template.pluginType !== PluginTypeEnum.folder}
onDragEnd={(e) => {
if (e.clientX < 360) return;
if (e.clientX < sliderWidth) return;
onAddNode({
template: template,
position: { x: e.clientX, y: e.clientY }
});
}}
onClick={(e) => {
if (isPc) return;
onClose();
if (template.pluginType === PluginTypeEnum.folder) {
return setCurrentParent({
parentId: template.id,
parentName: template.name
});
}
if (isPc) {
return onAddNode({
template,
position: { x: sliderWidth * 1.5, y: 200 }
});
}
onAddNode({
template: template,
position: { x: e.clientX, y: e.clientY }
});
onClose();
}}
>
<Avatar

View File

@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
import { ModalBody, Flex, Box, useTheme, ModalFooter, Button } from '@chakra-ui/react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useQuery } from '@tanstack/react-query';
import type { SelectAppItemType } from '@fastgpt/global/core/module/type';
import Avatar from '@/components/Avatar';

View File

@@ -8,7 +8,7 @@ import { TTSTypeEnum } from '@/constants/app';
import type { AppTTSConfigType } from '@fastgpt/global/core/module/type.d';
import { useAudioPlay } from '@/web/common/utils/voice';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import MySlider from '@/components/Slider';
import MySelect from '@fastgpt/web/components/common/MySelect';
@@ -67,7 +67,7 @@ const TTSSelect = ({
});
}
},
[onChange, value]
[audioSpeechModelList, onChange, value]
);
return (
@@ -79,17 +79,16 @@ const TTSSelect = ({
</MyTooltip>
<Box flex={1} />
<MyTooltip label={t('core.app.Select TTS')}>
<Box
cursor={'pointer'}
_hover={{ bg: 'myGray.100' }}
py={2}
px={3}
borderRadius={'md'}
<Button
variant={'transparentBase'}
iconSpacing={1}
size={'sm'}
fontSize={'md'}
mr={'-5px'}
onClick={onOpen}
color={'myGray.600'}
>
{formLabel}
</Box>
</Button>
</MyTooltip>
<MyModal
title={

View File

@@ -32,7 +32,7 @@ import { useForm } from 'react-hook-form';
import { useFieldArray } from 'react-hook-form';
import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import MyTooltip from '@/components/MyTooltip';
import { variableTip } from '@fastgpt/global/core/module/template/tip';
import { useTranslation } from 'next-i18next';
@@ -83,16 +83,6 @@ const VariableEdit = ({
name: 'variable.enums'
});
const BoxBtnStyles: BoxProps = {
cursor: 'pointer',
px: 3,
py: 1,
borderRadius: 'md',
_hover: {
bg: 'myGray.150'
}
};
const formatVariables = useMemo(() => {
const results = formatEditorVariablePickerIcon(variables);
return results.map((item) => {
@@ -114,17 +104,20 @@ const VariableEdit = ({
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</MyTooltip>
</Box>
<Flex
{...BoxBtnStyles}
alignItems={'center'}
<Button
variant={'transparentBase'}
leftIcon={<SmallAddIcon />}
iconSpacing={1}
size={'sm'}
mr={'-5px'}
fontSize={'md'}
onClick={() => {
resetEdit({ variable: addVariable() });
onOpenEdit();
}}
>
<SmallAddIcon />
{t('common.Add New')}
</Flex>
</Button>
</Flex>
{formatVariables.length > 0 && (
<Box mt={2} borderRadius={'md'} overflow={'hidden'} borderWidth={'1px'} borderBottom="none">

View File

@@ -11,7 +11,7 @@ import {
} from '@chakra-ui/react';
import type { ContextExtractAgentItemType } from '@fastgpt/global/core/module/type';
import { useForm } from 'react-hook-form';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import MyTooltip from '@/components/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { ModalBody, Button, ModalFooter, useDisclosure, Textarea, Box } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import { onChangeNode } from '../../../FlowProvider';

View File

@@ -41,6 +41,47 @@ import MySelect from '@fastgpt/web/components/common/MySelect';
import RenderToolInput from '../../render/RenderToolInput';
const OpenApiImportModal = dynamic(() => import('./OpenApiImportModal'));
export const HttpHeaders = [
{ key: 'A-IM', label: 'A-IM' },
{ key: 'Accept', label: 'Accept' },
{ key: 'Accept-Charset', label: 'Accept-Charset' },
{ key: 'Accept-Encoding', label: 'Accept-Encoding' },
{ key: 'Accept-Language', label: 'Accept-Language' },
{ key: 'Accept-Datetime', label: 'Accept-Datetime' },
{ key: 'Access-Control-Request-Method', label: 'Access-Control-Request-Method' },
{ key: 'Access-Control-Request-Headers', label: 'Access-Control-Request-Headers' },
{ key: 'Authorization', label: 'Authorization' },
{ key: 'Cache-Control', label: 'Cache-Control' },
{ key: 'Connection', label: 'Connection' },
{ key: 'Content-Length', label: 'Content-Length' },
{ key: 'Content-Type', label: 'Content-Type' },
{ key: 'Cookie', label: 'Cookie' },
{ key: 'Date', label: 'Date' },
{ key: 'Expect', label: 'Expect' },
{ key: 'Forwarded', label: 'Forwarded' },
{ key: 'From', label: 'From' },
{ key: 'Host', label: 'Host' },
{ key: 'If-Match', label: 'If-Match' },
{ key: 'If-Modified-Since', label: 'If-Modified-Since' },
{ key: 'If-None-Match', label: 'If-None-Match' },
{ key: 'If-Range', label: 'If-Range' },
{ key: 'If-Unmodified-Since', label: 'If-Unmodified-Since' },
{ key: 'Max-Forwards', label: 'Max-Forwards' },
{ key: 'Origin', label: 'Origin' },
{ key: 'Pragma', label: 'Pragma' },
{ key: 'Proxy-Authorization', label: 'Proxy-Authorization' },
{ key: 'Range', label: 'Range' },
{ key: 'Referer', label: 'Referer' },
{ key: 'TE', label: 'TE' },
{ key: 'User-Agent', label: 'User-Agent' },
{ key: 'Upgrade', label: 'Upgrade' },
{ key: 'Via', label: 'Via' },
{ key: 'Warning', label: 'Warning' },
{ key: 'Dnt', label: 'Dnt' },
{ key: 'X-Requested-With', label: 'X-Requested-With' },
{ key: 'X-CSRF-Token', label: 'X-CSRF-Token' }
];
enum TabEnum {
params = 'params',
headers = 'headers',
@@ -342,47 +383,6 @@ const RenderForm = ({
const [shouldUpdateNode, setShouldUpdateNode] = useState(false);
const leftVariables = useMemo(() => {
const HttpHeaders = [
{ key: 'A-IM', label: 'A-IM' },
{ key: 'Accept', label: 'Accept' },
{ key: 'Accept-Charset', label: 'Accept-Charset' },
{ key: 'Accept-Encoding', label: 'Accept-Encoding' },
{ key: 'Accept-Language', label: 'Accept-Language' },
{ key: 'Accept-Datetime', label: 'Accept-Datetime' },
{ key: 'Access-Control-Request-Method', label: 'Access-Control-Request-Method' },
{ key: 'Access-Control-Request-Headers', label: 'Access-Control-Request-Headers' },
{ key: 'Authorization', label: 'Authorization' },
{ key: 'Cache-Control', label: 'Cache-Control' },
{ key: 'Connection', label: 'Connection' },
{ key: 'Content-Length', label: 'Content-Length' },
{ key: 'Content-Type', label: 'Content-Type' },
{ key: 'Cookie', label: 'Cookie' },
{ key: 'Date', label: 'Date' },
{ key: 'Expect', label: 'Expect' },
{ key: 'Forwarded', label: 'Forwarded' },
{ key: 'From', label: 'From' },
{ key: 'Host', label: 'Host' },
{ key: 'If-Match', label: 'If-Match' },
{ key: 'If-Modified-Since', label: 'If-Modified-Since' },
{ key: 'If-None-Match', label: 'If-None-Match' },
{ key: 'If-Range', label: 'If-Range' },
{ key: 'If-Unmodified-Since', label: 'If-Unmodified-Since' },
{ key: 'Max-Forwards', label: 'Max-Forwards' },
{ key: 'Origin', label: 'Origin' },
{ key: 'Pragma', label: 'Pragma' },
{ key: 'Proxy-Authorization', label: 'Proxy-Authorization' },
{ key: 'Range', label: 'Range' },
{ key: 'Referer', label: 'Referer' },
{ key: 'TE', label: 'TE' },
{ key: 'User-Agent', label: 'User-Agent' },
{ key: 'Upgrade', label: 'Upgrade' },
{ key: 'Via', label: 'Via' },
{ key: 'Warning', label: 'Warning' },
{ key: 'Dnt', label: 'Dnt' },
{ key: 'X-Requested-With', label: 'X-Requested-With' },
{ key: 'X-CSRF-Token', label: 'X-CSRF-Token' }
];
return (tabType === TabEnum.headers ? HttpHeaders : variables).filter((variable) => {
const existVariables = list.map((item) => item.key);
return !existVariables.includes(variable.key);
@@ -455,7 +455,7 @@ const RenderForm = ({
};
return (
<TableContainer>
<TableContainer overflowY={'visible'} overflowX={'unset'}>
<Table>
<Thead>
<Tr>

View File

@@ -62,44 +62,48 @@ const NodePluginInput = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
position={'relative'}
mb={7}
>
<MyIcon
name={'common/settingLight'}
w={'14px'}
cursor={'pointer'}
mr={3}
_hover={{ color: 'primary.500' }}
onClick={() =>
setEditField({
inputType: item.type,
valueType: item.valueType,
key: item.key,
label: item.label,
description: item.description,
required: item.required,
isToolInput: !!item.toolDescription
})
}
/>
<MyIcon
className="delete"
name={'delete'}
w={'14px'}
cursor={'pointer'}
mr={3}
_hover={{ color: 'red.500' }}
onClick={() => {
onChangeNode({
moduleId,
type: 'delInput',
key: item.key
});
onChangeNode({
moduleId,
type: 'delOutput',
key: item.key
});
}}
/>
{item.edit && (
<>
<MyIcon
name={'common/settingLight'}
w={'14px'}
cursor={'pointer'}
mr={3}
_hover={{ color: 'primary.500' }}
onClick={() =>
setEditField({
inputType: item.type,
valueType: item.valueType,
key: item.key,
label: item.label,
description: item.description,
required: item.required,
isToolInput: !!item.toolDescription
})
}
/>
<MyIcon
className="delete"
name={'delete'}
w={'14px'}
cursor={'pointer'}
mr={3}
_hover={{ color: 'red.500' }}
onClick={() => {
onChangeNode({
moduleId,
type: 'delInput',
key: item.key
});
onChangeNode({
moduleId,
type: 'delOutput',
key: item.key
});
}}
/>
</>
)}
{item.description && (
<MyTooltip label={t(item.description)} forceShow>
<QuestionOutlineIcon display={['none', 'inline']} mr={1} />

View File

@@ -10,7 +10,12 @@ import RenderToolInput from '../render/RenderToolInput';
import { useTranslation } from 'next-i18next';
import { useFlowProviderStore } from '../../FlowProvider';
const NodeSimple = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
const NodeSimple = ({
data,
selected,
minW = '350px',
maxW
}: NodeProps<FlowModuleItemType> & { minW?: string | number; maxW?: string | number }) => {
const { t } = useTranslation();
const { splitToolInputs } = useFlowProviderStore();
const { moduleId, inputs, outputs } = data;
@@ -22,7 +27,7 @@ const NodeSimple = ({ data, selected }: NodeProps<FlowModuleItemType>) => {
);
return (
<NodeCard minW={'350px'} selected={selected} {...data}>
<NodeCard minW={minW} maxW={maxW} selected={selected} {...data}>
{toolInputs.length > 0 && (
<>
<Divider text={t('core.module.tool.Tool input')} />

View File

@@ -10,10 +10,10 @@ import {
Textarea
} from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { DYNAMIC_INPUT_KEY, ModuleIOValueTypeEnum } from '@fastgpt/global/core/module/constants';
import { useTranslation } from 'next-i18next';
import { FlowValueTypeMap } from '@/web/core/modules/constants/dataType';
import { FlowValueTypeMap } from '@/web/core/workflow/constants/dataType';
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum
@@ -265,10 +265,6 @@ const FieldEditModal = ({
placeholder="appointment/sql"
{...register('key', {
required: true,
pattern: {
value: /^[a-zA-Z]+[0-9]*$/,
message: '字段key必须是纯英文字母或数字并且不能以数字开头。'
},
onChange: (e) => {
const value = e.target.value;
// auto fill label

View File

@@ -6,13 +6,7 @@ import type { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
import { useTranslation } from 'next-i18next';
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
import { useToast } from '@fastgpt/web/hooks/useToast';
import {
onChangeNode,
onCopyNode,
onResetNode,
onDelNode,
useFlowProviderStore
} from '../../FlowProvider';
import { onChangeNode, onCopyNode, onResetNode, useFlowProviderStore } from '../../FlowProvider';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
import { useSystemStore } from '@/web/common/system/useSystemStore';
@@ -26,6 +20,7 @@ import { useEditTextarea } from '@fastgpt/web/hooks/useEditTextarea';
type Props = FlowModuleItemType & {
children?: React.ReactNode | React.ReactNode[] | string;
minW?: string | number;
maxW?: string | number;
forbidMenu?: boolean;
selected?: boolean;
};
@@ -38,6 +33,7 @@ const NodeCard = (props: Props) => {
name = t('core.module.template.UnKnow Module'),
intro,
minW = '300px',
maxW = '600px',
moduleId,
flowType,
inputs,
@@ -48,21 +44,25 @@ const NodeCard = (props: Props) => {
const { toast } = useToast();
const { setLoading } = useSystemStore();
const { nodes, splitToolInputs } = useFlowProviderStore();
const { nodes, splitToolInputs, onDelNode } = useFlowProviderStore();
// edit intro
const { onOpenModal: onOpenIntroModal, EditModal: EditIntroModal } = useEditTextarea({
title: t('core.module.Edit intro'),
tip: '调整该模块会对工具调用时机有影响。\n你可以通过精确的描述该模块功能引导模型进行工具调用。',
canEmpty: false
});
// custom title edit
const { onOpenModal, EditModal: EditTitleModal } = useEditTitle({
title: t('common.Custom Title'),
placeholder: t('app.module.Custom Title Tip') || ''
});
const { openConfirm, ConfirmModal } = useConfirm({
const { openConfirm: onOpenConfirmSync, ConfirmModal: ConfirmSyncModal } = useConfirm({
content: t('module.Confirm Sync Plugin')
});
const { openConfirm: onOpenConfirmDeleteNode, ConfirmModal: ConfirmDeleteModal } = useConfirm({
content: t('core.module.Confirm Delete Node'),
type: 'delete'
});
const showToolHandle = useMemo(
() => isTool && !!nodes.find((item) => item.data?.flowType === FlowNodeTypeEnum.tools),
@@ -86,7 +86,7 @@ const NodeCard = (props: Props) => {
(item) => item.key === ModuleInputKeyEnum.pluginId
)?.value;
if (!pluginId) return;
openConfirm(async () => {
onOpenConfirmSync(async () => {
try {
setLoading(true);
const pluginModule = await getPreviewPluginModule(pluginId);
@@ -140,7 +140,7 @@ const NodeCard = (props: Props) => {
icon: 'delete',
label: t('common.Delete'),
variant: 'whiteDanger',
onClick: () => onDelNode(moduleId)
onClick: onOpenConfirmDeleteNode(() => onDelNode(moduleId))
}
];
@@ -211,21 +211,23 @@ const NodeCard = (props: Props) => {
</Box>
);
}, [
avatar,
flowType,
forbidMenu,
inputs,
intro,
moduleId,
moduleIsTool,
name,
onOpenIntroModal,
onOpenModal,
openConfirm,
setLoading,
showToolHandle,
t,
toast
onOpenConfirmDeleteNode,
showToolHandle,
moduleId,
avatar,
name,
forbidMenu,
intro,
moduleIsTool,
inputs,
onOpenConfirmSync,
setLoading,
toast,
onOpenModal,
onDelNode,
onOpenIntroModal
]);
const RenderModal = useMemo(() => {
@@ -233,15 +235,16 @@ const NodeCard = (props: Props) => {
<>
<EditTitleModal maxLength={20} />
{moduleIsTool && <EditIntroModal maxLength={500} />}
<ConfirmModal />
<ConfirmSyncModal />
<ConfirmDeleteModal />
</>
);
}, [ConfirmModal, EditIntroModal, EditTitleModal, moduleIsTool]);
}, [ConfirmDeleteModal, ConfirmSyncModal, EditIntroModal, EditTitleModal, moduleIsTool]);
return (
<Box
minW={minW}
maxW={'600px'}
maxW={maxW}
bg={'white'}
borderWidth={'1px'}
borderColor={selected ? 'primary.600' : 'borderColor.base'}

View File

@@ -42,12 +42,12 @@ const RenderList: {
Component: dynamic(() => import('./templates/SelectApp'))
},
{
types: [FlowNodeInputTypeEnum.aiSettings],
Component: dynamic(() => import('./templates/AiSetting'))
types: [FlowNodeInputTypeEnum.selectLLMModel],
Component: dynamic(() => import('./templates/SelectLLMModel'))
},
{
types: [FlowNodeInputTypeEnum.selectLLMModel],
Component: dynamic(() => import('./templates/SelectAiModel'))
types: [FlowNodeInputTypeEnum.settingLLMModel],
Component: dynamic(() => import('./templates/SettingLLMModel'))
},
{
types: [FlowNodeInputTypeEnum.selectDataset],
@@ -64,6 +64,10 @@ const RenderList: {
{
types: [FlowNodeInputTypeEnum.JSONEditor],
Component: dynamic(() => import('./templates/JsonEditor'))
},
{
types: [FlowNodeInputTypeEnum.settingDatasetQuotePrompt],
Component: dynamic(() => import('./templates/SettingQuotePrompt'))
}
];
const UserChatInput = dynamic(() => import('./templates/UserChatInput'));

View File

@@ -1,63 +0,0 @@
import React, { useMemo } from 'react';
import type { RenderInputProps } from '../type';
import { onChangeNode } from '../../../../FlowProvider';
import { useTranslation } from 'next-i18next';
import { Button, useDisclosure } from '@chakra-ui/react';
import { AIChatModuleProps } from '@fastgpt/global/core/module/node/type';
import MyIcon from '@fastgpt/web/components/common/Icon';
import AIChatSettingsModal from '@/components/core/module/AIChatSettingsModal';
const AiSettingRender = ({ inputs = [], moduleId }: RenderInputProps) => {
const { t } = useTranslation();
const chatModulesData = useMemo(() => {
const obj: Record<string, any> = {};
inputs.forEach((item) => {
obj[item.key] = item.value;
});
return obj as AIChatModuleProps;
}, [inputs]);
const {
isOpen: isOpenAIChatSetting,
onOpen: onOpenAIChatSetting,
onClose: onCloseAIChatSetting
} = useDisclosure();
return (
<>
<Button
variant={'whitePrimary'}
leftIcon={<MyIcon name={'common/settingLight'} w={'14px'} />}
onClick={onOpenAIChatSetting}
>
{t('app.AI Settings')}
</Button>
{isOpenAIChatSetting && (
<AIChatSettingsModal
isAdEdit
onClose={onCloseAIChatSetting}
onSuccess={(e) => {
for (let key in e) {
const item = inputs.find((input) => input.key === key);
if (!item) continue;
onChangeNode({
moduleId,
type: 'updateInput',
key,
value: {
...item,
//@ts-ignore
value: e[key]
}
});
}
onCloseAIChatSetting();
}}
defaultData={chatModulesData}
/>
)}
</>
);
};
export default React.memo(AiSettingRender);

View File

@@ -1,83 +0,0 @@
import React, { useCallback, useEffect } from 'react';
import type { RenderInputProps } from '../type';
import { onChangeNode } from '../../../../FlowProvider';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import SelectAiModel from '@/components/Select/SelectAiModel';
import { llmModelTypeFilterMap } from '@fastgpt/global/core/ai/constants';
const SelectAiModelRender = ({ item, inputs = [], moduleId }: RenderInputProps) => {
const { llmModelList } = useSystemStore();
const modelList = llmModelList
.filter((model) => {
if (!item.llmModelType) return true;
const filterField = llmModelTypeFilterMap[item.llmModelType];
if (!filterField) return true;
//@ts-ignore
return !!model[filterField];
})
.map((item) => ({
model: item.model,
name: item.name,
maxResponse: item.maxResponse
}));
const onChangeModel = useCallback(
(e: string) => {
onChangeNode({
moduleId,
type: 'updateInput',
key: item.key,
value: {
...item,
value: e
}
});
// update max tokens
const model = modelList.find((item) => item.model === e) || modelList[0];
if (!model) return;
onChangeNode({
moduleId,
type: 'updateInput',
key: 'maxToken',
value: {
...inputs.find((input) => input.key === 'maxToken'),
markList: [
{ label: '100', value: 100 },
{ label: `${model.maxResponse}`, value: model.maxResponse }
],
max: model.maxResponse,
value: model.maxResponse / 2
}
});
},
[inputs, item, modelList, moduleId]
);
const list = modelList.map((item) => {
return {
value: item.model,
label: item.name
};
});
useEffect(() => {
if (!item.value && list.length > 0) {
onChangeModel(list[0].value);
}
}, [item.value, list, onChangeModel]);
return (
<SelectAiModel
minW={'350px'}
width={'100%'}
value={item.value}
list={list}
onchange={onChangeModel}
/>
);
};
export default React.memo(SelectAiModelRender);

View File

@@ -0,0 +1,54 @@
import React, { useCallback, useEffect } from 'react';
import type { RenderInputProps } from '../type';
import { onChangeNode } from '../../../../FlowProvider';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { llmModelTypeFilterMap } from '@fastgpt/global/core/ai/constants';
import AIModelSelector from '@/components/Select/AIModelSelector';
const SelectAiModelRender = ({ item, moduleId }: RenderInputProps) => {
const { llmModelList } = useSystemStore();
const modelList = llmModelList.filter((model) => {
if (!item.llmModelType) return true;
const filterField = llmModelTypeFilterMap[item.llmModelType];
if (!filterField) return true;
//@ts-ignore
return !!model[filterField];
});
const onChangeModel = useCallback(
(e: string) => {
onChangeNode({
moduleId,
type: 'updateInput',
key: item.key,
value: {
...item,
value: e
}
});
},
[item, moduleId]
);
useEffect(() => {
if (!item.value && modelList.length > 0) {
onChangeModel(modelList[0].model);
}
}, [item.value, modelList, onChangeModel]);
return (
<AIModelSelector
minW={'350px'}
width={'100%'}
value={item.value}
list={modelList.map((item) => ({
value: item.model,
label: item.name
}))}
onchange={onChangeModel}
/>
);
};
export default React.memo(SelectAiModelRender);

View File

@@ -0,0 +1,49 @@
import React, { useCallback } from 'react';
import type { RenderInputProps } from '../type';
import { onChangeNode } from '../../../../FlowProvider';
import { SettingAIDataType } from '@fastgpt/global/core/module/node/type';
import SettingLLMModel from '@/components/core/ai/SettingLLMModel';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
const SelectAiModelRender = ({ item, inputs = [], moduleId }: RenderInputProps) => {
const onChangeModel = useCallback(
(e: SettingAIDataType) => {
for (const key in e) {
const input = inputs.find((input) => input.key === key);
input &&
onChangeNode({
moduleId,
type: 'updateInput',
key,
value: {
...input,
// @ts-ignore
value: e[key]
}
});
}
},
[inputs, moduleId]
);
const llmModelData: SettingAIDataType = {
model: inputs.find((input) => input.key === ModuleInputKeyEnum.aiModel)?.value ?? '',
maxToken:
inputs.find((input) => input.key === ModuleInputKeyEnum.aiChatMaxToken)?.value ?? 2048,
temperature:
inputs.find((input) => input.key === ModuleInputKeyEnum.aiChatTemperature)?.value ?? 1,
isResponseAnswerText: inputs.find(
(input) => input.key === ModuleInputKeyEnum.aiChatIsResponseText
)?.value
};
return (
<SettingLLMModel
llmModelType={item.llmModelType}
defaultData={llmModelData}
onChange={onChangeModel}
/>
);
};
export default React.memo(SelectAiModelRender);

View File

@@ -0,0 +1,243 @@
import React, { useMemo, useState } from 'react';
import type { RenderInputProps } from '../type';
import { Box, BoxProps, Button, Flex, ModalFooter, useDisclosure } from '@chakra-ui/react';
import { onChangeNode, useFlowProviderStore } from '../../../../FlowProvider';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useForm } from 'react-hook-form';
import { PromptTemplateItem } from '@fastgpt/global/core/ai/type';
import { useTranslation } from 'next-i18next';
import {
formatEditorVariablePickerIcon,
getGuideModule,
splitGuideModule
} from '@fastgpt/global/core/module/utils';
import { ModalBody } from '@chakra-ui/react';
import MyTooltip from '@/components/MyTooltip';
import {
Prompt_QuotePromptList,
Prompt_QuoteTemplateList
} from '@fastgpt/global/core/ai/prompt/AIChat';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
import PromptTemplate from '@/components/PromptTemplate';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
const SettingQuotePrompt = ({ inputs = [], moduleId }: RenderInputProps) => {
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
const { nodes } = useFlowProviderStore();
const { watch, setValue, handleSubmit } = useForm({
defaultValues: {
quoteTemplate: inputs.find((input) => input.key === 'quoteTemplate')?.value || '',
quotePrompt: inputs.find((input) => input.key === 'quotePrompt')?.value || ''
}
});
const aiChatQuoteTemplate = watch('quoteTemplate');
const aiChatQuotePrompt = watch('quotePrompt');
const variables = useMemo(() => {
const globalVariables = formatEditorVariablePickerIcon(
splitGuideModule(getGuideModule(nodes.map((node) => node.data)))?.variableModules || []
);
const moduleVariables = formatEditorVariablePickerIcon(
inputs
.filter((input) => input.edit)
.map((item) => ({
key: item.key,
label: item.label
}))
);
const systemVariables = [
{
key: 'cTime',
label: t('core.module.http.Current time')
}
];
return [...globalVariables, ...moduleVariables, ...systemVariables];
}, [inputs, t]);
const [selectTemplateData, setSelectTemplateData] = useState<{
title: string;
templates: PromptTemplateItem[];
}>();
const quoteTemplateVariables = (() => [
{
key: 'q',
label: 'q',
icon: 'core/app/simpleMode/variable'
},
{
key: 'a',
label: 'a',
icon: 'core/app/simpleMode/variable'
},
{
key: 'source',
label: t('core.dataset.search.Source name'),
icon: 'core/app/simpleMode/variable'
},
{
key: 'sourceId',
label: t('core.dataset.search.Source id'),
icon: 'core/app/simpleMode/variable'
},
{
key: 'index',
label: t('core.dataset.search.Quote index'),
icon: 'core/app/simpleMode/variable'
},
...variables
])();
const quotePromptVariables = (() => [
{
key: 'quote',
label: t('core.app.Quote templates'),
icon: 'core/app/simpleMode/variable'
},
{
key: 'question',
label: t('core.module.input.label.user question'),
icon: 'core/app/simpleMode/variable'
},
...variables
])();
const LabelStyles: BoxProps = {
fontSize: ['sm', 'md']
};
const selectTemplateBtn: BoxProps = {
color: 'primary.500',
cursor: 'pointer'
};
const onSubmit = (data: { quoteTemplate: string; quotePrompt: string }) => {
const quoteTemplateInput = inputs.find(
(input) => input.key === ModuleInputKeyEnum.aiChatQuoteTemplate
);
const quotePromptInput = inputs.find(
(input) => input.key === ModuleInputKeyEnum.aiChatQuotePrompt
);
if (quoteTemplateInput) {
onChangeNode({
moduleId,
type: 'updateInput',
key: quoteTemplateInput.key,
value: {
...quoteTemplateInput,
value: data.quoteTemplate
}
});
}
if (quotePromptInput) {
onChangeNode({
moduleId,
type: 'updateInput',
key: quotePromptInput.key,
value: {
...quotePromptInput,
value: data.quotePrompt
}
});
}
onClose();
};
return (
<>
<Button variant={'whitePrimary'} size={'sm'} onClick={onOpen}>
{t('core.module.Setting quote prompt')}
</Button>
<MyModal
isOpen={isOpen}
iconSrc={'modal/edit'}
title={t('core.module.Quote prompt setting')}
w={'600px'}
>
<ModalBody>
<Box>
<Flex {...LabelStyles} mb={1}>
{t('core.app.Quote templates')}
<MyTooltip
label={t('template.Quote Content Tip', {
default: Prompt_QuoteTemplateList[0].value
})}
forceShow
>
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</MyTooltip>
<Box flex={1} />
<Box
{...selectTemplateBtn}
onClick={() =>
setSelectTemplateData({
title: t('core.app.Select quote template'),
templates: Prompt_QuoteTemplateList
})
}
>
{t('common.Select template')}
</Box>
</Flex>
<PromptEditor
variables={quoteTemplateVariables}
h={160}
title={t('core.app.Quote templates')}
placeholder={t('template.Quote Content Tip', {
default: Prompt_QuoteTemplateList[0].value
})}
value={aiChatQuoteTemplate}
onChange={(e) => {
setValue('quoteTemplate', e);
}}
/>
</Box>
<Box mt={4}>
<Flex {...LabelStyles} mb={1}>
{t('core.app.Quote prompt')}
<MyTooltip
label={t('template.Quote Prompt Tip', { default: Prompt_QuotePromptList[0].value })}
forceShow
>
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</MyTooltip>
</Flex>
<PromptEditor
variables={quotePromptVariables}
title={t('core.app.Quote prompt')}
h={280}
placeholder={t('template.Quote Prompt Tip', {
default: Prompt_QuotePromptList[0].value
})}
value={aiChatQuotePrompt}
onChange={(e) => {
setValue('quotePrompt', e);
}}
/>
</Box>
</ModalBody>
<ModalFooter>
<Button variant={'whiteBase'} mr={2} onClick={onClose}>
{t('common.Close')}
</Button>
<Button onClick={handleSubmit(onSubmit)}>{t('common.Confirm')}</Button>
</ModalFooter>
</MyModal>
{!!selectTemplateData && (
<PromptTemplate
title={selectTemplateData.title}
templates={selectTemplateData.templates}
onClose={() => setSelectTemplateData(undefined)}
onSuccess={(e) => {
const quoteVal = e.value;
const promptVal = Prompt_QuotePromptList.find((item) => item.title === e.title)?.value;
setValue('quoteTemplate', quoteVal);
setValue('quotePrompt', promptVal);
}}
/>
)}
</>
);
};
export default React.memo(SettingQuotePrompt);

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useRef } from 'react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import type { EditFieldModalProps } from './type.d';
import { useTranslation } from 'next-i18next';
import {

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { Box, BoxProps } from '@chakra-ui/react';
import { Handle, Position } from 'reactflow';
import { FlowValueTypeMap } from '@/web/core/modules/constants/dataType';
import { FlowValueTypeMap } from '@/web/core/workflow/constants/dataType';
import MyTooltip from '@/components/MyTooltip';
import { useTranslation } from 'next-i18next';
import { ModuleIOValueTypeEnum } from '@fastgpt/global/core/module/constants';

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { Box, BoxProps } from '@chakra-ui/react';
import { Handle, OnConnect, Position } from 'reactflow';
import { FlowValueTypeMap } from '@/web/core/modules/constants/dataType';
import { FlowValueTypeMap } from '@/web/core/workflow/constants/dataType';
import MyTooltip from '@/components/MyTooltip';
import { useTranslation } from 'next-i18next';
import { ModuleIOValueTypeEnum } from '@fastgpt/global/core/module/constants';

View File

@@ -1,5 +1,5 @@
import MyTooltip from '@/components/MyTooltip';
import { FlowValueTypeMap } from '@/web/core/modules/constants/dataType';
import { FlowValueTypeMap } from '@/web/core/workflow/constants/dataType';
import { Box, BoxProps } from '@chakra-ui/react';
import {
ModuleIOValueTypeEnum,

View File

@@ -1,5 +1,11 @@
import React, { useCallback, useMemo } from 'react';
import ReactFlow, { Background, Connection, Controls, ReactFlowProvider } from 'reactflow';
import ReactFlow, {
Background,
Connection,
Controls,
NodeProps,
ReactFlowProvider
} from 'reactflow';
import { Box, Flex, IconButton, useDisclosure } from '@chakra-ui/react';
import { SmallCloseIcon } from '@chakra-ui/icons';
import { EDGE_TYPE, FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
@@ -7,12 +13,13 @@ import { EDGE_TYPE, FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/co
import dynamic from 'next/dynamic';
import ButtonEdge from './components/modules/ButtonEdge';
import ModuleTemplateList, { type ModuleTemplateProps } from './ModuleTemplateList';
import ModuleTemplateList from './ModuleTemplateList';
import { useFlowProviderStore } from './FlowProvider';
import 'reactflow/dist/style.css';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useTranslation } from 'next-i18next';
import { FlowModuleItemType } from '@fastgpt/global/core/module/type';
const NodeSimple = dynamic(() => import('./components/nodes/NodeSimple'));
const nodeTypes: Record<`${FlowNodeTypeEnum}`, any> = {
@@ -34,7 +41,10 @@ const nodeTypes: Record<`${FlowNodeTypeEnum}`, any> = {
[FlowNodeTypeEnum.pluginOutput]: dynamic(() => import('./components/nodes/NodePluginOutput')),
[FlowNodeTypeEnum.pluginModule]: NodeSimple,
[FlowNodeTypeEnum.queryExtension]: NodeSimple,
[FlowNodeTypeEnum.tools]: dynamic(() => import('./components/nodes/NodeTools'))
[FlowNodeTypeEnum.tools]: dynamic(() => import('./components/nodes/NodeTools')),
[FlowNodeTypeEnum.stopTool]: (data: NodeProps<FlowModuleItemType>) => (
<NodeSimple {...data} minW={'100px'} maxW={'300px'} />
)
};
const edgeTypes = {
[EDGE_TYPE]: ButtonEdge
@@ -99,11 +109,7 @@ const Container = React.memo(function Container() {
);
});
const Flow = ({
Header,
templates,
...data
}: ModuleTemplateProps & { Header: React.ReactNode }) => {
const Flow = ({ Header, ...data }: { Header: React.ReactNode }) => {
const {
isOpen: isOpenTemplate,
onOpen: onOpenTemplate,
@@ -143,14 +149,10 @@ const Flow = ({
<Container {...data} />
<ModuleTemplateList
templates={templates}
isOpen={isOpenTemplate}
onClose={onCloseTemplate}
/>
<ModuleTemplateList isOpen={isOpenTemplate} onClose={onCloseTemplate} />
</Box>
);
}, [data, isOpenTemplate, onCloseTemplate, onOpenTemplate, templates]);
}, [data, isOpenTemplate, onCloseTemplate, onOpenTemplate]);
return (
<Box h={'100%'} position={'fixed'} zIndex={999} top={0} left={0} right={0} bottom={0}>

View File

@@ -35,7 +35,7 @@ import { useCopyData } from '@/web/common/hooks/useCopyData';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useTranslation } from 'next-i18next';
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useForm } from 'react-hook-form';
import { useRequest } from '@/web/common/hooks/useRequest';
import MyTooltip from '@/components/MyTooltip';

View File

@@ -12,7 +12,9 @@ const PermissionIconText = ({
return PermissionTypeMap[permission] ? (
<Flex alignItems={'center'} {...props}>
<MyIcon name={PermissionTypeMap[permission]?.iconLight as any} w={'14px'} />
<Box ml={'2px'}>{t(PermissionTypeMap[permission]?.label)}</Box>
<Box ml={'2px'} lineHeight={1}>
{t(PermissionTypeMap[permission]?.label)}
</Box>
</Flex>
) : null;
};

View File

@@ -6,7 +6,7 @@ import { compressImgFileAndUpload } from '@/web/common/file/controller';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { useRequest } from '@/web/common/hooks/useRequest';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { Box, Button, Flex, Input, ModalBody, ModalFooter } from '@chakra-ui/react';
import MyTooltip from '@/components/MyTooltip';
import Avatar from '@/components/Avatar';

View File

@@ -1,5 +1,5 @@
import React, { useMemo, useState } from 'react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { ModalCloseButton, ModalBody, Box, ModalFooter, Button } from '@chakra-ui/react';
import TagTextarea from '@/components/common/Textarea/TagTextarea';

View File

@@ -1,5 +1,5 @@
import React, { useMemo, useState } from 'react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { useQuery } from '@tanstack/react-query';
import { DragHandleIcon } from '@chakra-ui/icons';
@@ -194,7 +194,6 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
bg: 'myGray.100'
}
})}
onClick={() => onSwitchTeam(team.teamId)}
>
<Avatar src={team.avatar} w={['18px', '22px']} />
<Box

View File

@@ -1,5 +1,5 @@
import React from 'react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import {
Box,
Button,

View File

@@ -1,6 +1,6 @@
import React, { useEffect } from 'react';
import { useTranslation } from 'next-i18next';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import {
Button,
ModalFooter,

View File

@@ -0,0 +1,35 @@
import React from 'react';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { Button, ModalBody, ModalFooter } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import { useSystemStore } from '@/web/common/system/useSystemStore';
const NotSufficientModal = () => {
const { t } = useTranslation();
const router = useRouter();
const { setIsNotSufficientModal } = useSystemStore();
const onClose = () => setIsNotSufficientModal(false);
return (
<MyModal isOpen iconSrc="common/confirm/deleteTip" title={t('common.Warning')}>
<ModalBody>{t('support.wallet.Not sufficient')}</ModalBody>
<ModalFooter>
<Button variant={'whiteBase'} mr={2} onClick={onClose}>
{t('common.Close')}
</Button>
<Button
onClick={() => {
router.push('/account');
onClose();
}}
>
{t('support.wallet.To read plan')}
</Button>
</ModalFooter>
</MyModal>
);
};
export default NotSufficientModal;

View File

@@ -1,4 +1,4 @@
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import React, { useEffect } from 'react';
import { useTranslation } from 'next-i18next';
import { Box, ModalBody, ModalFooter } from '@chakra-ui/react';

View File

@@ -5,6 +5,10 @@ import { standardSubLevelMap } from '@fastgpt/global/support/wallet/sub/constant
import { Box, Flex, Grid } from '@chakra-ui/react';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useTranslation } from 'next-i18next';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { useRouter } from 'next/router';
import { AI_POINT_USAGE_CARD_ROUTE } from '@/web/support/wallet/sub/constants';
const StandardPlanContentList = ({
level,
@@ -15,6 +19,7 @@ const StandardPlanContentList = ({
}) => {
const { t } = useTranslation();
const { subPlans } = useSystemStore();
const router = useRouter();
const planContent = useMemo(() => {
const plan = subPlans?.standard?.[level];
@@ -87,6 +92,14 @@ const StandardPlanContentList = ({
amount: planContent.totalPoints
})}
</Box>
<MyTooltip label={t('support.wallet.subscription.AI points click to read tip')}>
<QuestionOutlineIcon
ml={'2px'}
onClick={() => {
router.push(AI_POINT_USAGE_CARD_ROUTE);
}}
/>
</MyTooltip>
</Flex>
</Flex>
<Flex alignItems={'center'}>

View File

@@ -6,7 +6,6 @@ export const defaultApp: AppDetailType = {
userId: 'userId',
name: '应用加载中',
type: 'simple',
simpleTemplateId: 'fastgpt-universal',
avatar: '/icon/logo.svg',
intro: '',
updateTime: Date.now(),

View File

@@ -7,7 +7,6 @@ import type {
} from '@fastgpt/global/core/ai/model.d';
import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d';
import { AppSimpleEditConfigTemplateType } from '@fastgpt/global/core/app/type';
import { SubPlanType } from '@fastgpt/global/support/wallet/sub/type';
export type InitDateResponse = {
@@ -19,5 +18,4 @@ export type InitDateResponse = {
feConfigs: FastGPTFeConfigsType;
subPlans?: SubPlanType;
systemVersion: string;
simpleModeTemplates: AppSimpleEditConfigTemplateType[];
};

View File

@@ -1,32 +0,0 @@
import { AppSimpleEditConfigTemplateType } from '@fastgpt/global/core/app/type.d';
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
export const SimpleModeTemplate_FastGPT_Universal: AppSimpleEditConfigTemplateType = {
id: 'fastgpt-universal',
name: 'core.app.template.Common template',
desc: 'core.app.template.Common template tip',
systemForm: {
aiSettings: {
model: true,
systemPrompt: true,
temperature: true,
maxToken: true,
quoteTemplate: true,
quotePrompt: true
},
dataset: {
datasets: true,
similarity: true,
limit: true,
searchMode: DatasetSearchModeEnum.embedding,
usingReRank: true,
searchEmptyText: true
},
userGuide: {
welcomeText: true,
variables: true,
questionGuide: true,
tts: true
}
}
};

View File

@@ -19,7 +19,6 @@ export type CreateDatasetParams = {
avatar: string;
vectorModel?: string;
agentModel?: string;
type: `${DatasetTypeEnum}`;
};
/* ================= collection ===================== */

View File

@@ -1,116 +0,0 @@
import { PromptTemplateItem } from '@fastgpt/global/core/ai/type.d';
export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
{
title: '标准模板',
desc: '标准提示词,用于结构不固定的知识库。',
value: `{{q}}
{{a}}`
},
{
title: '问答模板',
desc: '适合 QA 问答结构的知识库可以让AI较为严格的按预设内容回答',
value: `<Question>
{{q}}
</Question>
<Answer>
{{a}}
</Answer>`
},
{
title: '标准严格模板',
desc: '在标准模板基础上,对模型的回答做更严格的要求。',
value: `{{q}}
{{a}}`
},
{
title: '严格问答模板',
desc: '在问答模板基础上,对模型的回答做更严格的要求。',
value: `<Question>
{{q}}
</Question>
<Answer>
{{a}}
</Answer>`
}
];
export const Prompt_QuotePromptList: PromptTemplateItem[] = [
{
title: '标准模板',
desc: '',
value: `使用 <Data></Data> 标记中的内容作为你的知识:
<Data>
{{quote}}
</Data>
回答要求:
- 如果你不清楚答案,你需要澄清。
- 避免提及你是从 <Data></Data> 获取的知识。
- 保持答案与 <Data></Data> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
问题:"""{{question}}"""`
},
{
title: '问答模板',
desc: '',
value: `使用 <QA></QA> 标记中的问答对进行回答。
<QA>
{{quote}}
</QA>
回答要求:
- 选择其中一个或多个问答对进行回答。
- 回答的内容应尽可能与 <答案></答案> 中的内容一致。
- 如果没有相关的问答对,你需要澄清。
- 避免提及你是从 QA 获取的知识,只需要回复答案。
问题:"""{{question}}"""`
},
{
title: '标准严格模板',
desc: '',
value: `忘记你已有的知识,仅使用 <Data></Data> 标记中的内容作为你的知识:
<Data>
{{quote}}
</Data>
思考流程:
1. 判断问题是否与 <Data></Data> 标记中的内容有关。
2. 如果有关,你按下面的要求回答。
3. 如果无关,你直接拒绝回答本次问题。
回答要求:
- 避免提及你是从 <Data></Data> 获取的知识。
- 保持答案与 <Data></Data> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
问题:"""{{question}}"""`
},
{
title: '严格问答模板',
desc: '',
value: `忘记你已有的知识,仅使用 <QA></QA> 标记中的问答对进行回答。
<QA>
{{quote}}
</QA>}
思考流程:
1. 判断问题是否与 <QA></QA> 标记中的内容有关。
2. 如果无关,你直接拒绝回答本次问题。
3. 判断是否有相近或相同的问题。
4. 如果有相同的问题,直接输出对应答案。
5. 如果只有相近的问题,请把相近的问题和答案一起输出。
最后,避免提及你是从 QA 获取的知识,只需要回复答案。
问题:"""{{question}}"""`
}
];

View File

@@ -1,62 +0,0 @@
export const Prompt_AgentQA = {
description: `<Context></Context> 标记中是一段文本,学习和分析它,并整理学习成果:
- 提出问题并给出每个问题的答案。
- 答案需详细完整,尽可能保留原文描述。
- 答案可以包含普通文字、链接、代码、表格、公示、媒体链接等 Markdown 元素。
- 最多提出 30 个问题。
`,
fixedText: `请按以下格式整理学习成果:
<Context>
文本
</Context>
Q1: 问题。
A1: 答案。
Q2:
A2:
------
我们开始吧!
<Context>
{{text}}
<Context/>
`
};
export const Prompt_ExtractJson = `你可以从 <对话记录></对话记录> 中提取指定 JSON 信息,你仅需返回 JSON 字符串,无需回答问题。
<提取要求>
{{description}}
</提取要求>
<字段说明>
1. 下面的 JSON 字符串均按照 JSON Schema 的规则描述。
2. key 代表字段名description 代表字段的描述enum 是可选值,代表可选的 value。
3. 如果没有可提取的内容,忽略该字段。
4. 本次需提取的JSON Schema{{json}}
</字段说明>
<对话记录>
{{text}}
</对话记录>
`;
export const Prompt_CQJson = `我会给你几个问题类型请参考背景知识可能为空和对话记录判断我“本次问题”的类型并返回一个问题“类型ID”:
<问题类型>
{{typeList}}
</问题类型>
<背景知识>
{{systemPrompt}}
</背景知识>
<对话记录>
{{history}}
</对话记录>
Human"{{question}}"
类型ID=
`;
export const Prompt_QuestionGuide = `我不太清楚问你什么问题,请帮我生成 3 个问题引导我继续提问。问题的长度应小于20个字符按 JSON 格式返回: ["问题1", "问题2", "问题3"]`;

View File

@@ -30,7 +30,7 @@ import MyBox from '@/components/common/MyBox';
import { useRequest } from '@/web/common/hooks/useRequest';
import { standardSubLevelMap, subModeMap } from '@fastgpt/global/support/wallet/sub/constants';
import MySelect from '@fastgpt/web/components/common/MySelect';
import MyModal from '@fastgpt/web/components/common/CustomModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { usePagination } from '@fastgpt/web/hooks/usePagination';
const BillTable = () => {

View File

@@ -16,6 +16,7 @@ import { useToast } from '@fastgpt/web/hooks/useToast';
import { useUserStore } from '@/web/support/user/useUserStore';
import type { UserType } from '@fastgpt/global/support/user/type.d';
import { useQuery } from '@tanstack/react-query';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import dynamic from 'next/dynamic';
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
import { compressImgFileAndUpload } from '@/web/common/file/controller';
@@ -29,16 +30,24 @@ import { formatStorePrice2Read } from '@fastgpt/global/support/wallet/usage/tool
import { putUpdateMemberName } from '@/web/support/user/team/api';
import { getDocPath } from '@/web/common/system/doc';
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
import { standardSubLevelMap } from '@fastgpt/global/support/wallet/sub/constants';
import {
StandardSubLevelEnum,
standardSubLevelMap
} from '@fastgpt/global/support/wallet/sub/constants';
import { formatTime2YMD } from '@fastgpt/global/common/string/time';
import { AI_POINT_USAGE_CARD_ROUTE } from '@/web/support/wallet/sub/constants';
import {
AI_POINT_USAGE_CARD_ROUTE,
EXTRA_PLAN_CARD_ROUTE
} from '@/web/support/wallet/sub/constants';
import StandardPlanContentList from '@/components/support/wallet/StandardPlanContentList';
const StandDetailModal = dynamic(() => import('./standardDetailModal'));
const TeamMenu = dynamic(() => import('@/components/support/user/team/TeamMenu'));
const PayModal = dynamic(() => import('./PayModal'));
const UpdatePswModal = dynamic(() => import('./UpdatePswModal'));
const OpenAIAccountModal = dynamic(() => import('./OpenAIAccountModal'));
const CommunityModal = dynamic(() => import('@/components/CommunityModal'));
const Account = () => {
const { isPc } = useSystemStore();
@@ -113,11 +122,11 @@ const MyInfo = () => {
});
reset(data);
toast({
title: '更新数据成功',
title: t('dataset.data.Update Success Tip'),
status: 'success'
});
},
[reset, toast, updateUserInfo]
[reset, t, toast, updateUserInfo]
);
const onSelectFile = useCallback(
@@ -184,7 +193,7 @@ const MyInfo = () => {
cursor={'pointer'}
onClick={onOpenSelectFile}
>
<MyTooltip label={'更换头像'}>
<MyTooltip label={t('common.avatar.Select Avatar')}>
<Box
w={['44px', '54px']}
h={['44px', '54px']}
@@ -269,7 +278,6 @@ const MyInfo = () => {
);
};
const PlanUsage = () => {
const { isPc } = useSystemStore();
const router = useRouter();
const { t } = useTranslation();
const { userInfo, initUserInfo, teamPlanStatus } = useUserStore();
@@ -288,6 +296,21 @@ const PlanUsage = () => {
return standardSubLevelMap[teamPlanStatus.standard.currentSubLevel].label;
}, [teamPlanStatus?.standard?.currentSubLevel]);
const standardPlan = teamPlanStatus?.standard;
const isFreeTeam = useMemo(() => {
if (!teamPlanStatus || !teamPlanStatus?.standardConstants) return false;
const hasExtraDatasetSize =
teamPlanStatus.datasetMaxSize > teamPlanStatus.standardConstants.maxDatasetSize;
const hasExtraPoints =
teamPlanStatus.totalPoints > teamPlanStatus.standardConstants.totalPoints;
if (
teamPlanStatus?.standard?.currentSubLevel === StandardSubLevelEnum.free &&
!hasExtraDatasetSize &&
!hasExtraPoints
) {
return true;
}
return false;
}, [teamPlanStatus]);
useQuery(['init'], initUserInfo, {
onSuccess(res) {
@@ -374,6 +397,11 @@ const PlanUsage = () => {
<Box fontWeight={'bold'} fontSize="xl">
{t(planName)}
</Box>
{isFreeTeam && (
<Box mt="3" color={'#485264'} fontSize="sm">
15使
</Box>
)}
<Flex mt="3" color={'#485264'} fontSize="sm">
<Box>{t('common.Expired Time')}:</Box>
<Box ml={2}>{formatTime2YMD(standardPlan?.expiredTime)}</Box>
@@ -399,9 +427,29 @@ const PlanUsage = () => {
borderColor={'borderColor.low'}
borderRadius={'md'}
px={[5, 10]}
py={[4, 7]}
pt={[2, 4]}
pb={[4, 7]}
>
<Box width={'100%'}>
<Flex>
<Flex flex={'1 0 0'} alignItems={'flex-end'}>
<Box fontSize={'xl'}></Box>
<Box fontSize={'sm'} color={'myGray.500'}>
()
</Box>
</Flex>
<Link
href={EXTRA_PLAN_CARD_ROUTE}
transform={'translateX(15px)'}
display={'flex'}
alignItems={'center'}
color={'primary.600'}
cursor={'pointer'}
>
<MyIcon ml={1} name={'common/rightArrowLight'} w={'12px'} />
</Link>
</Flex>
<Box width={'100%'} mt={5}>
<Flex alignItems={'center'}>
<Flex alignItems={'center'}>
<Box fontWeight={'bold'}>{t('support.user.team.Dataset usage')}</Box>
@@ -426,7 +474,10 @@ const PlanUsage = () => {
<Box mt="9" width={'100%'}>
<Flex alignItems={'center'}>
<Flex alignItems={'center'}>
<Box fontWeight={'bold'}>{t('support.wallet.subscription.AI points')}</Box>
<Box fontWeight={'bold'}>{t('support.wallet.subscription.AI points usage')}</Box>
<MyTooltip label={t('support.wallet.subscription.AI points usage tip')}>
<QuestionOutlineIcon ml={'2px'} />
</MyTooltip>
<Box color={'myGray.600'} ml={2}>
{aiPointsUsageMap.used}/{aiPointsUsageMap.max}
</Box>
@@ -445,7 +496,6 @@ const PlanUsage = () => {
/>
</Box>
</Box>
<Flex></Flex>
</Box>
{isOpenStandardModal && <StandDetailModal onClose={onCloseStandardModal} />}
</Box>
@@ -462,6 +512,7 @@ const Other = () => {
});
const { isOpen: isOpenOpenai, onClose: onCloseOpenai, onOpen: onOpenOpenai } = useDisclosure();
const { isOpen: isOpenConcat, onClose: onCloseConcat, onOpen: onOpenConcat } = useDisclosure();
const onclickSave = useCallback(
async (data: UserType) => {
@@ -552,6 +603,17 @@ const Other = () => {
/>
</Flex>
)}
{feConfigs?.concatMd && (
<Button
variant={'whiteBase'}
justifyContent={'flex-start'}
leftIcon={<MyIcon name={'modal/concat'} w={'18px'} color={'myGray.600'} />}
onClick={onOpenConcat}
h={'48px'}
>
</Button>
)}
</Grid>
{isOpenOpenai && userInfo && (
@@ -566,6 +628,7 @@ const Other = () => {
onClose={onCloseOpenai}
/>
)}
{isOpenConcat && <CommunityModal onClose={onCloseConcat} />}
</Box>
);
};

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { useForm } from 'react-hook-form';
import { useRequest } from '@/web/common/hooks/useRequest';

View File

@@ -1,15 +1,16 @@
import React, { useState, useCallback, useMemo } from 'react';
import { ModalFooter, ModalBody, Button, Input, Box, Grid } from '@chakra-ui/react';
import { ModalFooter, ModalBody, Button, Input, Box, Grid, Link } from '@chakra-ui/react';
import { getWxPayQRCode } from '@/web/support/wallet/bill/api';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useRouter } from 'next/router';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { useTranslation } from 'next-i18next';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants';
import QRCodePayModal, { type QRPayProps } from '@/components/support/wallet/QRCodePayModal';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { EXTRA_PLAN_CARD_ROUTE } from '@/web/support/wallet/sub/constants';
const PayModal = ({
onClose,
@@ -59,8 +60,12 @@ const PayModal = ({
return (
<MyModal isOpen={true} onClose={onClose} title={t('user.Pay')} iconSrc="/imgs/modal/pay.svg">
<ModalBody px={0} display={'flex'} flexDirection={'column'}>
<Box px={6} fontSize={'sm'} color={'myGray.600'} mb={2} maxW={'400px'}>
<Box px={6} fontSize={'sm'} mb={2} py={2} maxW={'400px'}>
<Link href={EXTRA_PLAN_CARD_ROUTE} color={'primary.600'} textDecoration={'underline'}>
</Link>
</Box>
<Grid gridTemplateColumns={'repeat(3,1fr)'} gridGap={5} mb={4} px={6}>
{payList.map((item) => (

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { useForm } from 'react-hook-form';
import { useRequest } from '@/web/common/hooks/useRequest';

View File

@@ -14,7 +14,7 @@ import {
import { UsageItemType } from '@fastgpt/global/support/wallet/usage/type.d';
import dayjs from 'dayjs';
import { UsageSourceMap } from '@fastgpt/global/support/wallet/usage/constants';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { formatNumber } from '@fastgpt/global/common/math/tools';

View File

@@ -11,7 +11,7 @@ import {
TableContainer,
ModalCloseButton
} from '@chakra-ui/react';
import MyModal from '@/components/MyModal';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { useQuery } from '@tanstack/react-query';
import { useLoading } from '@fastgpt/web/hooks/useLoading';

View File

@@ -1,70 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { delay } from '@fastgpt/global/common/system/utils';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema';
import { jiebaSplit } from '@/service/common/string/jieba';
let success = 0;
/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { limit = 50 } = req.body as { limit: number };
await authCert({ req, authRoot: true });
await connectToDatabase();
success = 0;
console.log(
'total',
await MongoDatasetData.countDocuments({
fullTextToken: { $exists: false },
updateTime: { $lt: new Date() }
})
);
await initFullTextToken(limit, new Date());
jsonRes(res, {
message: 'success'
});
} catch (error) {
console.log(error);
jsonRes(res, {
code: 500,
error
});
}
}
export async function initFullTextToken(limit = 50, endDate: Date): Promise<any> {
try {
const dataList = await MongoDatasetData.find(
{ fullTextToken: { $exists: false }, updateTime: { $lt: endDate } },
'_id q a'
)
.limit(limit)
.lean();
if (dataList.length === 0) return;
const result = await Promise.allSettled(
dataList.map((item) => {
const text = item.q + (item.a || '');
const tokens = jiebaSplit({ text });
return MongoDatasetData.findByIdAndUpdate(item._id, {
$set: {
fullTextToken: tokens
}
});
})
);
success += result.filter((item) => item.status === 'fulfilled').length;
console.log(`success: ${success}`);
return initFullTextToken(limit, endDate);
} catch (error) {
await delay(1000);
return initFullTextToken(limit, endDate);
}
}

View File

@@ -1,62 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { delay } from '@fastgpt/global/common/system/utils';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema';
import { jiebaSplit } from '@/service/common/string/jieba';
let success = 0;
/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { limit = 50 } = req.body as { limit: number };
await authCert({ req, authRoot: true });
await connectToDatabase();
success = 0;
console.log('total', await MongoDatasetData.countDocuments({ inited: { $exists: false } }));
await initFullTextToken(limit);
jsonRes(res, {
message: 'success'
});
} catch (error) {
console.log(error);
jsonRes(res, {
code: 500,
error
});
}
}
export async function initFullTextToken(limit = 50): Promise<any> {
try {
const dataList = await MongoDatasetData.find({ inited: { $exists: false } }, '_id q a')
.limit(limit)
.lean();
if (dataList.length === 0) return;
const result = await Promise.allSettled(
dataList.map((item) => {
const text = item.q + (item.a || '');
const tokens = jiebaSplit({ text });
return MongoDatasetData.findByIdAndUpdate(item._id, {
$set: {
inited: true,
fullTextToken: tokens
}
});
})
);
success += result.filter((item) => item.status === 'fulfilled').length;
console.log(`success: ${success}`);
return initFullTextToken(limit);
} catch (error) {
await delay(1000);
return initFullTextToken(limit);
}
}

View File

@@ -1,109 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema';
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
import { DatasetStatusEnum, TrainingModeEnum } from '@fastgpt/global/core/dataset/constants';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
let success = 0;
/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { limit = 50 } = req.body as { limit: number };
await authCert({ req, authRoot: true });
await connectToDatabase();
success = 0;
await MongoDatasetCollection.updateMany({ createTime: { $exists: false } }, [
{
$set: {
createTime: '$updateTime'
}
}
]);
await MongoDatasetCollection.updateMany({ trainingType: { $exists: false } }, [
{
$set: {
trainingType: {
$cond: {
if: { $ifNull: ['$a', false] },
then: TrainingModeEnum.qa,
else: TrainingModeEnum.chunk
}
}
}
}
]);
await MongoDatasetCollection.updateMany({ chunkSize: { $exists: false } }, [
{
$set: {
chunkSize: 0
}
}
]);
await MongoDatasetCollection.updateMany({ fileId: { $exists: false } }, [
{
$set: {
fileId: '$metadata.fileId'
}
}
]);
await MongoDatasetCollection.updateMany({ rawLink: { $exists: false } }, [
{
$set: {
rawLink: '$metadata.rawLink'
}
}
]);
await MongoDatasetData.updateMany(
{ chunkIndex: { $exists: false } },
{
chunkIndex: 0
}
);
await MongoDatasetData.updateMany(
{ updateTime: { $exists: false } },
{
updateTime: new Date()
}
);
await MongoDataset.updateMany(
{ status: { $exists: false } },
{
$set: {
status: DatasetStatusEnum.active
}
}
);
// dataset tags to intro
await MongoDataset.updateMany({ tags: { $exists: true } }, [
{
$set: {
intro: {
$reduce: {
input: '$tags',
initialValue: '',
in: { $concat: ['$$value', ' ', '$$this'] }
}
}
}
}
]);
jsonRes(res, {
message: 'success'
});
} catch (error) {
console.log(error);
jsonRes(res, {
code: 500,
error
});
}
}

View File

@@ -0,0 +1,49 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoUsage } from '@fastgpt/service/support/wallet/usage/schema';
import { connectionMongo } from '@fastgpt/service/common/mongo';
import { checkFiles } from '../timerTask/dataset/checkInValidDatasetFiles';
import { addHours } from 'date-fns';
import { checkInvalid as checkInvalidImg } from '../timerTask/dataset/checkInvalidDatasetImage';
import { checkInvalidCollection } from '../timerTask/dataset/checkInvalidMongoCollection';
import { checkInvalidVector } from '../timerTask/dataset/checkInvalidVector';
import { MongoPlugin } from '@fastgpt/service/core/plugin/schema';
import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants';
/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
await authCert({ req, authRoot: true });
await MongoPlugin.updateMany(
{ type: { $exists: false } },
{
$set: {
type: PluginTypeEnum.custom
}
}
);
await MongoPlugin.updateMany(
{ parentId: { $exists: false } },
{
$set: {
parentId: null
}
}
);
jsonRes(res, {
message: 'success'
});
} catch (error) {
console.log(error);
jsonRes(res, {
code: 500,
error
});
}
}

View File

@@ -30,8 +30,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
})) || [],
whisperModel: global.whisperModel,
audioSpeechModels: global.audioSpeechModels,
systemVersion: global.systemVersion || '0.0.0',
simpleModeTemplates: global.simpleModeTemplates
systemVersion: global.systemVersion || '0.0.0'
}
});
}
@@ -43,7 +42,7 @@ const defaultFeConfigs: FastGPTFeConfigsType = {
openAPIDocUrl: 'https://doc.fastgpt.in/docs/development/openapi',
systemTitle: 'FastGPT',
concatMd:
'* 项目开源地址: [FastGPT GitHub](https://github.com/labring/FastGPT)\n* 交流群: ![](https://doc.fastgpt.in/wechat-fastgpt.webp)',
'* 项目开源地址: [FastGPT GitHub](https://github.com/labring/FastGPT)\n* 交流群: ![](https://oss.laf.run/htr4n1-images/fastgpt-qr-code.jpg)',
limit: {
exportDatasetLimitMinutes: 0,
websiteSyncLimitMinuted: 0
@@ -68,7 +67,6 @@ export async function getInitConfig() {
]);
console.log({
// simpleModeTemplates: global.simpleModeTemplates,
communityPlugins: global.communityPlugins
});
} catch (error) {
@@ -141,39 +139,6 @@ export function getSystemVersion() {
}
}
// async function getSimpleModeTemplates() {
// if (global.simpleModeTemplates && global.simpleModeTemplates.length > 0) return;
// try {
// const basePath =
// process.env.NODE_ENV === 'development' ? 'data/simpleTemplates' : '/app/data/simpleTemplates';
// // read data/simpleTemplates directory, get all json file
// const files = readdirSync(basePath);
// // filter json file
// const filterFiles = files.filter((item) => item.endsWith('.json'));
// // read json file
// const fileTemplates = filterFiles.map((item) => {
// const content = readFileSync(`${basePath}/${item}`, 'utf-8');
// return {
// id: item.replace('.json', ''),
// ...JSON.parse(content)
// };
// });
// // fetch templates from plus
// const plusTemplates = await getSimpleTemplatesFromPlus();
// global.simpleModeTemplates = [
// SimpleModeTemplate_FastGPT_Universal,
// ...plusTemplates,
// ...fileTemplates
// ];
// } catch (error) {
// global.simpleModeTemplates = [SimpleModeTemplate_FastGPT_Universal];
// }
// }
function getSystemPlugin() {
if (global.communityPlugins && global.communityPlugins.length > 0) return;

View File

@@ -5,7 +5,6 @@ import type { CreateAppParams } from '@fastgpt/global/core/app/api.d';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
import { SimpleModeTemplate_FastGPT_Universal } from '@/global/core/app/constants';
import { checkTeamAppLimit } from '@fastgpt/service/support/permission/teamLimit';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
@@ -35,8 +34,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
teamId,
tmbId,
modules,
type,
simpleTemplateId: SimpleModeTemplate_FastGPT_Universal.id
type
});
jsonRes(res, {

Some files were not shown because too many files have changed in this diff Show More