balibabu
commited on
Commit
·
be99f83
1
Parent(s):
92cae19
feat: add custom edge (#1061)
Browse files### What problem does this PR solve?
feat: add custom edge
feat: add flow card
feat: add store for canvas
#918
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
- web/package-lock.json +87 -203
- web/package.json +4 -1
- web/src/app.tsx +16 -11
- web/src/components/knowledge-base-item.tsx +37 -0
- web/src/components/llm-setting-items/index.less +6 -0
- web/src/components/llm-setting-items/index.tsx +259 -0
- web/src/components/top-n-item.tsx +23 -0
- web/src/hooks/flow-hooks.ts +70 -0
- web/src/hooks/userSettingHook.ts +8 -4
- web/src/interfaces/database/flow.ts +4 -4
- web/src/locales/en.ts +1 -0
- web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx +2 -24
- web/src/pages/chat/chat-configuration-modal/model-setting.tsx +9 -15
- web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx +2 -15
- web/src/pages/flow/answer-form/index.tsx +5 -0
- web/src/pages/flow/begin-form/index.tsx +47 -0
- web/src/pages/flow/canvas/context-menu/index.tsx +1 -1
- web/src/pages/flow/canvas/edge/index.less +15 -0
- web/src/pages/flow/canvas/edge/index.tsx +72 -0
- web/src/pages/flow/canvas/index.less +4 -0
- web/src/pages/flow/canvas/index.tsx +42 -41
- web/src/pages/flow/canvas/node/index.less +10 -1
- web/src/pages/flow/canvas/node/index.tsx +15 -3
- web/src/pages/flow/constant.ts +6 -0
- web/src/pages/flow/flow-drawer/index.tsx +32 -4
- web/src/pages/flow/generate-form/index.tsx +83 -0
- web/src/pages/flow/hooks.ts +63 -50
- web/src/pages/flow/index.tsx +4 -1
- web/src/pages/flow/interface.ts +58 -0
- web/src/pages/flow/list/flow-card/index.less +78 -0
- web/src/pages/flow/list/flow-card/index.tsx +94 -0
- web/src/pages/flow/list/hooks.ts +48 -0
- web/src/pages/flow/list/index.less +48 -0
- web/src/pages/flow/list/index.tsx +53 -0
- web/src/pages/flow/mock.tsx +15 -8
- web/src/pages/flow/retrieval-form/index.tsx +43 -0
- web/src/pages/flow/store.ts +106 -0
- web/src/pages/flow/utils.ts +33 -0
- web/src/routes.ts +4 -0
- web/src/services/flow-service.ts +43 -0
- web/src/utils/api.ts +8 -0
- web/src/utils/registerServer.ts +1 -1
web/package-lock.json
CHANGED
@@ -10,6 +10,7 @@
|
|
10 |
"@ant-design/pro-components": "^2.6.46",
|
11 |
"@ant-design/pro-layout": "^7.17.16",
|
12 |
"@js-preview/excel": "^1.7.8",
|
|
|
13 |
"ahooks": "^3.7.10",
|
14 |
"antd": "^5.12.7",
|
15 |
"axios": "^1.6.3",
|
@@ -39,10 +40,12 @@
|
|
39 |
"umi": "^4.0.90",
|
40 |
"umi-request": "^1.4.0",
|
41 |
"unist-util-visit-parents": "^6.0.1",
|
42 |
-
"uuid": "^9.0.1"
|
|
|
43 |
},
|
44 |
"devDependencies": {
|
45 |
"@react-dev-inspector/umi4-plugin": "^2.0.1",
|
|
|
46 |
"@testing-library/jest-dom": "^6.4.5",
|
47 |
"@testing-library/react": "^15.0.7",
|
48 |
"@types/dagre": "^0.7.52",
|
@@ -3915,40 +3918,6 @@
|
|
3915 |
"react-dom": ">=17"
|
3916 |
}
|
3917 |
},
|
3918 |
-
"node_modules/@reactflow/background/node_modules/immer": {
|
3919 |
-
"version": "10.1.1",
|
3920 |
-
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
3921 |
-
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
3922 |
-
"optional": true,
|
3923 |
-
"peer": true
|
3924 |
-
},
|
3925 |
-
"node_modules/@reactflow/background/node_modules/zustand": {
|
3926 |
-
"version": "4.5.2",
|
3927 |
-
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.2.tgz",
|
3928 |
-
"integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==",
|
3929 |
-
"dependencies": {
|
3930 |
-
"use-sync-external-store": "1.2.0"
|
3931 |
-
},
|
3932 |
-
"engines": {
|
3933 |
-
"node": ">=12.7.0"
|
3934 |
-
},
|
3935 |
-
"peerDependencies": {
|
3936 |
-
"@types/react": ">=16.8",
|
3937 |
-
"immer": ">=9.0.6",
|
3938 |
-
"react": ">=16.8"
|
3939 |
-
},
|
3940 |
-
"peerDependenciesMeta": {
|
3941 |
-
"@types/react": {
|
3942 |
-
"optional": true
|
3943 |
-
},
|
3944 |
-
"immer": {
|
3945 |
-
"optional": true
|
3946 |
-
},
|
3947 |
-
"react": {
|
3948 |
-
"optional": true
|
3949 |
-
}
|
3950 |
-
}
|
3951 |
-
},
|
3952 |
"node_modules/@reactflow/controls": {
|
3953 |
"version": "11.2.12",
|
3954 |
"resolved": "https://registry.npmmirror.com/@reactflow/controls/-/controls-11.2.12.tgz",
|
@@ -3963,40 +3932,6 @@
|
|
3963 |
"react-dom": ">=17"
|
3964 |
}
|
3965 |
},
|
3966 |
-
"node_modules/@reactflow/controls/node_modules/immer": {
|
3967 |
-
"version": "10.1.1",
|
3968 |
-
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
3969 |
-
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
3970 |
-
"optional": true,
|
3971 |
-
"peer": true
|
3972 |
-
},
|
3973 |
-
"node_modules/@reactflow/controls/node_modules/zustand": {
|
3974 |
-
"version": "4.5.2",
|
3975 |
-
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.2.tgz",
|
3976 |
-
"integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==",
|
3977 |
-
"dependencies": {
|
3978 |
-
"use-sync-external-store": "1.2.0"
|
3979 |
-
},
|
3980 |
-
"engines": {
|
3981 |
-
"node": ">=12.7.0"
|
3982 |
-
},
|
3983 |
-
"peerDependencies": {
|
3984 |
-
"@types/react": ">=16.8",
|
3985 |
-
"immer": ">=9.0.6",
|
3986 |
-
"react": ">=16.8"
|
3987 |
-
},
|
3988 |
-
"peerDependenciesMeta": {
|
3989 |
-
"@types/react": {
|
3990 |
-
"optional": true
|
3991 |
-
},
|
3992 |
-
"immer": {
|
3993 |
-
"optional": true
|
3994 |
-
},
|
3995 |
-
"react": {
|
3996 |
-
"optional": true
|
3997 |
-
}
|
3998 |
-
}
|
3999 |
-
},
|
4000 |
"node_modules/@reactflow/core": {
|
4001 |
"version": "11.11.2",
|
4002 |
"resolved": "https://registry.npmmirror.com/@reactflow/core/-/core-11.11.2.tgz",
|
@@ -4017,40 +3952,6 @@
|
|
4017 |
"react-dom": ">=17"
|
4018 |
}
|
4019 |
},
|
4020 |
-
"node_modules/@reactflow/core/node_modules/immer": {
|
4021 |
-
"version": "10.1.1",
|
4022 |
-
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
4023 |
-
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
4024 |
-
"optional": true,
|
4025 |
-
"peer": true
|
4026 |
-
},
|
4027 |
-
"node_modules/@reactflow/core/node_modules/zustand": {
|
4028 |
-
"version": "4.5.2",
|
4029 |
-
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.2.tgz",
|
4030 |
-
"integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==",
|
4031 |
-
"dependencies": {
|
4032 |
-
"use-sync-external-store": "1.2.0"
|
4033 |
-
},
|
4034 |
-
"engines": {
|
4035 |
-
"node": ">=12.7.0"
|
4036 |
-
},
|
4037 |
-
"peerDependencies": {
|
4038 |
-
"@types/react": ">=16.8",
|
4039 |
-
"immer": ">=9.0.6",
|
4040 |
-
"react": ">=16.8"
|
4041 |
-
},
|
4042 |
-
"peerDependenciesMeta": {
|
4043 |
-
"@types/react": {
|
4044 |
-
"optional": true
|
4045 |
-
},
|
4046 |
-
"immer": {
|
4047 |
-
"optional": true
|
4048 |
-
},
|
4049 |
-
"react": {
|
4050 |
-
"optional": true
|
4051 |
-
}
|
4052 |
-
}
|
4053 |
-
},
|
4054 |
"node_modules/@reactflow/minimap": {
|
4055 |
"version": "11.7.12",
|
4056 |
"resolved": "https://registry.npmmirror.com/@reactflow/minimap/-/minimap-11.7.12.tgz",
|
@@ -4069,40 +3970,6 @@
|
|
4069 |
"react-dom": ">=17"
|
4070 |
}
|
4071 |
},
|
4072 |
-
"node_modules/@reactflow/minimap/node_modules/immer": {
|
4073 |
-
"version": "10.1.1",
|
4074 |
-
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
4075 |
-
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
4076 |
-
"optional": true,
|
4077 |
-
"peer": true
|
4078 |
-
},
|
4079 |
-
"node_modules/@reactflow/minimap/node_modules/zustand": {
|
4080 |
-
"version": "4.5.2",
|
4081 |
-
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.2.tgz",
|
4082 |
-
"integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==",
|
4083 |
-
"dependencies": {
|
4084 |
-
"use-sync-external-store": "1.2.0"
|
4085 |
-
},
|
4086 |
-
"engines": {
|
4087 |
-
"node": ">=12.7.0"
|
4088 |
-
},
|
4089 |
-
"peerDependencies": {
|
4090 |
-
"@types/react": ">=16.8",
|
4091 |
-
"immer": ">=9.0.6",
|
4092 |
-
"react": ">=16.8"
|
4093 |
-
},
|
4094 |
-
"peerDependenciesMeta": {
|
4095 |
-
"@types/react": {
|
4096 |
-
"optional": true
|
4097 |
-
},
|
4098 |
-
"immer": {
|
4099 |
-
"optional": true
|
4100 |
-
},
|
4101 |
-
"react": {
|
4102 |
-
"optional": true
|
4103 |
-
}
|
4104 |
-
}
|
4105 |
-
},
|
4106 |
"node_modules/@reactflow/node-resizer": {
|
4107 |
"version": "2.2.12",
|
4108 |
"resolved": "https://registry.npmmirror.com/@reactflow/node-resizer/-/node-resizer-2.2.12.tgz",
|
@@ -4119,40 +3986,6 @@
|
|
4119 |
"react-dom": ">=17"
|
4120 |
}
|
4121 |
},
|
4122 |
-
"node_modules/@reactflow/node-resizer/node_modules/immer": {
|
4123 |
-
"version": "10.1.1",
|
4124 |
-
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
4125 |
-
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
4126 |
-
"optional": true,
|
4127 |
-
"peer": true
|
4128 |
-
},
|
4129 |
-
"node_modules/@reactflow/node-resizer/node_modules/zustand": {
|
4130 |
-
"version": "4.5.2",
|
4131 |
-
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.2.tgz",
|
4132 |
-
"integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==",
|
4133 |
-
"dependencies": {
|
4134 |
-
"use-sync-external-store": "1.2.0"
|
4135 |
-
},
|
4136 |
-
"engines": {
|
4137 |
-
"node": ">=12.7.0"
|
4138 |
-
},
|
4139 |
-
"peerDependencies": {
|
4140 |
-
"@types/react": ">=16.8",
|
4141 |
-
"immer": ">=9.0.6",
|
4142 |
-
"react": ">=16.8"
|
4143 |
-
},
|
4144 |
-
"peerDependenciesMeta": {
|
4145 |
-
"@types/react": {
|
4146 |
-
"optional": true
|
4147 |
-
},
|
4148 |
-
"immer": {
|
4149 |
-
"optional": true
|
4150 |
-
},
|
4151 |
-
"react": {
|
4152 |
-
"optional": true
|
4153 |
-
}
|
4154 |
-
}
|
4155 |
-
},
|
4156 |
"node_modules/@reactflow/node-toolbar": {
|
4157 |
"version": "1.3.12",
|
4158 |
"resolved": "https://registry.npmmirror.com/@reactflow/node-toolbar/-/node-toolbar-1.3.12.tgz",
|
@@ -4167,38 +4000,17 @@
|
|
4167 |
"react-dom": ">=17"
|
4168 |
}
|
4169 |
},
|
4170 |
-
"node_modules/@
|
4171 |
-
"version": "
|
4172 |
-
"resolved": "https://registry.npmmirror.com/
|
4173 |
-
"integrity": "sha512-
|
4174 |
-
"
|
4175 |
-
"peer": true
|
4176 |
-
},
|
4177 |
-
"node_modules/@reactflow/node-toolbar/node_modules/zustand": {
|
4178 |
-
"version": "4.5.2",
|
4179 |
-
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.2.tgz",
|
4180 |
-
"integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==",
|
4181 |
"dependencies": {
|
4182 |
-
"
|
4183 |
-
|
4184 |
-
"engines": {
|
4185 |
-
"node": ">=12.7.0"
|
4186 |
},
|
4187 |
"peerDependencies": {
|
4188 |
-
"
|
4189 |
-
"immer": ">=9.0.6",
|
4190 |
-
"react": ">=16.8"
|
4191 |
-
},
|
4192 |
-
"peerDependenciesMeta": {
|
4193 |
-
"@types/react": {
|
4194 |
-
"optional": true
|
4195 |
-
},
|
4196 |
-
"immer": {
|
4197 |
-
"optional": true
|
4198 |
-
},
|
4199 |
-
"react": {
|
4200 |
-
"optional": true
|
4201 |
-
}
|
4202 |
}
|
4203 |
},
|
4204 |
"node_modules/@rgrove/parse-xml": {
|
@@ -4441,6 +4253,30 @@
|
|
4441 |
"integrity": "sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==",
|
4442 |
"dev": true
|
4443 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4444 |
"node_modules/@testing-library/dom": {
|
4445 |
"version": "10.1.0",
|
4446 |
"resolved": "https://registry.npmmirror.com/@testing-library/dom/-/dom-10.1.0.tgz",
|
@@ -6692,6 +6528,16 @@
|
|
6692 |
"value-equal": "^1.0.1"
|
6693 |
}
|
6694 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6695 |
"node_modules/@umijs/plugins/node_modules/isarray": {
|
6696 |
"version": "0.0.1",
|
6697 |
"resolved": "https://registry.npmmirror.com/isarray/-/isarray-0.0.1.tgz",
|
@@ -13621,9 +13467,20 @@
|
|
13621 |
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
13622 |
},
|
13623 |
"node_modules/immer": {
|
13624 |
-
"version": "
|
13625 |
-
"resolved": "https://registry.npmmirror.com/immer/-/immer-
|
13626 |
-
"integrity": "sha512-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13627 |
"dev": true
|
13628 |
},
|
13629 |
"node_modules/import-fresh": {
|
@@ -26064,6 +25921,33 @@
|
|
26064 |
"node": ">=10"
|
26065 |
}
|
26066 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26067 |
"node_modules/zwitch": {
|
26068 |
"version": "2.0.4",
|
26069 |
"resolved": "https://registry.npmmirror.com/zwitch/-/zwitch-2.0.4.tgz",
|
|
|
10 |
"@ant-design/pro-components": "^2.6.46",
|
11 |
"@ant-design/pro-layout": "^7.17.16",
|
12 |
"@js-preview/excel": "^1.7.8",
|
13 |
+
"@tanstack/react-query": "^5.40.0",
|
14 |
"ahooks": "^3.7.10",
|
15 |
"antd": "^5.12.7",
|
16 |
"axios": "^1.6.3",
|
|
|
40 |
"umi": "^4.0.90",
|
41 |
"umi-request": "^1.4.0",
|
42 |
"unist-util-visit-parents": "^6.0.1",
|
43 |
+
"uuid": "^9.0.1",
|
44 |
+
"zustand": "^4.5.2"
|
45 |
},
|
46 |
"devDependencies": {
|
47 |
"@react-dev-inspector/umi4-plugin": "^2.0.1",
|
48 |
+
"@redux-devtools/extension": "^3.3.0",
|
49 |
"@testing-library/jest-dom": "^6.4.5",
|
50 |
"@testing-library/react": "^15.0.7",
|
51 |
"@types/dagre": "^0.7.52",
|
|
|
3918 |
"react-dom": ">=17"
|
3919 |
}
|
3920 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3921 |
"node_modules/@reactflow/controls": {
|
3922 |
"version": "11.2.12",
|
3923 |
"resolved": "https://registry.npmmirror.com/@reactflow/controls/-/controls-11.2.12.tgz",
|
|
|
3932 |
"react-dom": ">=17"
|
3933 |
}
|
3934 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3935 |
"node_modules/@reactflow/core": {
|
3936 |
"version": "11.11.2",
|
3937 |
"resolved": "https://registry.npmmirror.com/@reactflow/core/-/core-11.11.2.tgz",
|
|
|
3952 |
"react-dom": ">=17"
|
3953 |
}
|
3954 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3955 |
"node_modules/@reactflow/minimap": {
|
3956 |
"version": "11.7.12",
|
3957 |
"resolved": "https://registry.npmmirror.com/@reactflow/minimap/-/minimap-11.7.12.tgz",
|
|
|
3970 |
"react-dom": ">=17"
|
3971 |
}
|
3972 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3973 |
"node_modules/@reactflow/node-resizer": {
|
3974 |
"version": "2.2.12",
|
3975 |
"resolved": "https://registry.npmmirror.com/@reactflow/node-resizer/-/node-resizer-2.2.12.tgz",
|
|
|
3986 |
"react-dom": ">=17"
|
3987 |
}
|
3988 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3989 |
"node_modules/@reactflow/node-toolbar": {
|
3990 |
"version": "1.3.12",
|
3991 |
"resolved": "https://registry.npmmirror.com/@reactflow/node-toolbar/-/node-toolbar-1.3.12.tgz",
|
|
|
4000 |
"react-dom": ">=17"
|
4001 |
}
|
4002 |
},
|
4003 |
+
"node_modules/@redux-devtools/extension": {
|
4004 |
+
"version": "3.3.0",
|
4005 |
+
"resolved": "https://registry.npmmirror.com/@redux-devtools/extension/-/extension-3.3.0.tgz",
|
4006 |
+
"integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==",
|
4007 |
+
"dev": true,
|
|
|
|
|
|
|
|
|
|
|
|
|
4008 |
"dependencies": {
|
4009 |
+
"@babel/runtime": "^7.23.2",
|
4010 |
+
"immutable": "^4.3.4"
|
|
|
|
|
4011 |
},
|
4012 |
"peerDependencies": {
|
4013 |
+
"redux": "^3.1.0 || ^4.0.0 || ^5.0.0"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4014 |
}
|
4015 |
},
|
4016 |
"node_modules/@rgrove/parse-xml": {
|
|
|
4253 |
"integrity": "sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==",
|
4254 |
"dev": true
|
4255 |
},
|
4256 |
+
"node_modules/@tanstack/react-query": {
|
4257 |
+
"version": "5.40.0",
|
4258 |
+
"resolved": "https://registry.npmmirror.com/@tanstack/react-query/-/react-query-5.40.0.tgz",
|
4259 |
+
"integrity": "sha512-iv/W0Axc4aXhFzkrByToE1JQqayxTPNotCoSCnarR/A1vDIHaoKpg7FTIfP3Ev2mbKn1yrxq0ZKYUdLEJxs6Tg==",
|
4260 |
+
"dependencies": {
|
4261 |
+
"@tanstack/query-core": "5.40.0"
|
4262 |
+
},
|
4263 |
+
"funding": {
|
4264 |
+
"type": "github",
|
4265 |
+
"url": "https://github.com/sponsors/tannerlinsley"
|
4266 |
+
},
|
4267 |
+
"peerDependencies": {
|
4268 |
+
"react": "^18.0.0"
|
4269 |
+
}
|
4270 |
+
},
|
4271 |
+
"node_modules/@tanstack/react-query/node_modules/@tanstack/query-core": {
|
4272 |
+
"version": "5.40.0",
|
4273 |
+
"resolved": "https://registry.npmmirror.com/@tanstack/query-core/-/query-core-5.40.0.tgz",
|
4274 |
+
"integrity": "sha512-eD8K8jsOIq0Z5u/QbvOmfvKKE/XC39jA7yv4hgpl/1SRiU+J8QCIwgM/mEHuunQsL87dcvnHqSVLmf9pD4CiaA==",
|
4275 |
+
"funding": {
|
4276 |
+
"type": "github",
|
4277 |
+
"url": "https://github.com/sponsors/tannerlinsley"
|
4278 |
+
}
|
4279 |
+
},
|
4280 |
"node_modules/@testing-library/dom": {
|
4281 |
"version": "10.1.0",
|
4282 |
"resolved": "https://registry.npmmirror.com/@testing-library/dom/-/dom-10.1.0.tgz",
|
|
|
6528 |
"value-equal": "^1.0.1"
|
6529 |
}
|
6530 |
},
|
6531 |
+
"node_modules/@umijs/plugins/node_modules/immer": {
|
6532 |
+
"version": "8.0.4",
|
6533 |
+
"resolved": "https://registry.npmmirror.com/immer/-/immer-8.0.4.tgz",
|
6534 |
+
"integrity": "sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ==",
|
6535 |
+
"dev": true,
|
6536 |
+
"funding": {
|
6537 |
+
"type": "opencollective",
|
6538 |
+
"url": "https://opencollective.com/immer"
|
6539 |
+
}
|
6540 |
+
},
|
6541 |
"node_modules/@umijs/plugins/node_modules/isarray": {
|
6542 |
"version": "0.0.1",
|
6543 |
"resolved": "https://registry.npmmirror.com/isarray/-/isarray-0.0.1.tgz",
|
|
|
13467 |
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
13468 |
},
|
13469 |
"node_modules/immer": {
|
13470 |
+
"version": "10.1.1",
|
13471 |
+
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
13472 |
+
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
13473 |
+
"optional": true,
|
13474 |
+
"peer": true,
|
13475 |
+
"funding": {
|
13476 |
+
"type": "opencollective",
|
13477 |
+
"url": "https://opencollective.com/immer"
|
13478 |
+
}
|
13479 |
+
},
|
13480 |
+
"node_modules/immutable": {
|
13481 |
+
"version": "4.3.6",
|
13482 |
+
"resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.6.tgz",
|
13483 |
+
"integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==",
|
13484 |
"dev": true
|
13485 |
},
|
13486 |
"node_modules/import-fresh": {
|
|
|
25921 |
"node": ">=10"
|
25922 |
}
|
25923 |
},
|
25924 |
+
"node_modules/zustand": {
|
25925 |
+
"version": "4.5.2",
|
25926 |
+
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.2.tgz",
|
25927 |
+
"integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==",
|
25928 |
+
"dependencies": {
|
25929 |
+
"use-sync-external-store": "1.2.0"
|
25930 |
+
},
|
25931 |
+
"engines": {
|
25932 |
+
"node": ">=12.7.0"
|
25933 |
+
},
|
25934 |
+
"peerDependencies": {
|
25935 |
+
"@types/react": ">=16.8",
|
25936 |
+
"immer": ">=9.0.6",
|
25937 |
+
"react": ">=16.8"
|
25938 |
+
},
|
25939 |
+
"peerDependenciesMeta": {
|
25940 |
+
"@types/react": {
|
25941 |
+
"optional": true
|
25942 |
+
},
|
25943 |
+
"immer": {
|
25944 |
+
"optional": true
|
25945 |
+
},
|
25946 |
+
"react": {
|
25947 |
+
"optional": true
|
25948 |
+
}
|
25949 |
+
}
|
25950 |
+
},
|
25951 |
"node_modules/zwitch": {
|
25952 |
"version": "2.0.4",
|
25953 |
"resolved": "https://registry.npmmirror.com/zwitch/-/zwitch-2.0.4.tgz",
|
web/package.json
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
"@ant-design/pro-components": "^2.6.46",
|
16 |
"@ant-design/pro-layout": "^7.17.16",
|
17 |
"@js-preview/excel": "^1.7.8",
|
|
|
18 |
"ahooks": "^3.7.10",
|
19 |
"antd": "^5.12.7",
|
20 |
"axios": "^1.6.3",
|
@@ -44,10 +45,12 @@
|
|
44 |
"umi": "^4.0.90",
|
45 |
"umi-request": "^1.4.0",
|
46 |
"unist-util-visit-parents": "^6.0.1",
|
47 |
-
"uuid": "^9.0.1"
|
|
|
48 |
},
|
49 |
"devDependencies": {
|
50 |
"@react-dev-inspector/umi4-plugin": "^2.0.1",
|
|
|
51 |
"@testing-library/jest-dom": "^6.4.5",
|
52 |
"@testing-library/react": "^15.0.7",
|
53 |
"@types/dagre": "^0.7.52",
|
|
|
15 |
"@ant-design/pro-components": "^2.6.46",
|
16 |
"@ant-design/pro-layout": "^7.17.16",
|
17 |
"@js-preview/excel": "^1.7.8",
|
18 |
+
"@tanstack/react-query": "^5.40.0",
|
19 |
"ahooks": "^3.7.10",
|
20 |
"antd": "^5.12.7",
|
21 |
"axios": "^1.6.3",
|
|
|
45 |
"umi": "^4.0.90",
|
46 |
"umi-request": "^1.4.0",
|
47 |
"unist-util-visit-parents": "^6.0.1",
|
48 |
+
"uuid": "^9.0.1",
|
49 |
+
"zustand": "^4.5.2"
|
50 |
},
|
51 |
"devDependencies": {
|
52 |
"@react-dev-inspector/umi4-plugin": "^2.0.1",
|
53 |
+
"@redux-devtools/extension": "^3.3.0",
|
54 |
"@testing-library/jest-dom": "^6.4.5",
|
55 |
"@testing-library/react": "^15.0.7",
|
56 |
"@types/dagre": "^0.7.52",
|
web/src/app.tsx
CHANGED
@@ -6,13 +6,14 @@ import zh_HK from 'antd/locale/zh_HK';
|
|
6 |
import React, { ReactNode, useEffect, useState } from 'react';
|
7 |
import storage from './utils/authorizationUtil';
|
8 |
|
|
|
9 |
import dayjs from 'dayjs';
|
10 |
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
11 |
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
12 |
import localeData from 'dayjs/plugin/localeData';
|
13 |
-
import weekday from 'dayjs/plugin/weekday';
|
14 |
import weekOfYear from 'dayjs/plugin/weekOfYear';
|
15 |
import weekYear from 'dayjs/plugin/weekYear';
|
|
|
16 |
|
17 |
dayjs.extend(customParseFormat);
|
18 |
dayjs.extend(advancedFormat);
|
@@ -27,6 +28,8 @@ const AntLanguageMap = {
|
|
27 |
'zh-TRADITIONAL': zh_HK,
|
28 |
};
|
29 |
|
|
|
|
|
30 |
type Locale = ConfigProviderProps['locale'];
|
31 |
|
32 |
const RootProvider = ({ children }: React.PropsWithChildren) => {
|
@@ -49,16 +52,18 @@ const RootProvider = ({ children }: React.PropsWithChildren) => {
|
|
49 |
}, []);
|
50 |
|
51 |
return (
|
52 |
-
<
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
|
|
|
|
62 |
);
|
63 |
};
|
64 |
|
|
|
6 |
import React, { ReactNode, useEffect, useState } from 'react';
|
7 |
import storage from './utils/authorizationUtil';
|
8 |
|
9 |
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
10 |
import dayjs from 'dayjs';
|
11 |
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
12 |
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
13 |
import localeData from 'dayjs/plugin/localeData';
|
|
|
14 |
import weekOfYear from 'dayjs/plugin/weekOfYear';
|
15 |
import weekYear from 'dayjs/plugin/weekYear';
|
16 |
+
import weekday from 'dayjs/plugin/weekday';
|
17 |
|
18 |
dayjs.extend(customParseFormat);
|
19 |
dayjs.extend(advancedFormat);
|
|
|
28 |
'zh-TRADITIONAL': zh_HK,
|
29 |
};
|
30 |
|
31 |
+
const queryClient = new QueryClient();
|
32 |
+
|
33 |
type Locale = ConfigProviderProps['locale'];
|
34 |
|
35 |
const RootProvider = ({ children }: React.PropsWithChildren) => {
|
|
|
52 |
}, []);
|
53 |
|
54 |
return (
|
55 |
+
<QueryClientProvider client={queryClient}>
|
56 |
+
<ConfigProvider
|
57 |
+
theme={{
|
58 |
+
token: {
|
59 |
+
fontFamily: 'Inter',
|
60 |
+
},
|
61 |
+
}}
|
62 |
+
locale={locale}
|
63 |
+
>
|
64 |
+
<App> {children}</App>
|
65 |
+
</ConfigProvider>
|
66 |
+
</QueryClientProvider>
|
67 |
);
|
68 |
};
|
69 |
|
web/src/components/knowledge-base-item.tsx
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useTranslate } from '@/hooks/commonHooks';
|
2 |
+
import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
|
3 |
+
import { Form, Select } from 'antd';
|
4 |
+
|
5 |
+
const KnowledgeBaseItem = () => {
|
6 |
+
const { t } = useTranslate('chat');
|
7 |
+
|
8 |
+
const { list: knowledgeList } = useFetchKnowledgeList(true);
|
9 |
+
|
10 |
+
const knowledgeOptions = knowledgeList.map((x) => ({
|
11 |
+
label: x.name,
|
12 |
+
value: x.id,
|
13 |
+
}));
|
14 |
+
|
15 |
+
return (
|
16 |
+
<Form.Item
|
17 |
+
label={t('knowledgeBases')}
|
18 |
+
name="kb_ids"
|
19 |
+
tooltip={t('knowledgeBasesTip')}
|
20 |
+
rules={[
|
21 |
+
{
|
22 |
+
required: true,
|
23 |
+
message: t('knowledgeBasesMessage'),
|
24 |
+
type: 'array',
|
25 |
+
},
|
26 |
+
]}
|
27 |
+
>
|
28 |
+
<Select
|
29 |
+
mode="multiple"
|
30 |
+
options={knowledgeOptions}
|
31 |
+
placeholder={t('knowledgeBasesMessage')}
|
32 |
+
></Select>
|
33 |
+
</Form.Item>
|
34 |
+
);
|
35 |
+
};
|
36 |
+
|
37 |
+
export default KnowledgeBaseItem;
|
web/src/components/llm-setting-items/index.less
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.sliderInputNumber {
|
2 |
+
width: 80px;
|
3 |
+
}
|
4 |
+
.variableSlider {
|
5 |
+
width: 100%;
|
6 |
+
}
|
web/src/components/llm-setting-items/index.tsx
ADDED
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { LlmModelType, ModelVariableType } from '@/constants/knowledge';
|
2 |
+
import { Divider, Flex, Form, InputNumber, Select, Slider, Switch } from 'antd';
|
3 |
+
import camelCase from 'lodash/camelCase';
|
4 |
+
|
5 |
+
import { useTranslate } from '@/hooks/commonHooks';
|
6 |
+
import { useSelectLlmOptionsByModelType } from '@/hooks/llmHooks';
|
7 |
+
import { useMemo } from 'react';
|
8 |
+
import styles from './index.less';
|
9 |
+
|
10 |
+
interface IProps {
|
11 |
+
prefix?: string;
|
12 |
+
handleParametersChange(value: ModelVariableType): void;
|
13 |
+
}
|
14 |
+
|
15 |
+
const LlmSettingItems = ({ prefix, handleParametersChange }: IProps) => {
|
16 |
+
const { t } = useTranslate('chat');
|
17 |
+
const parameterOptions = Object.values(ModelVariableType).map((x) => ({
|
18 |
+
label: t(camelCase(x)),
|
19 |
+
value: x,
|
20 |
+
}));
|
21 |
+
|
22 |
+
const memorizedPrefix = useMemo(() => (prefix ? [prefix] : []), [prefix]);
|
23 |
+
|
24 |
+
const modelOptions = useSelectLlmOptionsByModelType();
|
25 |
+
|
26 |
+
return (
|
27 |
+
<>
|
28 |
+
<Form.Item
|
29 |
+
label={t('model')}
|
30 |
+
name="llm_id"
|
31 |
+
tooltip={t('modelTip')}
|
32 |
+
rules={[{ required: true, message: t('modelMessage') }]}
|
33 |
+
>
|
34 |
+
<Select options={modelOptions[LlmModelType.Chat]} showSearch />
|
35 |
+
</Form.Item>
|
36 |
+
<Divider></Divider>
|
37 |
+
<Form.Item
|
38 |
+
label={t('freedom')}
|
39 |
+
name="parameters"
|
40 |
+
tooltip={t('freedomTip')}
|
41 |
+
initialValue={ModelVariableType.Precise}
|
42 |
+
>
|
43 |
+
<Select<ModelVariableType>
|
44 |
+
options={parameterOptions}
|
45 |
+
onChange={handleParametersChange}
|
46 |
+
/>
|
47 |
+
</Form.Item>
|
48 |
+
<Form.Item label={t('temperature')} tooltip={t('temperatureTip')}>
|
49 |
+
<Flex gap={20} align="center">
|
50 |
+
<Form.Item
|
51 |
+
name={'temperatureEnabled'}
|
52 |
+
valuePropName="checked"
|
53 |
+
noStyle
|
54 |
+
>
|
55 |
+
<Switch size="small" />
|
56 |
+
</Form.Item>
|
57 |
+
<Form.Item noStyle dependencies={['temperatureEnabled']}>
|
58 |
+
{({ getFieldValue }) => {
|
59 |
+
const disabled = !getFieldValue('temperatureEnabled');
|
60 |
+
return (
|
61 |
+
<>
|
62 |
+
<Flex flex={1}>
|
63 |
+
<Form.Item
|
64 |
+
name={[...memorizedPrefix, 'temperature']}
|
65 |
+
noStyle
|
66 |
+
>
|
67 |
+
<Slider
|
68 |
+
className={styles.variableSlider}
|
69 |
+
max={1}
|
70 |
+
step={0.01}
|
71 |
+
disabled={disabled}
|
72 |
+
/>
|
73 |
+
</Form.Item>
|
74 |
+
</Flex>
|
75 |
+
<Form.Item name={[...memorizedPrefix, 'temperature']} noStyle>
|
76 |
+
<InputNumber
|
77 |
+
className={styles.sliderInputNumber}
|
78 |
+
max={1}
|
79 |
+
min={0}
|
80 |
+
step={0.01}
|
81 |
+
disabled={disabled}
|
82 |
+
/>
|
83 |
+
</Form.Item>
|
84 |
+
</>
|
85 |
+
);
|
86 |
+
}}
|
87 |
+
</Form.Item>
|
88 |
+
</Flex>
|
89 |
+
</Form.Item>
|
90 |
+
<Form.Item label={t('topP')} tooltip={t('topPTip')}>
|
91 |
+
<Flex gap={20} align="center">
|
92 |
+
<Form.Item name={'topPEnabled'} valuePropName="checked" noStyle>
|
93 |
+
<Switch size="small" />
|
94 |
+
</Form.Item>
|
95 |
+
<Form.Item noStyle dependencies={['topPEnabled']}>
|
96 |
+
{({ getFieldValue }) => {
|
97 |
+
const disabled = !getFieldValue('topPEnabled');
|
98 |
+
return (
|
99 |
+
<>
|
100 |
+
<Flex flex={1}>
|
101 |
+
<Form.Item name={[...memorizedPrefix, 'top_p']} noStyle>
|
102 |
+
<Slider
|
103 |
+
className={styles.variableSlider}
|
104 |
+
max={1}
|
105 |
+
step={0.01}
|
106 |
+
disabled={disabled}
|
107 |
+
/>
|
108 |
+
</Form.Item>
|
109 |
+
</Flex>
|
110 |
+
<Form.Item name={[...memorizedPrefix, 'top_p']} noStyle>
|
111 |
+
<InputNumber
|
112 |
+
className={styles.sliderInputNumber}
|
113 |
+
max={1}
|
114 |
+
min={0}
|
115 |
+
step={0.01}
|
116 |
+
disabled={disabled}
|
117 |
+
/>
|
118 |
+
</Form.Item>
|
119 |
+
</>
|
120 |
+
);
|
121 |
+
}}
|
122 |
+
</Form.Item>
|
123 |
+
</Flex>
|
124 |
+
</Form.Item>
|
125 |
+
<Form.Item label={t('presencePenalty')} tooltip={t('presencePenaltyTip')}>
|
126 |
+
<Flex gap={20} align="center">
|
127 |
+
<Form.Item
|
128 |
+
name={'presencePenaltyEnabled'}
|
129 |
+
valuePropName="checked"
|
130 |
+
noStyle
|
131 |
+
>
|
132 |
+
<Switch size="small" />
|
133 |
+
</Form.Item>
|
134 |
+
<Form.Item noStyle dependencies={['presencePenaltyEnabled']}>
|
135 |
+
{({ getFieldValue }) => {
|
136 |
+
const disabled = !getFieldValue('presencePenaltyEnabled');
|
137 |
+
return (
|
138 |
+
<>
|
139 |
+
<Flex flex={1}>
|
140 |
+
<Form.Item
|
141 |
+
name={[...memorizedPrefix, 'presence_penalty']}
|
142 |
+
noStyle
|
143 |
+
>
|
144 |
+
<Slider
|
145 |
+
className={styles.variableSlider}
|
146 |
+
max={1}
|
147 |
+
step={0.01}
|
148 |
+
disabled={disabled}
|
149 |
+
/>
|
150 |
+
</Form.Item>
|
151 |
+
</Flex>
|
152 |
+
<Form.Item
|
153 |
+
name={[...memorizedPrefix, 'presence_penalty']}
|
154 |
+
noStyle
|
155 |
+
>
|
156 |
+
<InputNumber
|
157 |
+
className={styles.sliderInputNumber}
|
158 |
+
max={1}
|
159 |
+
min={0}
|
160 |
+
step={0.01}
|
161 |
+
disabled={disabled}
|
162 |
+
/>
|
163 |
+
</Form.Item>
|
164 |
+
</>
|
165 |
+
);
|
166 |
+
}}
|
167 |
+
</Form.Item>
|
168 |
+
</Flex>
|
169 |
+
</Form.Item>
|
170 |
+
<Form.Item
|
171 |
+
label={t('frequencyPenalty')}
|
172 |
+
tooltip={t('frequencyPenaltyTip')}
|
173 |
+
>
|
174 |
+
<Flex gap={20} align="center">
|
175 |
+
<Form.Item
|
176 |
+
name={'frequencyPenaltyEnabled'}
|
177 |
+
valuePropName="checked"
|
178 |
+
noStyle
|
179 |
+
>
|
180 |
+
<Switch size="small" />
|
181 |
+
</Form.Item>
|
182 |
+
<Form.Item noStyle dependencies={['frequencyPenaltyEnabled']}>
|
183 |
+
{({ getFieldValue }) => {
|
184 |
+
const disabled = !getFieldValue('frequencyPenaltyEnabled');
|
185 |
+
return (
|
186 |
+
<>
|
187 |
+
<Flex flex={1}>
|
188 |
+
<Form.Item
|
189 |
+
name={[...memorizedPrefix, 'frequency_penalty']}
|
190 |
+
noStyle
|
191 |
+
>
|
192 |
+
<Slider
|
193 |
+
className={styles.variableSlider}
|
194 |
+
max={1}
|
195 |
+
step={0.01}
|
196 |
+
disabled={disabled}
|
197 |
+
/>
|
198 |
+
</Form.Item>
|
199 |
+
</Flex>
|
200 |
+
<Form.Item
|
201 |
+
name={[...memorizedPrefix, 'frequency_penalty']}
|
202 |
+
noStyle
|
203 |
+
>
|
204 |
+
<InputNumber
|
205 |
+
className={styles.sliderInputNumber}
|
206 |
+
max={1}
|
207 |
+
min={0}
|
208 |
+
step={0.01}
|
209 |
+
disabled={disabled}
|
210 |
+
/>
|
211 |
+
</Form.Item>
|
212 |
+
</>
|
213 |
+
);
|
214 |
+
}}
|
215 |
+
</Form.Item>
|
216 |
+
</Flex>
|
217 |
+
</Form.Item>
|
218 |
+
<Form.Item label={t('maxTokens')} tooltip={t('maxTokensTip')}>
|
219 |
+
<Flex gap={20} align="center">
|
220 |
+
<Form.Item name={'maxTokensEnabled'} valuePropName="checked" noStyle>
|
221 |
+
<Switch size="small" />
|
222 |
+
</Form.Item>
|
223 |
+
<Form.Item noStyle dependencies={['maxTokensEnabled']}>
|
224 |
+
{({ getFieldValue }) => {
|
225 |
+
const disabled = !getFieldValue('maxTokensEnabled');
|
226 |
+
|
227 |
+
return (
|
228 |
+
<>
|
229 |
+
<Flex flex={1}>
|
230 |
+
<Form.Item
|
231 |
+
name={[...memorizedPrefix, 'max_tokens']}
|
232 |
+
noStyle
|
233 |
+
>
|
234 |
+
<Slider
|
235 |
+
className={styles.variableSlider}
|
236 |
+
max={2048}
|
237 |
+
disabled={disabled}
|
238 |
+
/>
|
239 |
+
</Form.Item>
|
240 |
+
</Flex>
|
241 |
+
<Form.Item name={[...memorizedPrefix, 'max_tokens']} noStyle>
|
242 |
+
<InputNumber
|
243 |
+
disabled={disabled}
|
244 |
+
className={styles.sliderInputNumber}
|
245 |
+
max={2048}
|
246 |
+
min={0}
|
247 |
+
/>
|
248 |
+
</Form.Item>
|
249 |
+
</>
|
250 |
+
);
|
251 |
+
}}
|
252 |
+
</Form.Item>
|
253 |
+
</Flex>
|
254 |
+
</Form.Item>
|
255 |
+
</>
|
256 |
+
);
|
257 |
+
};
|
258 |
+
|
259 |
+
export default LlmSettingItems;
|
web/src/components/top-n-item.tsx
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useTranslate } from '@/hooks/commonHooks';
|
2 |
+
import { Form, Slider } from 'antd';
|
3 |
+
|
4 |
+
type FieldType = {
|
5 |
+
top_n?: number;
|
6 |
+
};
|
7 |
+
|
8 |
+
const TopNItem = () => {
|
9 |
+
const { t } = useTranslate('chat');
|
10 |
+
|
11 |
+
return (
|
12 |
+
<Form.Item<FieldType>
|
13 |
+
label={t('topN')}
|
14 |
+
name={'top_n'}
|
15 |
+
initialValue={8}
|
16 |
+
tooltip={t('topNTip')}
|
17 |
+
>
|
18 |
+
<Slider max={30} />
|
19 |
+
</Form.Item>
|
20 |
+
);
|
21 |
+
};
|
22 |
+
|
23 |
+
export default TopNItem;
|
web/src/hooks/flow-hooks.ts
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import flowService from '@/services/flow-service';
|
2 |
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
3 |
+
|
4 |
+
export const useFetchFlowTemplates = () => {
|
5 |
+
const { data } = useQuery({
|
6 |
+
queryKey: ['fetchFlowTemplates'],
|
7 |
+
initialData: [],
|
8 |
+
queryFn: async () => {
|
9 |
+
const { data } = await flowService.listTemplates();
|
10 |
+
|
11 |
+
return data;
|
12 |
+
},
|
13 |
+
});
|
14 |
+
|
15 |
+
return data;
|
16 |
+
};
|
17 |
+
|
18 |
+
export const useFetchFlowList = () => {
|
19 |
+
const { data, isFetching: loading } = useQuery({
|
20 |
+
queryKey: ['fetchFlowList'],
|
21 |
+
initialData: [],
|
22 |
+
queryFn: async () => {
|
23 |
+
const { data } = await flowService.listCanvas();
|
24 |
+
|
25 |
+
return data?.data ?? [];
|
26 |
+
},
|
27 |
+
});
|
28 |
+
|
29 |
+
return { data, loading };
|
30 |
+
};
|
31 |
+
|
32 |
+
export const useSetFlow = () => {
|
33 |
+
const queryClient = useQueryClient();
|
34 |
+
const {
|
35 |
+
data,
|
36 |
+
isPending: loading,
|
37 |
+
mutateAsync,
|
38 |
+
} = useMutation({
|
39 |
+
mutationKey: ['setFlow'],
|
40 |
+
mutationFn: async (params: any) => {
|
41 |
+
const { data } = await flowService.setCanvas(params);
|
42 |
+
if (data.retcode === 0) {
|
43 |
+
queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] });
|
44 |
+
}
|
45 |
+
return data?.retcode;
|
46 |
+
},
|
47 |
+
});
|
48 |
+
|
49 |
+
return { data, loading, setFlow: mutateAsync };
|
50 |
+
};
|
51 |
+
|
52 |
+
export const useDeleteFlow = () => {
|
53 |
+
const queryClient = useQueryClient();
|
54 |
+
const {
|
55 |
+
data,
|
56 |
+
isPending: loading,
|
57 |
+
mutateAsync,
|
58 |
+
} = useMutation({
|
59 |
+
mutationKey: ['deleteFlow'],
|
60 |
+
mutationFn: async (canvasIds: string[]) => {
|
61 |
+
const { data } = await flowService.removeCanvas({ canvasIds });
|
62 |
+
if (data.retcode === 0) {
|
63 |
+
queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] });
|
64 |
+
}
|
65 |
+
return data?.data ?? [];
|
66 |
+
},
|
67 |
+
});
|
68 |
+
|
69 |
+
return { data, loading, deleteFlow: mutateAsync };
|
70 |
+
};
|
web/src/hooks/userSettingHook.ts
CHANGED
@@ -99,10 +99,14 @@ export const useFetchSystemVersion = () => {
|
|
99 |
const [loading, setLoading] = useState(false);
|
100 |
|
101 |
const fetchSystemVersion = useCallback(async () => {
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
|
|
|
|
|
|
|
|
106 |
setLoading(false);
|
107 |
}
|
108 |
}, []);
|
|
|
99 |
const [loading, setLoading] = useState(false);
|
100 |
|
101 |
const fetchSystemVersion = useCallback(async () => {
|
102 |
+
try {
|
103 |
+
setLoading(true);
|
104 |
+
const { data } = await userService.getSystemVersion();
|
105 |
+
if (data.retcode === 0) {
|
106 |
+
setVersion(data.data);
|
107 |
+
setLoading(false);
|
108 |
+
}
|
109 |
+
} catch (error) {
|
110 |
setLoading(false);
|
111 |
}
|
112 |
}, []);
|
web/src/interfaces/database/flow.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
export type DSLComponents = Record<string,
|
2 |
|
3 |
export interface DSL {
|
4 |
components: DSLComponents;
|
@@ -7,13 +7,13 @@ export interface DSL {
|
|
7 |
answer: any[];
|
8 |
}
|
9 |
|
10 |
-
export interface
|
11 |
-
obj:
|
12 |
downstream: string[];
|
13 |
upstream: string[];
|
14 |
}
|
15 |
|
16 |
-
export interface
|
17 |
component_name: string;
|
18 |
params: Record<string, unknown>;
|
19 |
}
|
|
|
1 |
+
export type DSLComponents = Record<string, IOperator>;
|
2 |
|
3 |
export interface DSL {
|
4 |
components: DSLComponents;
|
|
|
7 |
answer: any[];
|
8 |
}
|
9 |
|
10 |
+
export interface IOperator {
|
11 |
+
obj: IOperatorNode;
|
12 |
downstream: string[];
|
13 |
upstream: string[];
|
14 |
}
|
15 |
|
16 |
+
export interface IOperatorNode {
|
17 |
component_name: string;
|
18 |
params: Record<string, unknown>;
|
19 |
}
|
web/src/locales/en.ts
CHANGED
@@ -541,6 +541,7 @@ The above is the content you need to summarize.`,
|
|
541 |
preview: 'Preview',
|
542 |
fileError: 'File error',
|
543 |
},
|
|
|
544 |
footer: {
|
545 |
profile: 'All rights reserved @ React',
|
546 |
},
|
|
|
541 |
preview: 'Preview',
|
542 |
fileError: 'File error',
|
543 |
},
|
544 |
+
flow: { cite: 'Cite', citeTip: 'citeTip' },
|
545 |
footer: {
|
546 |
profile: 'All rights reserved @ React',
|
547 |
},
|
web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx
CHANGED
@@ -1,18 +1,13 @@
|
|
1 |
-
import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
|
2 |
import { PlusOutlined } from '@ant-design/icons';
|
3 |
import { Form, Input, Select, Switch, Upload } from 'antd';
|
4 |
import classNames from 'classnames';
|
5 |
import { ISegmentedContentProps } from '../interface';
|
6 |
|
|
|
7 |
import { useTranslate } from '@/hooks/commonHooks';
|
8 |
import styles from './index.less';
|
9 |
|
10 |
const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
11 |
-
const { list: knowledgeList } = useFetchKnowledgeList(true);
|
12 |
-
const knowledgeOptions = knowledgeList.map((x) => ({
|
13 |
-
label: x.name,
|
14 |
-
value: x.id,
|
15 |
-
}));
|
16 |
const { t } = useTranslate('chat');
|
17 |
|
18 |
const normFile = (e: any) => {
|
@@ -95,24 +90,7 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
|
95 |
>
|
96 |
<Switch />
|
97 |
</Form.Item>
|
98 |
-
<
|
99 |
-
label={t('knowledgeBases')}
|
100 |
-
name="kb_ids"
|
101 |
-
tooltip={t('knowledgeBasesTip')}
|
102 |
-
rules={[
|
103 |
-
{
|
104 |
-
required: true,
|
105 |
-
message: t('knowledgeBasesMessage'),
|
106 |
-
type: 'array',
|
107 |
-
},
|
108 |
-
]}
|
109 |
-
>
|
110 |
-
<Select
|
111 |
-
mode="multiple"
|
112 |
-
options={knowledgeOptions}
|
113 |
-
placeholder={t('knowledgeBasesMessage')}
|
114 |
-
></Select>
|
115 |
-
</Form.Item>
|
116 |
</section>
|
117 |
);
|
118 |
};
|
|
|
|
|
1 |
import { PlusOutlined } from '@ant-design/icons';
|
2 |
import { Form, Input, Select, Switch, Upload } from 'antd';
|
3 |
import classNames from 'classnames';
|
4 |
import { ISegmentedContentProps } from '../interface';
|
5 |
|
6 |
+
import KnowledgeBaseItem from '@/components/knowledge-base-item';
|
7 |
import { useTranslate } from '@/hooks/commonHooks';
|
8 |
import styles from './index.less';
|
9 |
|
10 |
const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
|
|
|
|
|
|
|
|
|
|
11 |
const { t } = useTranslate('chat');
|
12 |
|
13 |
const normFile = (e: any) => {
|
|
|
90 |
>
|
91 |
<Switch />
|
92 |
</Form.Item>
|
93 |
+
<KnowledgeBaseItem></KnowledgeBaseItem>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
</section>
|
95 |
);
|
96 |
};
|
web/src/pages/chat/chat-configuration-modal/model-setting.tsx
CHANGED
@@ -1,16 +1,12 @@
|
|
1 |
import {
|
2 |
-
LlmModelType,
|
3 |
ModelVariableType,
|
4 |
settledModelVariableMap,
|
5 |
} from '@/constants/knowledge';
|
6 |
-
import { Divider, Flex, Form, InputNumber, Select, Slider, Switch } from 'antd';
|
7 |
import classNames from 'classnames';
|
8 |
-
import camelCase from 'lodash/camelCase';
|
9 |
import { useEffect } from 'react';
|
10 |
import { ISegmentedContentProps } from '../interface';
|
11 |
|
12 |
-
import
|
13 |
-
import { useSelectLlmOptionsByModelType } from '@/hooks/llmHooks';
|
14 |
import { Variable } from '@/interfaces/database/chat';
|
15 |
import { variableEnabledFieldMap } from '../constants';
|
16 |
import styles from './index.less';
|
@@ -24,14 +20,6 @@ const ModelSetting = ({
|
|
24 |
initialLlmSetting?: Variable;
|
25 |
visible?: boolean;
|
26 |
}) => {
|
27 |
-
const { t } = useTranslate('chat');
|
28 |
-
const parameterOptions = Object.values(ModelVariableType).map((x) => ({
|
29 |
-
label: t(camelCase(x)),
|
30 |
-
value: x,
|
31 |
-
}));
|
32 |
-
|
33 |
-
const modelOptions = useSelectLlmOptionsByModelType();
|
34 |
-
|
35 |
const handleParametersChange = (value: ModelVariableType) => {
|
36 |
const variable = settledModelVariableMap[value];
|
37 |
form.setFieldsValue({ llm_setting: variable });
|
@@ -62,7 +50,13 @@ const ModelSetting = ({
|
|
62 |
[styles.segmentedHidden]: !show,
|
63 |
})}
|
64 |
>
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
label={t('model')}
|
67 |
name="llm_id"
|
68 |
tooltip={t('modelTip')}
|
@@ -279,7 +273,7 @@ const ModelSetting = ({
|
|
279 |
}}
|
280 |
</Form.Item>
|
281 |
</Flex>
|
282 |
-
</Form.Item>
|
283 |
</section>
|
284 |
);
|
285 |
};
|
|
|
1 |
import {
|
|
|
2 |
ModelVariableType,
|
3 |
settledModelVariableMap,
|
4 |
} from '@/constants/knowledge';
|
|
|
5 |
import classNames from 'classnames';
|
|
|
6 |
import { useEffect } from 'react';
|
7 |
import { ISegmentedContentProps } from '../interface';
|
8 |
|
9 |
+
import LlmSettingItems from '@/components/llm-setting-items';
|
|
|
10 |
import { Variable } from '@/interfaces/database/chat';
|
11 |
import { variableEnabledFieldMap } from '../constants';
|
12 |
import styles from './index.less';
|
|
|
20 |
initialLlmSetting?: Variable;
|
21 |
visible?: boolean;
|
22 |
}) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
const handleParametersChange = (value: ModelVariableType) => {
|
24 |
const variable = settledModelVariableMap[value];
|
25 |
form.setFieldsValue({ llm_setting: variable });
|
|
|
50 |
[styles.segmentedHidden]: !show,
|
51 |
})}
|
52 |
>
|
53 |
+
{visible && (
|
54 |
+
<LlmSettingItems
|
55 |
+
prefix="llm_setting"
|
56 |
+
handleParametersChange={handleParametersChange}
|
57 |
+
></LlmSettingItems>
|
58 |
+
)}
|
59 |
+
{/* <Form.Item
|
60 |
label={t('model')}
|
61 |
name="llm_id"
|
62 |
tooltip={t('modelTip')}
|
|
|
273 |
}}
|
274 |
</Form.Item>
|
275 |
</Flex>
|
276 |
+
</Form.Item> */}
|
277 |
</section>
|
278 |
);
|
279 |
};
|
web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx
CHANGED
@@ -7,7 +7,6 @@ import {
|
|
7 |
Form,
|
8 |
Input,
|
9 |
Row,
|
10 |
-
Slider,
|
11 |
Switch,
|
12 |
Table,
|
13 |
TableProps,
|
@@ -30,16 +29,11 @@ import {
|
|
30 |
import { EditableCell, EditableRow } from './editable-cell';
|
31 |
|
32 |
import Rerank from '@/components/rerank';
|
|
|
33 |
import { useTranslate } from '@/hooks/commonHooks';
|
34 |
import { useSelectPromptConfigParameters } from '../hooks';
|
35 |
import styles from './index.less';
|
36 |
|
37 |
-
type FieldType = {
|
38 |
-
similarity_threshold?: number;
|
39 |
-
vector_similarity_weight?: number;
|
40 |
-
top_n?: number;
|
41 |
-
};
|
42 |
-
|
43 |
const PromptEngine = (
|
44 |
{ show }: ISegmentedContentProps,
|
45 |
ref: ForwardedRef<Array<IPromptConfigParameters>>,
|
@@ -165,14 +159,7 @@ const PromptEngine = (
|
|
165 |
</Form.Item>
|
166 |
<Divider></Divider>
|
167 |
<SimilaritySlider isTooltipShown></SimilaritySlider>
|
168 |
-
<
|
169 |
-
label={t('topN')}
|
170 |
-
name={'top_n'}
|
171 |
-
initialValue={8}
|
172 |
-
tooltip={t('topNTip')}
|
173 |
-
>
|
174 |
-
<Slider max={30} />
|
175 |
-
</Form.Item>
|
176 |
<Rerank></Rerank>
|
177 |
<section className={classNames(styles.variableContainer)}>
|
178 |
<Row align={'middle'} justify="end">
|
|
|
7 |
Form,
|
8 |
Input,
|
9 |
Row,
|
|
|
10 |
Switch,
|
11 |
Table,
|
12 |
TableProps,
|
|
|
29 |
import { EditableCell, EditableRow } from './editable-cell';
|
30 |
|
31 |
import Rerank from '@/components/rerank';
|
32 |
+
import TopNItem from '@/components/top-n-item';
|
33 |
import { useTranslate } from '@/hooks/commonHooks';
|
34 |
import { useSelectPromptConfigParameters } from '../hooks';
|
35 |
import styles from './index.less';
|
36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
const PromptEngine = (
|
38 |
{ show }: ISegmentedContentProps,
|
39 |
ref: ForwardedRef<Array<IPromptConfigParameters>>,
|
|
|
159 |
</Form.Item>
|
160 |
<Divider></Divider>
|
161 |
<SimilaritySlider isTooltipShown></SimilaritySlider>
|
162 |
+
<TopNItem></TopNItem>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
<Rerank></Rerank>
|
164 |
<section className={classNames(styles.variableContainer)}>
|
165 |
<Row align={'middle'} justify="end">
|
web/src/pages/flow/answer-form/index.tsx
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const AnswerForm = () => {
|
2 |
+
return <div>AnswerForm</div>;
|
3 |
+
};
|
4 |
+
|
5 |
+
export default AnswerForm;
|
web/src/pages/flow/begin-form/index.tsx
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useTranslate } from '@/hooks/commonHooks';
|
2 |
+
import type { FormProps } from 'antd';
|
3 |
+
import { Form, Input } from 'antd';
|
4 |
+
import { IOperatorForm } from '../interface';
|
5 |
+
|
6 |
+
type FieldType = {
|
7 |
+
prologue?: string;
|
8 |
+
};
|
9 |
+
|
10 |
+
const onFinish: FormProps<FieldType>['onFinish'] = (values) => {
|
11 |
+
console.log('Success:', values);
|
12 |
+
};
|
13 |
+
|
14 |
+
const onFinishFailed: FormProps<FieldType>['onFinishFailed'] = (errorInfo) => {
|
15 |
+
console.log('Failed:', errorInfo);
|
16 |
+
};
|
17 |
+
|
18 |
+
const BeginForm = ({ onValuesChange }: IOperatorForm) => {
|
19 |
+
const { t } = useTranslate('chat');
|
20 |
+
const [form] = Form.useForm();
|
21 |
+
|
22 |
+
return (
|
23 |
+
<Form
|
24 |
+
name="basic"
|
25 |
+
labelCol={{ span: 8 }}
|
26 |
+
wrapperCol={{ span: 16 }}
|
27 |
+
style={{ maxWidth: 600 }}
|
28 |
+
initialValues={{ remember: true }}
|
29 |
+
onFinish={onFinish}
|
30 |
+
onFinishFailed={onFinishFailed}
|
31 |
+
onValuesChange={onValuesChange}
|
32 |
+
autoComplete="off"
|
33 |
+
form={form}
|
34 |
+
>
|
35 |
+
<Form.Item<FieldType>
|
36 |
+
name={'prologue'}
|
37 |
+
label={t('setAnOpener')}
|
38 |
+
tooltip={t('setAnOpenerTip')}
|
39 |
+
initialValue={t('setAnOpenerInitial')}
|
40 |
+
>
|
41 |
+
<Input.TextArea autoSize={{ minRows: 5 }} />
|
42 |
+
</Form.Item>
|
43 |
+
</Form>
|
44 |
+
);
|
45 |
+
};
|
46 |
+
|
47 |
+
export default BeginForm;
|
web/src/pages/flow/canvas/context-menu/index.tsx
CHANGED
@@ -86,7 +86,7 @@ export const useHandleNodeContextMenu = (sideWidth: number) => {
|
|
86 |
|
87 |
setMenu({
|
88 |
id: node.id,
|
89 |
-
top: event.clientY -
|
90 |
left: event.clientX - sideWidth,
|
91 |
// top: event.clientY < pane.height - 200 ? event.clientY - 72 : 0,
|
92 |
// left: event.clientX < pane.width - 200 ? event.clientX : 0,
|
|
|
86 |
|
87 |
setMenu({
|
88 |
id: node.id,
|
89 |
+
top: event.clientY - 144,
|
90 |
left: event.clientX - sideWidth,
|
91 |
// top: event.clientY < pane.height - 200 ? event.clientY - 72 : 0,
|
92 |
// left: event.clientX < pane.width - 200 ? event.clientX : 0,
|
web/src/pages/flow/canvas/edge/index.less
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.edgeButton {
|
2 |
+
width: 14px;
|
3 |
+
height: 14px;
|
4 |
+
background: #eee;
|
5 |
+
border: 1px solid #fff;
|
6 |
+
padding: 0;
|
7 |
+
cursor: pointer;
|
8 |
+
border-radius: 50%;
|
9 |
+
font-size: 10px;
|
10 |
+
line-height: 1;
|
11 |
+
}
|
12 |
+
|
13 |
+
.edgeButton:hover {
|
14 |
+
box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.08);
|
15 |
+
}
|
web/src/pages/flow/canvas/edge/index.tsx
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
BaseEdge,
|
3 |
+
EdgeLabelRenderer,
|
4 |
+
EdgeProps,
|
5 |
+
getBezierPath,
|
6 |
+
} from 'reactflow';
|
7 |
+
import useStore from '../../store';
|
8 |
+
|
9 |
+
import { useMemo } from 'react';
|
10 |
+
import styles from './index.less';
|
11 |
+
|
12 |
+
export function ButtonEdge({
|
13 |
+
id,
|
14 |
+
sourceX,
|
15 |
+
sourceY,
|
16 |
+
targetX,
|
17 |
+
targetY,
|
18 |
+
sourcePosition,
|
19 |
+
targetPosition,
|
20 |
+
style = {},
|
21 |
+
markerEnd,
|
22 |
+
selected,
|
23 |
+
}: EdgeProps) {
|
24 |
+
const deleteEdgeById = useStore((state) => state.deleteEdgeById);
|
25 |
+
const [edgePath, labelX, labelY] = getBezierPath({
|
26 |
+
sourceX,
|
27 |
+
sourceY,
|
28 |
+
sourcePosition,
|
29 |
+
targetX,
|
30 |
+
targetY,
|
31 |
+
targetPosition,
|
32 |
+
});
|
33 |
+
|
34 |
+
const selectedStyle = useMemo(() => {
|
35 |
+
return selected ? { strokeWidth: 1, stroke: '#1677ff' } : {};
|
36 |
+
}, [selected]);
|
37 |
+
|
38 |
+
const onEdgeClick = () => {
|
39 |
+
deleteEdgeById(id);
|
40 |
+
};
|
41 |
+
|
42 |
+
return (
|
43 |
+
<>
|
44 |
+
<BaseEdge
|
45 |
+
path={edgePath}
|
46 |
+
markerEnd={markerEnd}
|
47 |
+
style={{ ...style, ...selectedStyle }}
|
48 |
+
/>
|
49 |
+
<EdgeLabelRenderer>
|
50 |
+
<div
|
51 |
+
style={{
|
52 |
+
position: 'absolute',
|
53 |
+
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
|
54 |
+
fontSize: 12,
|
55 |
+
// everything inside EdgeLabelRenderer has no pointer events by default
|
56 |
+
// if you have an interactive element, set pointer-events: all
|
57 |
+
pointerEvents: 'all',
|
58 |
+
}}
|
59 |
+
className="nodrag nopan"
|
60 |
+
>
|
61 |
+
<button
|
62 |
+
className={styles.edgeButton}
|
63 |
+
type="button"
|
64 |
+
onClick={onEdgeClick}
|
65 |
+
>
|
66 |
+
×
|
67 |
+
</button>
|
68 |
+
</div>
|
69 |
+
</EdgeLabelRenderer>
|
70 |
+
</>
|
71 |
+
);
|
72 |
+
}
|
web/src/pages/flow/canvas/index.less
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.canvasWrapper {
|
2 |
+
position: relative;
|
3 |
+
height: 100%;
|
4 |
+
}
|
web/src/pages/flow/canvas/index.tsx
CHANGED
@@ -1,76 +1,64 @@
|
|
1 |
-
import { useCallback
|
2 |
import ReactFlow, {
|
3 |
Background,
|
4 |
Controls,
|
5 |
-
|
6 |
-
Node,
|
7 |
NodeMouseHandler,
|
8 |
-
OnConnect,
|
9 |
-
OnEdgesChange,
|
10 |
-
OnNodesChange,
|
11 |
-
addEdge,
|
12 |
-
applyEdgeChanges,
|
13 |
-
applyNodeChanges,
|
14 |
} from 'reactflow';
|
15 |
import 'reactflow/dist/style.css';
|
16 |
|
17 |
import { NodeContextMenu, useHandleNodeContextMenu } from './context-menu';
|
|
|
18 |
|
19 |
import FlowDrawer from '../flow-drawer';
|
20 |
import {
|
21 |
useHandleDrop,
|
22 |
useHandleKeyUp,
|
23 |
-
|
24 |
useShowDrawer,
|
25 |
} from '../hooks';
|
26 |
-
import { dsl } from '../mock';
|
27 |
import { TextUpdaterNode } from './node';
|
28 |
|
|
|
|
|
29 |
const nodeTypes = { textUpdater: TextUpdaterNode };
|
30 |
|
|
|
|
|
|
|
|
|
31 |
interface IProps {
|
32 |
sideWidth: number;
|
33 |
}
|
34 |
|
35 |
function FlowCanvas({ sideWidth }: IProps) {
|
36 |
-
const
|
37 |
-
|
38 |
-
|
39 |
-
|
|
|
|
|
|
|
|
|
40 |
|
41 |
const { ref, menu, onNodeContextMenu, onPaneClick } =
|
42 |
useHandleNodeContextMenu(sideWidth);
|
43 |
-
const { drawerVisible, hideDrawer, showDrawer } =
|
44 |
-
|
45 |
-
const onNodesChange: OnNodesChange = useCallback(
|
46 |
-
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
|
47 |
-
[],
|
48 |
-
);
|
49 |
-
const onEdgesChange: OnEdgesChange = useCallback(
|
50 |
-
(changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
|
51 |
-
[],
|
52 |
-
);
|
53 |
|
54 |
-
const
|
55 |
-
(
|
56 |
-
|
|
|
|
|
57 |
);
|
58 |
|
59 |
-
const
|
60 |
-
showDrawer();
|
61 |
-
}, [showDrawer]);
|
62 |
-
|
63 |
-
const { onDrop, onDragOver, setReactFlowInstance } = useHandleDrop(setNodes);
|
64 |
-
|
65 |
-
const { handleKeyUp } = useHandleKeyUp(selectedEdges, selectedNodes);
|
66 |
|
67 |
-
|
68 |
-
console.info('nodes:', nodes);
|
69 |
-
console.info('edges:', edges);
|
70 |
-
}, [nodes, edges]);
|
71 |
|
72 |
return (
|
73 |
-
<div
|
74 |
<ReactFlow
|
75 |
ref={ref}
|
76 |
nodes={nodes}
|
@@ -81,12 +69,21 @@ function FlowCanvas({ sideWidth }: IProps) {
|
|
81 |
fitView
|
82 |
onConnect={onConnect}
|
83 |
nodeTypes={nodeTypes}
|
|
|
84 |
onPaneClick={onPaneClick}
|
85 |
onDrop={onDrop}
|
86 |
onDragOver={onDragOver}
|
87 |
onNodeClick={onNodeClick}
|
88 |
onInit={setReactFlowInstance}
|
89 |
onKeyUp={handleKeyUp}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
>
|
91 |
<Background />
|
92 |
<Controls />
|
@@ -94,7 +91,11 @@ function FlowCanvas({ sideWidth }: IProps) {
|
|
94 |
<NodeContextMenu onClick={onPaneClick} {...(menu as any)} />
|
95 |
)}
|
96 |
</ReactFlow>
|
97 |
-
<FlowDrawer
|
|
|
|
|
|
|
|
|
98 |
</div>
|
99 |
);
|
100 |
}
|
|
|
1 |
+
import { useCallback } from 'react';
|
2 |
import ReactFlow, {
|
3 |
Background,
|
4 |
Controls,
|
5 |
+
MarkerType,
|
|
|
6 |
NodeMouseHandler,
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
} from 'reactflow';
|
8 |
import 'reactflow/dist/style.css';
|
9 |
|
10 |
import { NodeContextMenu, useHandleNodeContextMenu } from './context-menu';
|
11 |
+
import { ButtonEdge } from './edge';
|
12 |
|
13 |
import FlowDrawer from '../flow-drawer';
|
14 |
import {
|
15 |
useHandleDrop,
|
16 |
useHandleKeyUp,
|
17 |
+
useSelectCanvasData,
|
18 |
useShowDrawer,
|
19 |
} from '../hooks';
|
|
|
20 |
import { TextUpdaterNode } from './node';
|
21 |
|
22 |
+
import styles from './index.less';
|
23 |
+
|
24 |
const nodeTypes = { textUpdater: TextUpdaterNode };
|
25 |
|
26 |
+
const edgeTypes = {
|
27 |
+
buttonEdge: ButtonEdge,
|
28 |
+
};
|
29 |
+
|
30 |
interface IProps {
|
31 |
sideWidth: number;
|
32 |
}
|
33 |
|
34 |
function FlowCanvas({ sideWidth }: IProps) {
|
35 |
+
const {
|
36 |
+
nodes,
|
37 |
+
edges,
|
38 |
+
onConnect,
|
39 |
+
onEdgesChange,
|
40 |
+
onNodesChange,
|
41 |
+
onSelectionChange,
|
42 |
+
} = useSelectCanvasData();
|
43 |
|
44 |
const { ref, menu, onNodeContextMenu, onPaneClick } =
|
45 |
useHandleNodeContextMenu(sideWidth);
|
46 |
+
const { drawerVisible, hideDrawer, showDrawer, clickedNode } =
|
47 |
+
useShowDrawer();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
|
49 |
+
const onNodeClick: NodeMouseHandler = useCallback(
|
50 |
+
(e, node) => {
|
51 |
+
showDrawer(node);
|
52 |
+
},
|
53 |
+
[showDrawer],
|
54 |
);
|
55 |
|
56 |
+
const { onDrop, onDragOver, setReactFlowInstance } = useHandleDrop();
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
|
58 |
+
const { handleKeyUp } = useHandleKeyUp();
|
|
|
|
|
|
|
59 |
|
60 |
return (
|
61 |
+
<div className={styles.canvasWrapper}>
|
62 |
<ReactFlow
|
63 |
ref={ref}
|
64 |
nodes={nodes}
|
|
|
69 |
fitView
|
70 |
onConnect={onConnect}
|
71 |
nodeTypes={nodeTypes}
|
72 |
+
edgeTypes={edgeTypes}
|
73 |
onPaneClick={onPaneClick}
|
74 |
onDrop={onDrop}
|
75 |
onDragOver={onDragOver}
|
76 |
onNodeClick={onNodeClick}
|
77 |
onInit={setReactFlowInstance}
|
78 |
onKeyUp={handleKeyUp}
|
79 |
+
onSelectionChange={onSelectionChange}
|
80 |
+
nodeOrigin={[0.5, 0]}
|
81 |
+
defaultEdgeOptions={{
|
82 |
+
type: 'buttonEdge',
|
83 |
+
markerEnd: {
|
84 |
+
type: MarkerType.ArrowClosed,
|
85 |
+
},
|
86 |
+
}}
|
87 |
>
|
88 |
<Background />
|
89 |
<Controls />
|
|
|
91 |
<NodeContextMenu onClick={onPaneClick} {...(menu as any)} />
|
92 |
)}
|
93 |
</ReactFlow>
|
94 |
+
<FlowDrawer
|
95 |
+
node={clickedNode}
|
96 |
+
visible={drawerVisible}
|
97 |
+
hideModal={hideDrawer}
|
98 |
+
></FlowDrawer>
|
99 |
</div>
|
100 |
);
|
101 |
}
|
web/src/pages/flow/canvas/node/index.less
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
.textUpdaterNode {
|
2 |
// height: 50px;
|
3 |
-
border: 1px solid
|
4 |
padding: 5px;
|
5 |
border-radius: 5px;
|
6 |
background: white;
|
@@ -10,3 +10,12 @@
|
|
10 |
font-size: 12px;
|
11 |
}
|
12 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
.textUpdaterNode {
|
2 |
// height: 50px;
|
3 |
+
border: 1px solid gray;
|
4 |
padding: 5px;
|
5 |
border-radius: 5px;
|
6 |
background: white;
|
|
|
10 |
font-size: 12px;
|
11 |
}
|
12 |
}
|
13 |
+
.selectedNode {
|
14 |
+
border-color: #1677ff;
|
15 |
+
}
|
16 |
+
|
17 |
+
.handle {
|
18 |
+
display: inline-flex;
|
19 |
+
text-align: center;
|
20 |
+
// align-items: center;
|
21 |
+
}
|
web/src/pages/flow/canvas/node/index.tsx
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
import { Handle, NodeProps, Position } from 'reactflow';
|
2 |
|
3 |
import styles from './index.less';
|
@@ -5,19 +6,30 @@ import styles from './index.less';
|
|
5 |
export function TextUpdaterNode({
|
6 |
data,
|
7 |
isConnectable = true,
|
|
|
8 |
}: NodeProps<{ label: string }>) {
|
9 |
return (
|
10 |
-
<div
|
|
|
|
|
|
|
|
|
11 |
<Handle
|
12 |
type="target"
|
13 |
position={Position.Left}
|
14 |
isConnectable={isConnectable}
|
15 |
-
|
|
|
|
|
|
|
16 |
<Handle
|
17 |
type="source"
|
18 |
position={Position.Right}
|
19 |
isConnectable={isConnectable}
|
20 |
-
|
|
|
|
|
|
|
21 |
<div>{data.label}</div>
|
22 |
</div>
|
23 |
);
|
|
|
1 |
+
import classNames from 'classnames';
|
2 |
import { Handle, NodeProps, Position } from 'reactflow';
|
3 |
|
4 |
import styles from './index.less';
|
|
|
6 |
export function TextUpdaterNode({
|
7 |
data,
|
8 |
isConnectable = true,
|
9 |
+
selected,
|
10 |
}: NodeProps<{ label: string }>) {
|
11 |
return (
|
12 |
+
<div
|
13 |
+
className={classNames(styles.textUpdaterNode, {
|
14 |
+
[styles.selectedNode]: selected,
|
15 |
+
})}
|
16 |
+
>
|
17 |
<Handle
|
18 |
type="target"
|
19 |
position={Position.Left}
|
20 |
isConnectable={isConnectable}
|
21 |
+
className={styles.handle}
|
22 |
+
>
|
23 |
+
{/* <PlusCircleOutlined style={{ fontSize: 10 }} /> */}
|
24 |
+
</Handle>
|
25 |
<Handle
|
26 |
type="source"
|
27 |
position={Position.Right}
|
28 |
isConnectable={isConnectable}
|
29 |
+
className={styles.handle}
|
30 |
+
>
|
31 |
+
{/* <PlusCircleOutlined style={{ fontSize: 10 }} /> */}
|
32 |
+
</Handle>
|
33 |
<div>{data.label}</div>
|
34 |
</div>
|
35 |
);
|
web/src/pages/flow/constant.ts
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export enum Operator {
|
2 |
+
Begin = 'Begin',
|
3 |
+
Retrieval = 'Retrieval',
|
4 |
+
Generate = 'Generate',
|
5 |
+
Answer = 'Answer',
|
6 |
+
}
|
web/src/pages/flow/flow-drawer/index.tsx
CHANGED
@@ -1,18 +1,46 @@
|
|
1 |
import { IModalProps } from '@/interfaces/common';
|
2 |
import { Drawer } from 'antd';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
-
const FlowDrawer = ({ visible, hideModal }: IModalProps<any>) => {
|
5 |
return (
|
6 |
<Drawer
|
7 |
-
title=
|
8 |
placement="right"
|
9 |
-
// closable={false}
|
10 |
onClose={hideModal}
|
11 |
open={visible}
|
12 |
getContainer={false}
|
13 |
mask={false}
|
|
|
14 |
>
|
15 |
-
|
|
|
|
|
16 |
</Drawer>
|
17 |
);
|
18 |
};
|
|
|
1 |
import { IModalProps } from '@/interfaces/common';
|
2 |
import { Drawer } from 'antd';
|
3 |
+
import { Node } from 'reactflow';
|
4 |
+
import AnswerForm from '../answer-form';
|
5 |
+
import BeginForm from '../begin-form';
|
6 |
+
import { Operator } from '../constant';
|
7 |
+
import GenerateForm from '../generate-form';
|
8 |
+
import { useHandleFormValuesChange } from '../hooks';
|
9 |
+
import RetrievalForm from '../retrieval-form';
|
10 |
+
|
11 |
+
interface IProps {
|
12 |
+
node?: Node;
|
13 |
+
}
|
14 |
+
|
15 |
+
const FormMap = {
|
16 |
+
[Operator.Begin]: BeginForm,
|
17 |
+
[Operator.Retrieval]: RetrievalForm,
|
18 |
+
[Operator.Generate]: GenerateForm,
|
19 |
+
[Operator.Answer]: AnswerForm,
|
20 |
+
};
|
21 |
+
|
22 |
+
const FlowDrawer = ({
|
23 |
+
visible,
|
24 |
+
hideModal,
|
25 |
+
node,
|
26 |
+
}: IModalProps<any> & IProps) => {
|
27 |
+
const operatorName: Operator = node?.data.label;
|
28 |
+
const OperatorForm = FormMap[operatorName];
|
29 |
+
const { handleValuesChange } = useHandleFormValuesChange(node?.id);
|
30 |
|
|
|
31 |
return (
|
32 |
<Drawer
|
33 |
+
title={node?.data.label}
|
34 |
placement="right"
|
|
|
35 |
onClose={hideModal}
|
36 |
open={visible}
|
37 |
getContainer={false}
|
38 |
mask={false}
|
39 |
+
width={470}
|
40 |
>
|
41 |
+
{visible && (
|
42 |
+
<OperatorForm onValuesChange={handleValuesChange}></OperatorForm>
|
43 |
+
)}
|
44 |
</Drawer>
|
45 |
);
|
46 |
};
|
web/src/pages/flow/generate-form/index.tsx
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import LlmSettingItems from '@/components/llm-setting-items';
|
2 |
+
import {
|
3 |
+
ModelVariableType,
|
4 |
+
settledModelVariableMap,
|
5 |
+
} from '@/constants/knowledge';
|
6 |
+
import { useTranslate } from '@/hooks/commonHooks';
|
7 |
+
import { Variable } from '@/interfaces/database/chat';
|
8 |
+
import { variableEnabledFieldMap } from '@/pages/chat/constants';
|
9 |
+
import { Form, Input, Switch } from 'antd';
|
10 |
+
import { useCallback, useEffect } from 'react';
|
11 |
+
import { IOperatorForm } from '../interface';
|
12 |
+
|
13 |
+
const GenerateForm = ({ onValuesChange }: IOperatorForm) => {
|
14 |
+
const { t } = useTranslate('flow');
|
15 |
+
const [form] = Form.useForm();
|
16 |
+
const initialLlmSetting = undefined;
|
17 |
+
|
18 |
+
const handleParametersChange = useCallback(
|
19 |
+
(value: ModelVariableType) => {
|
20 |
+
const variable = settledModelVariableMap[value];
|
21 |
+
form.setFieldsValue(variable);
|
22 |
+
},
|
23 |
+
[form],
|
24 |
+
);
|
25 |
+
|
26 |
+
useEffect(() => {
|
27 |
+
const switchBoxValues = Object.keys(variableEnabledFieldMap).reduce<
|
28 |
+
Record<string, boolean>
|
29 |
+
>((pre, field) => {
|
30 |
+
pre[field] =
|
31 |
+
initialLlmSetting === undefined
|
32 |
+
? true
|
33 |
+
: !!initialLlmSetting[
|
34 |
+
variableEnabledFieldMap[
|
35 |
+
field as keyof typeof variableEnabledFieldMap
|
36 |
+
] as keyof Variable
|
37 |
+
];
|
38 |
+
return pre;
|
39 |
+
}, {});
|
40 |
+
const otherValues = settledModelVariableMap[ModelVariableType.Precise];
|
41 |
+
form.setFieldsValue({ ...switchBoxValues, ...otherValues });
|
42 |
+
}, [form, initialLlmSetting]);
|
43 |
+
|
44 |
+
return (
|
45 |
+
<Form
|
46 |
+
name="basic"
|
47 |
+
labelCol={{ span: 9 }}
|
48 |
+
wrapperCol={{ span: 15 }}
|
49 |
+
autoComplete="off"
|
50 |
+
form={form}
|
51 |
+
onValuesChange={onValuesChange}
|
52 |
+
>
|
53 |
+
<LlmSettingItems
|
54 |
+
handleParametersChange={handleParametersChange}
|
55 |
+
></LlmSettingItems>
|
56 |
+
<Form.Item
|
57 |
+
name={['prompt']}
|
58 |
+
label={t('prompt', { keyPrefix: 'knowledgeConfiguration' })}
|
59 |
+
initialValue={t('promptText', { keyPrefix: 'knowledgeConfiguration' })}
|
60 |
+
tooltip={t('promptTip', { keyPrefix: 'knowledgeConfiguration' })}
|
61 |
+
rules={[
|
62 |
+
{
|
63 |
+
required: true,
|
64 |
+
message: t('promptMessage'),
|
65 |
+
},
|
66 |
+
]}
|
67 |
+
>
|
68 |
+
<Input.TextArea rows={8} />
|
69 |
+
</Form.Item>
|
70 |
+
<Form.Item
|
71 |
+
name={['cite']}
|
72 |
+
label={t('cite')}
|
73 |
+
initialValue={true}
|
74 |
+
valuePropName="checked"
|
75 |
+
tooltip={t('citeTip')}
|
76 |
+
>
|
77 |
+
<Switch />
|
78 |
+
</Form.Item>
|
79 |
+
</Form>
|
80 |
+
);
|
81 |
+
};
|
82 |
+
|
83 |
+
export default GenerateForm;
|
web/src/pages/flow/hooks.ts
CHANGED
@@ -1,19 +1,26 @@
|
|
1 |
import { useSetModalState } from '@/hooks/commonHooks';
|
2 |
-
import
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
useCallback,
|
7 |
-
useState,
|
8 |
-
} from 'react';
|
9 |
-
import {
|
10 |
-
Node,
|
11 |
-
Position,
|
12 |
-
ReactFlowInstance,
|
13 |
-
useOnSelectionChange,
|
14 |
-
useReactFlow,
|
15 |
-
} from 'reactflow';
|
16 |
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
export const useHandleDrag = () => {
|
19 |
const handleDragStart = useCallback(
|
@@ -27,7 +34,8 @@ export const useHandleDrag = () => {
|
|
27 |
return { handleDragStart };
|
28 |
};
|
29 |
|
30 |
-
export const useHandleDrop = (
|
|
|
31 |
const [reactFlowInstance, setReactFlowInstance] =
|
32 |
useState<ReactFlowInstance<any, any>>();
|
33 |
|
@@ -66,59 +74,40 @@ export const useHandleDrop = (setNodes: Dispatch<SetStateAction<Node[]>>) => {
|
|
66 |
targetPosition: Position.Left,
|
67 |
};
|
68 |
|
69 |
-
|
70 |
},
|
71 |
-
[reactFlowInstance,
|
72 |
);
|
73 |
|
74 |
return { onDrop, onDragOver, setReactFlowInstance };
|
75 |
};
|
76 |
|
77 |
export const useShowDrawer = () => {
|
|
|
78 |
const {
|
79 |
visible: drawerVisible,
|
80 |
hideModal: hideDrawer,
|
81 |
showModal: showDrawer,
|
82 |
} = useSetModalState();
|
83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
return {
|
85 |
drawerVisible,
|
86 |
hideDrawer,
|
87 |
-
showDrawer,
|
|
|
88 |
};
|
89 |
};
|
90 |
|
91 |
-
export const
|
92 |
-
const
|
93 |
-
const [selectedEdges, setSelectedEdges] = useState<string[]>([]);
|
94 |
-
|
95 |
-
useOnSelectionChange({
|
96 |
-
onChange: ({ nodes, edges }) => {
|
97 |
-
setSelectedNodes(nodes.map((node) => node.id));
|
98 |
-
setSelectedEdges(edges.map((edge) => edge.id));
|
99 |
-
},
|
100 |
-
});
|
101 |
-
|
102 |
-
return { selectedEdges, selectedNodes };
|
103 |
-
};
|
104 |
-
|
105 |
-
export const useDeleteEdge = (selectedEdges: string[]) => {
|
106 |
-
const { setEdges } = useReactFlow();
|
107 |
-
|
108 |
-
const deleteEdge = useCallback(() => {
|
109 |
-
setEdges((edges) =>
|
110 |
-
edges.filter((edge) => selectedEdges.every((x) => x !== edge.id)),
|
111 |
-
);
|
112 |
-
}, [setEdges, selectedEdges]);
|
113 |
-
|
114 |
-
return deleteEdge;
|
115 |
-
};
|
116 |
-
|
117 |
-
export const useHandleKeyUp = (
|
118 |
-
selectedEdges: string[],
|
119 |
-
selectedNodes: string[],
|
120 |
-
) => {
|
121 |
-
const deleteEdge = useDeleteEdge(selectedEdges);
|
122 |
const handleKeyUp: KeyboardEventHandler = useCallback(
|
123 |
(e) => {
|
124 |
if (e.code === 'Delete') {
|
@@ -132,7 +121,31 @@ export const useHandleKeyUp = (
|
|
132 |
};
|
133 |
|
134 |
export const useSaveGraph = () => {
|
135 |
-
const
|
|
|
|
|
|
|
|
|
136 |
|
137 |
return { saveGraph };
|
138 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import { useSetModalState } from '@/hooks/commonHooks';
|
2 |
+
import { useFetchFlowTemplates } from '@/hooks/flow-hooks';
|
3 |
+
import { useFetchLlmList } from '@/hooks/llmHooks';
|
4 |
+
import React, { KeyboardEventHandler, useCallback, useState } from 'react';
|
5 |
+
import { Node, Position, ReactFlowInstance } from 'reactflow';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
import { v4 as uuidv4 } from 'uuid';
|
7 |
+
import useStore, { RFState } from './store';
|
8 |
+
import { buildDslComponentsByGraph } from './utils';
|
9 |
+
|
10 |
+
const selector = (state: RFState) => ({
|
11 |
+
nodes: state.nodes,
|
12 |
+
edges: state.edges,
|
13 |
+
onNodesChange: state.onNodesChange,
|
14 |
+
onEdgesChange: state.onEdgesChange,
|
15 |
+
onConnect: state.onConnect,
|
16 |
+
setNodes: state.setNodes,
|
17 |
+
onSelectionChange: state.onSelectionChange,
|
18 |
+
});
|
19 |
+
|
20 |
+
export const useSelectCanvasData = () => {
|
21 |
+
// return useStore(useShallow(selector)); throw error
|
22 |
+
return useStore(selector);
|
23 |
+
};
|
24 |
|
25 |
export const useHandleDrag = () => {
|
26 |
const handleDragStart = useCallback(
|
|
|
34 |
return { handleDragStart };
|
35 |
};
|
36 |
|
37 |
+
export const useHandleDrop = () => {
|
38 |
+
const addNode = useStore((state) => state.addNode);
|
39 |
const [reactFlowInstance, setReactFlowInstance] =
|
40 |
useState<ReactFlowInstance<any, any>>();
|
41 |
|
|
|
74 |
targetPosition: Position.Left,
|
75 |
};
|
76 |
|
77 |
+
addNode(newNode);
|
78 |
},
|
79 |
+
[reactFlowInstance, addNode],
|
80 |
);
|
81 |
|
82 |
return { onDrop, onDragOver, setReactFlowInstance };
|
83 |
};
|
84 |
|
85 |
export const useShowDrawer = () => {
|
86 |
+
const [clickedNode, setClickedNode] = useState<Node>();
|
87 |
const {
|
88 |
visible: drawerVisible,
|
89 |
hideModal: hideDrawer,
|
90 |
showModal: showDrawer,
|
91 |
} = useSetModalState();
|
92 |
|
93 |
+
const handleShow = useCallback(
|
94 |
+
(node: Node) => {
|
95 |
+
setClickedNode(node);
|
96 |
+
showDrawer();
|
97 |
+
},
|
98 |
+
[showDrawer],
|
99 |
+
);
|
100 |
+
|
101 |
return {
|
102 |
drawerVisible,
|
103 |
hideDrawer,
|
104 |
+
showDrawer: handleShow,
|
105 |
+
clickedNode,
|
106 |
};
|
107 |
};
|
108 |
|
109 |
+
export const useHandleKeyUp = () => {
|
110 |
+
const deleteEdge = useStore((state) => state.deleteEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
const handleKeyUp: KeyboardEventHandler = useCallback(
|
112 |
(e) => {
|
113 |
if (e.code === 'Delete') {
|
|
|
121 |
};
|
122 |
|
123 |
export const useSaveGraph = () => {
|
124 |
+
const { nodes, edges } = useStore((state) => state);
|
125 |
+
const saveGraph = useCallback(() => {
|
126 |
+
const x = buildDslComponentsByGraph(nodes, edges);
|
127 |
+
console.info('components:', x);
|
128 |
+
}, [nodes, edges]);
|
129 |
|
130 |
return { saveGraph };
|
131 |
};
|
132 |
+
|
133 |
+
export const useHandleFormValuesChange = (id?: string) => {
|
134 |
+
const updateNodeForm = useStore((state) => state.updateNodeForm);
|
135 |
+
const handleValuesChange = useCallback(
|
136 |
+
(changedValues: any, values: any) => {
|
137 |
+
console.info(changedValues, values);
|
138 |
+
if (id) {
|
139 |
+
updateNodeForm(id, values);
|
140 |
+
}
|
141 |
+
},
|
142 |
+
[updateNodeForm, id],
|
143 |
+
);
|
144 |
+
|
145 |
+
return { handleValuesChange };
|
146 |
+
};
|
147 |
+
|
148 |
+
export const useFetchDataOnMount = () => {
|
149 |
+
useFetchFlowTemplates();
|
150 |
+
useFetchLlmList();
|
151 |
+
};
|
web/src/pages/flow/index.tsx
CHANGED
@@ -4,19 +4,22 @@ import { ReactFlowProvider } from 'reactflow';
|
|
4 |
import FlowCanvas from './canvas';
|
5 |
import Sider from './flow-sider';
|
6 |
import FlowHeader from './header';
|
|
|
7 |
|
8 |
const { Content } = Layout;
|
9 |
|
10 |
function RagFlow() {
|
11 |
const [collapsed, setCollapsed] = useState(false);
|
12 |
|
|
|
|
|
13 |
return (
|
14 |
<Layout>
|
15 |
<ReactFlowProvider>
|
16 |
<Sider setCollapsed={setCollapsed} collapsed={collapsed}></Sider>
|
17 |
<Layout>
|
18 |
<FlowHeader></FlowHeader>
|
19 |
-
<Content style={{ margin:
|
20 |
<FlowCanvas sideWidth={collapsed ? 0 : 200}></FlowCanvas>
|
21 |
</Content>
|
22 |
</Layout>
|
|
|
4 |
import FlowCanvas from './canvas';
|
5 |
import Sider from './flow-sider';
|
6 |
import FlowHeader from './header';
|
7 |
+
import { useFetchDataOnMount } from './hooks';
|
8 |
|
9 |
const { Content } = Layout;
|
10 |
|
11 |
function RagFlow() {
|
12 |
const [collapsed, setCollapsed] = useState(false);
|
13 |
|
14 |
+
useFetchDataOnMount();
|
15 |
+
|
16 |
return (
|
17 |
<Layout>
|
18 |
<ReactFlowProvider>
|
19 |
<Sider setCollapsed={setCollapsed} collapsed={collapsed}></Sider>
|
20 |
<Layout>
|
21 |
<FlowHeader></FlowHeader>
|
22 |
+
<Content style={{ margin: 0 }}>
|
23 |
<FlowCanvas sideWidth={collapsed ? 0 : 200}></FlowCanvas>
|
24 |
</Content>
|
25 |
</Layout>
|
web/src/pages/flow/interface.ts
CHANGED
@@ -1,4 +1,62 @@
|
|
|
|
|
|
1 |
export interface DSLComponentList {
|
2 |
id: string;
|
3 |
name: string;
|
4 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Edge, Node } from 'reactflow';
|
2 |
+
|
3 |
export interface DSLComponentList {
|
4 |
id: string;
|
5 |
name: string;
|
6 |
}
|
7 |
+
|
8 |
+
export interface IOperatorForm {
|
9 |
+
onValuesChange?(changedValues: any, values: any): void;
|
10 |
+
}
|
11 |
+
|
12 |
+
export interface IBeginForm {
|
13 |
+
prologue?: string;
|
14 |
+
}
|
15 |
+
|
16 |
+
export interface IRetrievalForm {
|
17 |
+
similarity_threshold?: number;
|
18 |
+
keywords_similarity_weight?: number;
|
19 |
+
top_n?: number;
|
20 |
+
top_k?: number;
|
21 |
+
rerank_id?: string;
|
22 |
+
empty_response?: string;
|
23 |
+
kb_ids: string[];
|
24 |
+
}
|
25 |
+
|
26 |
+
export interface IGenerateForm {
|
27 |
+
max_tokens?: number;
|
28 |
+
temperature?: number;
|
29 |
+
top_p?: number;
|
30 |
+
presence_penalty?: number;
|
31 |
+
frequency_penalty?: number;
|
32 |
+
cite?: boolean;
|
33 |
+
prompt: number;
|
34 |
+
llm_id: string;
|
35 |
+
parameters: { key: string; component_id: string };
|
36 |
+
}
|
37 |
+
|
38 |
+
export type NodeData = {
|
39 |
+
label: string;
|
40 |
+
color: string;
|
41 |
+
form: IBeginForm | IRetrievalForm | IGenerateForm;
|
42 |
+
};
|
43 |
+
|
44 |
+
export interface IFlow {
|
45 |
+
avatar: null;
|
46 |
+
canvas_type: null;
|
47 |
+
create_date: string;
|
48 |
+
create_time: number;
|
49 |
+
description: null;
|
50 |
+
dsl: {
|
51 |
+
answer: any[];
|
52 |
+
components: DSLComponentList;
|
53 |
+
graph: { nodes: Node[]; edges: Edge[] };
|
54 |
+
history: any[];
|
55 |
+
path: string[];
|
56 |
+
};
|
57 |
+
id: string;
|
58 |
+
title: string;
|
59 |
+
update_date: string;
|
60 |
+
update_time: number;
|
61 |
+
user_id: string;
|
62 |
+
}
|
web/src/pages/flow/list/flow-card/index.less
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.container {
|
2 |
+
height: 251px;
|
3 |
+
display: flex;
|
4 |
+
flex-direction: column;
|
5 |
+
justify-content: space-between;
|
6 |
+
|
7 |
+
.delete {
|
8 |
+
height: 24px;
|
9 |
+
}
|
10 |
+
|
11 |
+
.content {
|
12 |
+
display: flex;
|
13 |
+
justify-content: space-between;
|
14 |
+
|
15 |
+
.context {
|
16 |
+
flex: 1;
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
.footer {
|
21 |
+
// text-align: left;
|
22 |
+
}
|
23 |
+
.footerTop {
|
24 |
+
padding-bottom: 2px;
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
.card {
|
29 |
+
border-radius: 12px;
|
30 |
+
border: 1px solid rgba(234, 236, 240, 1);
|
31 |
+
box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
|
32 |
+
padding: 24px;
|
33 |
+
width: 300px;
|
34 |
+
cursor: pointer;
|
35 |
+
|
36 |
+
.titleWrapper {
|
37 |
+
// flex: 1;
|
38 |
+
.title {
|
39 |
+
font-size: 24px;
|
40 |
+
line-height: 32px;
|
41 |
+
font-weight: 600;
|
42 |
+
color: rgba(0, 0, 0, 0.88);
|
43 |
+
word-break: break-all;
|
44 |
+
}
|
45 |
+
.description {
|
46 |
+
font-size: 12px;
|
47 |
+
font-weight: 600;
|
48 |
+
line-height: 20px;
|
49 |
+
color: rgba(0, 0, 0, 0.45);
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
:global {
|
54 |
+
.ant-card-body {
|
55 |
+
padding: 0;
|
56 |
+
margin: 0;
|
57 |
+
}
|
58 |
+
}
|
59 |
+
.bottom {
|
60 |
+
display: flex;
|
61 |
+
align-items: center;
|
62 |
+
justify-content: space-between;
|
63 |
+
}
|
64 |
+
.bottomLeft {
|
65 |
+
vertical-align: middle;
|
66 |
+
}
|
67 |
+
.leftIcon {
|
68 |
+
margin-right: 10px;
|
69 |
+
font-size: 18px;
|
70 |
+
vertical-align: middle;
|
71 |
+
}
|
72 |
+
.rightText {
|
73 |
+
font-size: 12px;
|
74 |
+
font-weight: 600;
|
75 |
+
color: rgba(0, 0, 0, 0.65);
|
76 |
+
vertical-align: middle;
|
77 |
+
}
|
78 |
+
}
|
web/src/pages/flow/list/flow-card/index.tsx
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { ReactComponent as MoreIcon } from '@/assets/svg/more.svg';
|
2 |
+
import { useShowDeleteConfirm } from '@/hooks/commonHooks';
|
3 |
+
import { formatDate } from '@/utils/date';
|
4 |
+
import {
|
5 |
+
CalendarOutlined,
|
6 |
+
DeleteOutlined,
|
7 |
+
UserOutlined,
|
8 |
+
} from '@ant-design/icons';
|
9 |
+
import { Avatar, Card, Dropdown, MenuProps, Space } from 'antd';
|
10 |
+
import { useTranslation } from 'react-i18next';
|
11 |
+
import { useNavigate } from 'umi';
|
12 |
+
|
13 |
+
import { useDeleteFlow } from '@/hooks/flow-hooks';
|
14 |
+
import { IFlow } from '../../interface';
|
15 |
+
import styles from './index.less';
|
16 |
+
|
17 |
+
interface IProps {
|
18 |
+
item: IFlow;
|
19 |
+
}
|
20 |
+
|
21 |
+
const FlowCard = ({ item }: IProps) => {
|
22 |
+
const navigate = useNavigate();
|
23 |
+
const showDeleteConfirm = useShowDeleteConfirm();
|
24 |
+
const { t } = useTranslation();
|
25 |
+
const { deleteFlow } = useDeleteFlow();
|
26 |
+
|
27 |
+
const removeKnowledge = () => {
|
28 |
+
return deleteFlow([item.id]);
|
29 |
+
};
|
30 |
+
|
31 |
+
const handleDelete = () => {
|
32 |
+
showDeleteConfirm({ onOk: removeKnowledge });
|
33 |
+
};
|
34 |
+
|
35 |
+
const items: MenuProps['items'] = [
|
36 |
+
{
|
37 |
+
key: '1',
|
38 |
+
label: (
|
39 |
+
<Space>
|
40 |
+
{t('common.delete')}
|
41 |
+
<DeleteOutlined />
|
42 |
+
</Space>
|
43 |
+
),
|
44 |
+
},
|
45 |
+
];
|
46 |
+
|
47 |
+
const handleDropdownMenuClick: MenuProps['onClick'] = ({ domEvent, key }) => {
|
48 |
+
domEvent.preventDefault();
|
49 |
+
domEvent.stopPropagation();
|
50 |
+
if (key === '1') {
|
51 |
+
handleDelete();
|
52 |
+
}
|
53 |
+
};
|
54 |
+
|
55 |
+
const handleCardClick = () => {
|
56 |
+
navigate(`/flow/${item.id}`);
|
57 |
+
};
|
58 |
+
|
59 |
+
return (
|
60 |
+
<Card className={styles.card} onClick={handleCardClick}>
|
61 |
+
<div className={styles.container}>
|
62 |
+
<div className={styles.content}>
|
63 |
+
<Avatar size={34} icon={<UserOutlined />} src={item.avatar} />
|
64 |
+
<Dropdown
|
65 |
+
menu={{
|
66 |
+
items,
|
67 |
+
onClick: handleDropdownMenuClick,
|
68 |
+
}}
|
69 |
+
>
|
70 |
+
<span className={styles.delete}>
|
71 |
+
<MoreIcon />
|
72 |
+
</span>
|
73 |
+
</Dropdown>
|
74 |
+
</div>
|
75 |
+
<div className={styles.titleWrapper}>
|
76 |
+
<span className={styles.title}>{item.title}</span>
|
77 |
+
<p>{item.description}</p>
|
78 |
+
</div>
|
79 |
+
<div className={styles.footer}>
|
80 |
+
<div className={styles.bottom}>
|
81 |
+
<div className={styles.bottomLeft}>
|
82 |
+
<CalendarOutlined className={styles.leftIcon} />
|
83 |
+
<span className={styles.rightText}>
|
84 |
+
{formatDate(item.update_time)}
|
85 |
+
</span>
|
86 |
+
</div>
|
87 |
+
</div>
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
</Card>
|
91 |
+
);
|
92 |
+
};
|
93 |
+
|
94 |
+
export default FlowCard;
|
web/src/pages/flow/list/hooks.ts
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useSetModalState } from '@/hooks/commonHooks';
|
2 |
+
import { useFetchFlowList, useSetFlow } from '@/hooks/flow-hooks';
|
3 |
+
import { useCallback, useState } from 'react';
|
4 |
+
import { dsl } from '../mock';
|
5 |
+
|
6 |
+
export const useFetchDataOnMount = () => {
|
7 |
+
const { data, loading } = useFetchFlowList();
|
8 |
+
|
9 |
+
return { list: data, loading };
|
10 |
+
};
|
11 |
+
|
12 |
+
export const useSaveFlow = () => {
|
13 |
+
const [currentFlow, setCurrentFlow] = useState({});
|
14 |
+
const {
|
15 |
+
visible: flowSettingVisible,
|
16 |
+
hideModal: hideFlowSettingModal,
|
17 |
+
showModal: showFileRenameModal,
|
18 |
+
} = useSetModalState();
|
19 |
+
const { loading, setFlow } = useSetFlow();
|
20 |
+
|
21 |
+
const onFlowOk = useCallback(
|
22 |
+
async (title: string) => {
|
23 |
+
const ret = await setFlow({ title, dsl });
|
24 |
+
|
25 |
+
if (ret === 0) {
|
26 |
+
hideFlowSettingModal();
|
27 |
+
}
|
28 |
+
},
|
29 |
+
[setFlow, hideFlowSettingModal],
|
30 |
+
);
|
31 |
+
|
32 |
+
const handleShowFlowSettingModal = useCallback(
|
33 |
+
async (record: any) => {
|
34 |
+
setCurrentFlow(record);
|
35 |
+
showFileRenameModal();
|
36 |
+
},
|
37 |
+
[showFileRenameModal],
|
38 |
+
);
|
39 |
+
|
40 |
+
return {
|
41 |
+
flowSettingLoading: loading,
|
42 |
+
initialFlowName: '',
|
43 |
+
onFlowOk,
|
44 |
+
flowSettingVisible,
|
45 |
+
hideFlowSettingModal,
|
46 |
+
showFlowSettingModal: handleShowFlowSettingModal,
|
47 |
+
};
|
48 |
+
};
|
web/src/pages/flow/list/index.less
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.flowListWrapper {
|
2 |
+
padding: 48px;
|
3 |
+
}
|
4 |
+
|
5 |
+
.topWrapper {
|
6 |
+
display: flex;
|
7 |
+
justify-content: space-between;
|
8 |
+
align-items: flex-start;
|
9 |
+
padding: 0 60px 72px;
|
10 |
+
|
11 |
+
.title {
|
12 |
+
font-family: Inter;
|
13 |
+
font-size: 30px;
|
14 |
+
font-style: normal;
|
15 |
+
font-weight: @fontWeight600;
|
16 |
+
line-height: 38px;
|
17 |
+
color: rgba(16, 24, 40, 1);
|
18 |
+
}
|
19 |
+
.description {
|
20 |
+
font-family: Inter;
|
21 |
+
font-size: 16px;
|
22 |
+
font-style: normal;
|
23 |
+
font-weight: 400;
|
24 |
+
line-height: 24px;
|
25 |
+
color: rgba(71, 84, 103, 1);
|
26 |
+
}
|
27 |
+
|
28 |
+
.topButton {
|
29 |
+
font-family: Inter;
|
30 |
+
font-size: 14px;
|
31 |
+
font-style: normal;
|
32 |
+
font-weight: @fontWeight600;
|
33 |
+
line-height: 20px;
|
34 |
+
}
|
35 |
+
|
36 |
+
.filterButton {
|
37 |
+
display: flex;
|
38 |
+
align-items: center;
|
39 |
+
.topButton();
|
40 |
+
}
|
41 |
+
}
|
42 |
+
.flowCardContainer {
|
43 |
+
padding: 0 60px;
|
44 |
+
overflow: auto;
|
45 |
+
.knowledgeEmpty {
|
46 |
+
width: 100%;
|
47 |
+
}
|
48 |
+
}
|
web/src/pages/flow/list/index.tsx
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import RenameModal from '@/components/rename-modal';
|
2 |
+
import { PlusOutlined } from '@ant-design/icons';
|
3 |
+
import { Button, Empty, Flex, Spin } from 'antd';
|
4 |
+
import FlowCard from './flow-card';
|
5 |
+
import { useFetchDataOnMount, useSaveFlow } from './hooks';
|
6 |
+
|
7 |
+
import styles from './index.less';
|
8 |
+
|
9 |
+
const FlowList = () => {
|
10 |
+
const {
|
11 |
+
showFlowSettingModal,
|
12 |
+
hideFlowSettingModal,
|
13 |
+
flowSettingVisible,
|
14 |
+
flowSettingLoading,
|
15 |
+
onFlowOk,
|
16 |
+
} = useSaveFlow();
|
17 |
+
|
18 |
+
const { list, loading } = useFetchDataOnMount();
|
19 |
+
|
20 |
+
return (
|
21 |
+
<Flex className={styles.flowListWrapper} vertical flex={1} gap={'large'}>
|
22 |
+
<Flex justify={'end'}>
|
23 |
+
<Button
|
24 |
+
type="primary"
|
25 |
+
icon={<PlusOutlined />}
|
26 |
+
onClick={showFlowSettingModal}
|
27 |
+
>
|
28 |
+
create canvas
|
29 |
+
</Button>
|
30 |
+
</Flex>
|
31 |
+
<Spin spinning={loading}>
|
32 |
+
<Flex gap={'large'} wrap="wrap" className={styles.flowCardContainer}>
|
33 |
+
{list.length > 0 ? (
|
34 |
+
list.map((item: any) => {
|
35 |
+
return <FlowCard item={item} key={item.name}></FlowCard>;
|
36 |
+
})
|
37 |
+
) : (
|
38 |
+
<Empty className={styles.knowledgeEmpty}></Empty>
|
39 |
+
)}
|
40 |
+
</Flex>
|
41 |
+
</Spin>
|
42 |
+
<RenameModal
|
43 |
+
visible={flowSettingVisible}
|
44 |
+
onOk={onFlowOk}
|
45 |
+
loading={flowSettingLoading}
|
46 |
+
hideModal={hideFlowSettingModal}
|
47 |
+
initialName=""
|
48 |
+
></RenameModal>
|
49 |
+
</Flex>
|
50 |
+
);
|
51 |
+
};
|
52 |
+
|
53 |
+
export default FlowList;
|
web/src/pages/flow/mock.tsx
CHANGED
@@ -1,12 +1,7 @@
|
|
1 |
-
import {
|
2 |
-
MergeCellsOutlined,
|
3 |
-
RocketOutlined,
|
4 |
-
SendOutlined,
|
5 |
-
} from '@ant-design/icons';
|
6 |
import { Position } from 'reactflow';
|
7 |
|
8 |
export const componentList = [
|
9 |
-
{ name: 'Begin', icon: <SendOutlined />, description: '' },
|
10 |
{ name: 'Retrieval', icon: <RocketOutlined />, description: '' },
|
11 |
{ name: 'Generate', icon: <MergeCellsOutlined />, description: '' },
|
12 |
];
|
@@ -159,7 +154,14 @@ export const dsl = {
|
|
159 |
'Retrieval:China': {
|
160 |
obj: {
|
161 |
component_name: 'Retrieval',
|
162 |
-
params: {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
},
|
164 |
downstream: ['Generate:China'],
|
165 |
upstream: ['Answer:China'],
|
@@ -167,7 +169,12 @@ export const dsl = {
|
|
167 |
'Generate:China': {
|
168 |
obj: {
|
169 |
component_name: 'Generate',
|
170 |
-
params: {
|
|
|
|
|
|
|
|
|
|
|
171 |
},
|
172 |
downstream: ['Answer:China'],
|
173 |
upstream: ['Retrieval:China'],
|
|
|
1 |
+
import { MergeCellsOutlined, RocketOutlined } from '@ant-design/icons';
|
|
|
|
|
|
|
|
|
2 |
import { Position } from 'reactflow';
|
3 |
|
4 |
export const componentList = [
|
|
|
5 |
{ name: 'Retrieval', icon: <RocketOutlined />, description: '' },
|
6 |
{ name: 'Generate', icon: <MergeCellsOutlined />, description: '' },
|
7 |
];
|
|
|
154 |
'Retrieval:China': {
|
155 |
obj: {
|
156 |
component_name: 'Retrieval',
|
157 |
+
params: {
|
158 |
+
similarity_threshold: 0.2,
|
159 |
+
keywords_similarity_weight: 0.3,
|
160 |
+
top_n: 6,
|
161 |
+
top_k: 1024,
|
162 |
+
rerank_id: 'BAAI/bge-reranker-v2-m3',
|
163 |
+
kb_ids: ['568aa82603b611efa9d9fa163e197198'],
|
164 |
+
},
|
165 |
},
|
166 |
downstream: ['Generate:China'],
|
167 |
upstream: ['Answer:China'],
|
|
|
169 |
'Generate:China': {
|
170 |
obj: {
|
171 |
component_name: 'Generate',
|
172 |
+
params: {
|
173 |
+
llm_id: 'deepseek-chat',
|
174 |
+
prompt:
|
175 |
+
'You are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence "The answer you are looking for is not found in the knowledge base!" Answers need to consider chat history.\n Here is the knowledge base:\n {input}\n The above is the knowledge base.',
|
176 |
+
temperature: 0.2,
|
177 |
+
},
|
178 |
},
|
179 |
downstream: ['Answer:China'],
|
180 |
upstream: ['Retrieval:China'],
|
web/src/pages/flow/retrieval-form/index.tsx
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import KnowledgeBaseItem from '@/components/knowledge-base-item';
|
2 |
+
import Rerank from '@/components/rerank';
|
3 |
+
import SimilaritySlider from '@/components/similarity-slider';
|
4 |
+
import TopNItem from '@/components/top-n-item';
|
5 |
+
import type { FormProps } from 'antd';
|
6 |
+
import { Form } from 'antd';
|
7 |
+
import { IOperatorForm } from '../interface';
|
8 |
+
|
9 |
+
type FieldType = {
|
10 |
+
top_n?: number;
|
11 |
+
};
|
12 |
+
|
13 |
+
const onFinish: FormProps<FieldType>['onFinish'] = (values) => {
|
14 |
+
console.log('Success:', values);
|
15 |
+
};
|
16 |
+
|
17 |
+
const onFinishFailed: FormProps<FieldType>['onFinishFailed'] = (errorInfo) => {
|
18 |
+
console.log('Failed:', errorInfo);
|
19 |
+
};
|
20 |
+
|
21 |
+
const RetrievalForm = ({ onValuesChange }: IOperatorForm) => {
|
22 |
+
const [form] = Form.useForm();
|
23 |
+
|
24 |
+
return (
|
25 |
+
<Form
|
26 |
+
name="basic"
|
27 |
+
labelCol={{ span: 12 }}
|
28 |
+
wrapperCol={{ span: 12 }}
|
29 |
+
onFinish={onFinish}
|
30 |
+
onFinishFailed={onFinishFailed}
|
31 |
+
autoComplete="off"
|
32 |
+
onValuesChange={onValuesChange}
|
33 |
+
form={form}
|
34 |
+
>
|
35 |
+
<SimilaritySlider isTooltipShown></SimilaritySlider>
|
36 |
+
<TopNItem></TopNItem>
|
37 |
+
<Rerank></Rerank>
|
38 |
+
<KnowledgeBaseItem></KnowledgeBaseItem>
|
39 |
+
</Form>
|
40 |
+
);
|
41 |
+
};
|
42 |
+
|
43 |
+
export default RetrievalForm;
|
web/src/pages/flow/store.ts
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type {} from '@redux-devtools/extension';
|
2 |
+
import {
|
3 |
+
Connection,
|
4 |
+
Edge,
|
5 |
+
EdgeChange,
|
6 |
+
Node,
|
7 |
+
NodeChange,
|
8 |
+
OnConnect,
|
9 |
+
OnEdgesChange,
|
10 |
+
OnNodesChange,
|
11 |
+
OnSelectionChangeFunc,
|
12 |
+
OnSelectionChangeParams,
|
13 |
+
addEdge,
|
14 |
+
applyEdgeChanges,
|
15 |
+
applyNodeChanges,
|
16 |
+
} from 'reactflow';
|
17 |
+
import { create } from 'zustand';
|
18 |
+
import { devtools } from 'zustand/middleware';
|
19 |
+
import { NodeData } from './interface';
|
20 |
+
import { dsl } from './mock';
|
21 |
+
|
22 |
+
const { nodes: initialNodes, edges: initialEdges } = dsl.graph;
|
23 |
+
|
24 |
+
export type RFState = {
|
25 |
+
nodes: Node<NodeData>[];
|
26 |
+
edges: Edge[];
|
27 |
+
selectedNodeIds: string[];
|
28 |
+
selectedEdgeIds: string[];
|
29 |
+
onNodesChange: OnNodesChange;
|
30 |
+
onEdgesChange: OnEdgesChange;
|
31 |
+
onConnect: OnConnect;
|
32 |
+
setNodes: (nodes: Node[]) => void;
|
33 |
+
setEdges: (edges: Edge[]) => void;
|
34 |
+
updateNodeForm: (nodeId: string, values: any) => void;
|
35 |
+
onSelectionChange: OnSelectionChangeFunc;
|
36 |
+
addNode: (nodes: Node) => void;
|
37 |
+
deleteEdge: () => void;
|
38 |
+
deleteEdgeById: (id: string) => void;
|
39 |
+
};
|
40 |
+
|
41 |
+
// this is our useStore hook that we can use in our components to get parts of the store and call actions
|
42 |
+
const useStore = create<RFState>()(
|
43 |
+
devtools((set, get) => ({
|
44 |
+
nodes: initialNodes as Node[],
|
45 |
+
edges: initialEdges as Edge[],
|
46 |
+
selectedNodeIds: [],
|
47 |
+
selectedEdgeIds: [],
|
48 |
+
onNodesChange: (changes: NodeChange[]) => {
|
49 |
+
set({
|
50 |
+
nodes: applyNodeChanges(changes, get().nodes),
|
51 |
+
});
|
52 |
+
},
|
53 |
+
onEdgesChange: (changes: EdgeChange[]) => {
|
54 |
+
set({
|
55 |
+
edges: applyEdgeChanges(changes, get().edges),
|
56 |
+
});
|
57 |
+
},
|
58 |
+
onConnect: (connection: Connection) => {
|
59 |
+
set({
|
60 |
+
edges: addEdge(connection, get().edges),
|
61 |
+
});
|
62 |
+
},
|
63 |
+
onSelectionChange: ({ nodes, edges }: OnSelectionChangeParams) => {
|
64 |
+
set({
|
65 |
+
selectedEdgeIds: edges.map((x) => x.id),
|
66 |
+
selectedNodeIds: nodes.map((x) => x.id),
|
67 |
+
});
|
68 |
+
},
|
69 |
+
setNodes: (nodes: Node[]) => {
|
70 |
+
set({ nodes });
|
71 |
+
},
|
72 |
+
setEdges: (edges: Edge[]) => {
|
73 |
+
set({ edges });
|
74 |
+
},
|
75 |
+
addNode: (node: Node) => {
|
76 |
+
set({ nodes: get().nodes.concat(node) });
|
77 |
+
},
|
78 |
+
deleteEdge: () => {
|
79 |
+
const { edges, selectedEdgeIds } = get();
|
80 |
+
set({
|
81 |
+
edges: edges.filter((edge) =>
|
82 |
+
selectedEdgeIds.every((x) => x !== edge.id),
|
83 |
+
),
|
84 |
+
});
|
85 |
+
},
|
86 |
+
deleteEdgeById: (id: string) => {
|
87 |
+
const { edges } = get();
|
88 |
+
set({
|
89 |
+
edges: edges.filter((edge) => edge.id !== id),
|
90 |
+
});
|
91 |
+
},
|
92 |
+
updateNodeForm: (nodeId: string, values: any) => {
|
93 |
+
set({
|
94 |
+
nodes: get().nodes.map((node) => {
|
95 |
+
if (node.id === nodeId) {
|
96 |
+
node.data = { ...node.data, form: values };
|
97 |
+
}
|
98 |
+
|
99 |
+
return node;
|
100 |
+
}),
|
101 |
+
});
|
102 |
+
},
|
103 |
+
})),
|
104 |
+
);
|
105 |
+
|
106 |
+
export default useStore;
|
web/src/pages/flow/utils.ts
CHANGED
@@ -2,6 +2,7 @@ import { DSLComponents } from '@/interfaces/database/flow';
|
|
2 |
import dagre from 'dagre';
|
3 |
import { Edge, MarkerType, Node, Position } from 'reactflow';
|
4 |
import { v4 as uuidv4 } from 'uuid';
|
|
|
5 |
|
6 |
const buildEdges = (
|
7 |
operatorIds: string[],
|
@@ -96,3 +97,35 @@ export const getLayoutedElements = (
|
|
96 |
|
97 |
return { nodes, edges };
|
98 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import dagre from 'dagre';
|
3 |
import { Edge, MarkerType, Node, Position } from 'reactflow';
|
4 |
import { v4 as uuidv4 } from 'uuid';
|
5 |
+
import { NodeData } from './interface';
|
6 |
|
7 |
const buildEdges = (
|
8 |
operatorIds: string[],
|
|
|
97 |
|
98 |
return { nodes, edges };
|
99 |
};
|
100 |
+
|
101 |
+
const buildComponentDownstreamOrUpstream = (
|
102 |
+
edges: Edge[],
|
103 |
+
nodeId: string,
|
104 |
+
isBuildDownstream = true,
|
105 |
+
) => {
|
106 |
+
return edges
|
107 |
+
.filter((y) => y[isBuildDownstream ? 'source' : 'target'] === nodeId)
|
108 |
+
.map((y) => y[isBuildDownstream ? 'target' : 'source']);
|
109 |
+
};
|
110 |
+
|
111 |
+
// construct a dsl based on the node information of the graph
|
112 |
+
export const buildDslComponentsByGraph = (
|
113 |
+
nodes: Node<NodeData>[],
|
114 |
+
edges: Edge[],
|
115 |
+
): DSLComponents => {
|
116 |
+
const components: DSLComponents = {};
|
117 |
+
|
118 |
+
nodes.forEach((x) => {
|
119 |
+
const id = x.id;
|
120 |
+
components[id] = {
|
121 |
+
obj: {
|
122 |
+
component_name: x.data.label,
|
123 |
+
params: x.data.form as Record<string, unknown>,
|
124 |
+
},
|
125 |
+
downstream: buildComponentDownstreamOrUpstream(edges, id, true),
|
126 |
+
upstream: buildComponentDownstreamOrUpstream(edges, id, false),
|
127 |
+
};
|
128 |
+
});
|
129 |
+
|
130 |
+
return components;
|
131 |
+
};
|
web/src/routes.ts
CHANGED
@@ -90,6 +90,10 @@ const routes = [
|
|
90 |
},
|
91 |
{
|
92 |
path: '/flow',
|
|
|
|
|
|
|
|
|
93 |
component: '@/pages/flow',
|
94 |
},
|
95 |
],
|
|
|
90 |
},
|
91 |
{
|
92 |
path: '/flow',
|
93 |
+
component: '@/pages/flow/list',
|
94 |
+
},
|
95 |
+
{
|
96 |
+
path: '/flow/:id',
|
97 |
component: '@/pages/flow',
|
98 |
},
|
99 |
],
|
web/src/services/flow-service.ts
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import api from '@/utils/api';
|
2 |
+
import registerServer from '@/utils/registerServer';
|
3 |
+
import request from '@/utils/request';
|
4 |
+
|
5 |
+
const {
|
6 |
+
getCanvas,
|
7 |
+
setCanvas,
|
8 |
+
listCanvas,
|
9 |
+
resetCanvas,
|
10 |
+
removeCanvas,
|
11 |
+
listTemplates,
|
12 |
+
} = api;
|
13 |
+
|
14 |
+
const methods = {
|
15 |
+
getCanvas: {
|
16 |
+
url: getCanvas,
|
17 |
+
method: 'get',
|
18 |
+
},
|
19 |
+
setCanvas: {
|
20 |
+
url: setCanvas,
|
21 |
+
method: 'post',
|
22 |
+
},
|
23 |
+
listCanvas: {
|
24 |
+
url: listCanvas,
|
25 |
+
method: 'get',
|
26 |
+
},
|
27 |
+
resetCanvas: {
|
28 |
+
url: resetCanvas,
|
29 |
+
method: 'post',
|
30 |
+
},
|
31 |
+
removeCanvas: {
|
32 |
+
url: removeCanvas,
|
33 |
+
method: 'post',
|
34 |
+
},
|
35 |
+
listTemplates: {
|
36 |
+
url: listTemplates,
|
37 |
+
method: 'get',
|
38 |
+
},
|
39 |
+
} as const;
|
40 |
+
|
41 |
+
const chatService = registerServer<keyof typeof methods>(methods, request);
|
42 |
+
|
43 |
+
export default chatService;
|
web/src/utils/api.ts
CHANGED
@@ -81,4 +81,12 @@ export default {
|
|
81 |
// system
|
82 |
getSystemVersion: `${api_host}/system/version`,
|
83 |
getSystemStatus: `${api_host}/system/status`,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
};
|
|
|
81 |
// system
|
82 |
getSystemVersion: `${api_host}/system/version`,
|
83 |
getSystemStatus: `${api_host}/system/status`,
|
84 |
+
|
85 |
+
// flow
|
86 |
+
listTemplates: `${api_host}/canvas/templates`,
|
87 |
+
listCanvas: `${api_host}/canvas/list`,
|
88 |
+
getCanvas: `${api_host}/canvas/get`,
|
89 |
+
removeCanvas: `${api_host}/canvas/rm`,
|
90 |
+
setCanvas: `${api_host}/canvas/set`,
|
91 |
+
resetCanvas: `${api_host}/canvas/reset`,
|
92 |
};
|
web/src/utils/registerServer.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import omit from 'lodash/omit';
|
2 |
import { RequestMethod } from 'umi-request';
|
3 |
|
4 |
-
type Service<T extends string> = Record<T, (params
|
5 |
|
6 |
const registerServer = <T extends string>(
|
7 |
opt: Record<T, { url: string; method: string }>,
|
|
|
1 |
import omit from 'lodash/omit';
|
2 |
import { RequestMethod } from 'umi-request';
|
3 |
|
4 |
+
type Service<T extends string> = Record<T, (params?: any) => any>;
|
5 |
|
6 |
const registerServer = <T extends string>(
|
7 |
opt: Record<T, { url: string; method: string }>,
|