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 }>,
|