@lobehub/chat 0.38.0 → 0.39.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 +59 -0
- package/package.json +1 -1
- package/src/const/fetch.ts +2 -0
- package/src/locales/default/plugin.ts +6 -0
- package/src/pages/api/openai.api.ts +3 -2
- package/src/pages/api/openai.ts +7 -5
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/FunctionCall.tsx +27 -3
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/PluginMessage.tsx +1 -3
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/PluginResultRender.tsx +5 -32
- package/src/pages/chat/[id]/Conversation/ChatList/index.tsx +2 -0
- package/src/services/chatModel.ts +2 -1
- package/src/store/session/slices/chat/actions/message.ts +2 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,65 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.39.1](https://github.com/lobehub/lobe-chat/compare/v0.39.0...v0.39.1)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-08-04**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: 修正 basePath 在生产环境下不生效的问题.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: 修正 basePath 在生产环境下不生效的问题 ([71b9139](https://github.com/lobehub/lobe-chat/commit/71b9139))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 0.39.0](https://github.com/lobehub/lobe-chat/compare/v0.38.0...v0.39.0)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2023-08-04**</sup>
|
|
33
|
+
|
|
34
|
+
#### ✨ Features
|
|
35
|
+
|
|
36
|
+
- **misc**: 支持多轮的插件意图识别, 支持自定义 OpenAI 代理地址.
|
|
37
|
+
|
|
38
|
+
#### 💄 Styles
|
|
39
|
+
|
|
40
|
+
- **misc**: 优化插件的展示逻辑.
|
|
41
|
+
|
|
42
|
+
<br/>
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
46
|
+
|
|
47
|
+
#### What's improved
|
|
48
|
+
|
|
49
|
+
- **misc**: 支持多轮的插件意图识别 ([5127f1b](https://github.com/lobehub/lobe-chat/commit/5127f1b))
|
|
50
|
+
- **misc**: 支持自定义 OpenAI 代理地址 ([33a111c](https://github.com/lobehub/lobe-chat/commit/33a111c))
|
|
51
|
+
|
|
52
|
+
#### Styles
|
|
53
|
+
|
|
54
|
+
- **misc**: 优化插件的展示逻辑 ([7621bad](https://github.com/lobehub/lobe-chat/commit/7621bad))
|
|
55
|
+
|
|
56
|
+
</details>
|
|
57
|
+
|
|
58
|
+
<div align="right">
|
|
59
|
+
|
|
60
|
+
[](#readme-top)
|
|
61
|
+
|
|
62
|
+
</div>
|
|
63
|
+
|
|
5
64
|
## [Version 0.38.0](https://github.com/lobehub/lobe-chat/compare/v0.37.0...v0.38.0)
|
|
6
65
|
|
|
7
66
|
<sup>Released on **2023-08-04**</sup>
|
package/package.json
CHANGED
package/src/const/fetch.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export default {
|
|
2
|
+
debug: {
|
|
3
|
+
arguments: '调用参数',
|
|
4
|
+
function_call: '函数调用',
|
|
5
|
+
response: '返回结果',
|
|
6
|
+
},
|
|
2
7
|
loading: {
|
|
3
8
|
content: '数据获取中...',
|
|
4
9
|
plugin: '插件运行中...',
|
|
@@ -8,6 +13,7 @@ export default {
|
|
|
8
13
|
realtimeWeather: '实时天气预报',
|
|
9
14
|
searchEngine: '搜索引擎',
|
|
10
15
|
undefined: '插件检测中...',
|
|
16
|
+
|
|
11
17
|
websiteCrawler: '网页内容提取',
|
|
12
18
|
},
|
|
13
19
|
realtimeWeather: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LOBE_CHAT_ACCESS_CODE, OPENAI_API_KEY_HEADER_KEY } from '@/const/fetch';
|
|
1
|
+
import { LOBE_CHAT_ACCESS_CODE, OPENAI_API_KEY_HEADER_KEY, OPENAI_END_POINT } from '@/const/fetch';
|
|
2
2
|
import { ErrorType } from '@/types/fetch';
|
|
3
3
|
import { OpenAIStreamPayload } from '@/types/openai';
|
|
4
4
|
|
|
@@ -12,6 +12,7 @@ export default async function handler(req: Request) {
|
|
|
12
12
|
const payload = (await req.json()) as OpenAIStreamPayload;
|
|
13
13
|
const apiKey = req.headers.get(OPENAI_API_KEY_HEADER_KEY);
|
|
14
14
|
const accessCode = req.headers.get(LOBE_CHAT_ACCESS_CODE);
|
|
15
|
+
const endpoint = req.headers.get(OPENAI_END_POINT);
|
|
15
16
|
|
|
16
17
|
const result = checkAuth({ accessCode, apiKey });
|
|
17
18
|
|
|
@@ -19,5 +20,5 @@ export default async function handler(req: Request) {
|
|
|
19
20
|
return createErrorResponse(result.error as ErrorType);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
return createChatCompletion({ OPENAI_API_KEY: apiKey, payload });
|
|
23
|
+
return createChatCompletion({ OPENAI_API_KEY: apiKey, endpoint, payload });
|
|
23
24
|
}
|
package/src/pages/api/openai.ts
CHANGED
|
@@ -8,22 +8,23 @@ import { PluginsMap } from '@/plugins';
|
|
|
8
8
|
import { ErrorType } from '@/types/fetch';
|
|
9
9
|
import { OpenAIStreamPayload } from '@/types/openai';
|
|
10
10
|
|
|
11
|
-
const isDev = process.env.NODE_ENV === 'development';
|
|
12
|
-
|
|
13
11
|
// 创建 OpenAI 实例
|
|
14
|
-
export const createOpenAI = (userApiKey: string | null) => {
|
|
12
|
+
export const createOpenAI = (userApiKey: string | null, endpoint?: string | null) => {
|
|
15
13
|
const { OPENAI_API_KEY, OPENAI_PROXY_URL } = getServerConfig();
|
|
16
14
|
|
|
17
15
|
const config = new Configuration({
|
|
18
16
|
apiKey: !userApiKey ? OPENAI_API_KEY : userApiKey,
|
|
19
17
|
});
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
const basePath = endpoint ? endpoint : OPENAI_PROXY_URL ? OPENAI_PROXY_URL : undefined;
|
|
20
|
+
|
|
21
|
+
return new OpenAIApi(config, basePath);
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
interface CreateChatCompletionOptions {
|
|
25
25
|
OPENAI_API_KEY: string | null;
|
|
26
26
|
callbacks?: (payload: OpenAIStreamPayload) => OpenAIStreamCallbacks;
|
|
27
|
+
endpoint?: string | null;
|
|
27
28
|
payload: OpenAIStreamPayload;
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -31,10 +32,11 @@ export const createChatCompletion = async ({
|
|
|
31
32
|
payload,
|
|
32
33
|
callbacks,
|
|
33
34
|
OPENAI_API_KEY,
|
|
35
|
+
endpoint,
|
|
34
36
|
}: CreateChatCompletionOptions) => {
|
|
35
37
|
// ============ 0.创建 OpenAI 实例 ============ //
|
|
36
38
|
|
|
37
|
-
const openai = createOpenAI(OPENAI_API_KEY);
|
|
39
|
+
const openai = createOpenAI(OPENAI_API_KEY, endpoint);
|
|
38
40
|
|
|
39
41
|
const { messages, plugins: enabledPlugins, ...params } = payload;
|
|
40
42
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LoadingOutlined } from '@ant-design/icons';
|
|
2
2
|
import { Avatar, Highlighter, Icon } from '@lobehub/ui';
|
|
3
|
+
import { Tabs } from 'antd';
|
|
3
4
|
import { LucideChevronDown, LucideChevronUp, LucideToyBrick } from 'lucide-react';
|
|
4
5
|
import { memo, useState } from 'react';
|
|
5
6
|
import { useTranslation } from 'react-i18next';
|
|
@@ -8,14 +9,16 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
8
9
|
import { PluginsMap } from '@/plugins';
|
|
9
10
|
import { OpenAIFunctionCall } from '@/types/chatMessage';
|
|
10
11
|
|
|
12
|
+
import PluginResult from './PluginResultRender';
|
|
11
13
|
import { useStyles } from './style';
|
|
12
14
|
|
|
13
15
|
export interface FunctionCallProps {
|
|
16
|
+
content: string;
|
|
14
17
|
function_call?: OpenAIFunctionCall;
|
|
15
18
|
loading?: boolean;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
const FunctionCall = memo<FunctionCallProps>(({ function_call, loading }) => {
|
|
21
|
+
const FunctionCall = memo<FunctionCallProps>(({ function_call, loading, content }) => {
|
|
19
22
|
const { t } = useTranslation('plugin');
|
|
20
23
|
const { styles } = useStyles();
|
|
21
24
|
const [open, setOpen] = useState(false);
|
|
@@ -28,7 +31,8 @@ const FunctionCall = memo<FunctionCallProps>(({ function_call, loading }) => {
|
|
|
28
31
|
<Icon icon={LucideToyBrick} />
|
|
29
32
|
);
|
|
30
33
|
|
|
31
|
-
const args = JSON.stringify(
|
|
34
|
+
const args = JSON.stringify(function_call, null, 2);
|
|
35
|
+
const params = JSON.stringify(JSON.parse(function_call?.arguments || '{}'), null, 2);
|
|
32
36
|
|
|
33
37
|
return (
|
|
34
38
|
<Flexbox gap={8}>
|
|
@@ -51,7 +55,27 @@ const FunctionCall = memo<FunctionCallProps>(({ function_call, loading }) => {
|
|
|
51
55
|
{t(`plugins.${function_call?.name}` as any, { ns: 'plugin' })}
|
|
52
56
|
<Icon icon={open ? LucideChevronUp : LucideChevronDown} />
|
|
53
57
|
</Flexbox>
|
|
54
|
-
{open &&
|
|
58
|
+
{open && (
|
|
59
|
+
<Tabs
|
|
60
|
+
items={[
|
|
61
|
+
{
|
|
62
|
+
children: <Highlighter language={'json'}>{args}</Highlighter>,
|
|
63
|
+
key: 'function_call',
|
|
64
|
+
label: t('debug.function_call'),
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
children: <Highlighter language={'json'}>{params}</Highlighter>,
|
|
68
|
+
key: 'arguments',
|
|
69
|
+
label: t('debug.arguments'),
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
children: <PluginResult content={content} />,
|
|
73
|
+
key: 'response',
|
|
74
|
+
label: t('debug.response'),
|
|
75
|
+
},
|
|
76
|
+
]}
|
|
77
|
+
/>
|
|
78
|
+
)}
|
|
55
79
|
</Flexbox>
|
|
56
80
|
);
|
|
57
81
|
});
|
|
@@ -6,8 +6,6 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
6
6
|
import { PluginsRender } from '@/plugins/Render';
|
|
7
7
|
import { ChatMessage } from '@/types/chatMessage';
|
|
8
8
|
|
|
9
|
-
import PluginResult from './PluginResultRender';
|
|
10
|
-
|
|
11
9
|
export interface FunctionMessageProps extends ChatMessage {
|
|
12
10
|
loading?: boolean;
|
|
13
11
|
}
|
|
@@ -39,7 +37,7 @@ const PluginMessage = memo<FunctionMessageProps>(({ content, name }) => {
|
|
|
39
37
|
return <Render content={JSON.parse(content)} name={name || 'unknown'} />;
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
return
|
|
40
|
+
return null;
|
|
43
41
|
});
|
|
44
42
|
|
|
45
43
|
export default PluginMessage;
|
|
@@ -1,21 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { memo, useState } from 'react';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
|
-
|
|
7
|
-
import { useStyles } from './style';
|
|
1
|
+
import { Highlighter } from '@lobehub/ui';
|
|
2
|
+
import { memo } from 'react';
|
|
8
3
|
|
|
9
4
|
export interface FunctionMessageProps {
|
|
10
5
|
content: string;
|
|
11
6
|
}
|
|
12
7
|
|
|
13
8
|
const PluginResult = memo<FunctionMessageProps>(({ content }) => {
|
|
14
|
-
const { t } = useTranslation('plugin');
|
|
15
|
-
const { styles } = useStyles();
|
|
16
|
-
|
|
17
|
-
const [open, setOpen] = useState(false);
|
|
18
|
-
|
|
19
9
|
let data;
|
|
20
10
|
|
|
21
11
|
try {
|
|
@@ -25,26 +15,9 @@ const PluginResult = memo<FunctionMessageProps>(({ content }) => {
|
|
|
25
15
|
}
|
|
26
16
|
|
|
27
17
|
return (
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
className={styles.container}
|
|
32
|
-
gap={8}
|
|
33
|
-
horizontal
|
|
34
|
-
onClick={() => {
|
|
35
|
-
setOpen(!open);
|
|
36
|
-
}}
|
|
37
|
-
>
|
|
38
|
-
<Avatar avatar={'💾'} size={24} />
|
|
39
|
-
{t('responseData')}
|
|
40
|
-
<Icon icon={open ? LucideChevronUp : LucideChevronDown} />
|
|
41
|
-
</Flexbox>
|
|
42
|
-
{open && (
|
|
43
|
-
<Highlighter language={'json'} style={{ maxHeight: 200, maxWidth: 600 }}>
|
|
44
|
-
{data}
|
|
45
|
-
</Highlighter>
|
|
46
|
-
)}
|
|
47
|
-
</Flexbox>
|
|
18
|
+
<Highlighter language={'json'} style={{ maxHeight: 200, maxWidth: 800 }}>
|
|
19
|
+
{data}
|
|
20
|
+
</Highlighter>
|
|
48
21
|
);
|
|
49
22
|
});
|
|
50
23
|
|
|
@@ -48,6 +48,7 @@ const List = () => {
|
|
|
48
48
|
return (
|
|
49
49
|
<Flexbox gap={12}>
|
|
50
50
|
<FunctionCall
|
|
51
|
+
content={message.content}
|
|
51
52
|
function_call={message.function_call}
|
|
52
53
|
loading={message.id === chatLoadingId}
|
|
53
54
|
/>
|
|
@@ -58,6 +59,7 @@ const List = () => {
|
|
|
58
59
|
if (message.role === 'assistant') {
|
|
59
60
|
return isFunctionMessage(message.content) || !!message.function_call ? (
|
|
60
61
|
<FunctionCall
|
|
62
|
+
content={message.content}
|
|
61
63
|
function_call={message.function_call}
|
|
62
64
|
loading={message.id === chatLoadingId}
|
|
63
65
|
/>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { merge } from 'lodash-es';
|
|
2
2
|
|
|
3
|
-
import { LOBE_CHAT_ACCESS_CODE, OPENAI_API_KEY_HEADER_KEY } from '@/const/fetch';
|
|
3
|
+
import { LOBE_CHAT_ACCESS_CODE, OPENAI_API_KEY_HEADER_KEY, OPENAI_END_POINT } from '@/const/fetch';
|
|
4
4
|
import { initialLobeAgentConfig } from '@/store/session';
|
|
5
5
|
import { useSettings } from '@/store/settings';
|
|
6
6
|
import type { OpenAIStreamPayload } from '@/types/openai';
|
|
@@ -33,6 +33,7 @@ export const fetchChatModel = (
|
|
|
33
33
|
'Content-Type': 'application/json',
|
|
34
34
|
[LOBE_CHAT_ACCESS_CODE]: useSettings.getState().settings.password || '',
|
|
35
35
|
[OPENAI_API_KEY_HEADER_KEY]: useSettings.getState().settings.OPENAI_API_KEY || '',
|
|
36
|
+
[OPENAI_END_POINT]: useSettings.getState().settings.endpoint || '',
|
|
36
37
|
},
|
|
37
38
|
method: 'POST',
|
|
38
39
|
signal: options?.signal,
|
|
@@ -282,7 +282,7 @@ export const chatMessage: StateCreator<
|
|
|
282
282
|
},
|
|
283
283
|
|
|
284
284
|
triggerFunctionCall: async (id) => {
|
|
285
|
-
const { dispatchMessage,
|
|
285
|
+
const { dispatchMessage, realFetchAIResponse } = get();
|
|
286
286
|
const session = sessionSelectors.currentSession(get());
|
|
287
287
|
|
|
288
288
|
if (!session) return;
|
|
@@ -321,12 +321,8 @@ export const chatMessage: StateCreator<
|
|
|
321
321
|
|
|
322
322
|
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: data });
|
|
323
323
|
|
|
324
|
-
const mid = nanoid();
|
|
325
|
-
|
|
326
324
|
const chats = chatSelectors.currentChats(get());
|
|
327
325
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
await generateMessage(chats, mid);
|
|
326
|
+
await realFetchAIResponse(chats, message.id);
|
|
331
327
|
},
|
|
332
328
|
});
|