@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 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
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#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
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.38.0",
3
+ "version": "0.39.1",
4
4
  "description": "Lobe Chat is an open-source chatbot client using LangChain, Typescript and Next.js",
5
5
  "keywords": [
6
6
  "chatbot",
@@ -1,3 +1,5 @@
1
+ export const OPENAI_END_POINT = 'X-OPENAI-END_POINT';
2
+
1
3
  export const OPENAI_API_KEY_HEADER_KEY = 'X-OPENAI-API-KEY';
2
4
 
3
5
  export const LOBE_CHAT_ACCESS_CODE = 'X-LOBE_CHAT_ACCESS_CODE';
@@ -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
  }
@@ -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
- return new OpenAIApi(config, isDev && OPENAI_PROXY_URL ? OPENAI_PROXY_URL : undefined);
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(JSON.parse(function_call?.arguments || '{}'), null, 2);
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 && <Highlighter language={'json'}>{args}</Highlighter>}
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 <PluginResult content={content} />;
40
+ return null;
43
41
  });
44
42
 
45
43
  export default PluginMessage;
@@ -1,21 +1,11 @@
1
- import { Avatar, Highlighter, Icon } from '@lobehub/ui';
2
- import { LucideChevronDown, LucideChevronUp } from 'lucide-react';
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
- <Flexbox gap={8}>
29
- <Flexbox
30
- align={'center'}
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, generateMessage } = get();
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
- dispatchMessage({ id: mid, message: LOADING_FLAT, role: 'assistant', type: 'addMessage' });
329
-
330
- await generateMessage(chats, mid);
326
+ await realFetchAIResponse(chats, message.id);
331
327
  },
332
328
  });