@lobehub/chat 0.1.6
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 +20 -0
- package/README.md +147 -0
- package/locales/en_US/common.json +41 -0
- package/locales/en_US/setting.json +117 -0
- package/locales/zh_CN/common.json +41 -0
- package/locales/zh_CN/setting.json +117 -0
- package/next.config.mjs +32 -0
- package/package.json +140 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/scripts/genDefaultLocale.ts +18 -0
- package/scripts/genResources.ts +51 -0
- package/scripts/toc.ts +7 -0
- package/src/const/fetch.ts +1 -0
- package/src/const/modelTokens.ts +8 -0
- package/src/features/AvatarWithUpload/index.tsx +27 -0
- package/src/features/FolderPanel/index.tsx +55 -0
- package/src/features/SideBar/index.tsx +35 -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 +57 -0
- package/src/layout/style.ts +18 -0
- package/src/locales/create.ts +49 -0
- package/src/locales/default/common.ts +41 -0
- package/src/locales/default/setting.ts +117 -0
- package/src/locales/index.ts +5 -0
- package/src/locales/options.ts +19 -0
- package/src/locales/resources/en_US.ts +9 -0
- package/src/locales/resources/index.ts +13 -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/_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 +299 -0
- package/src/pages/setting/SliderWithInput/index.tsx +40 -0
- package/src/pages/setting/ThemeSwatches/ThemeSwatchesNeutral.tsx +33 -0
- package/src/pages/setting/ThemeSwatches/ThemeSwatchesPrimary.tsx +33 -0
- package/src/pages/setting/ThemeSwatches/index.ts +2 -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 +40 -0
- package/src/store/settings/index.ts +23 -0
- package/src/store/settings/initialState.ts +41 -0
- package/src/store/settings/selectors.ts +17 -0
- package/src/store/settings/store.ts +13 -0
- package/src/styles/antdOverride.ts +33 -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 +44 -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 +1 -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 +31 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { consola } from 'consola';
|
|
2
|
+
import { colors } from 'consola/utils';
|
|
3
|
+
import { tocForResources } from 'i18next-resources-for-ts';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
|
|
7
|
+
import i18nConfig from '../.i18nrc.js';
|
|
8
|
+
|
|
9
|
+
const locales = [i18nConfig.entryLocale, ...i18nConfig.outputLocales];
|
|
10
|
+
export const genResources = (output: string) => {
|
|
11
|
+
let index = '';
|
|
12
|
+
let indexObj = '';
|
|
13
|
+
consola.start(`Generate locale resources and types, found ${locales.length} locales...`);
|
|
14
|
+
for (const locale of locales) {
|
|
15
|
+
const files = fs
|
|
16
|
+
.readdirSync(resolve(i18nConfig.output, locale))
|
|
17
|
+
.filter((name) => name.includes('.json'));
|
|
18
|
+
index += `import ${locale} from "./${locale}";\n`;
|
|
19
|
+
indexObj += ` "${locale.replace('_', '-')}": ${locale},\n`;
|
|
20
|
+
const ns = [];
|
|
21
|
+
for (const file of files) {
|
|
22
|
+
ns.push({
|
|
23
|
+
name: file.replace('.json', ''),
|
|
24
|
+
path: resolve(i18nConfig.output, locale, file),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
let toc = tocForResources(ns, resolve(output)).replaceAll('\\', '/');
|
|
28
|
+
if (locale === i18nConfig.entryLocale) {
|
|
29
|
+
toc = toc.replaceAll('.json', '').replaceAll('../../../locales/zh_CN', '../default');
|
|
30
|
+
}
|
|
31
|
+
const filepath = resolve(output, `${locale}.ts`);
|
|
32
|
+
fs.writeFileSync(filepath, toc);
|
|
33
|
+
consola.success(colors.bgBlue(colors.black(` ${locale} `)), colors.gray(filepath));
|
|
34
|
+
}
|
|
35
|
+
const indexFilepath = resolve(output, `index.ts`);
|
|
36
|
+
fs.writeFileSync(
|
|
37
|
+
indexFilepath,
|
|
38
|
+
`${index}
|
|
39
|
+
const resources = {
|
|
40
|
+
${indexObj}} as const;
|
|
41
|
+
export default resources;
|
|
42
|
+
export const defaultResources = ${i18nConfig.entryLocale};
|
|
43
|
+
export type Resources = typeof resources;
|
|
44
|
+
export type DefaultResources = typeof defaultResources;
|
|
45
|
+
export type Namespaces = keyof DefaultResources;
|
|
46
|
+
export type Locales = keyof Resources;
|
|
47
|
+
`,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
consola.success(colors.bgGreen(colors.black(` INDEX `)), colors.gray(indexFilepath));
|
|
51
|
+
};
|
package/scripts/toc.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const OPENAI_SERVICE_ERROR_CODE = 555;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Avatar, Logo } from '@lobehub/ui';
|
|
2
|
+
import { Upload } from 'antd';
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { shallow } from 'zustand/shallow';
|
|
5
|
+
|
|
6
|
+
import { useSettings } from '@/store/settings';
|
|
7
|
+
import { createUploadImageHandler } from '@/utils/uploadFIle';
|
|
8
|
+
|
|
9
|
+
interface AvatarWithUploadProps {
|
|
10
|
+
size?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default memo<AvatarWithUploadProps>(({ size = 40 }) => {
|
|
14
|
+
const [avatar, setSettings] = useSettings((st) => [st.settings.avatar, st.setSettings], shallow);
|
|
15
|
+
|
|
16
|
+
const handleUploadAvatar = createUploadImageHandler((avatar) => {
|
|
17
|
+
setSettings({ avatar });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div style={{ maxHeight: size, maxWidth: size }}>
|
|
22
|
+
<Upload beforeUpload={handleUploadAvatar} itemRender={() => void 0} maxCount={1}>
|
|
23
|
+
{avatar ? <Avatar avatar={avatar} size={size} /> : <Logo size={size} />}
|
|
24
|
+
</Upload>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DraggablePanel } from '@lobehub/ui';
|
|
2
|
+
import { createStyles } from 'antd-style';
|
|
3
|
+
import isEqual from 'fast-deep-equal';
|
|
4
|
+
import { PropsWithChildren, memo, useState } from 'react';
|
|
5
|
+
import { shallow } from 'zustand/shallow';
|
|
6
|
+
|
|
7
|
+
import { useSettings } from '@/store/settings';
|
|
8
|
+
|
|
9
|
+
export const useStyles = createStyles(({ css, token }) => ({
|
|
10
|
+
panel: css`
|
|
11
|
+
height: 100vh;
|
|
12
|
+
color: ${token.colorTextSecondary};
|
|
13
|
+
background: ${token.colorBgContainer};
|
|
14
|
+
`,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
export default memo<PropsWithChildren>(({ children }) => {
|
|
18
|
+
const { styles } = useStyles();
|
|
19
|
+
const [sessionsWidth, sessionExpandable] = useSettings(
|
|
20
|
+
(s) => [s.sessionsWidth, s.sessionExpandable],
|
|
21
|
+
shallow,
|
|
22
|
+
);
|
|
23
|
+
const [tmpWidth, setWidth] = useState(sessionsWidth);
|
|
24
|
+
if (tmpWidth !== sessionsWidth) setWidth(sessionsWidth);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<DraggablePanel
|
|
28
|
+
className={styles.panel}
|
|
29
|
+
defaultSize={{ width: tmpWidth }}
|
|
30
|
+
expand={sessionExpandable}
|
|
31
|
+
maxWidth={400}
|
|
32
|
+
minWidth={256}
|
|
33
|
+
onExpandChange={(expand) => {
|
|
34
|
+
useSettings.setState({
|
|
35
|
+
sessionExpandable: expand,
|
|
36
|
+
sessionsWidth: expand ? 320 : 0,
|
|
37
|
+
});
|
|
38
|
+
}}
|
|
39
|
+
onSizeChange={(_, size) => {
|
|
40
|
+
if (!size) return;
|
|
41
|
+
|
|
42
|
+
const nextWidth = typeof size.width === 'string' ? Number.parseInt(size.width) : size.width;
|
|
43
|
+
|
|
44
|
+
if (isEqual(nextWidth, sessionsWidth)) return;
|
|
45
|
+
|
|
46
|
+
setWidth(nextWidth);
|
|
47
|
+
useSettings.setState({ sessionsWidth: nextWidth });
|
|
48
|
+
}}
|
|
49
|
+
placement="left"
|
|
50
|
+
size={{ height: '100vh', width: sessionsWidth }}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</DraggablePanel>
|
|
54
|
+
);
|
|
55
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ActionIcon, SideNav } from '@lobehub/ui';
|
|
2
|
+
import { MessageSquare, Settings2, Sticker } from 'lucide-react';
|
|
3
|
+
import Router from 'next/router';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { shallow } from 'zustand/shallow';
|
|
6
|
+
|
|
7
|
+
import AvatarWithUpload from '@/features/AvatarWithUpload';
|
|
8
|
+
import { useSettings } from '@/store/settings';
|
|
9
|
+
|
|
10
|
+
export default memo(() => {
|
|
11
|
+
const [tab, setTab] = useSettings((s) => [s.sidebarKey, s.switchSideBar], shallow);
|
|
12
|
+
return (
|
|
13
|
+
<SideNav
|
|
14
|
+
avatar={<AvatarWithUpload />}
|
|
15
|
+
bottomActions={<ActionIcon icon={Settings2} onClick={() => Router.push('/setting')} />}
|
|
16
|
+
style={{ height: '100vh' }}
|
|
17
|
+
topActions={
|
|
18
|
+
<>
|
|
19
|
+
<ActionIcon
|
|
20
|
+
active={tab === 'chat'}
|
|
21
|
+
icon={MessageSquare}
|
|
22
|
+
onClick={() => setTab('chat')}
|
|
23
|
+
size="large"
|
|
24
|
+
/>
|
|
25
|
+
<ActionIcon
|
|
26
|
+
active={tab === 'market'}
|
|
27
|
+
icon={Sticker}
|
|
28
|
+
onClick={() => setTab('market')}
|
|
29
|
+
size="large"
|
|
30
|
+
/>
|
|
31
|
+
</>
|
|
32
|
+
}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ChatMessage } from '@lobehub/ui';
|
|
2
|
+
|
|
3
|
+
import { getInputVariablesFromMessages } from '@/helpers/prompt';
|
|
4
|
+
|
|
5
|
+
describe('getInputVariablesFromMessages 方法', () => {
|
|
6
|
+
it('应当在输入为空数组时返回空数组', () => {
|
|
7
|
+
const result = getInputVariablesFromMessages([]);
|
|
8
|
+
expect(result).toEqual([]);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('应当在输入消息不包含变量时返回空数组', () => {
|
|
12
|
+
const input: ChatMessage[] = [{ role: 'user', content: 'Hello, how are you?' }];
|
|
13
|
+
const result = getInputVariablesFromMessages(input);
|
|
14
|
+
expect(result).toEqual([]);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('应当在输入消息包含变量时返回包含变量、模板和消息索引的对象数组', () => {
|
|
18
|
+
const input: ChatMessage[] = [
|
|
19
|
+
{ role: 'user', content: 'Hello {name}, how are you?' },
|
|
20
|
+
{ role: 'user', content: 'My name is {name}' },
|
|
21
|
+
];
|
|
22
|
+
const expectedOutput = ['name'];
|
|
23
|
+
const result = getInputVariablesFromMessages(input);
|
|
24
|
+
expect(result).toEqual(expectedOutput);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('多个变量的情况', () => {
|
|
28
|
+
const input: ChatMessage[] = [
|
|
29
|
+
{ role: 'user', content: 'Hello {name}, how are {you}?' },
|
|
30
|
+
{ role: 'user', content: 'My name is {name}' },
|
|
31
|
+
];
|
|
32
|
+
const expectedOutput = ['name', 'you'];
|
|
33
|
+
const result = getInputVariablesFromMessages(input);
|
|
34
|
+
expect(result).toEqual(expectedOutput);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ChatMessage } from '@lobehub/ui';
|
|
2
|
+
import {
|
|
3
|
+
AIMessagePromptTemplate,
|
|
4
|
+
ChatPromptTemplate,
|
|
5
|
+
HumanMessagePromptTemplate,
|
|
6
|
+
SystemMessagePromptTemplate,
|
|
7
|
+
} from 'langchain/prompts';
|
|
8
|
+
|
|
9
|
+
export const getChatPromptTemplate = (chatMessages: ChatMessage[]) =>
|
|
10
|
+
ChatPromptTemplate.fromPromptMessages(
|
|
11
|
+
chatMessages.map((m) => {
|
|
12
|
+
switch (m.role) {
|
|
13
|
+
default:
|
|
14
|
+
case 'user': {
|
|
15
|
+
return HumanMessagePromptTemplate.fromTemplate(m.content);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
case 'system': {
|
|
19
|
+
return SystemMessagePromptTemplate.fromTemplate(m.content);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
case 'assistant': {
|
|
23
|
+
return AIMessagePromptTemplate.fromTemplate(m.content);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}),
|
|
27
|
+
);
|
|
28
|
+
export const getInputVariablesFromMessages = (chatMessages: ChatMessage[]) => {
|
|
29
|
+
let inputVariables: string[] = [];
|
|
30
|
+
try {
|
|
31
|
+
const chatPrompt = getChatPromptTemplate(chatMessages);
|
|
32
|
+
inputVariables = chatPrompt.inputVariables;
|
|
33
|
+
} catch {}
|
|
34
|
+
|
|
35
|
+
return inputVariables;
|
|
36
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ChatMessage } from '@lobehub/ui';
|
|
2
|
+
|
|
3
|
+
import { Compressor } from '@/utils/compass';
|
|
4
|
+
|
|
5
|
+
export const genShareMessagesUrl = (messages: ChatMessage[], systemRole?: string) => {
|
|
6
|
+
const compassedMsg = systemRole
|
|
7
|
+
? [{ content: systemRole, role: 'system' }, ...messages]
|
|
8
|
+
: messages;
|
|
9
|
+
|
|
10
|
+
return `/share?messages=${Compressor.compress(JSON.stringify(compassedMsg))}`;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const genSystemRoleQuery = async (content: string) => {
|
|
14
|
+
const x = { state: { systemRole: content } };
|
|
15
|
+
const systemRole = await Compressor.compressAsync(JSON.stringify(x));
|
|
16
|
+
return `#systemRole=${systemRole}`;
|
|
17
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ThemeProvider, lobeCustomTheme } from '@lobehub/ui';
|
|
2
|
+
import { App, ConfigProvider } from 'antd';
|
|
3
|
+
import { useThemeMode } from 'antd-style';
|
|
4
|
+
import 'antd/dist/reset.css';
|
|
5
|
+
import Zh_CN from 'antd/locale/zh_CN';
|
|
6
|
+
import { PropsWithChildren, useCallback, useEffect } from 'react';
|
|
7
|
+
import { shallow } from 'zustand/shallow';
|
|
8
|
+
|
|
9
|
+
import { useSessionStore } from '@/store/session';
|
|
10
|
+
import { useSettings } from '@/store/settings';
|
|
11
|
+
import { GlobalStyle } from '@/styles';
|
|
12
|
+
|
|
13
|
+
import i18n from '../locales';
|
|
14
|
+
import { useStyles } from './style';
|
|
15
|
+
|
|
16
|
+
const Layout = ({ children }: PropsWithChildren) => {
|
|
17
|
+
const { styles } = useStyles();
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
// 用一种比较奇怪的方式import 了 18n
|
|
21
|
+
i18n.finally(() => {});
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ConfigProvider locale={Zh_CN}>
|
|
26
|
+
<App className={styles.bg}>{children}</App>
|
|
27
|
+
</ConfigProvider>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default ({ children }: PropsWithChildren) => {
|
|
32
|
+
const themeMode = useSettings((s) => s.settings.themeMode, shallow);
|
|
33
|
+
const { primaryColor, neutralColor } = useSettings(
|
|
34
|
+
(s) => ({ neutralColor: s.settings.neutralColor, primaryColor: s.settings.primaryColor }),
|
|
35
|
+
shallow,
|
|
36
|
+
);
|
|
37
|
+
const { browserPrefers } = useThemeMode();
|
|
38
|
+
const isDarkMode = themeMode === 'auto' ? browserPrefers === 'dark' : themeMode === 'dark';
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
// refs: https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md#hashydrated
|
|
42
|
+
useSessionStore.persist.rehydrate();
|
|
43
|
+
useSettings.persist.rehydrate();
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const genCustomToken: any = useCallback(
|
|
47
|
+
() => lobeCustomTheme({ isDarkMode, neutralColor, primaryColor }),
|
|
48
|
+
[primaryColor, neutralColor, isDarkMode],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<ThemeProvider customToken={genCustomToken || {}} themeMode={themeMode}>
|
|
53
|
+
<GlobalStyle />
|
|
54
|
+
<Layout>{children}</Layout>
|
|
55
|
+
</ThemeProvider>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createStyles } from 'antd-style';
|
|
2
|
+
|
|
3
|
+
export const useStyles = createStyles(({ css, token }) => ({
|
|
4
|
+
bg: css`
|
|
5
|
+
overflow-y: scroll;
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
align-items: center;
|
|
9
|
+
|
|
10
|
+
height: 100%;
|
|
11
|
+
|
|
12
|
+
background: ${token.colorBgLayout};
|
|
13
|
+
|
|
14
|
+
:has(#ChatLayout, #FlowLayout) {
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
}
|
|
17
|
+
`,
|
|
18
|
+
}));
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import i18n from 'i18next';
|
|
2
|
+
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
3
|
+
import { isArray } from 'lodash-es';
|
|
4
|
+
import { initReactI18next } from 'react-i18next';
|
|
5
|
+
|
|
6
|
+
import type { Namespaces } from '@/types/locale';
|
|
7
|
+
|
|
8
|
+
import resources from './resources';
|
|
9
|
+
|
|
10
|
+
// const getRes = (res: Resources, namespace: Namespaces[]) => {
|
|
11
|
+
// const newRes: any = {};
|
|
12
|
+
// for (const [locale, value] of Object.entries(res)) {
|
|
13
|
+
// newRes[locale] = {};
|
|
14
|
+
// for (const ns of namespace) {
|
|
15
|
+
// newRes[locale][ns] = value[ns];
|
|
16
|
+
// }
|
|
17
|
+
// }
|
|
18
|
+
// return newRes;
|
|
19
|
+
// };
|
|
20
|
+
|
|
21
|
+
export const createI18nNext = (namespace?: Namespaces[] | Namespaces) => {
|
|
22
|
+
const ns: Namespaces[] = namespace
|
|
23
|
+
? isArray(namespace)
|
|
24
|
+
? ['common', ...namespace]
|
|
25
|
+
: ['common', namespace]
|
|
26
|
+
: ['common'];
|
|
27
|
+
return (
|
|
28
|
+
i18n
|
|
29
|
+
// detect user language
|
|
30
|
+
// learn more: https://github.com/i18next/i18next-browser-languageDetector
|
|
31
|
+
.use(LanguageDetector)
|
|
32
|
+
// pass the i18n instance to react-i18next.
|
|
33
|
+
.use(initReactI18next)
|
|
34
|
+
// init i18next
|
|
35
|
+
// for all options read: https://www.i18next.com/overview/configuration-options
|
|
36
|
+
.init({
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
debug: process.env.NODE_ENV === 'development',
|
|
39
|
+
defaultNS: ns,
|
|
40
|
+
fallbackLng: 'zh-CN',
|
|
41
|
+
interpolation: {
|
|
42
|
+
escapeValue: false, // not needed for react as it escapes by default
|
|
43
|
+
},
|
|
44
|
+
ns,
|
|
45
|
+
// resources: getRes(resources, ns),
|
|
46
|
+
resources,
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
'advanceSettings': '高级设置',
|
|
3
|
+
'agentAvatar': '头像',
|
|
4
|
+
'agentDescription': '描述',
|
|
5
|
+
'agentDescriptionPlaceholder': '请输入描述',
|
|
6
|
+
'agentModel': '模型',
|
|
7
|
+
'agentName': '名称',
|
|
8
|
+
'agentNamePlaceholder': '请输入名称',
|
|
9
|
+
'agentProfile': '助手信息',
|
|
10
|
+
'agentPrompt': '提示词',
|
|
11
|
+
'agentPromptPlaceholder': '请输入 AI 提示词',
|
|
12
|
+
'agentTag': '标签',
|
|
13
|
+
'agentTagPlaceholder': '请输入标签',
|
|
14
|
+
'archive': '归档',
|
|
15
|
+
'autoGenerate': '自动补全',
|
|
16
|
+
'autoGenerateTooltip': '基于提示词自动补全助手描述',
|
|
17
|
+
'cancel': '取消',
|
|
18
|
+
'close': '关闭',
|
|
19
|
+
'confirmRemoveSessionItemAlert': '即将删除该助手,删除后该将无法找回,请确认你的操作',
|
|
20
|
+
'defaultAgent': '默认助手',
|
|
21
|
+
'edit': '编辑',
|
|
22
|
+
'editAgentProfile': '编辑助手信息',
|
|
23
|
+
'export': '导出',
|
|
24
|
+
'gpt-3.5-turbo': 'GPT 3.5',
|
|
25
|
+
'gpt-3.5-turbo-16k': 'GPT 3.5 (16K)',
|
|
26
|
+
'gpt-4': 'GPT 4',
|
|
27
|
+
'gpt-4-32k': 'GPT 4 (32K)',
|
|
28
|
+
'modelConfig': '模型配置',
|
|
29
|
+
'modelTemperature': '发散度',
|
|
30
|
+
'newAgent': '新建助手',
|
|
31
|
+
'noDescription': '暂无描述',
|
|
32
|
+
'ok': '确定',
|
|
33
|
+
'profile': '助手身份',
|
|
34
|
+
'reset': '重置',
|
|
35
|
+
'searchAgentPlaceholder': '搜索助手和对话...',
|
|
36
|
+
'sessionSetting': '会话设置',
|
|
37
|
+
'setting': '设置',
|
|
38
|
+
'share': '分享',
|
|
39
|
+
'updateAgent': '更新助理信息',
|
|
40
|
+
'updatePrompt': '更新提示词',
|
|
41
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
danger: {
|
|
3
|
+
clear: {
|
|
4
|
+
action: '立即清除',
|
|
5
|
+
confirm: '确认清除所有聊天、设置数据?',
|
|
6
|
+
desc: '清除所有聊天、设置数据',
|
|
7
|
+
title: '清除所有数据',
|
|
8
|
+
},
|
|
9
|
+
reset: {
|
|
10
|
+
action: '立即重置',
|
|
11
|
+
confirm: '确认重置所有设置?',
|
|
12
|
+
currentVersion: '当前版本',
|
|
13
|
+
desc: '重置所有设置项回默认值',
|
|
14
|
+
title: '重置所有设置',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
header: '设置',
|
|
18
|
+
settingChat: {
|
|
19
|
+
compressThreshold: {
|
|
20
|
+
desc: '当未压缩的历史消息超过该值时,将进行压缩',
|
|
21
|
+
title: '历史消息长度压缩阈值',
|
|
22
|
+
},
|
|
23
|
+
enableCompressThreshold: {
|
|
24
|
+
title: '是否开启历史消息长度压缩阈值',
|
|
25
|
+
},
|
|
26
|
+
enableHistoryCount: {
|
|
27
|
+
title: '是否开启携带的历史消息数限制',
|
|
28
|
+
},
|
|
29
|
+
historyCount: {
|
|
30
|
+
desc: '每次请求携带的历史消息数',
|
|
31
|
+
title: '附带历史消息数',
|
|
32
|
+
},
|
|
33
|
+
inputTemplate: {
|
|
34
|
+
desc: '用户最新的一条消息会填充到此模板',
|
|
35
|
+
title: '用户输入预处理',
|
|
36
|
+
},
|
|
37
|
+
title: '聊天设置',
|
|
38
|
+
},
|
|
39
|
+
settingModel: {
|
|
40
|
+
enableMaxTokens: {
|
|
41
|
+
title: '开启单次回复限制',
|
|
42
|
+
},
|
|
43
|
+
frequencyPenalty: {
|
|
44
|
+
desc: '值越大,越有可能降低重复字词',
|
|
45
|
+
title: '频率惩罚度',
|
|
46
|
+
},
|
|
47
|
+
maxTokens: {
|
|
48
|
+
desc: '单次交互所用的最大 Token 数',
|
|
49
|
+
title: '单次回复限制',
|
|
50
|
+
},
|
|
51
|
+
model: {
|
|
52
|
+
desc: 'ChatGPT 模型',
|
|
53
|
+
title: '模型',
|
|
54
|
+
},
|
|
55
|
+
presencePenalty: {
|
|
56
|
+
desc: '值越大,越有可能扩展到新话题',
|
|
57
|
+
title: '话题新鲜度',
|
|
58
|
+
},
|
|
59
|
+
temperature: {
|
|
60
|
+
desc: '值越大,回复越随机',
|
|
61
|
+
title: '随机性',
|
|
62
|
+
},
|
|
63
|
+
title: '模型设置',
|
|
64
|
+
topP: {
|
|
65
|
+
desc: '与随机性类似,但不要和随机性一起更改',
|
|
66
|
+
title: '核采样',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
settingOpenAI: {
|
|
70
|
+
endpoint: {
|
|
71
|
+
desc: '除默认地址外,必须包含 http(s)://',
|
|
72
|
+
placeholder: 'https://api.openai.com/v1',
|
|
73
|
+
title: '接口代理地址',
|
|
74
|
+
},
|
|
75
|
+
title: 'OpenAI 设置',
|
|
76
|
+
token: {
|
|
77
|
+
desc: '使用自己的 OpenAI Key',
|
|
78
|
+
placeholder: 'OpenAI API Key',
|
|
79
|
+
title: 'API Key',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
settingSystem: {
|
|
83
|
+
accessCode: {
|
|
84
|
+
desc: '管理员已开启加密访问',
|
|
85
|
+
placeholder: '请输入访问密码',
|
|
86
|
+
title: '访问密码',
|
|
87
|
+
},
|
|
88
|
+
title: '系统设置',
|
|
89
|
+
},
|
|
90
|
+
settingTheme: {
|
|
91
|
+
avatar: {
|
|
92
|
+
title: '头像',
|
|
93
|
+
},
|
|
94
|
+
fontSize: {
|
|
95
|
+
desc: '聊天内容的字体大小',
|
|
96
|
+
title: '字体大小',
|
|
97
|
+
},
|
|
98
|
+
lang: {
|
|
99
|
+
title: '语言设置',
|
|
100
|
+
},
|
|
101
|
+
neutralColor: {
|
|
102
|
+
desc: '不同色彩倾向的灰阶自定义',
|
|
103
|
+
title: '中性色',
|
|
104
|
+
},
|
|
105
|
+
primaryColor: {
|
|
106
|
+
desc: '自定义主题色',
|
|
107
|
+
title: '主题色',
|
|
108
|
+
},
|
|
109
|
+
themeMode: {
|
|
110
|
+
auto: '自动',
|
|
111
|
+
dark: '深色',
|
|
112
|
+
light: '浅色',
|
|
113
|
+
title: '主题',
|
|
114
|
+
},
|
|
115
|
+
title: '主题设置',
|
|
116
|
+
},
|
|
117
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SelectProps } from 'antd';
|
|
2
|
+
|
|
3
|
+
import type { Locales } from '@/types/locale';
|
|
4
|
+
|
|
5
|
+
type LocaleOptions = SelectProps['options'] &
|
|
6
|
+
{
|
|
7
|
+
value: Locales;
|
|
8
|
+
}[];
|
|
9
|
+
|
|
10
|
+
export const options: LocaleOptions = [
|
|
11
|
+
{
|
|
12
|
+
label: '简体中文',
|
|
13
|
+
value: 'zh-CN',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
label: 'English',
|
|
17
|
+
value: 'en-US',
|
|
18
|
+
},
|
|
19
|
+
] as LocaleOptions;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import en_US from './en_US';
|
|
2
|
+
import zh_CN from './zh_CN';
|
|
3
|
+
|
|
4
|
+
const resources = {
|
|
5
|
+
'en-US': en_US,
|
|
6
|
+
'zh-CN': zh_CN,
|
|
7
|
+
} as const;
|
|
8
|
+
export default resources;
|
|
9
|
+
export const defaultResources = zh_CN;
|
|
10
|
+
export type Resources = typeof resources;
|
|
11
|
+
export type DefaultResources = typeof defaultResources;
|
|
12
|
+
export type Namespaces = keyof DefaultResources;
|
|
13
|
+
export type Locales = keyof Resources;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ConfigState } from '@/types/exportConfig';
|
|
2
|
+
import { VersionController } from '@/utils/VersionController';
|
|
3
|
+
|
|
4
|
+
// 当前最新的版本号
|
|
5
|
+
export const CURRENT_CONFIG_VERSION = 1;
|
|
6
|
+
|
|
7
|
+
// 历史记录版本升级模块
|
|
8
|
+
export const ConfigMigrations = [];
|
|
9
|
+
|
|
10
|
+
export const Migration = new VersionController<ConfigState>(
|
|
11
|
+
ConfigMigrations,
|
|
12
|
+
CURRENT_CONFIG_VERSION,
|
|
13
|
+
);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Analytics } from '@vercel/analytics/react';
|
|
2
|
+
import type { AppProps } from 'next/app';
|
|
3
|
+
|
|
4
|
+
import Layout from '@/layout';
|
|
5
|
+
|
|
6
|
+
export default ({ Component, pageProps }: AppProps) => {
|
|
7
|
+
return (
|
|
8
|
+
<Layout>
|
|
9
|
+
<Component {...pageProps} />
|
|
10
|
+
<Analytics />
|
|
11
|
+
</Layout>
|
|
12
|
+
);
|
|
13
|
+
};
|