@lobehub/chat 1.79.10 → 1.80.1
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/CHANGELOG.md +85 -0
- package/changelog/v1.json +27 -0
- package/docs/development/basic/feature-development.mdx +370 -619
- package/docs/development/basic/feature-development.zh-CN.mdx +368 -611
- package/docs/development/database-schema.dbml +2 -0
- package/locales/ar/setting.json +16 -0
- package/locales/bg-BG/setting.json +16 -0
- package/locales/de-DE/setting.json +16 -0
- package/locales/en-US/setting.json +16 -0
- package/locales/es-ES/setting.json +16 -0
- package/locales/fa-IR/setting.json +16 -0
- package/locales/fr-FR/setting.json +16 -0
- package/locales/it-IT/setting.json +16 -0
- package/locales/ja-JP/setting.json +16 -0
- package/locales/ko-KR/setting.json +16 -0
- package/locales/nl-NL/setting.json +16 -0
- package/locales/pl-PL/setting.json +16 -0
- package/locales/pt-BR/setting.json +16 -0
- package/locales/ru-RU/setting.json +16 -0
- package/locales/tr-TR/setting.json +16 -0
- package/locales/vi-VN/setting.json +16 -0
- package/locales/zh-CN/setting.json +16 -0
- package/locales/zh-TW/setting.json +16 -0
- package/package.json +1 -1
- package/scripts/generate-oidc-jwk.mjs +2 -1
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/OpeningQuestions.tsx +78 -0
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/WelcomeMessage.tsx +24 -4
- package/src/app/[variants]/(main)/chat/(workspace)/features/AgentSettings/CategoryContent/useCategory.tsx +6 -1
- package/src/app/[variants]/(main)/chat/(workspace)/features/AgentSettings/index.tsx +2 -0
- package/src/const/settings/agent.ts +1 -0
- package/src/database/_deprecated/schemas/session.ts +2 -0
- package/src/database/client/migrations.json +9 -0
- package/src/database/migrations/0021_add_agent_opening_settings.sql +2 -0
- package/src/database/migrations/meta/0021_snapshot.json +4988 -0
- package/src/database/migrations/meta/_journal.json +7 -0
- package/src/database/repositories/dataImporter/deprecated/__tests__/fixtures/messages.json +2 -0
- package/src/database/repositories/dataImporter/deprecated/__tests__/index.test.ts +19 -0
- package/src/database/schemas/agent.ts +3 -0
- package/src/features/AgentSetting/AgentOpening/OpeningMessage.tsx +80 -0
- package/src/features/AgentSetting/AgentOpening/OpeningQuestions.tsx +144 -0
- package/src/features/AgentSetting/AgentOpening/index.tsx +52 -0
- package/src/features/AgentSetting/store/selectors.ts +3 -0
- package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +7 -6
- package/src/hooks/useModelSupportFiles.ts +15 -0
- package/src/libs/agent-runtime/stepfun/index.ts +7 -1
- package/src/libs/agent-runtime/zhipu/index.ts +17 -10
- package/src/locales/default/setting.ts +16 -0
- package/src/migrations/FromV5ToV6/types/v6.ts +2 -0
- package/src/server/routers/lambda/session.ts +8 -1
- package/src/services/import/client.test.ts +18 -0
- package/src/services/session/server.test.ts +2 -0
- package/src/store/agent/slices/chat/selectors/__snapshots__/agent.test.ts.snap +1 -0
- package/src/store/agent/slices/chat/selectors/agent.ts +7 -0
- package/src/store/aiInfra/slices/aiModel/selectors.ts +7 -0
- package/src/store/global/initialState.ts +1 -0
- package/src/store/user/slices/settings/selectors/__snapshots__/settings.test.ts.snap +2 -0
- package/src/types/agent/index.ts +12 -0
@@ -147,6 +147,13 @@
|
|
147
147
|
"when": 1744458287757,
|
148
148
|
"tag": "0020_add_oidc",
|
149
149
|
"breakpoints": true
|
150
|
+
},
|
151
|
+
{
|
152
|
+
"idx": 21,
|
153
|
+
"version": "7",
|
154
|
+
"when": 1744602998656,
|
155
|
+
"tag": "0021_add_agent_opening_settings",
|
156
|
+
"breakpoints": true
|
150
157
|
}
|
151
158
|
],
|
152
159
|
"version": "6"
|
@@ -926,6 +926,8 @@
|
|
926
926
|
"ttsService": "openai",
|
927
927
|
"voice": { "openai": "alloy" }
|
928
928
|
},
|
929
|
+
"openingMessage": "I'm an AI assistant, how can I help you today?",
|
930
|
+
"openingQuestions": ["Question 1", "Question 2"],
|
929
931
|
"chatConfig": {
|
930
932
|
"autoCreateTopicThreshold": 2,
|
931
933
|
"displayMode": "chat",
|
@@ -94,6 +94,7 @@ describe('DataImporter', () => {
|
|
94
94
|
params: {},
|
95
95
|
systemRole: 'abc',
|
96
96
|
tts: {} as any,
|
97
|
+
openingQuestions: [],
|
97
98
|
},
|
98
99
|
meta: {
|
99
100
|
title: 'Session 1',
|
@@ -110,6 +111,7 @@ describe('DataImporter', () => {
|
|
110
111
|
params: {},
|
111
112
|
systemRole: 'abc',
|
112
113
|
tts: {} as any,
|
114
|
+
openingQuestions: [],
|
113
115
|
},
|
114
116
|
meta: {
|
115
117
|
title: 'Session 2',
|
@@ -156,6 +158,7 @@ describe('DataImporter', () => {
|
|
156
158
|
params: {},
|
157
159
|
systemRole: 'abc',
|
158
160
|
tts: {} as any,
|
161
|
+
openingQuestions: [],
|
159
162
|
},
|
160
163
|
meta: {
|
161
164
|
title: 'Session 1',
|
@@ -172,6 +175,7 @@ describe('DataImporter', () => {
|
|
172
175
|
params: {},
|
173
176
|
systemRole: 'abc',
|
174
177
|
tts: {} as any,
|
178
|
+
openingQuestions: [],
|
175
179
|
},
|
176
180
|
meta: {
|
177
181
|
title: 'Session 2',
|
@@ -207,6 +211,7 @@ describe('DataImporter', () => {
|
|
207
211
|
params: {},
|
208
212
|
systemRole: 'abc',
|
209
213
|
tts: {} as any,
|
214
|
+
openingQuestions: [],
|
210
215
|
},
|
211
216
|
meta: {
|
212
217
|
title: 'Session 1',
|
@@ -224,6 +229,7 @@ describe('DataImporter', () => {
|
|
224
229
|
params: {},
|
225
230
|
systemRole: 'abc',
|
226
231
|
tts: {} as any,
|
232
|
+
openingQuestions: [],
|
227
233
|
},
|
228
234
|
meta: {
|
229
235
|
title: 'Session 2',
|
@@ -241,6 +247,7 @@ describe('DataImporter', () => {
|
|
241
247
|
params: {},
|
242
248
|
systemRole: 'abc',
|
243
249
|
tts: {} as any,
|
250
|
+
openingQuestions: [],
|
244
251
|
},
|
245
252
|
meta: {
|
246
253
|
title: 'Session 3',
|
@@ -287,6 +294,7 @@ describe('DataImporter', () => {
|
|
287
294
|
params: {},
|
288
295
|
systemRole: 'Test Agent 1',
|
289
296
|
tts: {} as any,
|
297
|
+
openingQuestions: [],
|
290
298
|
},
|
291
299
|
meta: {
|
292
300
|
title: 'Session 1',
|
@@ -303,6 +311,7 @@ describe('DataImporter', () => {
|
|
303
311
|
params: {},
|
304
312
|
systemRole: 'Test Agent 2',
|
305
313
|
tts: {} as any,
|
314
|
+
openingQuestions: [],
|
306
315
|
},
|
307
316
|
meta: {
|
308
317
|
title: 'Session 2',
|
@@ -367,6 +376,7 @@ describe('DataImporter', () => {
|
|
367
376
|
params: {},
|
368
377
|
systemRole: 'Test Agent 1',
|
369
378
|
tts: {} as any,
|
379
|
+
openingQuestions: [],
|
370
380
|
},
|
371
381
|
meta: {
|
372
382
|
title: 'Session 1',
|
@@ -390,6 +400,7 @@ describe('DataImporter', () => {
|
|
390
400
|
params: {},
|
391
401
|
systemRole: 'Test Agent 1',
|
392
402
|
tts: {} as any,
|
403
|
+
openingQuestions: [],
|
393
404
|
},
|
394
405
|
meta: {
|
395
406
|
title: 'Session 1',
|
@@ -439,6 +450,7 @@ describe('DataImporter', () => {
|
|
439
450
|
params: {},
|
440
451
|
systemRole: 'abc',
|
441
452
|
tts: {} as any,
|
453
|
+
openingQuestions: [],
|
442
454
|
},
|
443
455
|
meta: {
|
444
456
|
title: 'Session 1',
|
@@ -455,6 +467,8 @@ describe('DataImporter', () => {
|
|
455
467
|
params: {},
|
456
468
|
systemRole: 'abc',
|
457
469
|
tts: {} as any,
|
470
|
+
openingQuestions: [],
|
471
|
+
openingMessage: `Hello, I'm Agent 2, learn more from [xxx](https://xxx.com)`,
|
458
472
|
},
|
459
473
|
meta: {
|
460
474
|
title: 'Session 2',
|
@@ -507,6 +521,7 @@ describe('DataImporter', () => {
|
|
507
521
|
params: {},
|
508
522
|
systemRole: 'abc',
|
509
523
|
tts: {} as any,
|
524
|
+
openingQuestions: [],
|
510
525
|
},
|
511
526
|
meta: {
|
512
527
|
title: 'Session 1',
|
@@ -582,6 +597,7 @@ describe('DataImporter', () => {
|
|
582
597
|
params: {},
|
583
598
|
systemRole: 'abc',
|
584
599
|
tts: {} as any,
|
600
|
+
openingQuestions: [],
|
585
601
|
},
|
586
602
|
meta: {
|
587
603
|
title: 'Session 1',
|
@@ -661,6 +677,7 @@ describe('DataImporter', () => {
|
|
661
677
|
params: {},
|
662
678
|
systemRole: 'abc',
|
663
679
|
tts: {} as any,
|
680
|
+
openingQuestions: [],
|
664
681
|
},
|
665
682
|
meta: {
|
666
683
|
title: 'Session 1',
|
@@ -872,6 +889,8 @@ describe('DataImporter', () => {
|
|
872
889
|
enableAutoCreateTopic: true,
|
873
890
|
historyCount: 1,
|
874
891
|
},
|
892
|
+
openingQuestions: ['Question 1', 'Question 2'],
|
893
|
+
openingMessage: `Hello, I'm Agent 1, learn more from [xxx](https://xxx.com)`,
|
875
894
|
},
|
876
895
|
group: 'XlUbvOvL',
|
877
896
|
meta: {
|
@@ -54,6 +54,9 @@ export const agents = pgTable(
|
|
54
54
|
systemRole: text('system_role'),
|
55
55
|
tts: jsonb('tts').$type<LobeAgentTTSConfig>(),
|
56
56
|
|
57
|
+
openingMessage: text('opening_message'),
|
58
|
+
openingQuestions: text('opening_questions').array().default([]),
|
59
|
+
|
57
60
|
...timestamps,
|
58
61
|
},
|
59
62
|
(t) => ({
|
@@ -0,0 +1,80 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { EditableMessage } from '@lobehub/ui';
|
4
|
+
import { Button } from 'antd';
|
5
|
+
import { createStyles } from 'antd-style';
|
6
|
+
import { PencilLine } from 'lucide-react';
|
7
|
+
import { memo, useCallback, useState } from 'react';
|
8
|
+
import { useTranslation } from 'react-i18next';
|
9
|
+
import { Flexbox } from 'react-layout-kit';
|
10
|
+
|
11
|
+
import { useStore } from '../store';
|
12
|
+
import { selectors } from '../store/selectors';
|
13
|
+
|
14
|
+
export const useStyles = createStyles(({ css, token }) => ({
|
15
|
+
markdown: css`
|
16
|
+
border: unset;
|
17
|
+
`,
|
18
|
+
wrapper: css`
|
19
|
+
width: 100%;
|
20
|
+
padding: 8px;
|
21
|
+
border: 1px solid ${token.colorBorder};
|
22
|
+
border-radius: ${token.borderRadiusLG - 1}px;
|
23
|
+
|
24
|
+
background: ${token.colorBgContainer};
|
25
|
+
`,
|
26
|
+
}));
|
27
|
+
|
28
|
+
const OpeningMessage = memo(() => {
|
29
|
+
const { t } = useTranslation('setting');
|
30
|
+
const { styles } = useStyles();
|
31
|
+
|
32
|
+
const openingMessage = useStore(selectors.openingMessage);
|
33
|
+
const updateConfig = useStore((s) => s.setAgentConfig);
|
34
|
+
const setOpeningMessage = useCallback(
|
35
|
+
(message: string) => {
|
36
|
+
updateConfig({ openingMessage: message });
|
37
|
+
},
|
38
|
+
[updateConfig],
|
39
|
+
);
|
40
|
+
|
41
|
+
const [editing, setEditing] = useState(false);
|
42
|
+
|
43
|
+
const handleEdit = useCallback(() => {
|
44
|
+
setEditing(true);
|
45
|
+
}, []);
|
46
|
+
|
47
|
+
const editIconButton = !editing && openingMessage && (
|
48
|
+
<Button onClick={handleEdit} size={'small'}>
|
49
|
+
<PencilLine size={16} />
|
50
|
+
</Button>
|
51
|
+
);
|
52
|
+
|
53
|
+
return (
|
54
|
+
<div className={styles.wrapper}>
|
55
|
+
<Flexbox direction={'horizontal'}>
|
56
|
+
<EditableMessage
|
57
|
+
classNames={{
|
58
|
+
markdown: styles.markdown,
|
59
|
+
}}
|
60
|
+
editButtonSize={'small'}
|
61
|
+
editing={editing}
|
62
|
+
height={'auto'}
|
63
|
+
inputType={'pure'}
|
64
|
+
onChange={setOpeningMessage}
|
65
|
+
onEditingChange={setEditing}
|
66
|
+
placeholder={t('settingOpening.openingMessage.placeholder')}
|
67
|
+
showEditWhenEmpty
|
68
|
+
text={{
|
69
|
+
cancel: t('cancel', { ns: 'common' }),
|
70
|
+
confirm: t('ok', { ns: 'common' }),
|
71
|
+
}}
|
72
|
+
value={openingMessage ?? ''}
|
73
|
+
/>
|
74
|
+
{editIconButton}
|
75
|
+
</Flexbox>
|
76
|
+
</div>
|
77
|
+
);
|
78
|
+
});
|
79
|
+
|
80
|
+
export default OpeningMessage;
|
@@ -0,0 +1,144 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
4
|
+
import { SortableList } from '@lobehub/ui';
|
5
|
+
import { Button, Empty, Input } from 'antd';
|
6
|
+
import { createStyles } from 'antd-style';
|
7
|
+
import { memo, useCallback, useMemo, useState } from 'react';
|
8
|
+
import { useTranslation } from 'react-i18next';
|
9
|
+
import { Flexbox } from 'react-layout-kit';
|
10
|
+
|
11
|
+
import { useStore } from '../store';
|
12
|
+
import { selectors } from '../store/selectors';
|
13
|
+
|
14
|
+
const useStyles = createStyles(({ css, token }) => ({
|
15
|
+
empty: css`
|
16
|
+
margin-block: 24px;
|
17
|
+
margin-inline: 0;
|
18
|
+
`,
|
19
|
+
questionItemContainer: css`
|
20
|
+
margin-block-end: 8px;
|
21
|
+
padding-block: 2px;
|
22
|
+
padding-inline: 10px 0;
|
23
|
+
background: ${token.colorBgContainer};
|
24
|
+
`,
|
25
|
+
questionItemContent: css`
|
26
|
+
flex: 1;
|
27
|
+
`,
|
28
|
+
questionsList: css`
|
29
|
+
width: 100%;
|
30
|
+
margin-block-start: 16px;
|
31
|
+
`,
|
32
|
+
repeatError: css`
|
33
|
+
margin: 0;
|
34
|
+
color: ${token.colorErrorText};
|
35
|
+
`,
|
36
|
+
}));
|
37
|
+
|
38
|
+
interface QuestionItem {
|
39
|
+
content: string;
|
40
|
+
id: number;
|
41
|
+
}
|
42
|
+
|
43
|
+
const OpeningQuestions = memo(() => {
|
44
|
+
const { t } = useTranslation('setting');
|
45
|
+
const { styles } = useStyles();
|
46
|
+
const [questionInput, setQuestionInput] = useState('');
|
47
|
+
|
48
|
+
const openingQuestions = useStore(selectors.openingQuestions);
|
49
|
+
const updateConfig = useStore((s) => s.setAgentConfig);
|
50
|
+
const setQuestions = useCallback(
|
51
|
+
(questions: string[]) => {
|
52
|
+
updateConfig({ openingQuestions: questions });
|
53
|
+
},
|
54
|
+
[updateConfig],
|
55
|
+
);
|
56
|
+
|
57
|
+
const addQuestion = useCallback(() => {
|
58
|
+
if (!questionInput.trim()) return;
|
59
|
+
|
60
|
+
setQuestions([...openingQuestions, questionInput.trim()]);
|
61
|
+
setQuestionInput('');
|
62
|
+
}, [openingQuestions, questionInput, setQuestions]);
|
63
|
+
|
64
|
+
const removeQuestion = useCallback(
|
65
|
+
(content: string) => {
|
66
|
+
const newQuestions = [...openingQuestions];
|
67
|
+
const index = newQuestions.indexOf(content);
|
68
|
+
newQuestions.splice(index, 1);
|
69
|
+
setQuestions(newQuestions);
|
70
|
+
},
|
71
|
+
[openingQuestions, setQuestions],
|
72
|
+
);
|
73
|
+
|
74
|
+
// 处理拖拽排序后的逻辑
|
75
|
+
const handleSortEnd = useCallback(
|
76
|
+
(items: QuestionItem[]) => {
|
77
|
+
setQuestions(items.map((item) => item.content));
|
78
|
+
},
|
79
|
+
[setQuestions],
|
80
|
+
);
|
81
|
+
|
82
|
+
const items: QuestionItem[] = useMemo(() => {
|
83
|
+
return openingQuestions.map((item, index) => ({
|
84
|
+
content: item,
|
85
|
+
id: index,
|
86
|
+
}));
|
87
|
+
}, [openingQuestions]);
|
88
|
+
|
89
|
+
const isRepeat = openingQuestions.includes(questionInput.trim());
|
90
|
+
|
91
|
+
return (
|
92
|
+
<Flexbox gap={8}>
|
93
|
+
<Flexbox gap={4}>
|
94
|
+
<Input
|
95
|
+
addonAfter={
|
96
|
+
<Button
|
97
|
+
// don't allow repeat
|
98
|
+
disabled={openingQuestions.includes(questionInput.trim())}
|
99
|
+
icon={<PlusOutlined />}
|
100
|
+
onClick={addQuestion}
|
101
|
+
size="small"
|
102
|
+
type="text"
|
103
|
+
/>
|
104
|
+
}
|
105
|
+
onChange={(e) => setQuestionInput(e.target.value)}
|
106
|
+
onPressEnter={addQuestion}
|
107
|
+
placeholder={t('settingOpening.openingQuestions.placeholder')}
|
108
|
+
value={questionInput}
|
109
|
+
/>
|
110
|
+
|
111
|
+
{isRepeat && (
|
112
|
+
<p className={styles.repeatError}>{t('settingOpening.openingQuestions.repeat')}</p>
|
113
|
+
)}
|
114
|
+
</Flexbox>
|
115
|
+
|
116
|
+
<div className={styles.questionsList}>
|
117
|
+
{openingQuestions.length > 0 ? (
|
118
|
+
<SortableList
|
119
|
+
items={items}
|
120
|
+
onChange={handleSortEnd}
|
121
|
+
renderItem={(item) => (
|
122
|
+
<SortableList.Item className={styles.questionItemContainer} id={item.id}>
|
123
|
+
<SortableList.DragHandle />
|
124
|
+
<div className={styles.questionItemContent}>{item.content}</div>
|
125
|
+
<Button
|
126
|
+
icon={<DeleteOutlined />}
|
127
|
+
onClick={() => removeQuestion(item.content)}
|
128
|
+
type="text"
|
129
|
+
/>
|
130
|
+
</SortableList.Item>
|
131
|
+
)}
|
132
|
+
/>
|
133
|
+
) : (
|
134
|
+
<Empty
|
135
|
+
className={styles.empty}
|
136
|
+
description={t('settingOpening.openingQuestions.empty')}
|
137
|
+
/>
|
138
|
+
)}
|
139
|
+
</div>
|
140
|
+
</Flexbox>
|
141
|
+
);
|
142
|
+
});
|
143
|
+
|
144
|
+
export default OpeningQuestions;
|
@@ -0,0 +1,52 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { Form } from '@lobehub/ui';
|
4
|
+
import { memo } from 'react';
|
5
|
+
import { useTranslation } from 'react-i18next';
|
6
|
+
|
7
|
+
import { FORM_STYLE } from '@/const/layoutTokens';
|
8
|
+
|
9
|
+
import OpeningMessage from './OpeningMessage';
|
10
|
+
import OpeningQuestions from './OpeningQuestions';
|
11
|
+
|
12
|
+
const wrapperCol = {
|
13
|
+
style: {
|
14
|
+
maxWidth: '100%',
|
15
|
+
width: '100%',
|
16
|
+
},
|
17
|
+
};
|
18
|
+
|
19
|
+
const AgentOpening = memo(() => {
|
20
|
+
const { t } = useTranslation('setting');
|
21
|
+
|
22
|
+
return (
|
23
|
+
<Form
|
24
|
+
items={[
|
25
|
+
{
|
26
|
+
children: [
|
27
|
+
{
|
28
|
+
children: <OpeningMessage />,
|
29
|
+
desc: t('settingOpening.openingMessage.desc'),
|
30
|
+
label: t('settingOpening.openingMessage.title'),
|
31
|
+
layout: 'vertical',
|
32
|
+
wrapperCol,
|
33
|
+
},
|
34
|
+
{
|
35
|
+
children: <OpeningQuestions />,
|
36
|
+
desc: t('settingOpening.openingQuestions.desc'),
|
37
|
+
label: t('settingOpening.openingQuestions.title'),
|
38
|
+
layout: 'vertical',
|
39
|
+
wrapperCol,
|
40
|
+
},
|
41
|
+
],
|
42
|
+
title: t('settingOpening.title'),
|
43
|
+
},
|
44
|
+
]}
|
45
|
+
itemsType={'group'}
|
46
|
+
variant={'pure'}
|
47
|
+
{...FORM_STYLE}
|
48
|
+
/>
|
49
|
+
);
|
50
|
+
});
|
51
|
+
|
52
|
+
export default AgentOpening;
|
@@ -6,6 +6,9 @@ import { Store } from './action';
|
|
6
6
|
const chatConfig = (s: Store): LobeAgentChatConfig =>
|
7
7
|
s.config.chatConfig || DEFAULT_AGENT_CHAT_CONFIG;
|
8
8
|
|
9
|
+
export const DEFAULT_OPENING_QUESTIONS: string[] = [];
|
9
10
|
export const selectors = {
|
10
11
|
chatConfig,
|
12
|
+
openingMessage: (s: Store) => s.config.openingMessage,
|
13
|
+
openingQuestions: (s: Store) => s.config.openingQuestions || DEFAULT_OPENING_QUESTIONS,
|
11
14
|
};
|
@@ -7,8 +7,8 @@ import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { useAgentStore } from '@/store/agent';
|
8
8
|
import { agentSelectors } from '@/store/agent/slices/chat';
|
9
9
|
import { useFileStore } from '@/store/file';
|
10
|
-
import {
|
11
|
-
import {
|
10
|
+
import { useModelSupportFiles } from "@/hooks/useModelSupportFiles";
|
11
|
+
import { useModelSupportVision } from "@/hooks/useModelSupportVision";
|
12
12
|
|
13
13
|
const FileUpload = memo(() => {
|
14
14
|
const { t } = useTranslation('chat');
|
@@ -16,10 +16,11 @@ const FileUpload = memo(() => {
|
|
16
16
|
const upload = useFileStore((s) => s.uploadChatFiles);
|
17
17
|
|
18
18
|
const model = useAgentStore(agentSelectors.currentAgentModel);
|
19
|
-
const
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
const provider = useAgentStore(agentSelectors.currentAgentModelProvider);
|
20
|
+
|
21
|
+
const enabledFiles = useModelSupportFiles(model, provider);
|
22
|
+
const supportVision = useModelSupportVision(model, provider);
|
23
|
+
const canUpload = enabledFiles || supportVision;
|
23
24
|
|
24
25
|
return (
|
25
26
|
<Upload
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { isDeprecatedEdition } from '@/const/version';
|
2
|
+
import { aiModelSelectors, useAiInfraStore } from '@/store/aiInfra';
|
3
|
+
import { useUserStore } from '@/store/user';
|
4
|
+
import { modelProviderSelectors } from '@/store/user/selectors';
|
5
|
+
|
6
|
+
export const useModelSupportFiles = (model: string, provider: string) => {
|
7
|
+
const newValue = useAiInfraStore(aiModelSelectors.isModelSupportFiles(model, provider));
|
8
|
+
|
9
|
+
// TODO: remove this in V2.0
|
10
|
+
const oldValue = useUserStore(modelProviderSelectors.isModelEnabledFiles(model));
|
11
|
+
if (isDeprecatedEdition) return oldValue;
|
12
|
+
//
|
13
|
+
|
14
|
+
return newValue;
|
15
|
+
};
|
@@ -46,9 +46,14 @@ export const LobeStepfunAI = LobeOpenAICompatibleFactory({
|
|
46
46
|
|
47
47
|
const visionKeywords = [
|
48
48
|
'step-1o-',
|
49
|
+
'step-r1-v-',
|
49
50
|
'step-1v-',
|
50
51
|
];
|
51
52
|
|
53
|
+
const reasoningKeywords = [
|
54
|
+
'step-r1-',
|
55
|
+
];
|
56
|
+
|
52
57
|
const modelsPage = await client.models.list() as any;
|
53
58
|
const modelList: StepfunModelCard[] = modelsPage.data;
|
54
59
|
|
@@ -66,7 +71,8 @@ export const LobeStepfunAI = LobeOpenAICompatibleFactory({
|
|
66
71
|
|| false,
|
67
72
|
id: model.id,
|
68
73
|
reasoning:
|
69
|
-
|
74
|
+
reasoningKeywords.some(keyword => model.id.toLowerCase().includes(keyword))
|
75
|
+
|| knownModel?.abilities?.reasoning
|
70
76
|
|| false,
|
71
77
|
vision:
|
72
78
|
visionKeywords.some(keyword => model.id.toLowerCase().includes(keyword))
|
@@ -50,23 +50,30 @@ export const LobeZhipuAI = LobeOpenAICompatibleFactory({
|
|
50
50
|
} as any;
|
51
51
|
},
|
52
52
|
},
|
53
|
-
constructorOptions: {
|
54
|
-
defaultHeaders: {
|
55
|
-
'Bigmodel-Organization': 'lobehub',
|
56
|
-
'Bigmodel-project': 'lobechat',
|
57
|
-
},
|
58
|
-
},
|
59
53
|
debug: {
|
60
54
|
chatCompletion: () => process.env.DEBUG_ZHIPU_CHAT_COMPLETION === '1',
|
61
55
|
},
|
62
56
|
models: async ({ client }) => {
|
63
57
|
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');
|
64
58
|
|
59
|
+
const reasoningKeywords = [
|
60
|
+
'glm-zero',
|
61
|
+
'glm-z1',
|
62
|
+
];
|
63
|
+
|
65
64
|
// ref: https://open.bigmodel.cn/console/modelcenter/square
|
66
|
-
|
65
|
+
const url = 'https://open.bigmodel.cn/api/fine-tuning/model_center/list?pageSize=100&pageNum=1';
|
66
|
+
const response = await fetch(url, {
|
67
|
+
headers: {
|
68
|
+
'Authorization': `Bearer ${client.apiKey}`,
|
69
|
+
'Bigmodel-Organization': 'lobehub',
|
70
|
+
'Bigmodel-Project': 'lobechat',
|
71
|
+
},
|
72
|
+
method: 'GET',
|
73
|
+
});
|
74
|
+
const json = await response.json();
|
67
75
|
|
68
|
-
const
|
69
|
-
const modelList: ZhipuModelCard[] = modelsPage.body.rows;
|
76
|
+
const modelList: ZhipuModelCard[] = json.rows;
|
70
77
|
|
71
78
|
return modelList
|
72
79
|
.map((model) => {
|
@@ -83,7 +90,7 @@ export const LobeZhipuAI = LobeOpenAICompatibleFactory({
|
|
83
90
|
|| false,
|
84
91
|
id: model.modelCode,
|
85
92
|
reasoning:
|
86
|
-
model.modelCode.toLowerCase().includes(
|
93
|
+
reasoningKeywords.some(keyword => model.modelCode.toLowerCase().includes(keyword))
|
87
94
|
|| knownModel?.abilities?.reasoning
|
88
95
|
|| false,
|
89
96
|
vision:
|
@@ -6,6 +6,7 @@ export default {
|
|
6
6
|
chat: '聊天偏好',
|
7
7
|
meta: '助手信息',
|
8
8
|
modal: '模型设置',
|
9
|
+
opening: '开场设置',
|
9
10
|
plugin: '插件设置',
|
10
11
|
prompt: '角色设定',
|
11
12
|
tts: '语音服务',
|
@@ -255,6 +256,21 @@ export default {
|
|
255
256
|
title: '思维开放度',
|
256
257
|
},
|
257
258
|
},
|
259
|
+
settingOpening: {
|
260
|
+
openingMessage: {
|
261
|
+
desc: '打开会话时的开场消息,用来介绍助手的功能',
|
262
|
+
placeholder: '你好,我是自定义助手。你可以立即与我开始对话,也可以前往助手设置完善我的信息。',
|
263
|
+
title: '开场消息',
|
264
|
+
},
|
265
|
+
openingQuestions: {
|
266
|
+
desc: '会话开始时展示的引导性问题',
|
267
|
+
empty: '暂无问题',
|
268
|
+
placeholder: '请输入问题',
|
269
|
+
repeat: '问题已存在',
|
270
|
+
title: '开场问题',
|
271
|
+
},
|
272
|
+
title: '开场设置',
|
273
|
+
},
|
258
274
|
settingPlugin: {
|
259
275
|
title: '插件列表',
|
260
276
|
},
|
@@ -76,7 +76,14 @@ export const sessionRouter = router({
|
|
76
76
|
.input(
|
77
77
|
z.object({
|
78
78
|
config: insertAgentSchema
|
79
|
-
.omit({
|
79
|
+
.omit({
|
80
|
+
chatConfig: true,
|
81
|
+
openingMessage: true,
|
82
|
+
openingQuestions: true,
|
83
|
+
plugins: true,
|
84
|
+
tags: true,
|
85
|
+
tts: true,
|
86
|
+
})
|
80
87
|
.passthrough()
|
81
88
|
.partial(),
|
82
89
|
session: insertSessionSchema.omit({ createdAt: true, updatedAt: true }).partial(),
|