@lobehub/chat 0.16.0 → 0.17.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/CHANGELOG.md CHANGED
@@ -2,6 +2,64 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 0.17.0](https://github.com/lobehub/lobe-chat/compare/v0.16.1...v0.17.0)
6
+
7
+ <sup>Released on **2023-07-24**</sup>
8
+
9
+ #### ✨ Features
10
+
11
+ - **misc**: 表单配置支持设定各项高级参数.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's improved
19
+
20
+ - **misc**: 表单配置支持设定各项高级参数 ([6949cc6](https://github.com/lobehub/lobe-chat/commit/6949cc6))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ### [Version 0.16.1](https://github.com/lobehub/lobe-chat/compare/v0.16.0...v0.16.1)
31
+
32
+ <sup>Released on **2023-07-24**</sup>
33
+
34
+ #### ♻ Code Refactoring
35
+
36
+ - **misc**: 重构优化 selectors 实现.
37
+
38
+ #### 💄 Styles
39
+
40
+ - **misc**: 优化 document title.
41
+
42
+ <br/>
43
+
44
+ <details>
45
+ <summary><kbd>Improvements and Fixes</kbd></summary>
46
+
47
+ #### Code refactoring
48
+
49
+ - **misc**: 重构优化 selectors 实现 ([97fe1cd](https://github.com/lobehub/lobe-chat/commit/97fe1cd))
50
+
51
+ #### Styles
52
+
53
+ - **misc**: 优化 document title ([c3cda00](https://github.com/lobehub/lobe-chat/commit/c3cda00))
54
+
55
+ </details>
56
+
57
+ <div align="right">
58
+
59
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
60
+
61
+ </div>
62
+
5
63
  ## [Version 0.16.0](https://github.com/lobehub/lobe-chat/compare/v0.15.1...v0.16.0)
6
64
 
7
65
  <sup>Released on **2023-07-24**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "Lobe Chat is an open-source chatbot client using LangChain, Typescript and Next.js",
5
5
  "keywords": [
6
6
  "chatbot",
@@ -17,6 +17,7 @@ export default {
17
17
  header: {
18
18
  global: '全局设置',
19
19
  session: '会话设置',
20
+ sessionWithName: '会话设置 · {{name}}',
20
21
  },
21
22
  settingAgent: {
22
23
  avatar: {
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
6
6
  import { Flexbox } from 'react-layout-kit';
7
7
  import { shallow } from 'zustand/shallow';
8
8
 
9
- import { chatSelectors, sessionSelectors, useSessionStore } from '@/store/session';
9
+ import { agentSelectors, chatSelectors, sessionSelectors, useSessionStore } from '@/store/session';
10
10
  import { useSettings } from '@/store/settings';
11
11
 
12
12
  import { useStyles } from './style';
@@ -39,10 +39,10 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading })
39
39
  const meta = session.meta;
40
40
  const systemRole = session.config.systemRole;
41
41
  return [
42
- meta.title,
42
+ agentSelectors.getTitle(meta),
43
43
  meta.description,
44
44
  systemRole,
45
- sessionSelectors.getAgentAvatar(meta),
45
+ agentSelectors.getAvatar(meta),
46
46
  meta.backgroundColor,
47
47
  session?.updateAt,
48
48
  session.config.model,
@@ -95,7 +95,7 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading })
95
95
  }
96
96
  loading={loading}
97
97
  style={{ color: theme.colorText }}
98
- title={title || t('defaultSession')}
98
+ title={title}
99
99
  />
100
100
  <Popconfirm
101
101
  arrow={false}
@@ -8,7 +8,7 @@ import { sessionSelectors, useSessionStore } from '@/store/session';
8
8
  import SessionItem from './SessionItem';
9
9
 
10
10
  const SessionList = memo(() => {
11
- const list = useSessionStore((s) => sessionSelectors.chatList(s), isEqual);
11
+ const list = useSessionStore((s) => sessionSelectors.sessionList(s), isEqual);
12
12
  const [activeId, loading] = useSessionStore(
13
13
  (s) => [s.activeId, s.autocompleteLoading.title],
14
14
  shallow,
@@ -15,7 +15,7 @@ import type { LobeAgentConfig } from '@/types/session';
15
15
 
16
16
  type SettingItemGroup = ItemGroup & {
17
17
  children: {
18
- name?: keyof LobeAgentConfig;
18
+ name?: keyof LobeAgentConfig | string[];
19
19
  }[];
20
20
  };
21
21
 
@@ -26,8 +26,6 @@ const AgentConfig = () => {
26
26
 
27
27
  const [updateAgentConfig] = useSessionStore((s) => [s.updateAgentConfig], shallow);
28
28
 
29
- // TODO: setting 结构嵌套,现在是扁平的 params: { temperature: 0.6 }
30
- // @ts-ignore
31
29
  const chat: SettingItemGroup = useMemo(
32
30
  () => ({
33
31
  children: [
@@ -42,13 +40,13 @@ const AgentConfig = () => {
42
40
  ),
43
41
  label: t('settingChat.chatStyleType.title'),
44
42
  minWidth: undefined,
45
- name: 'chatStyleType',
43
+ name: 'displayMode',
46
44
  },
47
45
  {
48
46
  children: <Input placeholder={t('settingChat.inputTemplate.placeholder')} />,
49
47
  desc: t('settingChat.inputTemplate.desc'),
50
48
  label: t('settingChat.inputTemplate.title'),
51
- name: 'enableHistoryCount',
49
+ name: 'inputTemplate',
52
50
  },
53
51
  {
54
52
  children: <Switch />,
@@ -60,8 +58,7 @@ const AgentConfig = () => {
60
58
  {
61
59
  children: <SliderWithInput max={32} min={0} />,
62
60
  desc: t('settingChat.historyCount.desc'),
63
- // @ts-ignore
64
- hidden: !config.params.enableHistoryCount,
61
+ hidden: !config.enableHistoryCount,
65
62
  label: t('settingChat.historyCount.title'),
66
63
  name: 'historyCount',
67
64
  },
@@ -75,8 +72,7 @@ const AgentConfig = () => {
75
72
  {
76
73
  children: <SliderWithInput max={32} min={0} />,
77
74
  desc: t('settingChat.compressThreshold.desc'),
78
- // @ts-ignore
79
- hidden: !config.params.enableCompressThreshold,
75
+ hidden: !config.enableCompressThreshold,
80
76
  label: t('settingChat.compressThreshold.title'),
81
77
  name: 'compressThreshold',
82
78
  },
@@ -87,8 +83,6 @@ const AgentConfig = () => {
87
83
  [config],
88
84
  );
89
85
 
90
- // TODO: setting 结构嵌套,现在是扁平的 params: { temperature: 0.6 }
91
- // @ts-ignore
92
86
  const model: SettingItemGroup = useMemo(
93
87
  () => ({
94
88
  children: [
@@ -110,28 +104,28 @@ const AgentConfig = () => {
110
104
  children: <SliderWithInput max={1} min={0} step={0.1} />,
111
105
  desc: t('settingModel.temperature.desc'),
112
106
  label: t('settingModel.temperature.title'),
113
- name: 'temperature',
107
+ name: ['params', 'temperature'],
114
108
  tag: 'temperature',
115
109
  },
116
110
  {
117
111
  children: <SliderWithInput max={1} min={0} step={0.1} />,
118
112
  desc: t('settingModel.topP.desc'),
119
113
  label: t('settingModel.topP.title'),
120
- name: 'topP',
114
+ name: ['params', 'top_p'],
121
115
  tag: 'top_p',
122
116
  },
123
117
  {
124
118
  children: <SliderWithInput max={2} min={-2} step={0.1} />,
125
119
  desc: t('settingModel.presencePenalty.desc'),
126
120
  label: t('settingModel.presencePenalty.title'),
127
- name: 'presencePenalty',
121
+ name: ['params', 'presence_penalty'],
128
122
  tag: 'presence_penalty',
129
123
  },
130
124
  {
131
125
  children: <SliderWithInput max={2} min={-2} step={0.1} />,
132
126
  desc: t('settingModel.frequencyPenalty.desc'),
133
127
  label: t('settingModel.frequencyPenalty.title'),
134
- name: 'frequencyPenalty',
128
+ name: ['params', 'frequency_penalty'],
135
129
  tag: 'frequency_penalty',
136
130
  },
137
131
  {
@@ -144,11 +138,9 @@ const AgentConfig = () => {
144
138
  {
145
139
  children: <SliderWithInput max={32_000} min={0} step={100} />,
146
140
  desc: t('settingModel.maxTokens.desc'),
147
- // TODO
148
- // @ts-ignore
149
- hidden: !config?.params?.enableMaxTokens,
141
+ hidden: !config?.enableMaxTokens,
150
142
  label: t('settingModel.maxTokens.title'),
151
- name: 'params.maxTokens',
143
+ name: ['params', 'max_tokens'],
152
144
  tag: 'max_tokens',
153
145
  },
154
146
  ],
@@ -158,12 +150,10 @@ const AgentConfig = () => {
158
150
  [config],
159
151
  );
160
152
 
161
- const items = useMemo(() => [chat, model], [config]);
162
-
163
153
  return (
164
154
  <Form
165
155
  initialValues={config}
166
- items={items}
156
+ items={[chat, model]}
167
157
  onValuesChange={debounce(updateAgentConfig, 100)}
168
158
  {...FORM_STYLE}
169
159
  />
@@ -2,9 +2,11 @@ import Head from 'next/head';
2
2
  import { memo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { Flexbox } from 'react-layout-kit';
5
+ import { shallow } from 'zustand/shallow';
5
6
 
6
7
  import HeaderSpacing from '@/components/HeaderSpacing';
7
8
  import { HEADER_HEIGHT } from '@/const/layoutTokens';
9
+ import { agentSelectors, useSessionStore } from '@/store/session';
8
10
  import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
9
11
 
10
12
  import ChatLayout from '../../layout';
@@ -17,7 +19,8 @@ import Header from './Header';
17
19
  const EditPage = memo(() => {
18
20
  const { t } = useTranslation('setting');
19
21
 
20
- const pageTitle = genSiteHeadTitle(t('header.session'));
22
+ const title = useSessionStore(agentSelectors.currentAgentTitle, shallow);
23
+ const pageTitle = genSiteHeadTitle(t('header.sessionWithName', { name: title }));
21
24
 
22
25
  return (
23
26
  <>
@@ -6,14 +6,14 @@ import { sessionSelectors, useSessionStore } from '@/store/session';
6
6
  import Chat from './[id]/index.page';
7
7
 
8
8
  export default () => {
9
- // 支持用户在进到首页时,自动激活第一个列表中的角色
9
+ // 支持用户在进到首页时,自动激活列表中的第一个角色
10
10
  useEffect(() => {
11
11
  const hasRehydrated = useSessionStore.persist.hasHydrated();
12
12
  // 只有当水合完毕后,才往下走
13
13
  if (!hasRehydrated) return;
14
14
 
15
15
  // 如果当前有会话,那么就激活第一个会话
16
- const list = sessionSelectors.chatList(useSessionStore.getState());
16
+ const list = sessionSelectors.sessionList(useSessionStore.getState());
17
17
  if (list.length > 0) {
18
18
  const sessionId = list[0].id;
19
19
  Router.push(`/chat/${sessionId}`);
@@ -1,3 +1,5 @@
1
+ import { t } from 'i18next';
2
+
1
3
  import { DEFAULT_AVATAR, DEFAULT_BACKGROUND_COLOR } from '@/const/meta';
2
4
  import { SessionStore } from '@/store/session';
3
5
  import { LanguageModel } from '@/types/llm';
@@ -13,7 +15,7 @@ const currentAgentMeta = (s: SessionStore): MetaData => {
13
15
  return { avatar: DEFAULT_AVATAR, backgroundColor: DEFAULT_BACKGROUND_COLOR, ...session?.meta };
14
16
  };
15
17
 
16
- const currentAgentTitle = (s: SessionStore) => currentAgentMeta(s)?.title;
18
+ const currentAgentTitle = (s: SessionStore) => currentAgentMeta(s)?.title || t('defaultSession');
17
19
 
18
20
  const currentAgentBackgroundColor = (s: SessionStore) => {
19
21
  const session = sessionSelectors.currentSession(s);
@@ -51,6 +53,10 @@ const hasSystemRole = (s: SessionStore) => {
51
53
 
52
54
  return !!config.systemRole;
53
55
  };
56
+
57
+ export const getAvatar = (s: MetaData) => s.avatar || DEFAULT_AVATAR;
58
+ export const getTitle = (s: MetaData) => s.title || t('defaultSession');
59
+
54
60
  export const agentSelectors = {
55
61
  currentAgentAvatar,
56
62
  currentAgentBackgroundColor,
@@ -60,5 +66,7 @@ export const agentSelectors = {
60
66
  currentAgentModel,
61
67
  currentAgentSystemRole,
62
68
  currentAgentTitle,
69
+ getAvatar,
70
+ getTitle,
63
71
  hasSystemRole,
64
72
  };
@@ -102,7 +102,11 @@ export const sessionsReducer = (state: LobeSessions, payload: SessionDispatch):
102
102
  const chat = draft[id];
103
103
  if (!chat) return;
104
104
 
105
- chat.config = { ...chat.config, ...config };
105
+ chat.config = {
106
+ ...chat.config,
107
+ ...config,
108
+ params: { ...chat.config.params, ...config.params },
109
+ };
106
110
  });
107
111
  }
108
112
 
@@ -1,20 +1,15 @@
1
- import { getAgentAvatar } from './chat';
2
1
  import {
3
- chatListSel,
4
2
  currentSessionSafe,
5
3
  currentSessionSel,
6
4
  getSessionById,
7
5
  getSessionMetaById,
6
+ sessionList,
8
7
  } from './list';
9
8
 
10
9
  export const sessionSelectors = {
11
- chatList: chatListSel,
12
10
  currentSession: currentSessionSel,
13
11
  currentSessionSafe,
14
-
15
- getAgentAvatar,
16
-
17
12
  getSessionById,
18
- // sessionTree: sessionTreeSel,
19
13
  getSessionMetaById,
14
+ sessionList,
20
15
  };
@@ -14,7 +14,7 @@ export const currentSessionSafe = (s: SessionStore): LobeAgentSession => {
14
14
  return currentSessionSel(s) || initLobeSession;
15
15
  };
16
16
 
17
- export const chatListSel = (s: SessionStore) => {
17
+ export const sessionList = (s: SessionStore) => {
18
18
  const filterChats = filterWithKeywords(s.sessions, s.searchKeywords, (item) => [
19
19
  Object.values(item.chats)
20
20
  .map((c) => c.content)
@@ -7,8 +7,8 @@ export const DEFAULT_SETTINGS: ConfigSettings = {
7
7
  accessCode: '',
8
8
  avatar: '',
9
9
  compressThreshold: 24,
10
- enableCompressThreshold: true,
11
- enableHistoryCount: true,
10
+ enableCompressThreshold: false,
11
+ enableHistoryCount: false,
12
12
  enableMaxTokens: true,
13
13
  endpoint: '',
14
14
  fontSize: 14,
@@ -26,10 +26,26 @@ interface LobeSessionBase extends BaseDataModel {
26
26
  }
27
27
 
28
28
  export interface LobeAgentConfig {
29
+ compressThreshold?: number;
30
+ displayMode?: 'chat' | 'docs';
31
+ /**
32
+ * 历史消息长度压缩阈值
33
+ */
34
+ enableCompressThreshold?: boolean;
35
+ /**
36
+ * 开启历史记录条数
37
+ */
38
+ enableHistoryCount?: boolean;
39
+ enableMaxTokens?: boolean;
29
40
  /**
30
41
  * 语言模型示例
31
42
  */
32
43
  example?: LLMExample;
44
+ /**
45
+ * 历史消息条数
46
+ */
47
+ historyCount?: number;
48
+ inputTemplate?: string;
33
49
  /**
34
50
  * 角色所使用的语言模型
35
51
  * @default gpt-3.5-turbo
@@ -1 +1 @@
1
- export const genSiteHeadTitle = (title?: string) => (title ? `${title} - LobeChat` : 'LobeChat');
1
+ export const genSiteHeadTitle = (title?: string) => (title ? `${title} · LobeChat` : 'LobeChat');
@@ -1,26 +0,0 @@
1
- import { createStyles } from 'antd-style';
2
- import { ReactNode, memo } from 'react';
3
- import { Flexbox } from 'react-layout-kit';
4
-
5
- const useStyles = createStyles(({ css, token }) => ({
6
- header: css``,
7
- title: css`
8
- color: ${token.colorTextSecondary};
9
- `,
10
- }));
11
-
12
- interface FormItemProps {
13
- children: ReactNode;
14
- label: string;
15
- }
16
-
17
- export const FormItem = memo<FormItemProps>(({ label, children }) => {
18
- const { styles } = useStyles();
19
-
20
- return (
21
- <Flexbox className={styles.header} gap={12}>
22
- <Flexbox className={styles.title}>{label}</Flexbox>
23
- <Flexbox>{children}</Flexbox>
24
- </Flexbox>
25
- );
26
- });
@@ -1,34 +0,0 @@
1
- import { createStyles } from 'antd-style';
2
-
3
- export const useStyles = createStyles(({ css, token }) => ({
4
- collapseHeader: css`
5
- .ant-collapse-header {
6
- align-items: center !important;
7
- }
8
- `,
9
- footer: css`
10
- position: sticky;
11
- bottom: 0;
12
- border-top: 1px solid ${token.colorBorder};
13
- `,
14
- form: css`
15
- overflow-y: auto;
16
- `,
17
- header: css`
18
- background: ${token.colorBgContainer};
19
- border-bottom: 1px solid ${token.colorSplit};
20
- `,
21
- profile: css`
22
- font-size: 20px;
23
- font-weight: bold;
24
- color: ${token.colorText};
25
- `,
26
- prompt: css`
27
- padding: 12px;
28
- background: ${token.colorFillTertiary};
29
- `,
30
- title: css`
31
- font-size: 16px;
32
- font-weight: 500;
33
- `,
34
- }));
@@ -1,4 +0,0 @@
1
- import { DEFAULT_AVATAR } from '@/const/meta';
2
- import { MetaData } from '@/types/meta';
3
-
4
- export const getAgentAvatar = (s: MetaData) => s.avatar || DEFAULT_AVATAR;