@lobehub/chat 0.128.10 → 0.129.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 +42 -0
- package/locales/ar/chat.json +1 -0
- package/locales/ar/common.json +2 -1
- package/locales/ar/error.json +6 -0
- package/locales/ar/setting.json +9 -1
- package/locales/de-DE/chat.json +1 -0
- package/locales/de-DE/common.json +1 -0
- package/locales/de-DE/error.json +6 -0
- package/locales/de-DE/setting.json +9 -1
- package/locales/en-US/chat.json +1 -0
- package/locales/en-US/common.json +1 -0
- package/locales/en-US/error.json +6 -0
- package/locales/en-US/setting.json +8 -0
- package/locales/es-ES/chat.json +1 -0
- package/locales/es-ES/common.json +1 -0
- package/locales/es-ES/error.json +6 -0
- package/locales/es-ES/setting.json +9 -1
- package/locales/fr-FR/chat.json +1 -0
- package/locales/fr-FR/common.json +1 -0
- package/locales/fr-FR/error.json +6 -0
- package/locales/fr-FR/setting.json +8 -0
- package/locales/it-IT/chat.json +1 -0
- package/locales/it-IT/common.json +1 -0
- package/locales/it-IT/error.json +6 -0
- package/locales/it-IT/setting.json +8 -0
- package/locales/ja-JP/chat.json +1 -0
- package/locales/ja-JP/common.json +1 -0
- package/locales/ja-JP/error.json +6 -0
- package/locales/ja-JP/setting.json +8 -0
- package/locales/ko-KR/chat.json +1 -0
- package/locales/ko-KR/common.json +1 -0
- package/locales/ko-KR/error.json +6 -0
- package/locales/ko-KR/setting.json +8 -0
- package/locales/nl-NL/chat.json +1 -0
- package/locales/nl-NL/common.json +2 -1
- package/locales/nl-NL/error.json +6 -0
- package/locales/nl-NL/setting.json +8 -0
- package/locales/pl-PL/chat.json +1 -0
- package/locales/pl-PL/common.json +2 -1
- package/locales/pl-PL/error.json +6 -0
- package/locales/pl-PL/setting.json +8 -0
- package/locales/pt-BR/chat.json +1 -0
- package/locales/pt-BR/common.json +1 -0
- package/locales/pt-BR/error.json +6 -0
- package/locales/pt-BR/setting.json +9 -1
- package/locales/ru-RU/chat.json +1 -0
- package/locales/ru-RU/common.json +1 -0
- package/locales/ru-RU/error.json +6 -0
- package/locales/ru-RU/setting.json +9 -1
- package/locales/tr-TR/chat.json +1 -0
- package/locales/tr-TR/common.json +1 -0
- package/locales/tr-TR/error.json +6 -0
- package/locales/tr-TR/setting.json +9 -1
- package/locales/vi-VN/chat.json +1 -0
- package/locales/vi-VN/common.json +1 -0
- package/locales/vi-VN/error.json +6 -0
- package/locales/vi-VN/setting.json +9 -1
- package/locales/zh-CN/chat.json +1 -0
- package/locales/zh-CN/common.json +1 -0
- package/locales/zh-CN/error.json +6 -0
- package/locales/zh-CN/setting.json +8 -0
- package/locales/zh-TW/chat.json +1 -0
- package/locales/zh-TW/common.json +1 -0
- package/locales/zh-TW/error.json +6 -0
- package/locales/zh-TW/setting.json +8 -0
- package/package.json +3 -3
- package/public/images/logo.png +0 -0
- package/src/app/api/chat/[provider]/agentRuntime.ts +13 -0
- package/src/app/api/config/route.ts +2 -0
- package/src/app/api/errorResponse.ts +3 -0
- package/src/app/chat/(desktop)/features/ChatInput/Footer/index.tsx +1 -0
- package/src/app/layout.tsx +18 -12
- package/src/app/settings/llm/Perplexity/index.tsx +52 -0
- package/src/app/settings/llm/index.tsx +2 -0
- package/src/app/settings/tts/page.tsx +1 -1
- package/src/components/ModelIcon/index.tsx +3 -1
- package/src/components/ModelProviderIcon/index.tsx +19 -1
- package/src/components/ModelTag/ModelIcon.tsx +3 -1
- package/src/config/modelProviders/index.ts +3 -0
- package/src/config/modelProviders/perplexity.ts +44 -0
- package/src/config/server/provider.ts +8 -0
- package/src/const/settings.ts +4 -0
- package/src/features/AvatarWithUpload/index.tsx +7 -6
- package/src/features/Conversation/Error/APIKeyForm/Perplexity.tsx +60 -0
- package/src/features/Conversation/Error/APIKeyForm/index.tsx +5 -0
- package/src/features/Conversation/Error/index.tsx +1 -0
- package/src/features/SideBar/BottomActions.tsx +5 -8
- package/src/features/SideBar/TopActions.tsx +2 -1
- package/src/libs/agent-runtime/error.ts +3 -0
- package/src/libs/agent-runtime/index.ts +1 -0
- package/src/libs/agent-runtime/perplexity/index.ts +86 -0
- package/src/libs/agent-runtime/types/type.ts +1 -0
- package/src/locales/default/chat.ts +1 -0
- package/src/locales/default/common.ts +1 -0
- package/src/locales/default/error.ts +7 -0
- package/src/locales/default/setting.ts +8 -0
- package/src/services/_auth.ts +4 -0
- package/src/store/global/slices/settings/selectors/modelProvider.ts +9 -0
- package/src/types/settings/modelProvider.ts +7 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Perplexity } from '@lobehub/icons';
|
|
2
|
+
import { Input } from 'antd';
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
import { ModelProvider } from '@/libs/agent-runtime';
|
|
8
|
+
|
|
9
|
+
import Checker from '../components/Checker';
|
|
10
|
+
import ProviderConfig from '../components/ProviderConfig';
|
|
11
|
+
import { LLMProviderApiTokenKey, LLMProviderConfigKey } from '../const';
|
|
12
|
+
|
|
13
|
+
const providerKey = 'perplexity';
|
|
14
|
+
|
|
15
|
+
const PerplexityProvider = memo(() => {
|
|
16
|
+
const { t } = useTranslation('setting');
|
|
17
|
+
|
|
18
|
+
const theme = useTheme();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<ProviderConfig
|
|
22
|
+
configItems={[
|
|
23
|
+
{
|
|
24
|
+
children: (
|
|
25
|
+
<Input.Password
|
|
26
|
+
autoComplete={'new-password'}
|
|
27
|
+
placeholder={t('llm.Perplexity.token.placeholder')}
|
|
28
|
+
/>
|
|
29
|
+
),
|
|
30
|
+
desc: t('llm.Perplexity.token.desc'),
|
|
31
|
+
label: t('llm.Perplexity.token.title'),
|
|
32
|
+
name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
children: <Checker model={'pplx-7b-chat'} provider={ModelProvider.Perplexity} />,
|
|
36
|
+
desc: t('llm.checker.desc'),
|
|
37
|
+
label: t('llm.checker.title'),
|
|
38
|
+
minWidth: '100%',
|
|
39
|
+
},
|
|
40
|
+
]}
|
|
41
|
+
provider={providerKey}
|
|
42
|
+
title={
|
|
43
|
+
<Perplexity.Combine
|
|
44
|
+
color={theme.isDarkMode ? theme.colorText : Perplexity.colorPrimary}
|
|
45
|
+
size={24}
|
|
46
|
+
/>
|
|
47
|
+
}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export default PerplexityProvider;
|
|
@@ -13,6 +13,7 @@ import Google from './Google';
|
|
|
13
13
|
import Moonshot from './Moonshot';
|
|
14
14
|
import Ollama from './Ollama';
|
|
15
15
|
import OpenAI from './OpenAI';
|
|
16
|
+
import Perplexity from './Perplexity';
|
|
16
17
|
import Zhipu from './Zhipu';
|
|
17
18
|
|
|
18
19
|
export default memo<{ showOllama: boolean }>(({ showOllama }) => {
|
|
@@ -27,6 +28,7 @@ export default memo<{ showOllama: boolean }>(({ showOllama }) => {
|
|
|
27
28
|
<Moonshot />
|
|
28
29
|
<Google />
|
|
29
30
|
<Bedrock />
|
|
31
|
+
<Perplexity />
|
|
30
32
|
{showOllama && <Ollama />}
|
|
31
33
|
<Footer>
|
|
32
34
|
<Trans i18nKey="llm.waitingForMore" ns={'setting'}>
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
Mistral,
|
|
10
10
|
Moonshot,
|
|
11
11
|
OpenAI,
|
|
12
|
+
Perplexity,
|
|
12
13
|
Tongyi,
|
|
13
14
|
} from '@lobehub/icons';
|
|
14
15
|
import { memo } from 'react';
|
|
@@ -33,7 +34,8 @@ const ModelIcon = memo<ModelProviderIconProps>(({ model, size = 12 }) => {
|
|
|
33
34
|
if (model.includes('moonshot')) return <Moonshot.Avatar size={size} />;
|
|
34
35
|
if (model.includes('baichuan'))
|
|
35
36
|
return <Baichuan.Avatar background={Baichuan.colorPrimary} size={size} />;
|
|
36
|
-
if (model.includes('mistral')) return <Mistral.Avatar size={size} />;
|
|
37
|
+
if (model.includes('mistral') || model.includes('mixtral')) return <Mistral.Avatar size={size} />;
|
|
38
|
+
if (model.includes('pplx')) return <Perplexity.Avatar size={size} />;
|
|
37
39
|
});
|
|
38
40
|
|
|
39
41
|
export default ModelIcon;
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Azure,
|
|
3
|
+
Bedrock,
|
|
4
|
+
Google,
|
|
5
|
+
Mistral,
|
|
6
|
+
Moonshot,
|
|
7
|
+
Ollama,
|
|
8
|
+
OpenAI,
|
|
9
|
+
Perplexity,
|
|
10
|
+
Zhipu,
|
|
11
|
+
} from '@lobehub/icons';
|
|
2
12
|
import { memo } from 'react';
|
|
3
13
|
import { Center } from 'react-layout-kit';
|
|
4
14
|
|
|
@@ -46,6 +56,14 @@ const ModelProviderIcon = memo<ModelProviderIconProps>(({ provider }) => {
|
|
|
46
56
|
return <Ollama size={20} />;
|
|
47
57
|
}
|
|
48
58
|
|
|
59
|
+
case ModelProvider.Perplexity: {
|
|
60
|
+
return <Perplexity size={20} />;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
case ModelProvider.Mistral: {
|
|
64
|
+
return <Mistral size={20} />;
|
|
65
|
+
}
|
|
66
|
+
|
|
49
67
|
default: {
|
|
50
68
|
return null;
|
|
51
69
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
Mistral,
|
|
10
10
|
Moonshot,
|
|
11
11
|
OpenAI,
|
|
12
|
+
Perplexity,
|
|
12
13
|
Tongyi,
|
|
13
14
|
} from '@lobehub/icons';
|
|
14
15
|
import { memo } from 'react';
|
|
@@ -31,7 +32,8 @@ const ModelIcon = memo<ModelIconProps>(({ model, size = 12 }) => {
|
|
|
31
32
|
if (model.includes('qwen')) return <Tongyi size={size} />;
|
|
32
33
|
if (model.includes('minmax')) return <Minimax size={size} />;
|
|
33
34
|
if (model.includes('baichuan')) return <Baichuan size={size} />;
|
|
34
|
-
if (model.includes('mistral')) return <Mistral size={size} />;
|
|
35
|
+
if (model.includes('mistral') || model.includes('mixtral')) return <Mistral size={size} />;
|
|
36
|
+
if (model.includes('pplx')) return <Perplexity size={size} />;
|
|
35
37
|
});
|
|
36
38
|
|
|
37
39
|
export default ModelIcon;
|
|
@@ -5,6 +5,7 @@ import GoogleProvider from './google';
|
|
|
5
5
|
import MoonshotProvider from './moonshot';
|
|
6
6
|
import OllamaProvider from './ollama';
|
|
7
7
|
import OpenAIProvider from './openai';
|
|
8
|
+
import PerplexityProvider from './perplexity';
|
|
8
9
|
import ZhiPuProvider from './zhipu';
|
|
9
10
|
|
|
10
11
|
export const LOBE_DEFAULT_MODEL_LIST: ChatModelCard[] = [
|
|
@@ -14,6 +15,7 @@ export const LOBE_DEFAULT_MODEL_LIST: ChatModelCard[] = [
|
|
|
14
15
|
GoogleProvider.chatModels,
|
|
15
16
|
MoonshotProvider.chatModels,
|
|
16
17
|
OllamaProvider.chatModels,
|
|
18
|
+
PerplexityProvider.chatModels,
|
|
17
19
|
].flat();
|
|
18
20
|
|
|
19
21
|
export { default as BedrockProvider } from './bedrock';
|
|
@@ -21,4 +23,5 @@ export { default as GoogleProvider } from './google';
|
|
|
21
23
|
export { default as MoonshotProvider } from './moonshot';
|
|
22
24
|
export { default as OllamaProvider } from './ollama';
|
|
23
25
|
export { default as OpenAIProvider } from './openai';
|
|
26
|
+
export { default as PerplexityProvider } from './perplexity';
|
|
24
27
|
export { default as ZhiPuProvider } from './zhipu';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ModelProviderCard } from '@/types/llm';
|
|
2
|
+
|
|
3
|
+
const Perplexity: ModelProviderCard = {
|
|
4
|
+
chatModels: [
|
|
5
|
+
{
|
|
6
|
+
displayName: 'Perplexity 7B Chat',
|
|
7
|
+
id: 'pplx-7b-chat',
|
|
8
|
+
tokens: 8192,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
displayName: 'Perplexity 70B Chat',
|
|
12
|
+
id: 'pplx-70b-chat',
|
|
13
|
+
tokens: 8192,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
displayName: 'Perplexity 7B Online',
|
|
17
|
+
id: 'pplx-7b-online',
|
|
18
|
+
tokens: 8192,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
displayName: 'Perplexity 70B Online',
|
|
22
|
+
id: 'pplx-70b-online',
|
|
23
|
+
tokens: 8192,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
displayName: 'Codellama 34B Instruct',
|
|
27
|
+
id: 'codellama-34b-instruct',
|
|
28
|
+
tokens: 16_384,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
displayName: 'Codellama 70B Instruct',
|
|
32
|
+
id: 'codellama-70b-instruct',
|
|
33
|
+
tokens: 16_384,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
displayName: 'Mixtral 8x7B Instruct',
|
|
37
|
+
id: 'mixtral-8x7b-instruct',
|
|
38
|
+
tokens: 8192,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
id: 'perplexity',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default Perplexity;
|
|
@@ -28,6 +28,9 @@ declare global {
|
|
|
28
28
|
MOONSHOT_API_KEY?: string;
|
|
29
29
|
MOONSHOT_PROXY_URL?: string;
|
|
30
30
|
|
|
31
|
+
// Perplexity Provider
|
|
32
|
+
PERPLEXITY_API_KEY?: string;
|
|
33
|
+
|
|
31
34
|
// AWS Credentials
|
|
32
35
|
AWS_REGION?: string;
|
|
33
36
|
AWS_ACCESS_KEY_ID?: string;
|
|
@@ -53,6 +56,8 @@ export const getProviderConfig = () => {
|
|
|
53
56
|
|
|
54
57
|
const MOONSHOT_API_KEY = process.env.MOONSHOT_API_KEY || '';
|
|
55
58
|
|
|
59
|
+
const PERPLEXITY_API_KEY = process.env.PERPLEXITY_API_KEY || '';
|
|
60
|
+
|
|
56
61
|
// region format: iad1,sfo1
|
|
57
62
|
let regions: string[] = [];
|
|
58
63
|
if (process.env.OPENAI_FUNCTION_REGIONS) {
|
|
@@ -72,6 +77,9 @@ export const getProviderConfig = () => {
|
|
|
72
77
|
ENABLED_GOOGLE: !!GOOGLE_API_KEY,
|
|
73
78
|
GOOGLE_API_KEY,
|
|
74
79
|
|
|
80
|
+
ENABLED_PERPLEXITY: !!PERPLEXITY_API_KEY,
|
|
81
|
+
PERPLEXITY_API_KEY,
|
|
82
|
+
|
|
75
83
|
ENABLED_MOONSHOT: !!MOONSHOT_API_KEY,
|
|
76
84
|
MOONSHOT_API_KEY,
|
|
77
85
|
MOONSHOT_PROXY_URL: process.env.MOONSHOT_PROXY_URL,
|
package/src/const/settings.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Logo } from '@lobehub/ui';
|
|
2
1
|
import { Upload } from 'antd';
|
|
3
2
|
import { createStyles } from 'antd-style';
|
|
4
3
|
import Avatar from 'next/image';
|
|
5
4
|
import { CSSProperties, memo } from 'react';
|
|
6
5
|
|
|
6
|
+
import { imageUrl } from '@/const/url';
|
|
7
7
|
import { useGlobalStore } from '@/store/global';
|
|
8
8
|
import { commonSelectors } from '@/store/global/selectors';
|
|
9
9
|
import { imageToBase64 } from '@/utils/imageToBase64';
|
|
@@ -55,11 +55,12 @@ const AvatarWithUpload = memo<AvatarWithUploadProps>(
|
|
|
55
55
|
return (
|
|
56
56
|
<div className={styles} id={id} style={{ maxHeight: size, maxWidth: size, ...style }}>
|
|
57
57
|
<Upload beforeUpload={handleUploadAvatar} itemRender={() => void 0} maxCount={1}>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
<Avatar
|
|
59
|
+
alt={avatar ? 'userAvatar' : 'LobeChat'}
|
|
60
|
+
height={size}
|
|
61
|
+
src={!!avatar ? avatar : imageUrl('logo.png')}
|
|
62
|
+
width={size}
|
|
63
|
+
/>
|
|
63
64
|
</Upload>
|
|
64
65
|
</div>
|
|
65
66
|
);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Perplexity } from '@lobehub/icons';
|
|
2
|
+
import { Input } from 'antd';
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
|
|
6
|
+
import { ModelProvider } from '@/libs/agent-runtime';
|
|
7
|
+
import { useGlobalStore } from '@/store/global';
|
|
8
|
+
import { modelProviderSelectors } from '@/store/global/selectors';
|
|
9
|
+
|
|
10
|
+
import { FormAction } from '../style';
|
|
11
|
+
|
|
12
|
+
const PerplexityForm = memo(() => {
|
|
13
|
+
const { t } = useTranslation('error');
|
|
14
|
+
// const [showProxy, setShow] = useState(false);
|
|
15
|
+
|
|
16
|
+
const [apiKey, setConfig] = useGlobalStore((s) => [
|
|
17
|
+
modelProviderSelectors.perplexityAPIKey(s),
|
|
18
|
+
s.setModelProviderConfig,
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<FormAction
|
|
23
|
+
avatar={<Perplexity size={56} />}
|
|
24
|
+
description={t('unlock.apikey.Perplexity.description')}
|
|
25
|
+
title={t('unlock.apikey.Perplexity.title')}
|
|
26
|
+
>
|
|
27
|
+
<Input.Password
|
|
28
|
+
autoComplete={'new-password'}
|
|
29
|
+
onChange={(e) => {
|
|
30
|
+
setConfig(ModelProvider.Perplexity, { apiKey: e.target.value });
|
|
31
|
+
}}
|
|
32
|
+
placeholder={'*********************************'}
|
|
33
|
+
type={'block'}
|
|
34
|
+
value={apiKey}
|
|
35
|
+
/>
|
|
36
|
+
{/*{showProxy ? (*/}
|
|
37
|
+
{/* <Input*/}
|
|
38
|
+
{/* onChange={(e) => {*/}
|
|
39
|
+
{/* setConfig({ endpoint: e.target.value });*/}
|
|
40
|
+
{/* }}*/}
|
|
41
|
+
{/* placeholder={'https://api.openai.com/v1'}*/}
|
|
42
|
+
{/* type={'block'}*/}
|
|
43
|
+
{/* value={proxyUrl}*/}
|
|
44
|
+
{/* />*/}
|
|
45
|
+
{/*) : (*/}
|
|
46
|
+
{/* <Button*/}
|
|
47
|
+
{/* icon={<Icon icon={Network} />}*/}
|
|
48
|
+
{/* onClick={() => {*/}
|
|
49
|
+
{/* setShow(true);*/}
|
|
50
|
+
{/* }}*/}
|
|
51
|
+
{/* type={'text'}*/}
|
|
52
|
+
{/* >*/}
|
|
53
|
+
{/* {t('unlock.apikey.addProxyUrl')}*/}
|
|
54
|
+
{/* </Button>*/}
|
|
55
|
+
{/*)}*/}
|
|
56
|
+
</FormAction>
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export default PerplexityForm;
|
|
@@ -10,6 +10,7 @@ import BedrockForm from './Bedrock';
|
|
|
10
10
|
import GoogleForm from './Google';
|
|
11
11
|
import MoonshotForm from './Moonshot';
|
|
12
12
|
import OpenAIForm from './OpenAI';
|
|
13
|
+
import PerplexityForm from './Perplexity';
|
|
13
14
|
import ZhipuForm from './Zhipu';
|
|
14
15
|
|
|
15
16
|
interface APIKeyFormProps {
|
|
@@ -40,6 +41,10 @@ const APIKeyForm = memo<APIKeyFormProps>(({ id, provider }) => {
|
|
|
40
41
|
return <MoonshotForm />;
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
case ModelProvider.Perplexity: {
|
|
45
|
+
return <PerplexityForm />;
|
|
46
|
+
}
|
|
47
|
+
|
|
43
48
|
default:
|
|
44
49
|
case ModelProvider.OpenAI: {
|
|
45
50
|
return <OpenAIForm />;
|
|
@@ -66,6 +66,7 @@ const ErrorMessageExtra = memo<{ data: ChatMessage }>(({ data }) => {
|
|
|
66
66
|
case AgentRuntimeErrorType.InvalidZhipuAPIKey:
|
|
67
67
|
case AgentRuntimeErrorType.InvalidMoonshotAPIKey:
|
|
68
68
|
case AgentRuntimeErrorType.InvalidGoogleAPIKey:
|
|
69
|
+
case AgentRuntimeErrorType.InvalidPerplexityAPIKey:
|
|
69
70
|
case AgentRuntimeErrorType.NoOpenAIAPIKey: {
|
|
70
71
|
return <InvalidAPIKey id={data.id} provider={data.error?.body?.provider} />;
|
|
71
72
|
}
|
|
@@ -17,7 +17,7 @@ import { memo } from 'react';
|
|
|
17
17
|
import { useTranslation } from 'react-i18next';
|
|
18
18
|
import { Flexbox } from 'react-layout-kit';
|
|
19
19
|
|
|
20
|
-
import { ABOUT, CHANGELOG, DISCORD, DOCUMENTS, FEEDBACK
|
|
20
|
+
import { ABOUT, CHANGELOG, DISCORD, DOCUMENTS, FEEDBACK } from '@/const/url';
|
|
21
21
|
import DataImporter from '@/features/DataImporter';
|
|
22
22
|
import { configService } from '@/services/config';
|
|
23
23
|
import { GlobalStore, useGlobalStore } from '@/store/global';
|
|
@@ -120,13 +120,10 @@ const BottomActions = memo<BottomActionProps>(({ tab }) => {
|
|
|
120
120
|
|
|
121
121
|
return (
|
|
122
122
|
<>
|
|
123
|
-
<
|
|
124
|
-
icon={Github}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
title={'GitHub'}
|
|
128
|
-
/>
|
|
129
|
-
<Link href={DOCUMENTS} target={'_blank'}>
|
|
123
|
+
<Link aria-label={'GitHub'} href={DOCUMENTS} target={'_blank'}>
|
|
124
|
+
<ActionIcon icon={Github} placement={'right'} title={'GitHub'} />
|
|
125
|
+
</Link>
|
|
126
|
+
<Link aria-label={t('document')} href={DOCUMENTS} target={'_blank'}>
|
|
130
127
|
<ActionIcon icon={Book} placement={'right'} title={t('document')} />
|
|
131
128
|
</Link>
|
|
132
129
|
<Dropdown arrow={false} menu={{ items }} trigger={['click']}>
|
|
@@ -19,6 +19,7 @@ const TopActions = memo<TopActionProps>(({ tab }) => {
|
|
|
19
19
|
return (
|
|
20
20
|
<>
|
|
21
21
|
<Link
|
|
22
|
+
aria-label={t('tab.chat')}
|
|
22
23
|
href={'/chat'}
|
|
23
24
|
onClick={(e) => {
|
|
24
25
|
e.preventDefault();
|
|
@@ -33,7 +34,7 @@ const TopActions = memo<TopActionProps>(({ tab }) => {
|
|
|
33
34
|
title={t('tab.chat')}
|
|
34
35
|
/>
|
|
35
36
|
</Link>
|
|
36
|
-
<Link href={'/market'}>
|
|
37
|
+
<Link aria-label={t('tab.market')} href={'/market'}>
|
|
37
38
|
<ActionIcon
|
|
38
39
|
active={tab === SidebarTabKey.Market}
|
|
39
40
|
icon={Compass}
|
|
@@ -25,6 +25,9 @@ export const AgentRuntimeErrorType = {
|
|
|
25
25
|
|
|
26
26
|
InvalidOllamaArgs: 'InvalidOllamaArgs',
|
|
27
27
|
OllamaBizError: 'OllamaBizError',
|
|
28
|
+
|
|
29
|
+
InvalidPerplexityAPIKey: 'InvalidPerplexityAPIKey',
|
|
30
|
+
PerplexityBizError: 'PerplexityBizError',
|
|
28
31
|
} as const;
|
|
29
32
|
|
|
30
33
|
export type ILobeAgentRuntimeErrorType =
|
|
@@ -6,6 +6,7 @@ export { LobeGoogleAI } from './google';
|
|
|
6
6
|
export { LobeMoonshotAI } from './moonshot';
|
|
7
7
|
export { LobeOllamaAI } from './ollama';
|
|
8
8
|
export { LobeOpenAI } from './openai';
|
|
9
|
+
export { LobePerplexityAI } from './perplexity';
|
|
9
10
|
export * from './types';
|
|
10
11
|
export { AgentRuntimeError } from './utils/createError';
|
|
11
12
|
export { LobeZhipuAI } from './zhipu';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { OpenAIStream, StreamingTextResponse } from 'ai';
|
|
2
|
+
import OpenAI from 'openai';
|
|
3
|
+
|
|
4
|
+
import { LobeRuntimeAI } from '../BaseAI';
|
|
5
|
+
import { AgentRuntimeErrorType } from '../error';
|
|
6
|
+
import { ChatStreamPayload, ModelProvider } from '../types';
|
|
7
|
+
import { AgentRuntimeError } from '../utils/createError';
|
|
8
|
+
import { debugStream } from '../utils/debugStream';
|
|
9
|
+
import { desensitizeUrl } from '../utils/desensitizeUrl';
|
|
10
|
+
import { DEBUG_CHAT_COMPLETION } from '../utils/env';
|
|
11
|
+
import { handleOpenAIError } from '../utils/handleOpenAIError';
|
|
12
|
+
|
|
13
|
+
const DEFAULT_BASE_URL = 'https://api.perplexity.ai';
|
|
14
|
+
|
|
15
|
+
export class LobePerplexityAI implements LobeRuntimeAI {
|
|
16
|
+
private _llm: OpenAI;
|
|
17
|
+
|
|
18
|
+
baseURL: string;
|
|
19
|
+
|
|
20
|
+
constructor(apiKey?: string, baseURL: string = DEFAULT_BASE_URL) {
|
|
21
|
+
if (!apiKey) throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidPerplexityAPIKey);
|
|
22
|
+
|
|
23
|
+
this._llm = new OpenAI({ apiKey, baseURL });
|
|
24
|
+
this.baseURL = this._llm.baseURL;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async chat(payload: ChatStreamPayload) {
|
|
28
|
+
try {
|
|
29
|
+
// Set a default frequency penalty value greater than 0
|
|
30
|
+
const defaultFrequencyPenalty = 0.1;
|
|
31
|
+
const chatPayload = {
|
|
32
|
+
...payload,
|
|
33
|
+
frequency_penalty: payload.frequency_penalty || defaultFrequencyPenalty,
|
|
34
|
+
};
|
|
35
|
+
const response = await this._llm.chat.completions.create(
|
|
36
|
+
chatPayload as unknown as OpenAI.ChatCompletionCreateParamsStreaming,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const stream = OpenAIStream(response);
|
|
40
|
+
|
|
41
|
+
const [debug, returnStream] = stream.tee();
|
|
42
|
+
|
|
43
|
+
if (DEBUG_CHAT_COMPLETION) {
|
|
44
|
+
debugStream(debug).catch(console.error);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return new StreamingTextResponse(returnStream);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
let desensitizedEndpoint = this.baseURL;
|
|
50
|
+
|
|
51
|
+
if (this.baseURL !== DEFAULT_BASE_URL) {
|
|
52
|
+
desensitizedEndpoint = desensitizeUrl(this.baseURL);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if ('status' in (error as any)) {
|
|
56
|
+
switch ((error as Response).status) {
|
|
57
|
+
case 401: {
|
|
58
|
+
throw AgentRuntimeError.chat({
|
|
59
|
+
endpoint: desensitizedEndpoint,
|
|
60
|
+
error: error as any,
|
|
61
|
+
errorType: AgentRuntimeErrorType.InvalidPerplexityAPIKey,
|
|
62
|
+
provider: ModelProvider.Perplexity,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
default: {
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const { errorResult, RuntimeError } = handleOpenAIError(error);
|
|
73
|
+
|
|
74
|
+
const errorType = RuntimeError || AgentRuntimeErrorType.PerplexityBizError;
|
|
75
|
+
|
|
76
|
+
throw AgentRuntimeError.chat({
|
|
77
|
+
endpoint: desensitizedEndpoint,
|
|
78
|
+
error: errorResult,
|
|
79
|
+
errorType,
|
|
80
|
+
provider: ModelProvider.Perplexity,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default LobePerplexityAI;
|
|
@@ -73,6 +73,9 @@ export default {
|
|
|
73
73
|
InvalidAzureAPIKey: 'Azure API Key 不正确或为空,请检查 Azure API Key 后重试',
|
|
74
74
|
AzureBizError: '请求 Azure AI 服务出错,请根据以下信息排查或重试',
|
|
75
75
|
|
|
76
|
+
InvalidPerplexityAPIKey: 'Perplexity API Key 不正确或为空,请检查 Perplexity API Key 后重试',
|
|
77
|
+
PerplexityBizError: '请求 Perplexity AI 服务出错,请根据以下信息排查或重试',
|
|
78
|
+
|
|
76
79
|
InvalidOllamaArgs: 'Ollama 配置不正确,请检查 Ollama 配置后重试',
|
|
77
80
|
OllamaBizError: '请求 Ollama 服务出错,请根据以下信息排查或重试',
|
|
78
81
|
|
|
@@ -106,6 +109,10 @@ export default {
|
|
|
106
109
|
description: '输入你的 OpenAI API Key 即可开始会话。应用不会记录你的 API Key',
|
|
107
110
|
title: '使用自定义 OpenAI API Key',
|
|
108
111
|
},
|
|
112
|
+
Perplexity: {
|
|
113
|
+
description: '输入你的 Perplexity API Key 即可开始会话。应用不会记录你的 API Key',
|
|
114
|
+
title: '使用自定义 Perplexity API Key',
|
|
115
|
+
},
|
|
109
116
|
Zhipu: {
|
|
110
117
|
description: '输入你的 Zhipu API Key 即可开始会话。应用不会记录你的 API Key',
|
|
111
118
|
title: '使用自定义 Zhipu API Key',
|
|
@@ -139,6 +139,14 @@ export default {
|
|
|
139
139
|
title: 'Azure OpenAI',
|
|
140
140
|
},
|
|
141
141
|
},
|
|
142
|
+
Perplexity: {
|
|
143
|
+
title: 'Perplexity',
|
|
144
|
+
token: {
|
|
145
|
+
desc: '填入来自 Perplexity AI 的 API Key',
|
|
146
|
+
placeholder: 'Perplexity AI API Key',
|
|
147
|
+
title: 'API Key',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
142
150
|
Zhipu: {
|
|
143
151
|
title: '智谱',
|
|
144
152
|
token: {
|
package/src/services/_auth.ts
CHANGED
|
@@ -48,6 +48,10 @@ export const getProviderAuthPayload = (provider: string) => {
|
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
case ModelProvider.Perplexity: {
|
|
52
|
+
return { apiKey: modelProviderSelectors.perplexityAPIKey(useGlobalStore.getState()) };
|
|
53
|
+
}
|
|
54
|
+
|
|
51
55
|
default:
|
|
52
56
|
case ModelProvider.OpenAI: {
|
|
53
57
|
const openai = modelProviderSelectors.openAIConfig(useGlobalStore.getState());
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
MoonshotProvider,
|
|
8
8
|
OllamaProvider,
|
|
9
9
|
OpenAIProvider,
|
|
10
|
+
PerplexityProvider,
|
|
10
11
|
ZhiPuProvider,
|
|
11
12
|
} from '@/config/modelProviders';
|
|
12
13
|
import { ChatModelCard, ModelProviderCard } from '@/types/llm';
|
|
@@ -48,6 +49,9 @@ const enableOllamaConfigInSettings = (s: GlobalStore) =>
|
|
|
48
49
|
const enableOllama = (s: GlobalStore) => modelProvider(s).ollama.enabled;
|
|
49
50
|
const ollamaProxyUrl = (s: GlobalStore) => modelProvider(s).ollama.endpoint;
|
|
50
51
|
|
|
52
|
+
const enablePerplexity = (s: GlobalStore) => modelProvider(s).perplexity.enabled;
|
|
53
|
+
const perplexityAPIKey = (s: GlobalStore) => modelProvider(s).perplexity.apiKey;
|
|
54
|
+
|
|
51
55
|
// const azureModelList = (s: GlobalStore): ModelProviderCard => {
|
|
52
56
|
// const azure = azureConfig(s);
|
|
53
57
|
// return {
|
|
@@ -133,6 +137,7 @@ const modelSelectList = (s: GlobalStore): ModelProviderCard[] => {
|
|
|
133
137
|
{ ...GoogleProvider, enabled: enableGoogle(s) },
|
|
134
138
|
{ ...BedrockProvider, enabled: enableBedrock(s) },
|
|
135
139
|
{ ...OllamaProvider, chatModels: ollamaChatModels, enabled: enableOllama(s) },
|
|
140
|
+
{ ...PerplexityProvider, enabled: enablePerplexity(s) },
|
|
136
141
|
];
|
|
137
142
|
};
|
|
138
143
|
|
|
@@ -203,4 +208,8 @@ export const modelProviderSelectors = {
|
|
|
203
208
|
enableOllamaConfigInSettings,
|
|
204
209
|
enableOllama,
|
|
205
210
|
ollamaProxyUrl,
|
|
211
|
+
|
|
212
|
+
// Perplexity
|
|
213
|
+
enablePerplexity,
|
|
214
|
+
perplexityAPIKey,
|
|
206
215
|
};
|
|
@@ -54,6 +54,12 @@ export interface OllamaConfig {
|
|
|
54
54
|
endpoint?: string;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
export interface PerplexityConfig {
|
|
58
|
+
apiKey?: string;
|
|
59
|
+
enabled: boolean;
|
|
60
|
+
endpoint?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
57
63
|
export interface GlobalLLMConfig {
|
|
58
64
|
azure: AzureOpenAIConfig;
|
|
59
65
|
bedrock: AWSBedrockConfig;
|
|
@@ -61,6 +67,7 @@ export interface GlobalLLMConfig {
|
|
|
61
67
|
moonshot: MoonshotConfig;
|
|
62
68
|
ollama: OllamaConfig;
|
|
63
69
|
openAI: OpenAIConfig;
|
|
70
|
+
perplexity: PerplexityConfig;
|
|
64
71
|
zhipu: ZhiPuConfig;
|
|
65
72
|
}
|
|
66
73
|
|