@lobehub/chat 1.0.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/.changelogrc.js +1 -0
- package/.commitlintrc.js +1 -0
- package/.editorconfig +16 -0
- package/.eslintignore +32 -0
- package/.eslintrc.js +6 -0
- package/.github/ISSUE_TEMPLATE/1_bug_report.yml +45 -0
- package/.github/ISSUE_TEMPLATE/2_feature_request.yml +21 -0
- package/.github/ISSUE_TEMPLATE/3_question.yml +15 -0
- package/.github/ISSUE_TEMPLATE/4_other.md +7 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- package/.github/dependabot.yml +17 -0
- package/.github/workflows/auto-merge.yml +32 -0
- package/.github/workflows/contributor-help.yml +29 -0
- package/.github/workflows/issue-check-inactive.yml +22 -0
- package/.github/workflows/issue-close-require.yml +46 -0
- package/.github/workflows/issue-remove-inactive.yml +25 -0
- package/.github/workflows/release.yml +34 -0
- package/.github/workflows/test.yml +30 -0
- package/.gitpod.yml +3 -0
- package/.husky/commit-msg +4 -0
- package/.husky/pre-commit +5 -0
- package/.i18nrc.js +13 -0
- package/.prettierignore +63 -0
- package/.prettierrc.js +1 -0
- package/.releaserc.js +1 -0
- package/.remarkrc.js +1 -0
- package/.stylelintrc.js +8 -0
- package/CHANGELOG.md +80 -0
- package/README.md +147 -0
- package/locales/en_US/common.json +40 -0
- package/locales/en_US/setting.json +97 -0
- package/locales/zh_CN/common.json +40 -0
- package/locales/zh_CN/setting.json +98 -0
- package/next.config.mjs +32 -0
- package/package.json +138 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/scripts/genDefaultLocale.mjs +12 -0
- package/scripts/toc.mjs +40 -0
- package/src/const/fetch.ts +1 -0
- package/src/const/modelTokens.ts +8 -0
- package/src/features/FolderPanel/index.tsx +55 -0
- package/src/helpers/prompt.test.ts +36 -0
- package/src/helpers/prompt.ts +36 -0
- package/src/helpers/url.ts +17 -0
- package/src/layout/index.tsx +42 -0
- package/src/layout/style.ts +18 -0
- package/src/locales/create.ts +48 -0
- package/src/locales/default/common.ts +41 -0
- package/src/locales/default/setting.ts +97 -0
- package/src/locales/index.ts +5 -0
- package/src/locales/resources/en_US.ts +9 -0
- package/src/locales/resources/index.ts +7 -0
- package/src/locales/resources/zh_CN.ts +9 -0
- package/src/migrations/FromV0ToV1.ts +12 -0
- package/src/migrations/index.ts +13 -0
- package/src/pages/Sidebar.tsx +36 -0
- package/src/pages/_app.page.tsx +13 -0
- package/src/pages/_document.page.tsx +70 -0
- package/src/pages/api/LangChainStream.ts +95 -0
- package/src/pages/api/chain.api.ts +17 -0
- package/src/pages/api/openai.api.ts +31 -0
- package/src/pages/chat/SessionList/Header.tsx +56 -0
- package/src/pages/chat/SessionList/List/SessionItem.tsx +90 -0
- package/src/pages/chat/SessionList/List/index.tsx +31 -0
- package/src/pages/chat/SessionList/List/style.ts +77 -0
- package/src/pages/chat/SessionList/index.tsx +18 -0
- package/src/pages/chat/[id]/Config/ConfigCell.tsx +68 -0
- package/src/pages/chat/[id]/Config/ReadMode.tsx +63 -0
- package/src/pages/chat/[id]/Config/index.tsx +79 -0
- package/src/pages/chat/[id]/Conversation/ChatList.tsx +36 -0
- package/src/pages/chat/[id]/Conversation/Input.tsx +61 -0
- package/src/pages/chat/[id]/Conversation/index.tsx +32 -0
- package/src/pages/chat/[id]/Header.tsx +86 -0
- package/src/pages/chat/[id]/edit/AgentConfig.tsx +95 -0
- package/src/pages/chat/[id]/edit/AgentMeta.tsx +117 -0
- package/src/pages/chat/[id]/edit/FormItem.tsx +26 -0
- package/src/pages/chat/[id]/edit/Prompt.tsx +68 -0
- package/src/pages/chat/[id]/edit/index.page.tsx +62 -0
- package/src/pages/chat/[id]/edit/style.ts +42 -0
- package/src/pages/chat/[id]/index.page.tsx +40 -0
- package/src/pages/chat/index.page.tsx +1 -0
- package/src/pages/chat/layout.tsx +51 -0
- package/src/pages/index.page.tsx +1 -0
- package/src/pages/setting/Header.tsx +27 -0
- package/src/pages/setting/SettingForm.tsx +42 -0
- package/src/pages/setting/index.page.tsx +41 -0
- package/src/prompts/agent.ts +65 -0
- package/src/services/chatModel.ts +34 -0
- package/src/services/langChain.ts +18 -0
- package/src/services/url.ts +8 -0
- package/src/store/middleware/createHashStorage.ts +49 -0
- package/src/store/session/index.ts +33 -0
- package/src/store/session/initialState.ts +11 -0
- package/src/store/session/selectors.ts +3 -0
- package/src/store/session/slices/agentConfig/action.ts +226 -0
- package/src/store/session/slices/agentConfig/index.ts +3 -0
- package/src/store/session/slices/agentConfig/initialState.ts +34 -0
- package/src/store/session/slices/agentConfig/selectors.ts +54 -0
- package/src/store/session/slices/chat/action.ts +210 -0
- package/src/store/session/slices/chat/index.ts +3 -0
- package/src/store/session/slices/chat/initialState.ts +12 -0
- package/src/store/session/slices/chat/messageReducer.test.ts +70 -0
- package/src/store/session/slices/chat/messageReducer.ts +84 -0
- package/src/store/session/slices/chat/selectors.ts +83 -0
- package/src/store/session/slices/session/action.ts +118 -0
- package/src/store/session/slices/session/index.ts +3 -0
- package/src/store/session/slices/session/initialState.ts +31 -0
- package/src/store/session/slices/session/reducers/session.test.ts +456 -0
- package/src/store/session/slices/session/reducers/session.ts +113 -0
- package/src/store/session/slices/session/selectors/chat.ts +4 -0
- package/src/store/session/slices/session/selectors/index.ts +20 -0
- package/src/store/session/slices/session/selectors/list.ts +65 -0
- package/src/store/session/store.ts +17 -0
- package/src/store/settings/action.ts +31 -0
- package/src/store/settings/index.ts +23 -0
- package/src/store/settings/initialState.ts +25 -0
- package/src/store/settings/selectors.ts +9 -0
- package/src/store/settings/store.ts +13 -0
- package/src/styles/antdOverride.ts +29 -0
- package/src/styles/global.ts +23 -0
- package/src/styles/index.ts +6 -0
- package/src/types/chatMessage.ts +46 -0
- package/src/types/exportConfig.ts +23 -0
- package/src/types/global.d.ts +14 -0
- package/src/types/i18next.d.ts +8 -0
- package/src/types/langchain.ts +34 -0
- package/src/types/llm.ts +49 -0
- package/src/types/locale.ts +7 -0
- package/src/types/meta.ts +26 -0
- package/src/types/openai.ts +62 -0
- package/src/types/session.ts +59 -0
- package/src/utils/VersionController.test.ts +90 -0
- package/src/utils/VersionController.ts +64 -0
- package/src/utils/compass.ts +94 -0
- package/src/utils/fetch.ts +132 -0
- package/src/utils/filter.test.ts +120 -0
- package/src/utils/filter.ts +29 -0
- package/src/utils/uploadFIle.ts +8 -0
- package/src/utils/uuid.ts +9 -0
- package/tsconfig.json +26 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
import { type PersistOptions, devtools, persist } from 'zustand/middleware';
|
|
3
|
+
|
|
4
|
+
import { type SettingsStore, createStore } from './store';
|
|
5
|
+
|
|
6
|
+
export const LOBE_SETTINGS = 'LOBE_SETTINGS';
|
|
7
|
+
|
|
8
|
+
const persistOptions: PersistOptions<SettingsStore> = {
|
|
9
|
+
name: LOBE_SETTINGS,
|
|
10
|
+
skipHydration: true,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const useSettings = create<SettingsStore>()(
|
|
14
|
+
persist(
|
|
15
|
+
devtools(createStore, {
|
|
16
|
+
name: LOBE_SETTINGS,
|
|
17
|
+
}),
|
|
18
|
+
persistOptions,
|
|
19
|
+
),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export * from './selectors';
|
|
23
|
+
export type { SettingsStore } from './store';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ThemeMode } from 'antd-style';
|
|
2
|
+
|
|
3
|
+
import type { ConfigSettings } from '@/types/exportConfig';
|
|
4
|
+
|
|
5
|
+
export type SidebarTabKey = 'chat' | 'market';
|
|
6
|
+
export const DEFAULT_SETTINGS: ConfigSettings = {
|
|
7
|
+
avatar: '',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export interface SettingsState {
|
|
11
|
+
inputHeight: number;
|
|
12
|
+
sessionExpandable?: boolean;
|
|
13
|
+
sessionsWidth: number;
|
|
14
|
+
settings: ConfigSettings;
|
|
15
|
+
sidebarKey: SidebarTabKey;
|
|
16
|
+
themeMode?: ThemeMode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const initialState: SettingsState = {
|
|
20
|
+
inputHeight: 200,
|
|
21
|
+
sessionExpandable: true,
|
|
22
|
+
sessionsWidth: 320,
|
|
23
|
+
settings: DEFAULT_SETTINGS,
|
|
24
|
+
sidebarKey: 'chat',
|
|
25
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { StateCreator } from 'zustand/vanilla';
|
|
2
|
+
|
|
3
|
+
import { type SettingsAction, createSettings } from './action';
|
|
4
|
+
import { type SettingsState, initialState } from './initialState';
|
|
5
|
+
|
|
6
|
+
export type SettingsStore = SettingsAction & SettingsState;
|
|
7
|
+
|
|
8
|
+
export const createStore: StateCreator<SettingsStore, [['zustand/devtools', never]]> = (
|
|
9
|
+
...parameters
|
|
10
|
+
) => ({
|
|
11
|
+
...initialState,
|
|
12
|
+
...createSettings(...parameters),
|
|
13
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Theme, css } from 'antd-style';
|
|
2
|
+
import { rgba } from 'polished';
|
|
3
|
+
|
|
4
|
+
export default (token: Theme) => css`
|
|
5
|
+
.ant-btn {
|
|
6
|
+
box-shadow: none;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ant-popover {
|
|
10
|
+
z-index: 1100;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.ant-notification .ant-notification-notice.notification-primary-info {
|
|
14
|
+
background: ${token.colorPrimary};
|
|
15
|
+
box-shadow: 0 6px 16px 0 ${rgba(token.colorPrimary, 0.1)},
|
|
16
|
+
0 3px 6px -4px ${rgba(token.colorPrimary, 0.2)},
|
|
17
|
+
0 9px 28px 8px ${rgba(token.colorPrimary, 0.1)};
|
|
18
|
+
|
|
19
|
+
.anticon {
|
|
20
|
+
color: ${token.colorTextLightSolid};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.ant-notification-notice-message {
|
|
24
|
+
margin-bottom: 0;
|
|
25
|
+
padding-right: 0;
|
|
26
|
+
color: ${token.colorTextLightSolid};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { css } from 'antd-style';
|
|
2
|
+
|
|
3
|
+
export default () => css`
|
|
4
|
+
body,
|
|
5
|
+
.ant-app {
|
|
6
|
+
::-webkit-scrollbar {
|
|
7
|
+
width: 0;
|
|
8
|
+
height: 0;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
#__next {
|
|
13
|
+
height: 100%;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
p {
|
|
17
|
+
margin-bottom: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
li {
|
|
21
|
+
display: block;
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { LLMRoleType } from './llm';
|
|
2
|
+
import { BaseDataModel } from './meta';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 聊天消息错误对象
|
|
6
|
+
*/
|
|
7
|
+
export interface ChatMessageError {
|
|
8
|
+
/**
|
|
9
|
+
* 错误信息
|
|
10
|
+
*/
|
|
11
|
+
message: string;
|
|
12
|
+
status: number;
|
|
13
|
+
type: 'general' | 'llm';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ChatMessage extends BaseDataModel {
|
|
17
|
+
archive?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @title 内容
|
|
21
|
+
* @description 消息内容
|
|
22
|
+
*/
|
|
23
|
+
content: string;
|
|
24
|
+
error?: any;
|
|
25
|
+
|
|
26
|
+
// 扩展字段
|
|
27
|
+
extra?: {
|
|
28
|
+
// 翻译
|
|
29
|
+
translate: {
|
|
30
|
+
target: string;
|
|
31
|
+
to: string;
|
|
32
|
+
};
|
|
33
|
+
// 语音
|
|
34
|
+
} & Record<string, any>;
|
|
35
|
+
|
|
36
|
+
parentId?: string;
|
|
37
|
+
// 引用
|
|
38
|
+
quotaId?: string;
|
|
39
|
+
/**
|
|
40
|
+
* 角色
|
|
41
|
+
* @description 消息发送者的角色
|
|
42
|
+
*/
|
|
43
|
+
role: LLMRoleType;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type ChatMessageMap = Record<string, ChatMessage>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 配置设置
|
|
3
|
+
*/
|
|
4
|
+
export interface ConfigSettings {
|
|
5
|
+
/**
|
|
6
|
+
* 头像链接
|
|
7
|
+
*/
|
|
8
|
+
avatar?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type ConfigKeys = keyof ConfigSettings;
|
|
12
|
+
|
|
13
|
+
export interface ConfigState {
|
|
14
|
+
settings: ConfigSettings;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ConfigFile {
|
|
18
|
+
state: ConfigState;
|
|
19
|
+
/**
|
|
20
|
+
* 配置文件的版本号
|
|
21
|
+
*/
|
|
22
|
+
version: number;
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LobeCustomStylish, LobeCustomToken } from '@lobehub/ui';
|
|
2
|
+
import 'antd-style';
|
|
3
|
+
import { AntdToken } from 'antd-style/lib/types/theme';
|
|
4
|
+
|
|
5
|
+
declare module 'antd-style' {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
7
|
+
export interface CustomToken extends LobeCustomToken {}
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
9
|
+
export interface CustomStylish extends LobeCustomStylish {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare module 'styled-components' {
|
|
13
|
+
export interface DefaultTheme extends AntdToken, LobeCustomToken {}
|
|
14
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ChatMessage } from '@lobehub/ui';
|
|
2
|
+
|
|
3
|
+
export interface LangChainParams {
|
|
4
|
+
llm: {
|
|
5
|
+
/**
|
|
6
|
+
* 控制生成文本中的惩罚系数,用于减少重复性
|
|
7
|
+
*/
|
|
8
|
+
frequency_penalty?: number;
|
|
9
|
+
/**
|
|
10
|
+
* 生成文本的最大长度
|
|
11
|
+
*/
|
|
12
|
+
max_tokens?: number;
|
|
13
|
+
model: string;
|
|
14
|
+
/**
|
|
15
|
+
* 控制生成文本中的惩罚系数,用于减少主题的变化
|
|
16
|
+
*/
|
|
17
|
+
presence_penalty?: number;
|
|
18
|
+
/**
|
|
19
|
+
* 生成文本的随机度量,用于控制文本的创造性和多样性
|
|
20
|
+
* @default 0.6
|
|
21
|
+
*/
|
|
22
|
+
temperature: number;
|
|
23
|
+
/**
|
|
24
|
+
* 控制生成文本中最高概率的单个令牌
|
|
25
|
+
*/
|
|
26
|
+
top_p?: number;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 聊天信息列表
|
|
31
|
+
*/
|
|
32
|
+
prompts: ChatMessage[];
|
|
33
|
+
vars: Record<string, string>;
|
|
34
|
+
}
|
package/src/types/llm.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM 模型
|
|
3
|
+
*/
|
|
4
|
+
export enum LanguageModel {
|
|
5
|
+
/**
|
|
6
|
+
* GPT 3.5 Turbo
|
|
7
|
+
*/
|
|
8
|
+
GPT3_5 = 'gpt-3.5-turbo',
|
|
9
|
+
GPT3_5_16K = 'gpt-3.5-turbo-16k',
|
|
10
|
+
/**
|
|
11
|
+
* GPT 4
|
|
12
|
+
*/
|
|
13
|
+
GPT4 = 'gpt-4',
|
|
14
|
+
GPT4_32K = 'gpt-4-32k',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 语言模型的设置参数
|
|
18
|
+
export interface LLMParams {
|
|
19
|
+
/**
|
|
20
|
+
* 控制生成文本中的惩罚系数,用于减少重复性
|
|
21
|
+
*/
|
|
22
|
+
frequency_penalty?: number;
|
|
23
|
+
/**
|
|
24
|
+
* 生成文本的最大长度
|
|
25
|
+
*/
|
|
26
|
+
max_tokens?: number;
|
|
27
|
+
/**
|
|
28
|
+
* 控制生成文本中的惩罚系数,用于减少主题的变化
|
|
29
|
+
*/
|
|
30
|
+
presence_penalty?: number;
|
|
31
|
+
/**
|
|
32
|
+
* 生成文本的随机度量,用于控制文本的创造性和多样性
|
|
33
|
+
* @default 0.6
|
|
34
|
+
*/
|
|
35
|
+
temperature?: number;
|
|
36
|
+
/**
|
|
37
|
+
* 控制生成文本中最高概率的单个 token
|
|
38
|
+
*/
|
|
39
|
+
top_p?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type LLMRoleType = 'user' | 'system' | 'assistant';
|
|
43
|
+
|
|
44
|
+
export interface LLMMessage {
|
|
45
|
+
content: string;
|
|
46
|
+
role: LLMRoleType;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type LLMExample = LLMMessage[];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import resources from '@/locales/resources';
|
|
2
|
+
import defaultResources from '@/locales/resources/zh_CN';
|
|
3
|
+
|
|
4
|
+
export type Resources = typeof resources;
|
|
5
|
+
export type DefaultResources = typeof defaultResources;
|
|
6
|
+
export type Namespaces = keyof DefaultResources;
|
|
7
|
+
export type Locales = keyof Resources;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface MetaData {
|
|
2
|
+
/**
|
|
3
|
+
* 角色头像
|
|
4
|
+
* @description 可选参数,如果不传则使用默认头像
|
|
5
|
+
*/
|
|
6
|
+
avatar?: string;
|
|
7
|
+
/**
|
|
8
|
+
* 背景色
|
|
9
|
+
* @description 可选参数,如果不传则使用默认背景色
|
|
10
|
+
*/
|
|
11
|
+
backgroundColor?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
tag?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* 名称
|
|
16
|
+
* @description 可选参数,如果不传则使用默认名称
|
|
17
|
+
*/
|
|
18
|
+
title?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface BaseDataModel {
|
|
22
|
+
createAt: number;
|
|
23
|
+
id: string;
|
|
24
|
+
meta: MetaData;
|
|
25
|
+
updateAt: number;
|
|
26
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { LLMRoleType } from '@/types/llm';
|
|
2
|
+
|
|
3
|
+
export interface OpenAIChatMessage {
|
|
4
|
+
/**
|
|
5
|
+
* @title 内容
|
|
6
|
+
* @description 消息内容
|
|
7
|
+
*/
|
|
8
|
+
content: string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 角色
|
|
12
|
+
* @description 消息发送者的角色
|
|
13
|
+
*/
|
|
14
|
+
role: LLMRoleType;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @title OpenAI Stream Payload
|
|
19
|
+
*/
|
|
20
|
+
export interface OpenAIStreamPayload {
|
|
21
|
+
/**
|
|
22
|
+
* @title 控制生成文本中的惩罚系数,用于减少重复性
|
|
23
|
+
* @default 0
|
|
24
|
+
*/
|
|
25
|
+
frequency_penalty?: number;
|
|
26
|
+
/**
|
|
27
|
+
* @title 生成文本的最大长度
|
|
28
|
+
*/
|
|
29
|
+
max_tokens?: number;
|
|
30
|
+
/**
|
|
31
|
+
* @title 聊天信息列表
|
|
32
|
+
*/
|
|
33
|
+
messages: OpenAIChatMessage[];
|
|
34
|
+
/**
|
|
35
|
+
* @title 模型名称
|
|
36
|
+
*/
|
|
37
|
+
model: string;
|
|
38
|
+
/**
|
|
39
|
+
* @title 返回的文本数量
|
|
40
|
+
*/
|
|
41
|
+
n?: number;
|
|
42
|
+
/**
|
|
43
|
+
* @title 控制生成文本中的惩罚系数,用于减少主题的变化
|
|
44
|
+
* @default 0
|
|
45
|
+
*/
|
|
46
|
+
presence_penalty?: number;
|
|
47
|
+
/**
|
|
48
|
+
* @title 是否开启流式请求
|
|
49
|
+
* @default true
|
|
50
|
+
*/
|
|
51
|
+
stream?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* @title 生成文本的随机度量,用于控制文本的创造性和多样性
|
|
54
|
+
* @default 0.5
|
|
55
|
+
*/
|
|
56
|
+
temperature: number;
|
|
57
|
+
/**
|
|
58
|
+
* @title 控制生成文本中最高概率的单个令牌
|
|
59
|
+
* @default 1
|
|
60
|
+
*/
|
|
61
|
+
top_p?: number;
|
|
62
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ChatMessageMap } from './chatMessage';
|
|
2
|
+
import { LLMExample, LLMParams, LanguageModel } from './llm';
|
|
3
|
+
import { BaseDataModel } from './meta';
|
|
4
|
+
|
|
5
|
+
export enum LobeSessionType {
|
|
6
|
+
/**
|
|
7
|
+
* 角色
|
|
8
|
+
*/
|
|
9
|
+
Agent = 'agent',
|
|
10
|
+
/**
|
|
11
|
+
* 群聊
|
|
12
|
+
*/
|
|
13
|
+
Group = 'group',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface LobeSessionBase extends BaseDataModel {
|
|
17
|
+
/**
|
|
18
|
+
* 聊天记录
|
|
19
|
+
*/
|
|
20
|
+
chats: ChatMessageMap;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 每个会话的类别
|
|
24
|
+
*/
|
|
25
|
+
type: LobeSessionType;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface LobeAgentConfig {
|
|
29
|
+
/**
|
|
30
|
+
* 语言模型示例
|
|
31
|
+
*/
|
|
32
|
+
example?: LLMExample;
|
|
33
|
+
/**
|
|
34
|
+
* 角色所使用的语言模型
|
|
35
|
+
* @default gpt-3.5-turbo
|
|
36
|
+
*/
|
|
37
|
+
model: LanguageModel;
|
|
38
|
+
/**
|
|
39
|
+
* 语言模型参数
|
|
40
|
+
*/
|
|
41
|
+
params: LLMParams;
|
|
42
|
+
/**
|
|
43
|
+
* 系统角色
|
|
44
|
+
*/
|
|
45
|
+
systemRole: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Lobe Agent会话
|
|
50
|
+
*/
|
|
51
|
+
export interface LobeAgentSession extends LobeSessionBase {
|
|
52
|
+
/**
|
|
53
|
+
* 语言模型角色设定
|
|
54
|
+
*/
|
|
55
|
+
config: LobeAgentConfig;
|
|
56
|
+
type: LobeSessionType.Agent;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type LobeSessions = Record<string, LobeAgentSession>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Migration, MigrationData, VersionController } from './VersionController';
|
|
2
|
+
|
|
3
|
+
class TestMigration0 implements Migration {
|
|
4
|
+
version = 0;
|
|
5
|
+
|
|
6
|
+
migrate(data: MigrationData): MigrationData {
|
|
7
|
+
return data;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
class TestMigration1 implements Migration {
|
|
11
|
+
version = 1;
|
|
12
|
+
|
|
13
|
+
migrate(data: MigrationData): MigrationData {
|
|
14
|
+
return {
|
|
15
|
+
state: {
|
|
16
|
+
...data.state,
|
|
17
|
+
value1: data.state.value * 2,
|
|
18
|
+
},
|
|
19
|
+
version: this.version,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class TestMigration2 implements Migration {
|
|
25
|
+
version = 2;
|
|
26
|
+
|
|
27
|
+
migrate(data: MigrationData): MigrationData {
|
|
28
|
+
return {
|
|
29
|
+
state: {
|
|
30
|
+
...data.state,
|
|
31
|
+
value2: data.state.value1 * 2,
|
|
32
|
+
},
|
|
33
|
+
version: this.version,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('VersionController', () => {
|
|
39
|
+
let migrations;
|
|
40
|
+
let versionController: VersionController<any>;
|
|
41
|
+
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
migrations = [TestMigration0, TestMigration1, TestMigration2];
|
|
44
|
+
versionController = new VersionController(migrations);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should instantiate with sorted migrations', () => {
|
|
48
|
+
expect(versionController['migrations'][0].version).toBe(0);
|
|
49
|
+
expect(versionController['migrations'][1].version).toBe(1);
|
|
50
|
+
expect(versionController['migrations'][2].version).toBe(2);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should throw error if data version is undefined', () => {
|
|
54
|
+
const data = {
|
|
55
|
+
state: { value: 10 },
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
expect(() => versionController.migrate(data as any)).toThrow(
|
|
59
|
+
'导入数据缺少版本号,请检查文件后重试',
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should migrate data correctly through multiple versions', () => {
|
|
64
|
+
const data: MigrationData = {
|
|
65
|
+
state: { value: 10 },
|
|
66
|
+
version: 0,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const migratedData = versionController.migrate(data);
|
|
70
|
+
|
|
71
|
+
expect(migratedData).toEqual({
|
|
72
|
+
state: { value: 10, value1: 20, value2: 40 },
|
|
73
|
+
version: 3,
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should migrate data correctly if starting from a specific version', () => {
|
|
78
|
+
const data: MigrationData = {
|
|
79
|
+
state: { value: 10, value1: 20 },
|
|
80
|
+
version: 1,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const migratedData = versionController.migrate(data);
|
|
84
|
+
|
|
85
|
+
expect(migratedData).toEqual({
|
|
86
|
+
state: { value: 10, value1: 20, value2: 40 },
|
|
87
|
+
version: 3,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 迁移接口
|
|
3
|
+
* @template T - 状态类型
|
|
4
|
+
*/
|
|
5
|
+
export interface Migration<T = any> {
|
|
6
|
+
/**
|
|
7
|
+
* 迁移数据
|
|
8
|
+
* @param data - 迁移数据
|
|
9
|
+
* @returns 迁移后的数据
|
|
10
|
+
*/
|
|
11
|
+
migrate(data: MigrationData<T>): MigrationData;
|
|
12
|
+
/**
|
|
13
|
+
* 迁移版本号
|
|
14
|
+
*/
|
|
15
|
+
version: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 迁移数据接口
|
|
20
|
+
* @template T - 状态类型
|
|
21
|
+
*/
|
|
22
|
+
export interface MigrationData<T = any> {
|
|
23
|
+
/**
|
|
24
|
+
* 状态数据
|
|
25
|
+
*/
|
|
26
|
+
state: T;
|
|
27
|
+
/**
|
|
28
|
+
* 迁移版本号
|
|
29
|
+
*/
|
|
30
|
+
version: number;
|
|
31
|
+
}
|
|
32
|
+
export class VersionController<T> {
|
|
33
|
+
private migrations: Migration[];
|
|
34
|
+
targetVersion: number;
|
|
35
|
+
|
|
36
|
+
constructor(migrations: any[], targetVersion: number = migrations.length) {
|
|
37
|
+
this.migrations = migrations
|
|
38
|
+
.map((cls) => {
|
|
39
|
+
return new cls() as Migration;
|
|
40
|
+
})
|
|
41
|
+
.sort((a, b) => a.version - b.version);
|
|
42
|
+
|
|
43
|
+
this.targetVersion = targetVersion;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
migrate(data: MigrationData<T>): MigrationData<T> {
|
|
47
|
+
let nextData = data;
|
|
48
|
+
const targetVersion = this.targetVersion || this.migrations.length;
|
|
49
|
+
if (data.version === undefined) throw new Error('导入数据缺少版本号,请检查文件后重试');
|
|
50
|
+
const currentVersion = data.version;
|
|
51
|
+
|
|
52
|
+
for (let i = currentVersion || 0; i < targetVersion; i++) {
|
|
53
|
+
const migration = this.migrations.find((m) => m.version === i);
|
|
54
|
+
if (!migration) throw new Error('程序出错');
|
|
55
|
+
|
|
56
|
+
nextData = migration.migrate(nextData);
|
|
57
|
+
|
|
58
|
+
nextData.version += 1;
|
|
59
|
+
console.log('迁移器:', migration, '数据:', nextData, '迁移后版本:', nextData.version);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return nextData;
|
|
63
|
+
}
|
|
64
|
+
}
|