balibabu commited on
Commit
452020d
·
1 Parent(s): f3d0ebd

feat: add temperature and top-p to ModelSetting and add ChatConfigurationModal and bind backend data to KnowledgeCard (#65)

Browse files

* feat: bind backend data to KnowledgeCard

* feat: add ChatConfigurationModal

* feat: add temperature and top-p to ModelSetting

web/package-lock.json CHANGED
@@ -18,16 +18,19 @@
18
  "lodash": "^4.17.21",
19
  "moment": "^2.30.1",
20
  "rc-tween-one": "^3.0.6",
 
21
  "react-i18next": "^14.0.0",
22
  "react-infinite-scroll-component": "^6.1.0",
23
  "umi": "^4.0.90",
24
- "umi-request": "^1.4.0"
 
25
  },
26
  "devDependencies": {
27
  "@react-dev-inspector/umi4-plugin": "^2.0.1",
28
  "@types/lodash": "^4.14.202",
29
  "@types/react": "^18.0.33",
30
  "@types/react-dom": "^18.0.11",
 
31
  "@umijs/lint": "^4.1.1",
32
  "@umijs/plugins": "^4.1.0",
33
  "cross-env": "^7.0.3",
@@ -2929,6 +2932,12 @@
2929
  "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==",
2930
  "dev": true
2931
  },
 
 
 
 
 
 
2932
  "node_modules/@types/yargs": {
2933
  "version": "16.0.9",
2934
  "resolved": "https://registry.npmmirror.com/@types/yargs/-/yargs-16.0.9.tgz",
@@ -10669,6 +10678,11 @@
10669
  "node": ">=8.9.0"
10670
  }
10671
  },
 
 
 
 
 
10672
  "node_modules/local-pkg": {
10673
  "version": "0.4.3",
10674
  "resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.4.3.tgz",
@@ -12666,6 +12680,15 @@
12666
  "resolved": "https://registry.npmmirror.com/process-warning/-/process-warning-1.0.0.tgz",
12667
  "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q=="
12668
  },
 
 
 
 
 
 
 
 
 
12669
  "node_modules/prompts": {
12670
  "version": "2.4.2",
12671
  "resolved": "https://registry.npmmirror.com/prompts/-/prompts-2.4.2.tgz",
@@ -13446,6 +13469,22 @@
13446
  "node": ">=0.10.0"
13447
  }
13448
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13449
  "node_modules/react-dev-inspector": {
13450
  "version": "2.0.1",
13451
  "resolved": "https://registry.npmmirror.com/react-dev-inspector/-/react-dev-inspector-2.0.1.tgz",
@@ -13784,6 +13823,14 @@
13784
  }
13785
  }
13786
  },
 
 
 
 
 
 
 
 
13787
  "node_modules/react-infinite-scroll-component": {
13788
  "version": "6.1.0",
13789
  "resolved": "https://registry.npmmirror.com/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz",
@@ -13924,6 +13971,17 @@
13924
  "react": ">=15"
13925
  }
13926
  },
 
 
 
 
 
 
 
 
 
 
 
13927
  "node_modules/reactcss": {
13928
  "version": "1.2.3",
13929
  "resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
@@ -14633,6 +14691,14 @@
14633
  "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
14634
  "dev": true
14635
  },
 
 
 
 
 
 
 
 
14636
  "node_modules/side-channel": {
14637
  "version": "1.0.4",
14638
  "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
@@ -15783,6 +15849,11 @@
15783
  "node": ">=12.22"
15784
  }
15785
  },
 
 
 
 
 
15786
  "node_modules/timers-browserify": {
15787
  "version": "2.0.12",
15788
  "resolved": "https://registry.npmmirror.com/timers-browserify/-/timers-browserify-2.0.12.tgz",
@@ -16859,6 +16930,14 @@
16859
  "resolved": "https://registry.npmmirror.com/utila/-/utila-0.4.0.tgz",
16860
  "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA=="
16861
  },
 
 
 
 
 
 
 
 
16862
  "node_modules/v8-compile-cache": {
16863
  "version": "2.4.0",
16864
  "resolved": "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz",
 
18
  "lodash": "^4.17.21",
19
  "moment": "^2.30.1",
20
  "rc-tween-one": "^3.0.6",
21
+ "react-chat-elements": "^12.0.13",
22
  "react-i18next": "^14.0.0",
23
  "react-infinite-scroll-component": "^6.1.0",
24
  "umi": "^4.0.90",
25
+ "umi-request": "^1.4.0",
26
+ "uuid": "^9.0.1"
27
  },
28
  "devDependencies": {
29
  "@react-dev-inspector/umi4-plugin": "^2.0.1",
30
  "@types/lodash": "^4.14.202",
31
  "@types/react": "^18.0.33",
32
  "@types/react-dom": "^18.0.11",
33
+ "@types/uuid": "^9.0.8",
34
  "@umijs/lint": "^4.1.1",
35
  "@umijs/plugins": "^4.1.0",
36
  "cross-env": "^7.0.3",
 
2932
  "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==",
2933
  "dev": true
2934
  },
2935
+ "node_modules/@types/uuid": {
2936
+ "version": "9.0.8",
2937
+ "resolved": "https://registry.npmmirror.com/@types/uuid/-/uuid-9.0.8.tgz",
2938
+ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
2939
+ "dev": true
2940
+ },
2941
  "node_modules/@types/yargs": {
2942
  "version": "16.0.9",
2943
  "resolved": "https://registry.npmmirror.com/@types/yargs/-/yargs-16.0.9.tgz",
 
10678
  "node": ">=8.9.0"
10679
  }
10680
  },
10681
+ "node_modules/loaders.css": {
10682
+ "version": "0.1.2",
10683
+ "resolved": "https://registry.npmmirror.com/loaders.css/-/loaders.css-0.1.2.tgz",
10684
+ "integrity": "sha512-Rhowlq24ey1VOeor+3wYOt9+MjaxBOJm1u4KlQgNC3+0xJ0LS4wq4iG57D/BPzvuD/7HHDGQOWJ+81oR2EI9bQ=="
10685
+ },
10686
  "node_modules/local-pkg": {
10687
  "version": "0.4.3",
10688
  "resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.4.3.tgz",
 
12680
  "resolved": "https://registry.npmmirror.com/process-warning/-/process-warning-1.0.0.tgz",
12681
  "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q=="
12682
  },
12683
+ "node_modules/progressbar.js": {
12684
+ "version": "1.1.1",
12685
+ "resolved": "https://registry.npmmirror.com/progressbar.js/-/progressbar.js-1.1.1.tgz",
12686
+ "integrity": "sha512-FBsw3BKsUbb+hNeYfiP3xzvAAQrPi4DnGDw66bCmfuRCDLcslxyxv2GyYUdBSKFGSIBa73CUP5WMcl6F8AAXlw==",
12687
+ "dependencies": {
12688
+ "lodash.merge": "^4.6.2",
12689
+ "shifty": "^2.8.3"
12690
+ }
12691
+ },
12692
  "node_modules/prompts": {
12693
  "version": "2.4.2",
12694
  "resolved": "https://registry.npmmirror.com/prompts/-/prompts-2.4.2.tgz",
 
13469
  "node": ">=0.10.0"
13470
  }
13471
  },
13472
+ "node_modules/react-chat-elements": {
13473
+ "version": "12.0.13",
13474
+ "resolved": "https://registry.npmmirror.com/react-chat-elements/-/react-chat-elements-12.0.13.tgz",
13475
+ "integrity": "sha512-Vu5x8kW4LPu8onKfz5vsuDwZsDhoQmTBHJdqKAhVsi42PCQ8KOfzHiDp0fPUJlinJZ/MTJTm69UAchpys4iSTQ==",
13476
+ "dependencies": {
13477
+ "classnames": "^2.2.5",
13478
+ "progressbar.js": "^1.1.0",
13479
+ "react-icons": "^4.3.1",
13480
+ "react-spinkit": "^3.0.0",
13481
+ "timeago.js": "^4.0.2"
13482
+ },
13483
+ "peerDependencies": {
13484
+ "react": "^18.2.0",
13485
+ "react-dom": "18.2.0"
13486
+ }
13487
+ },
13488
  "node_modules/react-dev-inspector": {
13489
  "version": "2.0.1",
13490
  "resolved": "https://registry.npmmirror.com/react-dev-inspector/-/react-dev-inspector-2.0.1.tgz",
 
13823
  }
13824
  }
13825
  },
13826
+ "node_modules/react-icons": {
13827
+ "version": "4.12.0",
13828
+ "resolved": "https://registry.npmmirror.com/react-icons/-/react-icons-4.12.0.tgz",
13829
+ "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==",
13830
+ "peerDependencies": {
13831
+ "react": "*"
13832
+ }
13833
+ },
13834
  "node_modules/react-infinite-scroll-component": {
13835
  "version": "6.1.0",
13836
  "resolved": "https://registry.npmmirror.com/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz",
 
13971
  "react": ">=15"
13972
  }
13973
  },
13974
+ "node_modules/react-spinkit": {
13975
+ "version": "3.0.0",
13976
+ "resolved": "https://registry.npmmirror.com/react-spinkit/-/react-spinkit-3.0.0.tgz",
13977
+ "integrity": "sha512-RrfGRPjqxHQiy7quPqhjPynTu0zobgQaZu1QYBMpJJ6pCSRRRK16EZMaxdE6fLVYFRJWpX/eGATWLMoVFFT5uQ==",
13978
+ "dependencies": {
13979
+ "classnames": "^2.2.3",
13980
+ "loaders.css": "^0.1.2",
13981
+ "object-assign": "^4.1.0",
13982
+ "prop-types": "^15.5.8"
13983
+ }
13984
+ },
13985
  "node_modules/reactcss": {
13986
  "version": "1.2.3",
13987
  "resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
 
14691
  "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
14692
  "dev": true
14693
  },
14694
+ "node_modules/shifty": {
14695
+ "version": "2.20.4",
14696
+ "resolved": "https://registry.npmmirror.com/shifty/-/shifty-2.20.4.tgz",
14697
+ "integrity": "sha512-4Y0qRkg8ME5XN8yGNAwmFOmsIURGFKT9UQfNL6DDJQErYtN5HsjyoBuJn41ZQfTkuu2rIbRMn9qazjKsDpO2TA==",
14698
+ "optionalDependencies": {
14699
+ "fsevents": "^2.3.2"
14700
+ }
14701
+ },
14702
  "node_modules/side-channel": {
14703
  "version": "1.0.4",
14704
  "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
 
15849
  "node": ">=12.22"
15850
  }
15851
  },
15852
+ "node_modules/timeago.js": {
15853
+ "version": "4.0.2",
15854
+ "resolved": "https://registry.npmmirror.com/timeago.js/-/timeago.js-4.0.2.tgz",
15855
+ "integrity": "sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w=="
15856
+ },
15857
  "node_modules/timers-browserify": {
15858
  "version": "2.0.12",
15859
  "resolved": "https://registry.npmmirror.com/timers-browserify/-/timers-browserify-2.0.12.tgz",
 
16930
  "resolved": "https://registry.npmmirror.com/utila/-/utila-0.4.0.tgz",
16931
  "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA=="
16932
  },
16933
+ "node_modules/uuid": {
16934
+ "version": "9.0.1",
16935
+ "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz",
16936
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
16937
+ "bin": {
16938
+ "uuid": "dist/bin/uuid"
16939
+ }
16940
+ },
16941
  "node_modules/v8-compile-cache": {
16942
  "version": "2.4.0",
16943
  "resolved": "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz",
web/package.json CHANGED
@@ -22,16 +22,19 @@
22
  "lodash": "^4.17.21",
23
  "moment": "^2.30.1",
24
  "rc-tween-one": "^3.0.6",
 
25
  "react-i18next": "^14.0.0",
26
  "react-infinite-scroll-component": "^6.1.0",
27
  "umi": "^4.0.90",
28
- "umi-request": "^1.4.0"
 
29
  },
30
  "devDependencies": {
31
  "@react-dev-inspector/umi4-plugin": "^2.0.1",
32
  "@types/lodash": "^4.14.202",
33
  "@types/react": "^18.0.33",
34
  "@types/react-dom": "^18.0.11",
 
35
  "@umijs/lint": "^4.1.1",
36
  "@umijs/plugins": "^4.1.0",
37
  "cross-env": "^7.0.3",
 
22
  "lodash": "^4.17.21",
23
  "moment": "^2.30.1",
24
  "rc-tween-one": "^3.0.6",
25
+ "react-chat-elements": "^12.0.13",
26
  "react-i18next": "^14.0.0",
27
  "react-infinite-scroll-component": "^6.1.0",
28
  "umi": "^4.0.90",
29
+ "umi-request": "^1.4.0",
30
+ "uuid": "^9.0.1"
31
  },
32
  "devDependencies": {
33
  "@react-dev-inspector/umi4-plugin": "^2.0.1",
34
  "@types/lodash": "^4.14.202",
35
  "@types/react": "^18.0.33",
36
  "@types/react-dom": "^18.0.11",
37
+ "@types/uuid": "^9.0.8",
38
  "@umijs/lint": "^4.1.1",
39
  "@umijs/plugins": "^4.1.0",
40
  "cross-env": "^7.0.3",
web/src/assets/svg/chat-configuration-atom.svg ADDED
web/src/layouts/components/header/index.less CHANGED
@@ -19,9 +19,9 @@
19
  .appName {
20
  vertical-align: middle;
21
  font-family: Inter;
22
- font-size: 14px;
23
  font-style: normal;
24
- font-weight: 400;
25
  line-height: 20px;
26
  }
27
 
 
19
  .appName {
20
  vertical-align: middle;
21
  font-family: Inter;
22
+ font-size: 16px;
23
  font-style: normal;
24
+ font-weight: 600;
25
  line-height: 20px;
26
  }
27
 
web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx CHANGED
@@ -68,7 +68,7 @@ const Configuration = () => {
68
  const fileList = values.avatar;
69
  let avatar;
70
 
71
- if (Array.isArray(fileList)) {
72
  avatar = fileList[0].thumbUrl;
73
  }
74
 
 
68
  const fileList = values.avatar;
69
  let avatar;
70
 
71
+ if (Array.isArray(fileList) && fileList.length > 0) {
72
  avatar = fileList[0].thumbUrl;
73
  }
74
 
web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Form, Input } from 'antd';
2
+
3
+ import classNames from 'classnames';
4
+ import { ISegmentedContentProps } from './interface';
5
+
6
+ import styles from './index.less';
7
+
8
+ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
9
+ return (
10
+ <section
11
+ className={classNames({
12
+ [styles.segmentedHidden]: !show,
13
+ })}
14
+ >
15
+ <Form.Item
16
+ name={'name'}
17
+ label="Assistant name"
18
+ rules={[{ required: true }]}
19
+ >
20
+ <Input placeholder="e.g. Resume Jarvis" />
21
+ </Form.Item>
22
+ <Form.Item name={'avatar'} label="Assistant avatar">
23
+ <Input />
24
+ </Form.Item>
25
+ <Form.Item name={'keywords'} label="Keywords">
26
+ <Input.TextArea autoSize={{ minRows: 3 }} />
27
+ </Form.Item>
28
+ <Form.Item name={'opener'} label="Set an opener">
29
+ <Input.TextArea autoSize={{ minRows: 5 }} />
30
+ </Form.Item>
31
+ </section>
32
+ );
33
+ };
34
+
35
+ export default AssistantSetting;
web/src/pages/chat/chat-configuration-modal/editable-cell.tsx ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Form, FormInstance, Input, InputRef } from 'antd';
2
+ import React, { useContext, useEffect, useRef, useState } from 'react';
3
+
4
+ const EditableContext = React.createContext<FormInstance<any> | null>(null);
5
+
6
+ interface EditableRowProps {
7
+ index: number;
8
+ }
9
+
10
+ interface Item {
11
+ key: string;
12
+ name: string;
13
+ age: string;
14
+ address: string;
15
+ }
16
+
17
+ export const EditableRow: React.FC<EditableRowProps> = ({
18
+ index,
19
+ ...props
20
+ }) => {
21
+ const [form] = Form.useForm();
22
+ return (
23
+ <Form form={form} component={false}>
24
+ <EditableContext.Provider value={form}>
25
+ <tr {...props} />
26
+ </EditableContext.Provider>
27
+ </Form>
28
+ );
29
+ };
30
+
31
+ interface EditableCellProps {
32
+ title: React.ReactNode;
33
+ editable: boolean;
34
+ children: React.ReactNode;
35
+ dataIndex: keyof Item;
36
+ record: Item;
37
+ handleSave: (record: Item) => void;
38
+ }
39
+
40
+ export const EditableCell: React.FC<EditableCellProps> = ({
41
+ title,
42
+ editable,
43
+ children,
44
+ dataIndex,
45
+ record,
46
+ handleSave,
47
+ ...restProps
48
+ }) => {
49
+ const [editing, setEditing] = useState(false);
50
+ const inputRef = useRef<InputRef>(null);
51
+ const form = useContext(EditableContext)!;
52
+
53
+ useEffect(() => {
54
+ if (editing) {
55
+ inputRef.current!.focus();
56
+ }
57
+ }, [editing]);
58
+
59
+ const toggleEdit = () => {
60
+ setEditing(!editing);
61
+ form.setFieldsValue({ [dataIndex]: record[dataIndex] });
62
+ };
63
+
64
+ const save = async () => {
65
+ try {
66
+ const values = await form.validateFields();
67
+
68
+ toggleEdit();
69
+ handleSave({ ...record, ...values });
70
+ } catch (errInfo) {
71
+ console.log('Save failed:', errInfo);
72
+ }
73
+ };
74
+
75
+ let childNode = children;
76
+
77
+ if (editable) {
78
+ childNode = editing ? (
79
+ <Form.Item
80
+ style={{ margin: 0 }}
81
+ name={dataIndex}
82
+ rules={[
83
+ {
84
+ required: true,
85
+ message: `${title} is required.`,
86
+ },
87
+ ]}
88
+ >
89
+ <Input ref={inputRef} onPressEnter={save} onBlur={save} />
90
+ </Form.Item>
91
+ ) : (
92
+ <div
93
+ className="editable-cell-value-wrap"
94
+ style={{ paddingRight: 24 }}
95
+ onClick={toggleEdit}
96
+ >
97
+ {children}
98
+ </div>
99
+ );
100
+ }
101
+
102
+ return <td {...restProps}>{childNode}</td>;
103
+ };
web/src/pages/chat/chat-configuration-modal/index.less ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .chatConfigurationDescription {
2
+ font-size: 14px;
3
+ }
4
+
5
+ .variableContainer {
6
+ padding-bottom: 20px;
7
+ .variableAlign {
8
+ text-align: right;
9
+ }
10
+
11
+ .variableLabel {
12
+ margin-right: 16px;
13
+ }
14
+
15
+ .variableTable {
16
+ margin-top: 14px;
17
+ }
18
+ .editableRow {
19
+ :global(.editable-cell) {
20
+ position: relative;
21
+ }
22
+
23
+ :global(.editable-cell-value-wrap) {
24
+ padding: 5px 12px;
25
+ cursor: pointer;
26
+ height: 22px !important;
27
+ }
28
+ &:hover {
29
+ :global(.editable-cell-value-wrap) {
30
+ padding: 4px 11px;
31
+ border: 1px solid #d9d9d9;
32
+ border-radius: 2px;
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+ .segmentedHidden {
39
+ opacity: 0;
40
+ height: 0;
41
+ width: 0;
42
+ margin: 0;
43
+ }
web/src/pages/chat/chat-configuration-modal/index.tsx ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ReactComponent as ChatConfigurationAtom } from '@/assets/svg/chat-configuration-atom.svg';
2
+ import { IModalManagerChildrenProps } from '@/components/modal-manager';
3
+ import { Divider, Flex, Form, Modal, Segmented } from 'antd';
4
+ import { SegmentedValue } from 'antd/es/segmented';
5
+ import { useState } from 'react';
6
+ import AssistantSetting from './assistant-setting';
7
+ import ModelSetting from './model-setting';
8
+ import PromptEngine from './prompt-engine';
9
+
10
+ import styles from './index.less';
11
+
12
+ enum ConfigurationSegmented {
13
+ AssistantSetting = 'Assistant Setting',
14
+ ModelSetting = 'Model Setting',
15
+ PromptEngine = 'Prompt Engine',
16
+ }
17
+
18
+ const segmentedMap = {
19
+ [ConfigurationSegmented.AssistantSetting]: AssistantSetting,
20
+ [ConfigurationSegmented.ModelSetting]: ModelSetting,
21
+ [ConfigurationSegmented.PromptEngine]: PromptEngine,
22
+ };
23
+
24
+ const layout = {
25
+ labelCol: { span: 6 },
26
+ wrapperCol: { span: 18 },
27
+ };
28
+
29
+ const validateMessages = {
30
+ required: '${label} is required!',
31
+ types: {
32
+ email: '${label} is not a valid email!',
33
+ number: '${label} is not a valid number!',
34
+ },
35
+ number: {
36
+ range: '${label} must be between ${min} and ${max}',
37
+ },
38
+ };
39
+
40
+ const ChatConfigurationModal = ({
41
+ visible,
42
+ hideModal,
43
+ }: IModalManagerChildrenProps) => {
44
+ const [form] = Form.useForm();
45
+ const [value, setValue] = useState<ConfigurationSegmented>(
46
+ ConfigurationSegmented.AssistantSetting,
47
+ );
48
+
49
+ const handleOk = async () => {
50
+ const x = await form.validateFields();
51
+ console.info(x);
52
+ };
53
+
54
+ const handleCancel = () => {
55
+ hideModal();
56
+ };
57
+
58
+ const handleSegmentedChange = (val: SegmentedValue) => {
59
+ setValue(val as ConfigurationSegmented);
60
+ };
61
+
62
+ const title = (
63
+ <Flex gap={16}>
64
+ <ChatConfigurationAtom></ChatConfigurationAtom>
65
+ <div>
66
+ <b>Chat Configuration</b>
67
+ <div className={styles.chatConfigurationDescription}>
68
+ Here, dress up a dedicated assistant for your special knowledge bases!
69
+ 💕
70
+ </div>
71
+ </div>
72
+ </Flex>
73
+ );
74
+
75
+ return (
76
+ <Modal
77
+ title={title}
78
+ width={688}
79
+ open={visible}
80
+ onOk={handleOk}
81
+ onCancel={handleCancel}
82
+ >
83
+ <Segmented
84
+ size={'large'}
85
+ value={value}
86
+ onChange={handleSegmentedChange}
87
+ options={Object.values(ConfigurationSegmented)}
88
+ block
89
+ />
90
+ <Divider></Divider>
91
+ <Form
92
+ {...layout}
93
+ name="nest-messages"
94
+ form={form}
95
+ style={{ maxWidth: 600 }}
96
+ validateMessages={validateMessages}
97
+ colon={false}
98
+ >
99
+ {Object.entries(segmentedMap).map(([key, Element]) => (
100
+ <Element key={key} show={key === value}></Element>
101
+ ))}
102
+ </Form>
103
+ </Modal>
104
+ );
105
+ };
106
+
107
+ export default ChatConfigurationModal;
web/src/pages/chat/chat-configuration-modal/interface.ts ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ export interface ISegmentedContentProps {
2
+ show: boolean;
3
+ }
web/src/pages/chat/chat-configuration-modal/model-setting.tsx ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Divider, Flex, Form, InputNumber, Select, Slider } from 'antd';
2
+ import classNames from 'classnames';
3
+ import { ISegmentedContentProps } from './interface';
4
+
5
+ import styles from './index.less';
6
+
7
+ const { Option } = Select;
8
+
9
+ const ModelSetting = ({ show }: ISegmentedContentProps) => {
10
+ return (
11
+ <section
12
+ className={classNames({
13
+ [styles.segmentedHidden]: !show,
14
+ })}
15
+ >
16
+ <Form.Item
17
+ label="Model"
18
+ name="model"
19
+ // rules={[{ required: true, message: 'Please input!' }]}
20
+ >
21
+ <Select />
22
+ </Form.Item>
23
+ <Divider></Divider>
24
+ <Form.Item
25
+ label="Parameters"
26
+ name="parameters"
27
+ // rules={[{ required: true, message: 'Please input!' }]}
28
+ >
29
+ <Select />
30
+ </Form.Item>
31
+ <Form.Item label="Temperature">
32
+ <Flex gap={20}>
33
+ <Flex flex={1}>
34
+ <Form.Item
35
+ name={['address', 'province']}
36
+ noStyle
37
+ rules={[{ required: true, message: 'Province is required' }]}
38
+ >
39
+ <Slider style={{ display: 'inline-block', width: '100%' }} />
40
+ </Form.Item>
41
+ </Flex>
42
+ <Form.Item
43
+ name={['address', 'street']}
44
+ noStyle
45
+ rules={[{ required: true, message: 'Street is required' }]}
46
+ >
47
+ <InputNumber
48
+ style={{
49
+ width: 50,
50
+ }}
51
+ />
52
+ </Form.Item>
53
+ </Flex>
54
+ </Form.Item>
55
+ <Form.Item label="Top P">
56
+ <Flex gap={20}>
57
+ <Flex flex={1}>
58
+ <Form.Item
59
+ name={['address', 'province']}
60
+ noStyle
61
+ rules={[{ required: true, message: 'Province is required' }]}
62
+ >
63
+ <Slider style={{ display: 'inline-block', width: '100%' }} />
64
+ </Form.Item>
65
+ </Flex>
66
+ <Form.Item
67
+ name={['address', 'street']}
68
+ noStyle
69
+ rules={[{ required: true, message: 'Street is required' }]}
70
+ >
71
+ <InputNumber
72
+ style={{
73
+ width: 50,
74
+ }}
75
+ />
76
+ </Form.Item>
77
+ </Flex>
78
+ </Form.Item>
79
+ <Form.Item label="Presence Penalty">
80
+ <Flex gap={20}>
81
+ <Flex flex={1}>
82
+ <Form.Item
83
+ name={['address', 'province']}
84
+ noStyle
85
+ rules={[{ required: true, message: 'Province is required' }]}
86
+ >
87
+ <Slider style={{ display: 'inline-block', width: '100%' }} />
88
+ </Form.Item>
89
+ </Flex>
90
+ <Form.Item
91
+ name={['address', 'street']}
92
+ noStyle
93
+ rules={[{ required: true, message: 'Street is required' }]}
94
+ >
95
+ <InputNumber
96
+ style={{
97
+ width: 50,
98
+ }}
99
+ />
100
+ </Form.Item>
101
+ </Flex>
102
+ </Form.Item>
103
+ <Form.Item label="Frequency Penalty">
104
+ <Flex gap={20}>
105
+ <Flex flex={1}>
106
+ <Form.Item
107
+ name={['address', 'province']}
108
+ noStyle
109
+ rules={[{ required: true, message: 'Province is required' }]}
110
+ >
111
+ <Slider style={{ display: 'inline-block', width: '100%' }} />
112
+ </Form.Item>
113
+ </Flex>
114
+ <Form.Item
115
+ name={['address', 'street']}
116
+ noStyle
117
+ rules={[{ required: true, message: 'Street is required' }]}
118
+ >
119
+ <InputNumber
120
+ style={{
121
+ width: 50,
122
+ }}
123
+ />
124
+ </Form.Item>
125
+ </Flex>
126
+ </Form.Item>
127
+ <Form.Item label="Max Tokens">
128
+ <Flex gap={20}>
129
+ <Flex flex={1}>
130
+ <Form.Item
131
+ name={['address', 'province']}
132
+ noStyle
133
+ rules={[{ required: true, message: 'Province is required' }]}
134
+ >
135
+ <Slider style={{ display: 'inline-block', width: '100%' }} />
136
+ </Form.Item>
137
+ </Flex>
138
+ <Form.Item
139
+ name={['address', 'street']}
140
+ noStyle
141
+ rules={[{ required: true, message: 'Street is required' }]}
142
+ >
143
+ <InputNumber
144
+ style={{
145
+ width: 50,
146
+ }}
147
+ />
148
+ </Form.Item>
149
+ </Flex>
150
+ </Form.Item>
151
+ </section>
152
+ );
153
+ };
154
+
155
+ export default ModelSetting;
web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { DeleteOutlined } from '@ant-design/icons';
2
+ import {
3
+ Button,
4
+ Col,
5
+ Divider,
6
+ Form,
7
+ Input,
8
+ Row,
9
+ Select,
10
+ Switch,
11
+ Table,
12
+ TableProps,
13
+ } from 'antd';
14
+ import classNames from 'classnames';
15
+ import { useState } from 'react';
16
+ import { v4 as uuid } from 'uuid';
17
+ import { EditableCell, EditableRow } from './editable-cell';
18
+ import { ISegmentedContentProps } from './interface';
19
+
20
+ import styles from './index.less';
21
+
22
+ interface DataType {
23
+ key: string;
24
+ optional: boolean;
25
+ }
26
+
27
+ const { Option } = Select;
28
+
29
+ const PromptEngine = ({ show }: ISegmentedContentProps) => {
30
+ const [dataSource, setDataSource] = useState<DataType[]>([]);
31
+
32
+ const components = {
33
+ body: {
34
+ row: EditableRow,
35
+ cell: EditableCell,
36
+ },
37
+ };
38
+
39
+ const handleRemove = (key: string) => () => {
40
+ const newData = dataSource.filter((item) => item.key !== key);
41
+ setDataSource(newData);
42
+ };
43
+
44
+ const handleSave = (row: DataType) => {
45
+ const newData = [...dataSource];
46
+ const index = newData.findIndex((item) => row.key === item.key);
47
+ const item = newData[index];
48
+ newData.splice(index, 1, {
49
+ ...item,
50
+ ...row,
51
+ });
52
+ setDataSource(newData);
53
+ };
54
+
55
+ const columns: TableProps<DataType>['columns'] = [
56
+ {
57
+ title: 'key',
58
+ dataIndex: 'variable',
59
+ key: 'variable',
60
+ onCell: (record: DataType) => ({
61
+ record,
62
+ editable: true,
63
+ dataIndex: 'variable',
64
+ title: 'key',
65
+ handleSave,
66
+ }),
67
+ },
68
+ {
69
+ title: 'optional',
70
+ dataIndex: 'optional',
71
+ key: 'optional',
72
+ width: 40,
73
+ align: 'center',
74
+ render() {
75
+ return <Switch size="small" />;
76
+ },
77
+ },
78
+ {
79
+ title: 'operation',
80
+ dataIndex: 'operation',
81
+ width: 30,
82
+ key: 'operation',
83
+ align: 'center',
84
+ render(_, record) {
85
+ return <DeleteOutlined onClick={handleRemove(record.key)} />;
86
+ },
87
+ },
88
+ ];
89
+
90
+ const handleAdd = () => {
91
+ setDataSource((state) => [
92
+ ...state,
93
+ {
94
+ key: uuid(),
95
+ variable: '',
96
+ optional: true,
97
+ },
98
+ ]);
99
+ };
100
+
101
+ return (
102
+ <section
103
+ className={classNames({
104
+ [styles.segmentedHidden]: !show,
105
+ })}
106
+ >
107
+ <Form.Item
108
+ label="Orchestrate"
109
+ name="orchestrate"
110
+ rules={[{ required: true, message: 'Please input!' }]}
111
+ >
112
+ <Input.TextArea autoSize={{ maxRows: 5, minRows: 5 }} />
113
+ </Form.Item>
114
+ <Divider></Divider>
115
+ <section className={classNames(styles.variableContainer)}>
116
+ <Row align={'middle'} justify="end">
117
+ <Col span={6} className={styles.variableAlign}>
118
+ <label className={styles.variableLabel}>Variables</label>
119
+ </Col>
120
+ <Col span={18} className={styles.variableAlign}>
121
+ <Button size="small" onClick={handleAdd}>
122
+ Add
123
+ </Button>
124
+ </Col>
125
+ </Row>
126
+ {dataSource.length > 0 && (
127
+ <Row>
128
+ <Col span={6}></Col>
129
+ <Col span={18}>
130
+ <Table
131
+ dataSource={dataSource}
132
+ columns={columns}
133
+ rowKey={'key'}
134
+ className={styles.variableTable}
135
+ components={components}
136
+ rowClassName={() => styles.editableRow}
137
+ />
138
+ </Col>
139
+ </Row>
140
+ )}
141
+ </section>
142
+ <Form.Item
143
+ label="Select one context"
144
+ name="context"
145
+ rules={[
146
+ {
147
+ required: true,
148
+ message: 'Please select your favourite colors!',
149
+ type: 'array',
150
+ },
151
+ ]}
152
+ >
153
+ <Select mode="multiple" placeholder="Please select favourite colors">
154
+ <Option value="red">Red</Option>
155
+ <Option value="green">Green</Option>
156
+ <Option value="blue">Blue</Option>
157
+ </Select>
158
+ </Form.Item>
159
+ </section>
160
+ );
161
+ };
162
+
163
+ export default PromptEngine;
web/src/pages/chat/chat-container/index.less ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .chatContainer {
2
+ padding: 0 24px 24px;
3
+ }
web/src/pages/chat/chat-container/index.tsx ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Button, Flex, Input } from 'antd';
2
+ import { ChangeEventHandler, useState } from 'react';
3
+
4
+ import styles from './index.less';
5
+
6
+ const ChatContainer = () => {
7
+ const [value, setValue] = useState('');
8
+
9
+ const handlePressEnter = () => {
10
+ console.info(value);
11
+ };
12
+
13
+ const handleInputChange: ChangeEventHandler<HTMLInputElement> = (e) => {
14
+ setValue(e.target.value);
15
+ };
16
+
17
+ return (
18
+ <Flex flex={1} className={styles.chatContainer} vertical>
19
+ <Flex flex={1}>xx</Flex>
20
+ <Input
21
+ size="large"
22
+ placeholder="Message Resume Assistant..."
23
+ value={value}
24
+ suffix={
25
+ <Button type="primary" onClick={handlePressEnter}>
26
+ Send
27
+ </Button>
28
+ }
29
+ onPressEnter={handlePressEnter}
30
+ onChange={handleInputChange}
31
+ />
32
+ </Flex>
33
+ );
34
+ };
35
+
36
+ export default ChatContainer;
web/src/pages/chat/index.less ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .chatWrapper {
2
+ height: 100%;
3
+
4
+ .chatAppWrapper {
5
+ width: 288px;
6
+ padding: 26px;
7
+ }
8
+ .chatTitleWrapper {
9
+ width: 220px;
10
+ padding: 26px 0;
11
+ }
12
+
13
+ .chatTitle {
14
+ padding: 5px 15px;
15
+ }
16
+
17
+ .chatTitleContent {
18
+ padding: 5px 10px;
19
+ }
20
+
21
+ .divider {
22
+ margin: 0;
23
+ height: 100%;
24
+ }
25
+ }
web/src/pages/chat/index.tsx CHANGED
@@ -1,8 +1,64 @@
 
 
1
  import { useSelector } from 'umi';
 
 
 
 
 
2
 
3
  const Chat = () => {
4
  const { name } = useSelector((state: any) => state.chatModel);
5
- return <div>chat:{name} </div>;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  };
7
 
8
  export default Chat;
 
1
+ import { FormOutlined } from '@ant-design/icons';
2
+ import { Button, Card, Divider, Flex, Space, Tag } from 'antd';
3
  import { useSelector } from 'umi';
4
+ import ChatContainer from './chat-container';
5
+
6
+ import ModalManager from '@/components/modal-manager';
7
+ import ChatConfigurationModal from './chat-configuration-modal';
8
+ import styles from './index.less';
9
 
10
  const Chat = () => {
11
  const { name } = useSelector((state: any) => state.chatModel);
12
+
13
+ return (
14
+ <Flex className={styles.chatWrapper}>
15
+ <Flex className={styles.chatAppWrapper}>
16
+ <Flex flex={1} vertical>
17
+ <ModalManager>
18
+ {({ visible, showModal, hideModal }) => {
19
+ return (
20
+ <>
21
+ <Button type="primary" onClick={() => showModal()}>
22
+ Create an Assistant
23
+ </Button>
24
+ <ChatConfigurationModal
25
+ visible={visible}
26
+ showModal={showModal}
27
+ hideModal={hideModal}
28
+ ></ChatConfigurationModal>
29
+ </>
30
+ );
31
+ }}
32
+ </ModalManager>
33
+
34
+ <Divider></Divider>
35
+ <Card>
36
+ <p>Card content</p>
37
+ </Card>
38
+ </Flex>
39
+ </Flex>
40
+ <Divider type={'vertical'} className={styles.divider}></Divider>
41
+ <Flex className={styles.chatTitleWrapper}>
42
+ <Flex flex={1} vertical>
43
+ <Flex
44
+ justify={'space-between'}
45
+ align="center"
46
+ className={styles.chatTitle}
47
+ >
48
+ <Space>
49
+ <b>Chat</b>
50
+ <Tag>25</Tag>
51
+ </Space>
52
+ <FormOutlined />
53
+ </Flex>
54
+ <Divider></Divider>
55
+ <section className={styles.chatTitleContent}>today</section>
56
+ </Flex>
57
+ </Flex>
58
+ <Divider type={'vertical'} className={styles.divider}></Divider>
59
+ <ChatContainer></ChatContainer>
60
+ </Flex>
61
+ );
62
  };
63
 
64
  export default Chat;
web/src/pages/chat/message-box.tsx ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // RCE CSS
2
+ import { MessageList } from 'react-chat-elements';
3
+ import 'react-chat-elements/dist/main.css';
4
+
5
+ const ChatBox = () => {
6
+ return (
7
+ <div style={{ width: 600 }}>
8
+ {/* <MessageBox
9
+ position={'left'}
10
+ type={'photo'}
11
+ text={'react.svg'}
12
+ data={{
13
+ uri: 'https://facebook.github.io/react/img/logo.svg',
14
+ status: {
15
+ click: false,
16
+ loading: 0,
17
+ },
18
+ }}
19
+ /> */}
20
+
21
+ <MessageList
22
+ // referance={messageListReferance}
23
+ className="message-list"
24
+ lockable={true}
25
+ toBottomHeight={'100%'}
26
+ dataSource={[
27
+ {
28
+ position: 'right',
29
+ type: 'text',
30
+ text: 'Lorem ipsum dolor sit amet',
31
+ date: new Date(),
32
+ },
33
+ {
34
+ position: 'left',
35
+ type: 'text',
36
+ text: 'Lorem ipsum dolor sit amet',
37
+ date: new Date(),
38
+ },
39
+ ]}
40
+ />
41
+ </div>
42
+ );
43
+ };
44
+
45
+ export default ChatBox;
web/src/pages/knowledge/knowledge-card/index.less CHANGED
@@ -26,7 +26,7 @@
26
  border: 1px solid rgba(234, 236, 240, 1);
27
  box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
28
  padding: 24px;
29
- max-width: 300px;
30
  cursor: pointer;
31
 
32
  .titleWrapper {
 
26
  border: 1px solid rgba(234, 236, 240, 1);
27
  box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
28
  padding: 24px;
29
+ width: 300px;
30
  cursor: pointer;
31
 
32
  .titleWrapper {
web/src/pages/knowledge/knowledge-card/index.tsx CHANGED
@@ -63,7 +63,7 @@ const KnowledgeCard = ({ item }: IProps) => {
63
  <Card className={styles.card} onClick={handleCardClick}>
64
  <div className={styles.container}>
65
  <div className={styles.content}>
66
- <Avatar size={34} icon={<UserOutlined />} />
67
 
68
  <span className={styles.delete}>
69
  <Dropdown
@@ -78,14 +78,14 @@ const KnowledgeCard = ({ item }: IProps) => {
78
  </div>
79
  <div className={styles.titleWrapper}>
80
  <span className={styles.title}>{item.name}</span>
81
- <p>A comprehensive knowledge base for crafting effective resumes.</p>
82
  </div>
83
  <div className={styles.footer}>
84
  <div className={styles.footerTop}>
85
  <div className={styles.bottomLeft}>
86
  <FileTextOutlined className={styles.leftIcon} />
87
  <span className={styles.rightText}>
88
- <Space>{item.doc_num}文档</Space>
89
  </span>
90
  </div>
91
  </div>
 
63
  <Card className={styles.card} onClick={handleCardClick}>
64
  <div className={styles.container}>
65
  <div className={styles.content}>
66
+ <Avatar size={34} icon={<UserOutlined />} src={item.avatar} />
67
 
68
  <span className={styles.delete}>
69
  <Dropdown
 
78
  </div>
79
  <div className={styles.titleWrapper}>
80
  <span className={styles.title}>{item.name}</span>
81
+ <p>{item.description}</p>
82
  </div>
83
  <div className={styles.footer}>
84
  <div className={styles.footerTop}>
85
  <div className={styles.bottomLeft}>
86
  <FileTextOutlined className={styles.leftIcon} />
87
  <span className={styles.rightText}>
88
+ <Space>{item.doc_num}Docs</Space>
89
  </span>
90
  </div>
91
  </div>