@lobehub/chat 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +3 -0
- package/CHANGELOG.md +66 -0
- package/locales/en_US/common.json +21 -20
- package/locales/en_US/plugin.json +2 -3
- package/locales/en_US/setting.json +34 -35
- package/locales/zh_CN/common.json +6 -2
- package/locales/zh_CN/setting.json +2 -2
- package/package.json +1 -1
- package/src/components/SliderWithInput/index.tsx +3 -0
- package/src/features/AgentSetting/AgentConfig/index.tsx +2 -1
- package/src/features/AgentSetting/AgentPrompt/index.tsx +19 -13
- package/src/locales/default/common.ts +6 -2
- package/src/locales/default/setting.ts +6 -3
- package/src/locales/resources/en_US.ts +1 -9
- package/src/pages/chat/SessionList/List/SessionItem.tsx +45 -49
- package/src/pages/chat/SessionList/List/style.ts +2 -31
- package/src/pages/chat/[id]/Conversation/ChatList/Error/ApiKeyForm.tsx +2 -2
- package/src/pages/chat/[id]/Conversation/Input/Action.tsx +46 -34
- package/src/pages/chat/[id]/Conversation/Input/ActionRight.tsx +31 -0
- package/src/pages/chat/[id]/Conversation/Input/Token.tsx +6 -2
- package/src/pages/chat/[id]/Conversation/Input/index.tsx +2 -0
- package/src/pages/chat/[id]/index.page.tsx +6 -6
- package/src/pages/settings/Settings/Common.tsx +1 -1
- package/src/store/session/slices/agentConfig/selectors.ts +5 -1
- package/src/store/session/slices/chat/actions/message.ts +12 -9
- package/src/store/session/slices/chat/selectors/chat.ts +26 -15
- package/src/store/session/slices/chat/selectors/index.ts +2 -1
- package/src/store/session/slices/chat/selectors/token.ts +10 -2
- package/src/store/session/slices/chat/utils.ts +13 -0
- package/src/types/session.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,72 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 0.36.0](https://github.com/lobehub/lobe-chat/compare/v0.35.1...v0.36.0)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-08-03**</sup>
|
|
8
|
+
|
|
9
|
+
#### ✨ Features
|
|
10
|
+
|
|
11
|
+
- **misc**: 实现自定义历史消息数功能.
|
|
12
|
+
|
|
13
|
+
#### 🐛 Bug Fixes
|
|
14
|
+
|
|
15
|
+
- **misc**: Fix setting type.
|
|
16
|
+
|
|
17
|
+
#### 💄 Styles
|
|
18
|
+
|
|
19
|
+
- **misc**: Fix session item height.
|
|
20
|
+
|
|
21
|
+
<br/>
|
|
22
|
+
|
|
23
|
+
<details>
|
|
24
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
25
|
+
|
|
26
|
+
#### What's improved
|
|
27
|
+
|
|
28
|
+
- **misc**: 实现自定义历史消息数功能 ([7baa022](https://github.com/lobehub/lobe-chat/commit/7baa022))
|
|
29
|
+
|
|
30
|
+
#### What's fixed
|
|
31
|
+
|
|
32
|
+
- **misc**: Fix setting type ([57e415e](https://github.com/lobehub/lobe-chat/commit/57e415e))
|
|
33
|
+
|
|
34
|
+
#### Styles
|
|
35
|
+
|
|
36
|
+
- **misc**: Fix session item height ([6cd1de5](https://github.com/lobehub/lobe-chat/commit/6cd1de5))
|
|
37
|
+
|
|
38
|
+
</details>
|
|
39
|
+
|
|
40
|
+
<div align="right">
|
|
41
|
+
|
|
42
|
+
[](#readme-top)
|
|
43
|
+
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
### [Version 0.35.1](https://github.com/lobehub/lobe-chat/compare/v0.35.0...v0.35.1)
|
|
47
|
+
|
|
48
|
+
<sup>Released on **2023-07-31**</sup>
|
|
49
|
+
|
|
50
|
+
#### 💄 Styles
|
|
51
|
+
|
|
52
|
+
- **misc**: Update doc mode and token tags.
|
|
53
|
+
|
|
54
|
+
<br/>
|
|
55
|
+
|
|
56
|
+
<details>
|
|
57
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
58
|
+
|
|
59
|
+
#### Styles
|
|
60
|
+
|
|
61
|
+
- **misc**: Update doc mode and token tags ([1d3c5b6](https://github.com/lobehub/lobe-chat/commit/1d3c5b6))
|
|
62
|
+
|
|
63
|
+
</details>
|
|
64
|
+
|
|
65
|
+
<div align="right">
|
|
66
|
+
|
|
67
|
+
[](#readme-top)
|
|
68
|
+
|
|
69
|
+
</div>
|
|
70
|
+
|
|
5
71
|
## [Version 0.35.0](https://github.com/lobehub/lobe-chat/compare/v0.34.0...v0.35.0)
|
|
6
72
|
|
|
7
73
|
<sup>Released on **2023-07-31**</sup>
|
|
@@ -1,33 +1,31 @@
|
|
|
1
1
|
{
|
|
2
|
-
"DefaultSession": "Default Session",
|
|
3
2
|
"about": "About",
|
|
4
3
|
"advanceSettings": "Advanced Settings",
|
|
5
4
|
"agentMaxToken": "Max Token Length",
|
|
6
5
|
"agentModel": "Model",
|
|
7
6
|
"agentProfile": "Agent Profile",
|
|
8
7
|
"archive": "Archive",
|
|
9
|
-
"archiveCurrentMessages": "Archive Current Session",
|
|
10
8
|
"autoGenerate": "Auto Generate",
|
|
11
9
|
"autoGenerateTooltip": "Auto generate assistant description based on prompts",
|
|
12
10
|
"cancel": "Cancel",
|
|
13
11
|
"changelog": "Changelog",
|
|
14
|
-
"clearCurrentMessages": "Clear Current
|
|
12
|
+
"clearCurrentMessages": "Clear Current Messages",
|
|
15
13
|
"close": "Close",
|
|
16
|
-
"confirmClearCurrentMessages": "You are about to clear the current
|
|
14
|
+
"confirmClearCurrentMessages": "You are about to clear the current messages. Once cleared, they cannot be recovered. Please confirm your action.",
|
|
17
15
|
"confirmRemoveSessionItemAlert": "You are about to delete this assistant. Once deleted, it cannot be recovered. Please confirm your action.",
|
|
18
16
|
"copy": "Copy",
|
|
19
|
-
"copySuccess": "Copy
|
|
17
|
+
"copySuccess": "Copy Successful",
|
|
20
18
|
"defaultAgent": "Default Assistant",
|
|
21
19
|
"defaultSession": "Default Session",
|
|
22
20
|
"delete": "Delete",
|
|
23
21
|
"edit": "Edit",
|
|
24
|
-
"export": "Export",
|
|
22
|
+
"export": "Export Configuration",
|
|
25
23
|
"exportType": {
|
|
26
|
-
"agent": "Export
|
|
27
|
-
"agentWithMessage": "Export
|
|
28
|
-
"all": "Export Global Settings and All
|
|
29
|
-
"allAgent": "Export All
|
|
30
|
-
"allAgentWithMessage": "Export All
|
|
24
|
+
"agent": "Export Assistant Settings",
|
|
25
|
+
"agentWithMessage": "Export Assistant and Messages",
|
|
26
|
+
"all": "Export Global Settings and All Assistant Data",
|
|
27
|
+
"allAgent": "Export All Assistant Settings",
|
|
28
|
+
"allAgentWithMessage": "Export All Assistants and Messages",
|
|
31
29
|
"globalSetting": "Export Global Settings"
|
|
32
30
|
},
|
|
33
31
|
"feedback": "Feedback",
|
|
@@ -35,21 +33,19 @@
|
|
|
35
33
|
"message": {
|
|
36
34
|
"function_loading": "Plugin request in progress..."
|
|
37
35
|
},
|
|
38
|
-
"moreSetting": "More
|
|
36
|
+
"moreSetting": "More Settings...",
|
|
39
37
|
"newAgent": "New Assistant",
|
|
40
38
|
"noDescription": "No description available",
|
|
41
39
|
"ok": "OK",
|
|
42
|
-
"overload": "Exceed Limit",
|
|
43
40
|
"pin": "Pin",
|
|
44
41
|
"pinOff": "Unpin",
|
|
45
42
|
"regenerate": "Regenerate",
|
|
46
43
|
"rename": "Rename",
|
|
47
44
|
"reset": "Reset",
|
|
48
|
-
"roleAndArchive": "Roles and
|
|
49
|
-
"searchAgentPlaceholder": "Search
|
|
45
|
+
"roleAndArchive": "Roles and Archive",
|
|
46
|
+
"searchAgentPlaceholder": "Search Assistants and Sessions...",
|
|
50
47
|
"send": "Send",
|
|
51
48
|
"sendPlaceholder": "Enter chat content...",
|
|
52
|
-
"sessionSetting": "Session Settings",
|
|
53
49
|
"setting": "Settings",
|
|
54
50
|
"share": "Share",
|
|
55
51
|
"tab": {
|
|
@@ -57,12 +53,17 @@
|
|
|
57
53
|
"market": "Assistant Market"
|
|
58
54
|
},
|
|
59
55
|
"temp": "Temporary",
|
|
60
|
-
"tokenDetail": "
|
|
56
|
+
"tokenDetail": "Role Setting: {{systemRoleToken}} · Chat History: {{chatsToken}}",
|
|
57
|
+
"tokenTag": {
|
|
58
|
+
"overload": "Exceeded Limit",
|
|
59
|
+
"remained": "Remaining",
|
|
60
|
+
"used": "Used"
|
|
61
|
+
},
|
|
61
62
|
"topic": {
|
|
62
|
-
"saveCurrentMessages": "Save Current Conversation as Topic",
|
|
63
|
-
"searchPlaceholder": "Search Topics...",
|
|
64
63
|
"confirmRemoveTopic": "You are about to delete this topic. Once deleted, it cannot be recovered. Please proceed with caution.",
|
|
65
|
-
"defaultTitle": "Default Topic"
|
|
64
|
+
"defaultTitle": "Default Topic",
|
|
65
|
+
"saveCurrentMessages": "Save the current session as a topic",
|
|
66
|
+
"searchPlaceholder": "Search Topics..."
|
|
66
67
|
},
|
|
67
68
|
"updateAgent": "Update Assistant Profile",
|
|
68
69
|
"updatePrompt": "Update Prompts"
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"loading": {
|
|
3
|
-
"content": "Loading...",
|
|
3
|
+
"content": "Loading data...",
|
|
4
4
|
"plugin": "Plugin is running..."
|
|
5
5
|
},
|
|
6
6
|
"pluginList": "Plugin List",
|
|
7
|
-
"pluginLoading": "Plugin Loading...",
|
|
8
7
|
"plugins": {
|
|
9
8
|
"realtimeWeather": "Real-time Weather Forecast",
|
|
10
9
|
"searchEngine": "Search Engine",
|
|
11
|
-
"undefined": "Plugin
|
|
10
|
+
"undefined": "Plugin detection in progress...",
|
|
12
11
|
"websiteCrawler": "Website Content Extraction"
|
|
13
12
|
},
|
|
14
13
|
"realtimeWeather": {
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"agentHeader": "Edit Assistant Information",
|
|
3
2
|
"danger": {
|
|
4
3
|
"clear": {
|
|
5
4
|
"action": "Clear Now",
|
|
6
|
-
"confirm": "
|
|
7
|
-
"desc": "Clear all
|
|
8
|
-
"
|
|
9
|
-
"
|
|
5
|
+
"confirm": "Confirm clearing all chat data?",
|
|
6
|
+
"desc": "Clear all session data",
|
|
7
|
+
"success": "All session messages have been cleared",
|
|
8
|
+
"title": "Clear All Session Messages"
|
|
10
9
|
},
|
|
11
10
|
"reset": {
|
|
12
11
|
"action": "Reset Now",
|
|
13
|
-
"confirm": "
|
|
12
|
+
"confirm": "Confirm resetting all settings?",
|
|
14
13
|
"currentVersion": "Current Version",
|
|
15
14
|
"desc": "Reset all settings to default values",
|
|
16
15
|
"title": "Reset All Settings"
|
|
@@ -25,34 +24,41 @@
|
|
|
25
24
|
"avatar": {
|
|
26
25
|
"title": "Avatar"
|
|
27
26
|
},
|
|
27
|
+
"backgroundColor": {
|
|
28
|
+
"title": "Background Color"
|
|
29
|
+
},
|
|
28
30
|
"description": {
|
|
29
|
-
"placeholder": "
|
|
31
|
+
"placeholder": "Enter assistant description",
|
|
30
32
|
"title": "Assistant Description"
|
|
31
33
|
},
|
|
32
34
|
"name": {
|
|
33
|
-
"placeholder": "
|
|
35
|
+
"placeholder": "Enter assistant name",
|
|
34
36
|
"title": "Name"
|
|
35
37
|
},
|
|
36
38
|
"prompt": {
|
|
37
|
-
"placeholder": "
|
|
38
|
-
"title": "
|
|
39
|
+
"placeholder": "Enter role prompt",
|
|
40
|
+
"title": "Role Prompt"
|
|
39
41
|
},
|
|
40
42
|
"tag": {
|
|
41
|
-
"placeholder": "
|
|
42
|
-
"title": "
|
|
43
|
+
"placeholder": "Enter tag",
|
|
44
|
+
"title": "Tag"
|
|
43
45
|
},
|
|
44
|
-
"title": "Assistant Information"
|
|
45
|
-
"backgroundColor": {
|
|
46
|
-
"title": "Background Color"
|
|
47
|
-
}
|
|
46
|
+
"title": "Assistant Information"
|
|
48
47
|
},
|
|
49
48
|
"settingChat": {
|
|
49
|
+
"chatStyleType": {
|
|
50
|
+
"title": "Chat Window Style",
|
|
51
|
+
"type": {
|
|
52
|
+
"chat": "Chat Mode",
|
|
53
|
+
"docs": "Document Mode"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
50
56
|
"compressThreshold": {
|
|
51
|
-
"desc": "When the uncompressed
|
|
52
|
-
"title": "
|
|
57
|
+
"desc": "When the uncompressed history messages exceed this value, compression will be performed",
|
|
58
|
+
"title": "History Message Length Compression Threshold"
|
|
53
59
|
},
|
|
54
60
|
"enableCompressThreshold": {
|
|
55
|
-
"title": "Enable
|
|
61
|
+
"title": "Enable History Message Length Compression Threshold"
|
|
56
62
|
},
|
|
57
63
|
"enableHistoryCount": {
|
|
58
64
|
"title": "Enable History Message Count Limit"
|
|
@@ -63,24 +69,17 @@
|
|
|
63
69
|
},
|
|
64
70
|
"inputTemplate": {
|
|
65
71
|
"desc": "The latest user message will be filled into this template",
|
|
66
|
-
"
|
|
67
|
-
"
|
|
72
|
+
"placeholder": "Enter the input template, {text} will be replaced with real-time input",
|
|
73
|
+
"title": "User Input Preprocessing"
|
|
68
74
|
},
|
|
69
|
-
"title": "Chat Settings"
|
|
70
|
-
"chatStyleType": {
|
|
71
|
-
"title": "Chat Window Style",
|
|
72
|
-
"type": {
|
|
73
|
-
"chat": "Chat Mode",
|
|
74
|
-
"docs": "Document Mode"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
75
|
+
"title": "Chat Settings"
|
|
77
76
|
},
|
|
78
77
|
"settingModel": {
|
|
79
78
|
"enableMaxTokens": {
|
|
80
79
|
"title": "Enable Single Reply Limit"
|
|
81
80
|
},
|
|
82
81
|
"frequencyPenalty": {
|
|
83
|
-
"desc": "The
|
|
82
|
+
"desc": "The larger the value, the more likely it is to reduce repeated words",
|
|
84
83
|
"title": "Frequency Penalty"
|
|
85
84
|
},
|
|
86
85
|
"maxTokens": {
|
|
@@ -98,18 +97,18 @@
|
|
|
98
97
|
"title": "Model"
|
|
99
98
|
},
|
|
100
99
|
"presencePenalty": {
|
|
101
|
-
"desc": "The
|
|
100
|
+
"desc": "The larger the value, the more likely it is to expand to new topics",
|
|
102
101
|
"title": "Topic Freshness"
|
|
103
102
|
},
|
|
104
103
|
"temperature": {
|
|
105
|
-
"desc": "The
|
|
104
|
+
"desc": "The larger the value, the more random the reply",
|
|
106
105
|
"title": "Randomness",
|
|
107
106
|
"titleWithValue": "Randomness {{value}}"
|
|
108
107
|
},
|
|
109
108
|
"title": "Model Settings",
|
|
110
109
|
"topP": {
|
|
111
110
|
"desc": "Similar to randomness, but do not change together with randomness",
|
|
112
|
-
"title": "
|
|
111
|
+
"title": "Top-p Sampling"
|
|
113
112
|
}
|
|
114
113
|
},
|
|
115
114
|
"settingOpenAI": {
|
|
@@ -130,8 +129,8 @@
|
|
|
130
129
|
},
|
|
131
130
|
"settingSystem": {
|
|
132
131
|
"accessCode": {
|
|
133
|
-
"desc": "
|
|
134
|
-
"placeholder": "
|
|
132
|
+
"desc": "Encryption access has been enabled by the administrator",
|
|
133
|
+
"placeholder": "Enter access password",
|
|
135
134
|
"title": "Access Password"
|
|
136
135
|
},
|
|
137
136
|
"title": "System Settings"
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
"newAgent": "新建助手",
|
|
38
38
|
"noDescription": "暂无描述",
|
|
39
39
|
"ok": "确定",
|
|
40
|
-
"overload": "超过限制",
|
|
41
40
|
"pin": "置顶",
|
|
42
41
|
"pinOff": "取消置顶",
|
|
43
42
|
"regenerate": "重新生成",
|
|
@@ -54,7 +53,12 @@
|
|
|
54
53
|
"market": "助手市场"
|
|
55
54
|
},
|
|
56
55
|
"temp": "临时",
|
|
57
|
-
"tokenDetail": "
|
|
56
|
+
"tokenDetail": "角色设定: {{systemRoleToken}} · 历史消息: {{chatsToken}}",
|
|
57
|
+
"tokenTag": {
|
|
58
|
+
"overload": "超过限制",
|
|
59
|
+
"remained": "剩余",
|
|
60
|
+
"used": "使用"
|
|
61
|
+
},
|
|
58
62
|
"topic": {
|
|
59
63
|
"confirmRemoveTopic": "即将删除该话题,删除后将不可恢复,请谨慎操作。",
|
|
60
64
|
"defaultTitle": "默认话题",
|
package/package.json
CHANGED
|
@@ -21,6 +21,7 @@ const SliderWithInput = memo<SliderWithInputProps>(
|
|
|
21
21
|
controls,
|
|
22
22
|
style,
|
|
23
23
|
className,
|
|
24
|
+
disabled,
|
|
24
25
|
...props
|
|
25
26
|
}) => {
|
|
26
27
|
const handleOnchange = useCallback((value: number | null) => {
|
|
@@ -38,6 +39,7 @@ const SliderWithInput = memo<SliderWithInputProps>(
|
|
|
38
39
|
>
|
|
39
40
|
<Slider
|
|
40
41
|
defaultValue={defaultValue}
|
|
42
|
+
disabled={disabled}
|
|
41
43
|
max={max}
|
|
42
44
|
min={min}
|
|
43
45
|
onChange={handleOnchange}
|
|
@@ -50,6 +52,7 @@ const SliderWithInput = memo<SliderWithInputProps>(
|
|
|
50
52
|
<InputNumber
|
|
51
53
|
controls={size !== 'small' || controls}
|
|
52
54
|
defaultValue={defaultValue}
|
|
55
|
+
disabled={disabled}
|
|
53
56
|
max={max}
|
|
54
57
|
min={min}
|
|
55
58
|
onChange={handleOnchange}
|
|
@@ -11,10 +11,11 @@ import { FORM_STYLE } from '@/const/layoutTokens';
|
|
|
11
11
|
import { AgentAction } from '@/store/session/slices/agentConfig';
|
|
12
12
|
import { LanguageModel } from '@/types/llm';
|
|
13
13
|
import type { LobeAgentConfig } from '@/types/session';
|
|
14
|
+
import { LobeAgentConfigKeys } from '@/types/session';
|
|
14
15
|
|
|
15
16
|
type SettingItemGroup = ItemGroup & {
|
|
16
17
|
children: {
|
|
17
|
-
name?:
|
|
18
|
+
name?: LobeAgentConfigKeys | string | string[];
|
|
18
19
|
}[];
|
|
19
20
|
};
|
|
20
21
|
|
|
@@ -11,15 +11,11 @@ import { AgentAction } from '@/store/session/slices/agentConfig';
|
|
|
11
11
|
import { LobeAgentConfig } from '@/types/session';
|
|
12
12
|
|
|
13
13
|
export const useStyles = createStyles(({ css, token }) => ({
|
|
14
|
-
|
|
15
|
-
padding:
|
|
16
|
-
background: ${token.
|
|
17
|
-
border: 1px solid ${token.
|
|
18
|
-
border-radius:
|
|
19
|
-
`,
|
|
20
|
-
markdown: css`
|
|
21
|
-
padding: 12px;
|
|
22
|
-
background: ${token.colorFillTertiary};
|
|
14
|
+
token: css`
|
|
15
|
+
padding-left: 8px;
|
|
16
|
+
background: ${token.colorBgLayout};
|
|
17
|
+
border: 1px solid ${token.colorBorder};
|
|
18
|
+
border-radius: ${token.borderRadiusSM}px;
|
|
23
19
|
`,
|
|
24
20
|
}));
|
|
25
21
|
|
|
@@ -30,14 +26,24 @@ export interface AgentPromptProps {
|
|
|
30
26
|
|
|
31
27
|
const AgentPrompt = memo<AgentPromptProps>(({ config, updateConfig }) => {
|
|
32
28
|
const { t } = useTranslation('setting');
|
|
33
|
-
|
|
29
|
+
const { styles } = useStyles();
|
|
34
30
|
const { systemRole, model } = config;
|
|
35
31
|
const systemTokenCount = useMemo(() => encode(systemRole || '').length, [systemRole]);
|
|
36
32
|
|
|
37
33
|
return (
|
|
38
34
|
<FormGroup
|
|
39
35
|
extra={
|
|
40
|
-
<TokenTag
|
|
36
|
+
<TokenTag
|
|
37
|
+
className={styles.token}
|
|
38
|
+
displayMode={'used'}
|
|
39
|
+
maxValue={ModelTokens[model]}
|
|
40
|
+
text={{
|
|
41
|
+
overload: t('tokenTag.overload', { ns: 'common' }),
|
|
42
|
+
remained: t('tokenTag.remained', { ns: 'common' }),
|
|
43
|
+
used: t('tokenTag.used', { ns: 'common' }),
|
|
44
|
+
}}
|
|
45
|
+
value={systemTokenCount}
|
|
46
|
+
/>
|
|
41
47
|
}
|
|
42
48
|
icon={Bot}
|
|
43
49
|
style={FORM_STYLE.style}
|
|
@@ -46,9 +52,9 @@ const AgentPrompt = memo<AgentPromptProps>(({ config, updateConfig }) => {
|
|
|
46
52
|
<CodeEditor
|
|
47
53
|
language={'md'}
|
|
48
54
|
onValueChange={(e) => updateConfig({ systemRole: e })}
|
|
49
|
-
placeholder={t('settingAgent.
|
|
55
|
+
placeholder={t('settingAgent.prompt.placeholder')}
|
|
50
56
|
resize={false}
|
|
51
|
-
style={{
|
|
57
|
+
style={{ padding: '16px 0' }}
|
|
52
58
|
type={'pure'}
|
|
53
59
|
value={systemRole}
|
|
54
60
|
/>
|
|
@@ -37,7 +37,6 @@ export default {
|
|
|
37
37
|
newAgent: '新建助手',
|
|
38
38
|
noDescription: '暂无描述',
|
|
39
39
|
ok: '确定',
|
|
40
|
-
overload: '超过限制',
|
|
41
40
|
pin: '置顶',
|
|
42
41
|
pinOff: '取消置顶',
|
|
43
42
|
regenerate: '重新生成',
|
|
@@ -54,7 +53,12 @@ export default {
|
|
|
54
53
|
market: '助手市场',
|
|
55
54
|
},
|
|
56
55
|
temp: '临时',
|
|
57
|
-
tokenDetail: '
|
|
56
|
+
tokenDetail: '角色设定: {{systemRoleToken}} · 历史消息: {{chatsToken}}',
|
|
57
|
+
tokenTag: {
|
|
58
|
+
overload: '超过限制',
|
|
59
|
+
remained: '剩余',
|
|
60
|
+
used: '使用',
|
|
61
|
+
},
|
|
58
62
|
topic: {
|
|
59
63
|
confirmRemoveTopic: '即将删除该话题,删除后将不可恢复,请谨慎操作。',
|
|
60
64
|
defaultTitle: '默认话题',
|
|
@@ -36,8 +36,8 @@ export default {
|
|
|
36
36
|
title: '名称',
|
|
37
37
|
},
|
|
38
38
|
prompt: {
|
|
39
|
-
placeholder: '
|
|
40
|
-
title: '
|
|
39
|
+
placeholder: '请输入角色 Prompt 提示词',
|
|
40
|
+
title: '角色设定',
|
|
41
41
|
},
|
|
42
42
|
tag: {
|
|
43
43
|
placeholder: '请输入标签',
|
|
@@ -61,7 +61,10 @@ export default {
|
|
|
61
61
|
title: '是否开启历史消息长度压缩阈值',
|
|
62
62
|
},
|
|
63
63
|
enableHistoryCount: {
|
|
64
|
-
|
|
64
|
+
alias: '不限制',
|
|
65
|
+
limited: '只包含 {{number}} 条会话消息',
|
|
66
|
+
title: '限制历史消息数',
|
|
67
|
+
unlimited: '不限历史消息数',
|
|
65
68
|
},
|
|
66
69
|
historyCount: {
|
|
67
70
|
desc: '每次请求携带的历史消息数',
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import plugin from '../../../locales/en_US/plugin.json';
|
|
3
|
-
import setting from '../../../locales/en_US/setting.json';
|
|
4
|
-
|
|
5
|
-
const resources = {
|
|
6
|
-
common,
|
|
7
|
-
plugin,
|
|
8
|
-
setting,
|
|
9
|
-
} as const;
|
|
1
|
+
const resources = {} as const;
|
|
10
2
|
|
|
11
3
|
export default resources;
|
|
@@ -2,7 +2,7 @@ import { ActionIcon, Avatar, Icon, List } from '@lobehub/ui';
|
|
|
2
2
|
import { useHover } from 'ahooks';
|
|
3
3
|
import { App, Dropdown, type MenuProps, Tag } from 'antd';
|
|
4
4
|
import { FolderOutput, MoreVertical, Pin, PinOff, Trash } from 'lucide-react';
|
|
5
|
-
import { FC, memo, useMemo, useRef } from 'react';
|
|
5
|
+
import { FC, memo, useMemo, useRef, useState } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
8
|
import { shallow } from 'zustand/shallow';
|
|
@@ -22,13 +22,13 @@ interface SessionItemProps {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading }) => {
|
|
25
|
+
const [open, setOpen] = useState(false);
|
|
25
26
|
const ref = useRef(null);
|
|
26
27
|
const isHovering = useHover(ref);
|
|
27
28
|
|
|
28
29
|
const { t } = useTranslation('common');
|
|
29
|
-
const isHighlight = isHovering;
|
|
30
30
|
|
|
31
|
-
const { styles, theme
|
|
31
|
+
const { styles, theme } = useStyles();
|
|
32
32
|
const [defaultModel] = useSettings((s) => [s.settings.model], shallow);
|
|
33
33
|
|
|
34
34
|
const [
|
|
@@ -50,13 +50,13 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading })
|
|
|
50
50
|
return [
|
|
51
51
|
session.pinned,
|
|
52
52
|
agentSelectors.getTitle(meta),
|
|
53
|
-
meta
|
|
53
|
+
agentSelectors.getDescription(meta),
|
|
54
54
|
systemRole,
|
|
55
55
|
agentSelectors.getAvatar(meta),
|
|
56
56
|
meta.backgroundColor,
|
|
57
57
|
session?.updateAt,
|
|
58
58
|
session.config.model,
|
|
59
|
-
chatSelectors.
|
|
59
|
+
chatSelectors.getChatsById(id)(s).length,
|
|
60
60
|
s.removeSession,
|
|
61
61
|
s.pinSession,
|
|
62
62
|
];
|
|
@@ -115,49 +115,15 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading })
|
|
|
115
115
|
},
|
|
116
116
|
},
|
|
117
117
|
],
|
|
118
|
-
[id],
|
|
118
|
+
[id, pin],
|
|
119
119
|
);
|
|
120
120
|
|
|
121
121
|
const showModel = model !== defaultModel;
|
|
122
122
|
const showChatLength = chatLength > 0;
|
|
123
123
|
|
|
124
124
|
return (
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
<Item
|
|
128
|
-
active={active}
|
|
129
|
-
avatar={
|
|
130
|
-
<Avatar
|
|
131
|
-
animation={isHovering}
|
|
132
|
-
avatar={avatar}
|
|
133
|
-
background={avatarBackground}
|
|
134
|
-
shape="circle"
|
|
135
|
-
size={46}
|
|
136
|
-
title={title}
|
|
137
|
-
/>
|
|
138
|
-
}
|
|
139
|
-
className={isHighlight ? styles.hover : undefined}
|
|
140
|
-
classNames={{ time: cx('session-time', styles.time) }}
|
|
141
|
-
date={updateAt}
|
|
142
|
-
description={
|
|
143
|
-
<Flexbox gap={4}>
|
|
144
|
-
<Flexbox>{description || systemRole}</Flexbox>
|
|
145
|
-
|
|
146
|
-
{!(showModel || showChatLength) ? undefined : (
|
|
147
|
-
<Flexbox horizontal>
|
|
148
|
-
{showModel && (
|
|
149
|
-
<Tag bordered={false} style={{ color: theme.colorTextSecondary }}>
|
|
150
|
-
{model}
|
|
151
|
-
</Tag>
|
|
152
|
-
)}
|
|
153
|
-
</Flexbox>
|
|
154
|
-
)}
|
|
155
|
-
</Flexbox>
|
|
156
|
-
}
|
|
157
|
-
loading={loading}
|
|
158
|
-
style={{ color: theme.colorText }}
|
|
159
|
-
title={title}
|
|
160
|
-
/>
|
|
125
|
+
<Item
|
|
126
|
+
actions={
|
|
161
127
|
<Dropdown
|
|
162
128
|
arrow={false}
|
|
163
129
|
menu={{
|
|
@@ -166,23 +132,53 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading })
|
|
|
166
132
|
domEvent.stopPropagation();
|
|
167
133
|
},
|
|
168
134
|
}}
|
|
135
|
+
onOpenChange={setOpen}
|
|
136
|
+
open={open}
|
|
169
137
|
trigger={['click']}
|
|
170
138
|
>
|
|
171
139
|
<ActionIcon
|
|
172
|
-
className="session-remove"
|
|
173
140
|
icon={MoreVertical}
|
|
174
|
-
onClick={(e) => {
|
|
175
|
-
e.preventDefault();
|
|
176
|
-
e.stopPropagation();
|
|
177
|
-
}}
|
|
178
141
|
size={{
|
|
179
142
|
blockSize: 28,
|
|
180
143
|
fontSize: 16,
|
|
181
144
|
}}
|
|
182
145
|
/>
|
|
183
146
|
</Dropdown>
|
|
184
|
-
|
|
185
|
-
|
|
147
|
+
}
|
|
148
|
+
active={active}
|
|
149
|
+
avatar={
|
|
150
|
+
<Avatar
|
|
151
|
+
animation={isHovering}
|
|
152
|
+
avatar={avatar}
|
|
153
|
+
background={avatarBackground}
|
|
154
|
+
shape="circle"
|
|
155
|
+
size={46}
|
|
156
|
+
title={title}
|
|
157
|
+
/>
|
|
158
|
+
}
|
|
159
|
+
className={styles.container}
|
|
160
|
+
date={updateAt}
|
|
161
|
+
description={
|
|
162
|
+
<Flexbox gap={4}>
|
|
163
|
+
<Flexbox>{description || systemRole}</Flexbox>
|
|
164
|
+
|
|
165
|
+
{!(showModel || showChatLength) ? undefined : (
|
|
166
|
+
<Flexbox horizontal>
|
|
167
|
+
{showModel && (
|
|
168
|
+
<Tag bordered={false} style={{ color: theme.colorTextSecondary }}>
|
|
169
|
+
{model}
|
|
170
|
+
</Tag>
|
|
171
|
+
)}
|
|
172
|
+
</Flexbox>
|
|
173
|
+
)}
|
|
174
|
+
</Flexbox>
|
|
175
|
+
}
|
|
176
|
+
loading={loading}
|
|
177
|
+
pin={pin}
|
|
178
|
+
ref={ref}
|
|
179
|
+
showAction={open || isHovering}
|
|
180
|
+
title={title}
|
|
181
|
+
/>
|
|
186
182
|
);
|
|
187
183
|
}, shallow);
|
|
188
184
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { createStyles } from 'antd-style';
|
|
2
2
|
import { rgba } from 'polished';
|
|
3
3
|
|
|
4
|
-
export const useStyles = createStyles(({ css, token }
|
|
4
|
+
export const useStyles = createStyles(({ css, token }) => {
|
|
5
5
|
return {
|
|
6
|
-
active: css`
|
|
7
|
-
display: flex;
|
|
8
|
-
`,
|
|
9
6
|
button: css`
|
|
10
7
|
position: sticky;
|
|
11
8
|
z-index: 30;
|
|
@@ -24,34 +21,8 @@ export const useStyles = createStyles(({ css, token }, isHighlight: boolean) =>
|
|
|
24
21
|
`,
|
|
25
22
|
container: css`
|
|
26
23
|
position: relative;
|
|
27
|
-
|
|
28
|
-
.session-remove {
|
|
29
|
-
position: absolute;
|
|
30
|
-
top: 50%;
|
|
31
|
-
right: 16px;
|
|
32
|
-
transform: translateY(-50%);
|
|
33
|
-
|
|
34
|
-
opacity: ${isHighlight ? 1 : 0};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.session-time {
|
|
38
|
-
opacity: ${isHighlight ? 0 : 1};
|
|
39
|
-
transition: opacity 100ms ${token.motionEaseOut};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
&:hover {
|
|
43
|
-
.session-time {
|
|
44
|
-
opacity: 0;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.session-remove {
|
|
48
|
-
opacity: 1;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
`,
|
|
52
|
-
hover: css`
|
|
53
|
-
background-color: ${token.colorFillSecondary};
|
|
54
24
|
`,
|
|
25
|
+
|
|
55
26
|
modalRoot: css`
|
|
56
27
|
z-index: 2000;
|
|
57
28
|
`,
|
|
@@ -19,10 +19,10 @@ const APIKeyForm = memo<{ onConfirm?: () => void }>(({ onConfirm }) => {
|
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<Center gap={16} style={{ maxWidth: 300 }}>
|
|
22
|
-
<Avatar avatar={'🔑'} background={theme.
|
|
22
|
+
<Avatar avatar={'🔑'} background={theme.colorFillContent} gap={12} size={80} />
|
|
23
23
|
<Flexbox style={{ fontSize: 20 }}>{t('unlock.apikey.title')}</Flexbox>
|
|
24
24
|
<Flexbox className={styles.desc}>{t('unlock.apikey.description')}</Flexbox>
|
|
25
|
-
<Input
|
|
25
|
+
<Input.Password
|
|
26
26
|
onChange={(e) => {
|
|
27
27
|
setSettings({ OPENAI_API_KEY: e.target.value });
|
|
28
28
|
}}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ActionIcon } from '@lobehub/ui';
|
|
2
|
-
import { Dropdown,
|
|
3
|
-
import { BrainCog,
|
|
2
|
+
import { Dropdown, Popover, Switch } from 'antd';
|
|
3
|
+
import { BrainCog, Thermometer, Timer, TimerOff } from 'lucide-react';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { Flexbox } from 'react-layout-kit';
|
|
6
7
|
import { shallow } from 'zustand/shallow';
|
|
7
8
|
|
|
8
9
|
import SliderWithInput from '@/components/SliderWithInput';
|
|
@@ -11,16 +12,15 @@ import { LanguageModel } from '@/types/llm';
|
|
|
11
12
|
|
|
12
13
|
const InputActions = memo(() => {
|
|
13
14
|
const { t } = useTranslation('setting');
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
shallow,
|
|
17
|
-
);
|
|
18
|
-
const [model, temperature] = useSessionStore((s) => {
|
|
15
|
+
|
|
16
|
+
const [model, temperature, historyCount, unlimited, updateAgentConfig] = useSessionStore((s) => {
|
|
19
17
|
const config = agentSelectors.currentAgentConfig(s);
|
|
20
18
|
return [
|
|
21
19
|
config.model,
|
|
22
20
|
config.params.temperature,
|
|
23
|
-
|
|
21
|
+
config.historyCount,
|
|
22
|
+
!config.enableHistoryCount,
|
|
23
|
+
s.updateAgentConfig,
|
|
24
24
|
];
|
|
25
25
|
}, shallow);
|
|
26
26
|
|
|
@@ -54,6 +54,7 @@ const InputActions = memo(() => {
|
|
|
54
54
|
value={temperature}
|
|
55
55
|
/>
|
|
56
56
|
}
|
|
57
|
+
placement={'top'}
|
|
57
58
|
trigger={'click'}
|
|
58
59
|
>
|
|
59
60
|
<ActionIcon
|
|
@@ -62,36 +63,47 @@ const InputActions = memo(() => {
|
|
|
62
63
|
title={t('settingModel.temperature.titleWithValue', { value: temperature })}
|
|
63
64
|
/>
|
|
64
65
|
</Popover>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
66
|
+
<Popover
|
|
67
|
+
arrow={false}
|
|
68
|
+
content={
|
|
69
|
+
<Flexbox align={'center'} gap={16} horizontal>
|
|
70
|
+
<SliderWithInput
|
|
71
|
+
disabled={unlimited}
|
|
72
|
+
max={30}
|
|
73
|
+
min={1}
|
|
74
|
+
onChange={(v) => {
|
|
75
|
+
updateAgentConfig({ historyCount: v });
|
|
76
|
+
}}
|
|
77
|
+
step={1}
|
|
78
|
+
style={{ width: 160 }}
|
|
79
|
+
value={historyCount}
|
|
80
|
+
/>
|
|
81
|
+
<Flexbox align={'center'} gap={4} horizontal>
|
|
82
|
+
<Switch
|
|
83
|
+
checked={unlimited}
|
|
84
|
+
onChange={(checked) => {
|
|
85
|
+
updateAgentConfig({ enableHistoryCount: !checked });
|
|
86
|
+
}}
|
|
87
|
+
size={'small'}
|
|
88
|
+
/>
|
|
89
|
+
{t('settingChat.enableHistoryCount.alias')}
|
|
90
|
+
</Flexbox>
|
|
91
|
+
</Flexbox>
|
|
92
|
+
}
|
|
93
|
+
placement={'top'}
|
|
94
|
+
trigger={'click'}
|
|
88
95
|
>
|
|
89
96
|
<ActionIcon
|
|
90
|
-
icon={
|
|
97
|
+
icon={unlimited ? TimerOff : Timer}
|
|
91
98
|
placement={'bottom'}
|
|
92
|
-
title={t(
|
|
99
|
+
title={t(
|
|
100
|
+
unlimited
|
|
101
|
+
? 'settingChat.enableHistoryCount.unlimited'
|
|
102
|
+
: 'settingChat.enableHistoryCount.limited',
|
|
103
|
+
{ number: historyCount || 0 },
|
|
104
|
+
)}
|
|
93
105
|
/>
|
|
94
|
-
</
|
|
106
|
+
</Popover>
|
|
95
107
|
</>
|
|
96
108
|
);
|
|
97
109
|
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ActionIcon } from '@lobehub/ui';
|
|
2
|
+
import { Popconfirm } from 'antd';
|
|
3
|
+
import { Eraser } from 'lucide-react';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { shallow } from 'zustand/shallow';
|
|
7
|
+
|
|
8
|
+
import { useSessionStore } from '@/store/session';
|
|
9
|
+
|
|
10
|
+
const ActionsRight = memo(() => {
|
|
11
|
+
const { t } = useTranslation('setting');
|
|
12
|
+
const [clearMessage] = useSessionStore((s) => [s.clearMessage, s.updateAgentConfig], shallow);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Popconfirm
|
|
16
|
+
cancelText={t('cancel', { ns: 'common' })}
|
|
17
|
+
okButtonProps={{ danger: true }}
|
|
18
|
+
okText={t('ok', { ns: 'common' })}
|
|
19
|
+
onConfirm={() => clearMessage()}
|
|
20
|
+
title={t('confirmClearCurrentMessages', { ns: 'common' })}
|
|
21
|
+
>
|
|
22
|
+
<ActionIcon
|
|
23
|
+
icon={Eraser}
|
|
24
|
+
placement={'bottom'}
|
|
25
|
+
title={t('clearCurrentMessages', { ns: 'common' })}
|
|
26
|
+
/>
|
|
27
|
+
</Popconfirm>
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export default ActionsRight;
|
|
@@ -23,10 +23,14 @@ const Token = memo<{ input: string }>(({ input }) => {
|
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
|
-
<Tooltip title={t('tokenDetail', { chatsToken, systemRoleToken })}>
|
|
26
|
+
<Tooltip placement={'bottom'} title={t('tokenDetail', { chatsToken, systemRoleToken })}>
|
|
27
27
|
<TokenTag
|
|
28
28
|
maxValue={ModelTokens[model]}
|
|
29
|
-
text={{
|
|
29
|
+
text={{
|
|
30
|
+
overload: t('tokenTag.overload'),
|
|
31
|
+
remained: t('tokenTag.remained'),
|
|
32
|
+
used: t('tokenTag.used'),
|
|
33
|
+
}}
|
|
30
34
|
value={totalToken + inputTokenCount}
|
|
31
35
|
/>
|
|
32
36
|
</Tooltip>
|
|
@@ -10,6 +10,7 @@ import { useSessionStore } from '@/store/session';
|
|
|
10
10
|
import { useSettings } from '@/store/settings';
|
|
11
11
|
|
|
12
12
|
import InputActions from './Action';
|
|
13
|
+
import ActionsRight from './ActionRight';
|
|
13
14
|
import Token from './Token';
|
|
14
15
|
|
|
15
16
|
const ChatInput = () => {
|
|
@@ -52,6 +53,7 @@ const ChatInput = () => {
|
|
|
52
53
|
<Token input={text} />
|
|
53
54
|
</>
|
|
54
55
|
}
|
|
56
|
+
actionsRight={<ActionsRight />}
|
|
55
57
|
expand={expand}
|
|
56
58
|
footer={footer}
|
|
57
59
|
minHeight={CHAT_TEXTAREA_HEIGHT}
|
|
@@ -3,7 +3,7 @@ import Head from 'next/head';
|
|
|
3
3
|
import { memo } from 'react';
|
|
4
4
|
import { Flexbox } from 'react-layout-kit';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { agentSelectors, useSessionStore } from '@/store/session';
|
|
7
7
|
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
8
8
|
|
|
9
9
|
import Layout from '../layout';
|
|
@@ -12,12 +12,12 @@ import Header from './Header';
|
|
|
12
12
|
import Config from './Sidebar';
|
|
13
13
|
|
|
14
14
|
const Chat = memo(() => {
|
|
15
|
-
const [title] = useSessionStore(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const [avatar, title] = useSessionStore(
|
|
16
|
+
(s) => [agentSelectors.currentAgentAvatar(s), agentSelectors.currentAgentTitle(s)],
|
|
17
|
+
isEqual,
|
|
18
|
+
);
|
|
19
19
|
|
|
20
|
-
const pageTitle = genSiteHeadTitle(title);
|
|
20
|
+
const pageTitle = genSiteHeadTitle([avatar, title].filter(Boolean).join(' '));
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<>
|
|
@@ -62,7 +62,10 @@ const hasSystemRole = (s: SessionStore) => {
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
export const getAvatar = (s: MetaData) => s.avatar || DEFAULT_AVATAR;
|
|
65
|
-
export const getTitle = (s: MetaData) => s.title || t('defaultSession');
|
|
65
|
+
export const getTitle = (s: MetaData) => s.title || t('defaultSession', { ns: 'common' });
|
|
66
|
+
|
|
67
|
+
export const getDescription = (s: MetaData) =>
|
|
68
|
+
s.description || t('noDescription', { ns: 'common' });
|
|
66
69
|
|
|
67
70
|
export const agentSelectors = {
|
|
68
71
|
currentAgentAvatar,
|
|
@@ -75,6 +78,7 @@ export const agentSelectors = {
|
|
|
75
78
|
currentAgentTitle,
|
|
76
79
|
currentAutocomplete,
|
|
77
80
|
getAvatar,
|
|
81
|
+
getDescription,
|
|
78
82
|
getTitle,
|
|
79
83
|
hasSystemRole,
|
|
80
84
|
};
|
|
@@ -5,6 +5,7 @@ import { LOADING_FLAT } from '@/const/message';
|
|
|
5
5
|
import { fetchChatModel } from '@/services/chatModel';
|
|
6
6
|
import { fetchPlugin } from '@/services/plugin';
|
|
7
7
|
import { SessionStore, agentSelectors, chatSelectors, sessionSelectors } from '@/store/session';
|
|
8
|
+
import { getSlicedMessagesWithConfig } from '@/store/session/slices/chat/utils';
|
|
8
9
|
import { ChatMessage, OpenAIFunctionCall } from '@/types/chatMessage';
|
|
9
10
|
import { fetchSSE } from '@/utils/fetch';
|
|
10
11
|
import { isFunctionMessage } from '@/utils/message';
|
|
@@ -123,12 +124,17 @@ export const chatMessage: StateCreator<
|
|
|
123
124
|
|
|
124
125
|
const compiler = template(config.inputTemplate, { interpolate: /{{([\S\s]+?)}}/g });
|
|
125
126
|
|
|
126
|
-
//
|
|
127
|
+
// ========================== //
|
|
128
|
+
// 对 messages 做统一预处理 //
|
|
129
|
+
// ========================== //
|
|
127
130
|
|
|
128
|
-
// 1.
|
|
131
|
+
// 1. 按参数设定截断长度
|
|
132
|
+
const slicedMessages = getSlicedMessagesWithConfig(messages, config);
|
|
133
|
+
|
|
134
|
+
// 2. 替换 inputMessage 模板
|
|
129
135
|
const postMessages = !config.inputTemplate
|
|
130
|
-
?
|
|
131
|
-
:
|
|
136
|
+
? slicedMessages
|
|
137
|
+
: slicedMessages.map((m) => {
|
|
132
138
|
if (m.role === 'user') {
|
|
133
139
|
try {
|
|
134
140
|
return { ...m, content: compiler({ text: m.content }) };
|
|
@@ -141,12 +147,9 @@ export const chatMessage: StateCreator<
|
|
|
141
147
|
return m;
|
|
142
148
|
});
|
|
143
149
|
|
|
144
|
-
// 2. TODO 按参数设定截断长度
|
|
145
|
-
|
|
146
150
|
// 3. 添加 systemRole
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
postMessages.unshift({ content: systemRole, role: 'system' } as ChatMessage);
|
|
151
|
+
if (config.systemRole) {
|
|
152
|
+
postMessages.unshift({ content: config.systemRole, role: 'system' } as ChatMessage);
|
|
150
153
|
}
|
|
151
154
|
|
|
152
155
|
const fetcher = () =>
|
|
@@ -1,29 +1,40 @@
|
|
|
1
1
|
import { DEFAULT_USER_AVATAR } from '@/const/meta';
|
|
2
|
-
import { agentSelectors } from '@/store/session';
|
|
3
2
|
import { useSettings } from '@/store/settings';
|
|
4
3
|
import { ChatMessage } from '@/types/chatMessage';
|
|
5
4
|
|
|
6
5
|
import type { SessionStore } from '../../../store';
|
|
6
|
+
import { agentSelectors } from '../../agentConfig';
|
|
7
7
|
import { sessionSelectors } from '../../session';
|
|
8
|
+
import { getSlicedMessagesWithConfig } from '../utils';
|
|
8
9
|
import { organizeChats } from './utils';
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
export const getChatsById =
|
|
12
|
+
(id: string) =>
|
|
13
|
+
(s: SessionStore): ChatMessage[] => {
|
|
14
|
+
const session = sessionSelectors.getSessionById(id)(s);
|
|
15
|
+
|
|
16
|
+
if (!session) return [];
|
|
17
|
+
|
|
18
|
+
return organizeChats(
|
|
19
|
+
session,
|
|
20
|
+
{
|
|
21
|
+
assistant: agentSelectors.currentAgentAvatar(s),
|
|
22
|
+
user: useSettings.getState().settings.avatar || DEFAULT_USER_AVATAR,
|
|
23
|
+
},
|
|
24
|
+
s.activeTopicId,
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// 当前激活的消息列表
|
|
11
29
|
export const currentChats = (s: SessionStore): ChatMessage[] => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return organizeChats(
|
|
16
|
-
session,
|
|
17
|
-
{
|
|
18
|
-
assistant: agentSelectors.currentAgentAvatar(s),
|
|
19
|
-
user: useSettings.getState().settings.avatar || DEFAULT_USER_AVATAR,
|
|
20
|
-
},
|
|
21
|
-
s.activeTopicId,
|
|
22
|
-
);
|
|
30
|
+
if (!s.activeId) return [];
|
|
31
|
+
|
|
32
|
+
return getChatsById(s.activeId)(s);
|
|
23
33
|
};
|
|
24
34
|
|
|
25
|
-
export const
|
|
35
|
+
export const currentChatsWithHistoryConfig = (s: SessionStore): ChatMessage[] => {
|
|
36
|
+
const chats = currentChats(s);
|
|
26
37
|
const config = agentSelectors.currentAgentConfig(s);
|
|
27
38
|
|
|
28
|
-
return config
|
|
39
|
+
return getSlicedMessagesWithConfig(chats, config);
|
|
29
40
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { currentChats } from './chat';
|
|
1
|
+
import { currentChats, getChatsById } from './chat';
|
|
2
2
|
import { chatsTokenCount, systemRoleTokenCount, totalTokenCount } from './token';
|
|
3
3
|
import { currentTopics, getTopicMessages } from './topic';
|
|
4
4
|
|
|
5
5
|
export const chatSelectors = {
|
|
6
6
|
chatsTokenCount,
|
|
7
7
|
currentChats,
|
|
8
|
+
getChatsById,
|
|
8
9
|
systemRoleTokenCount,
|
|
9
10
|
totalTokenCount,
|
|
10
11
|
};
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { encode } from 'gpt-tokenizer';
|
|
2
2
|
|
|
3
|
+
import { agentSelectors } from '@/store/session';
|
|
4
|
+
|
|
3
5
|
import type { SessionStore } from '../../../store';
|
|
4
|
-
import {
|
|
6
|
+
import { currentChatsWithHistoryConfig } from './chat';
|
|
7
|
+
|
|
8
|
+
export const systemRoleSel = (s: SessionStore): string => {
|
|
9
|
+
const config = agentSelectors.currentAgentConfig(s);
|
|
10
|
+
|
|
11
|
+
return config.systemRole;
|
|
12
|
+
};
|
|
5
13
|
|
|
6
14
|
const systemRoleTokens = (s: SessionStore): number[] => {
|
|
7
15
|
const systemRole = systemRoleSel(s);
|
|
@@ -10,7 +18,7 @@ const systemRoleTokens = (s: SessionStore): number[] => {
|
|
|
10
18
|
};
|
|
11
19
|
|
|
12
20
|
const chatsTokens = (s: SessionStore): number[] => {
|
|
13
|
-
const chats =
|
|
21
|
+
const chats = currentChatsWithHistoryConfig(s);
|
|
14
22
|
return encode(chats.map((m) => m.content).join(''));
|
|
15
23
|
};
|
|
16
24
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ChatMessage } from '@/types/chatMessage';
|
|
2
|
+
import { LobeAgentConfig } from '@/types/session';
|
|
3
|
+
|
|
4
|
+
export const getSlicedMessagesWithConfig = (
|
|
5
|
+
messages: ChatMessage[],
|
|
6
|
+
config: LobeAgentConfig,
|
|
7
|
+
): ChatMessage[] => {
|
|
8
|
+
// 如果没有开启历史消息数限制,或者限制为 0,则直接返回
|
|
9
|
+
if (!config.enableHistoryCount || !config.historyCount) return messages;
|
|
10
|
+
|
|
11
|
+
// 如果开启了,则返回尾部的N条消息
|
|
12
|
+
return messages.reverse().slice(0, config.historyCount).reverse();
|
|
13
|
+
};
|
package/src/types/session.ts
CHANGED