@lobehub/chat 1.51.1 → 1.51.3

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/Dockerfile +1 -1
  3. package/Dockerfile.database +1 -1
  4. package/changelog/v1.json +21 -0
  5. package/docs/usage/providers/wenxin.mdx +16 -13
  6. package/docs/usage/providers/wenxin.zh-CN.mdx +11 -8
  7. package/next.config.ts +6 -0
  8. package/package.json +1 -2
  9. package/src/app/(main)/settings/llm/ProviderList/providers.tsx +2 -4
  10. package/src/config/aiModels/ai360.ts +22 -2
  11. package/src/config/aiModels/fireworksai.ts +3 -0
  12. package/src/config/aiModels/giteeai.ts +60 -0
  13. package/src/config/aiModels/github.ts +7 -0
  14. package/src/config/aiModels/google.ts +2 -0
  15. package/src/config/aiModels/groq.ts +12 -0
  16. package/src/config/aiModels/huggingface.ts +6 -0
  17. package/src/config/aiModels/internlm.ts +19 -2
  18. package/src/config/aiModels/ollama.ts +1 -0
  19. package/src/config/aiModels/openai.ts +10 -0
  20. package/src/config/aiModels/perplexity.ts +3 -0
  21. package/src/config/aiModels/qwen.ts +2 -0
  22. package/src/config/aiModels/siliconcloud.ts +4 -0
  23. package/src/config/aiModels/togetherai.ts +64 -1
  24. package/src/config/aiModels/wenxin.ts +125 -19
  25. package/src/config/aiModels/zhipu.ts +3 -0
  26. package/src/config/llm.ts +3 -5
  27. package/src/config/modelProviders/wenxin.ts +100 -23
  28. package/src/const/auth.ts +0 -3
  29. package/src/features/Conversation/Error/APIKeyForm/index.tsx +0 -3
  30. package/src/features/Conversation/components/ChatItem/utils.test.ts +284 -0
  31. package/src/features/Conversation/components/ChatItem/utils.ts +39 -8
  32. package/src/features/Conversation/components/MarkdownElements/LobeArtifact/rehypePlugin.test.ts +125 -0
  33. package/src/features/DevPanel/CacheViewer/DataTable/index.tsx +33 -0
  34. package/src/features/DevPanel/CacheViewer/cacheProvider.tsx +64 -0
  35. package/src/features/DevPanel/CacheViewer/getCacheEntries.ts +52 -0
  36. package/src/features/DevPanel/CacheViewer/index.tsx +25 -0
  37. package/src/features/DevPanel/CacheViewer/schema.ts +49 -0
  38. package/src/features/DevPanel/FeatureFlagViewer/Form.tsx +93 -0
  39. package/src/features/DevPanel/FeatureFlagViewer/index.tsx +11 -0
  40. package/src/features/DevPanel/MetadataViewer/Ld.tsx +25 -0
  41. package/src/features/DevPanel/MetadataViewer/MetaData.tsx +30 -0
  42. package/src/features/DevPanel/MetadataViewer/Og.tsx +75 -0
  43. package/src/features/DevPanel/MetadataViewer/index.tsx +80 -0
  44. package/src/features/DevPanel/MetadataViewer/useHead.ts +16 -0
  45. package/src/features/DevPanel/PostgresViewer/DataTable/index.tsx +39 -49
  46. package/src/features/DevPanel/PostgresViewer/{TableColumns.tsx → SchemaSidebar/Columns.tsx} +6 -4
  47. package/src/features/DevPanel/PostgresViewer/{Schema.tsx → SchemaSidebar/index.tsx} +49 -55
  48. package/src/features/DevPanel/PostgresViewer/index.tsx +4 -2
  49. package/src/features/DevPanel/features/FloatPanel.tsx +218 -0
  50. package/src/features/DevPanel/features/Header.tsx +50 -0
  51. package/src/features/DevPanel/features/Table/TableCell.tsx +73 -0
  52. package/src/features/DevPanel/features/Table/TooltipContent.tsx +39 -0
  53. package/src/features/DevPanel/{PostgresViewer/DataTable/Table.tsx → features/Table/index.tsx} +12 -14
  54. package/src/features/DevPanel/index.tsx +29 -5
  55. package/src/libs/agent-runtime/AgentRuntime.test.ts +0 -1
  56. package/src/libs/agent-runtime/AgentRuntime.ts +7 -0
  57. package/src/libs/agent-runtime/wenxin/index.ts +10 -107
  58. package/src/locales/default/modelProvider.ts +0 -20
  59. package/src/server/modules/AgentRuntime/index.test.ts +0 -21
  60. package/src/services/_auth.ts +0 -14
  61. package/src/store/chat/slices/portal/selectors.test.ts +169 -3
  62. package/src/store/chat/slices/portal/selectors.ts +6 -1
  63. package/src/store/user/slices/modelList/selectors/keyVaults.ts +0 -2
  64. package/src/types/aiProvider.ts +0 -1
  65. package/src/types/user/settings/keyVaults.ts +1 -6
  66. package/src/app/(backend)/webapi/chat/wenxin/route.test.ts +0 -27
  67. package/src/app/(backend)/webapi/chat/wenxin/route.ts +0 -30
  68. package/src/app/(main)/settings/llm/ProviderList/Wenxin/index.tsx +0 -44
  69. package/src/app/(main)/settings/provider/(detail)/wenxin/page.tsx +0 -61
  70. package/src/features/Conversation/Error/APIKeyForm/Wenxin.tsx +0 -49
  71. package/src/features/DevPanel/FloatPanel.tsx +0 -136
  72. package/src/features/DevPanel/PostgresViewer/DataTable/TableCell.tsx +0 -34
  73. package/src/libs/agent-runtime/utils/streams/wenxin.test.ts +0 -153
  74. package/src/libs/agent-runtime/utils/streams/wenxin.ts +0 -38
  75. package/src/libs/agent-runtime/wenxin/type.ts +0 -84
@@ -0,0 +1,218 @@
1
+ 'use client';
2
+
3
+ import { ActionIcon, FluentEmoji, Icon, SideNav } from '@lobehub/ui';
4
+ import { Dropdown, FloatButton } from 'antd';
5
+ import { createStyles } from 'antd-style';
6
+ import { BugIcon, BugOff, XIcon } from 'lucide-react';
7
+ import { ReactNode, memo, useEffect, useState } from 'react';
8
+ import { Flexbox } from 'react-layout-kit';
9
+ import { Rnd } from 'react-rnd';
10
+
11
+ import { BRANDING_NAME } from '@/const/branding';
12
+
13
+ // 定义样式
14
+ const useStyles = createStyles(({ token, css, prefixCls }) => {
15
+ return {
16
+ collapsed: css`
17
+ pointer-events: none;
18
+ transform: scale(0.8);
19
+ opacity: 0;
20
+ `,
21
+ expanded: css`
22
+ pointer-events: auto;
23
+ transform: scale(1);
24
+ opacity: 1;
25
+ `,
26
+ floatButton: css`
27
+ inset-block-end: 16px;
28
+ inset-inline-end: 16px;
29
+
30
+ width: 36px;
31
+ height: 36px;
32
+ border: 1px solid ${token.colorBorderSecondary};
33
+
34
+ font-size: 20px;
35
+ .${prefixCls}-float-btn-body {
36
+ background: ${token.colorBgLayout};
37
+
38
+ &:hover {
39
+ width: auto;
40
+ background: ${token.colorBgElevated};
41
+ }
42
+ }
43
+ `,
44
+ header: css`
45
+ cursor: move;
46
+ user-select: none;
47
+
48
+ padding-block: 8px;
49
+ padding-inline: 16px;
50
+ border-block-end: 1px solid ${token.colorBorderSecondary};
51
+
52
+ color: ${token.colorText};
53
+
54
+ background: ${token.colorFillAlter};
55
+ `,
56
+ panel: css`
57
+ position: fixed;
58
+ z-index: 1000;
59
+
60
+ overflow: hidden;
61
+ display: flex;
62
+
63
+ border: 1px solid ${token.colorBorderSecondary};
64
+ border-radius: 12px;
65
+
66
+ background: ${token.colorBgContainer};
67
+ box-shadow: ${token.boxShadow};
68
+
69
+ transition: opacity ${token.motionDurationMid} ${token.motionEaseInOut};
70
+ `,
71
+ };
72
+ });
73
+
74
+ const minWidth = 800;
75
+ const minHeight = 600;
76
+
77
+ interface CollapsibleFloatPanelProps {
78
+ items: { children: ReactNode; icon: ReactNode; key: string }[];
79
+ }
80
+
81
+ const CollapsibleFloatPanel = memo<CollapsibleFloatPanelProps>(({ items }) => {
82
+ const { styles, theme } = useStyles();
83
+ const [tab, setTab] = useState<string>(items[0].key);
84
+ const [isHide, setIsHide] = useState(false);
85
+ const [isExpanded, setIsExpanded] = useState(false);
86
+ const [position, setPosition] = useState({ x: 100, y: 100 });
87
+ const [size, setSize] = useState({ height: minHeight, width: minWidth });
88
+
89
+ useEffect(() => {
90
+ try {
91
+ const localStoragePosition = localStorage.getItem('debug-panel-position');
92
+ if (localStoragePosition && JSON.parse(localStoragePosition)) {
93
+ setPosition(JSON.parse(localStoragePosition));
94
+ }
95
+ } catch {
96
+ /* empty */
97
+ }
98
+
99
+ try {
100
+ const localStorageSize = localStorage.getItem('debug-panel-size');
101
+ if (localStorageSize && JSON.parse(localStorageSize)) {
102
+ setSize(JSON.parse(localStorageSize));
103
+ }
104
+ } catch {
105
+ /* empty */
106
+ }
107
+ }, []);
108
+
109
+ return (
110
+ <>
111
+ {!isHide && (
112
+ <Dropdown
113
+ menu={{
114
+ items: [
115
+ {
116
+ icon: (
117
+ <Icon color={theme.colorTextSecondary} icon={BugOff} size={{ fontSize: 16 }} />
118
+ ),
119
+ key: 'hide',
120
+ label: 'Hide Toolbar',
121
+ onClick: () => setIsHide(true),
122
+ },
123
+ ],
124
+ }}
125
+ trigger={['hover']}
126
+ >
127
+ <FloatButton
128
+ className={styles.floatButton}
129
+ icon={<Icon icon={isExpanded ? BugOff : BugIcon} />}
130
+ onClick={() => setIsExpanded(!isExpanded)}
131
+ />
132
+ </Dropdown>
133
+ )}
134
+ {isExpanded && (
135
+ <Rnd
136
+ bounds="window"
137
+ className={`${styles.panel} ${isExpanded ? styles.expanded : styles.collapsed}`}
138
+ dragHandleClassName="panel-drag-handle"
139
+ minHeight={minHeight}
140
+ minWidth={minWidth}
141
+ onDragStop={(e, d) => {
142
+ setPosition({ x: d.x, y: d.y });
143
+ }}
144
+ onResizeStop={(e, direction, ref, delta, position) => {
145
+ setSize({
146
+ height: Number(ref.style.height),
147
+ width: Number(ref.style.width),
148
+ });
149
+ setPosition(position);
150
+ }}
151
+ position={position}
152
+ size={size}
153
+ >
154
+ <Flexbox
155
+ height={'100%'}
156
+ horizontal
157
+ style={{ overflow: 'hidden', position: 'relative' }}
158
+ width={'100%'}
159
+ >
160
+ <SideNav
161
+ avatar={<FluentEmoji emoji={'🧰'} size={24} />}
162
+ bottomActions={[]}
163
+ style={{
164
+ paddingBlock: 12,
165
+ width: 48,
166
+ }}
167
+ topActions={items.map((item) => (
168
+ <ActionIcon
169
+ active={tab === item.key}
170
+ key={item.key}
171
+ onClick={() => setTab(item.key)}
172
+ placement={'right'}
173
+ title={item.key}
174
+ >
175
+ {item.icon}
176
+ </ActionIcon>
177
+ ))}
178
+ />
179
+ <Flexbox
180
+ height={'100%'}
181
+ style={{ overflow: 'hidden', position: 'relative' }}
182
+ width={'100%'}
183
+ >
184
+ <Flexbox
185
+ align={'center'}
186
+ className={`panel-drag-handle ${styles.header}`}
187
+ horizontal
188
+ justify={'space-between'}
189
+ >
190
+ <Flexbox align={'baseline'} gap={6} horizontal>
191
+ <b>{BRANDING_NAME} Dev Tools</b>
192
+ <span style={{ color: theme.colorTextDescription }}>/</span>
193
+ <span style={{ color: theme.colorTextDescription }}>{tab}</span>
194
+ </Flexbox>
195
+ <ActionIcon icon={XIcon} onClick={() => setIsExpanded(false)} />
196
+ </Flexbox>
197
+ {items.map((item) => (
198
+ <Flexbox
199
+ flex={1}
200
+ height={'100%'}
201
+ key={item.key}
202
+ style={{
203
+ display: tab === item.key ? 'flex' : 'none',
204
+ overflow: 'hidden',
205
+ }}
206
+ >
207
+ {item.children}
208
+ </Flexbox>
209
+ ))}
210
+ </Flexbox>
211
+ </Flexbox>
212
+ </Rnd>
213
+ )}
214
+ </>
215
+ );
216
+ });
217
+
218
+ export default CollapsibleFloatPanel;
@@ -0,0 +1,50 @@
1
+ import { ActionIcon, type ActionIconProps } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import React, { ReactNode } from 'react';
4
+ import { Flexbox, FlexboxProps } from 'react-layout-kit';
5
+
6
+ const useStyles = createStyles(({ token, css }) => ({
7
+ header: css`
8
+ border-block-end: 1px solid ${token.colorBorderSecondary};
9
+ `,
10
+ title: css`
11
+ font-weight: 550;
12
+ `,
13
+ }));
14
+
15
+ interface HeaderProps extends Omit<FlexboxProps, 'title' | 'children'> {
16
+ actions?: ActionIconProps[];
17
+ extra?: ReactNode;
18
+ title?: ReactNode;
19
+ }
20
+
21
+ const Header = ({ title, actions = [], extra, ...rest }: HeaderProps) => {
22
+ const { styles } = useStyles();
23
+
24
+ return (
25
+ <Flexbox
26
+ align={'center'}
27
+ className={styles.header}
28
+ flex={'none'}
29
+ height={46}
30
+ horizontal
31
+ justify={'space-between'}
32
+ paddingInline={16}
33
+ {...rest}
34
+ >
35
+ <div className={styles.title}>{title}</div>
36
+ <Flexbox align={'center'} gap={4} horizontal>
37
+ {extra}
38
+ {actions.map((action, index) => (
39
+ <ActionIcon
40
+ {...action}
41
+ key={action.title || index}
42
+ size={{ blockSize: 28, fontSize: 16 }}
43
+ />
44
+ ))}
45
+ </Flexbox>
46
+ </Flexbox>
47
+ );
48
+ };
49
+
50
+ export default Header;
@@ -0,0 +1,73 @@
1
+ import { Typography } from 'antd';
2
+ import { createStyles } from 'antd-style';
3
+ import dayjs from 'dayjs';
4
+ import { get, isDate } from 'lodash-es';
5
+ import React, { useMemo } from 'react';
6
+
7
+ import TooltipContent from './TooltipContent';
8
+
9
+ const { Text } = Typography;
10
+
11
+ const useStyles = createStyles(({ token, css }) => ({
12
+ cell: css`
13
+ font-family: ${token.fontFamilyCode};
14
+ font-size: ${token.fontSizeSM}px;
15
+ `,
16
+ tooltip: css`
17
+ border: 1px solid ${token.colorBorder};
18
+
19
+ font-family: ${token.fontFamilyCode};
20
+ font-size: ${token.fontSizeSM}px;
21
+ color: ${token.colorText} !important;
22
+ word-break: break-all;
23
+
24
+ background: ${token.colorBgElevated} !important;
25
+ `,
26
+ }));
27
+
28
+ interface TableCellProps {
29
+ column: string;
30
+ dataItem: any;
31
+ rowIndex: number;
32
+ }
33
+
34
+ const TableCell = ({ dataItem, column, rowIndex }: TableCellProps) => {
35
+ const { styles } = useStyles();
36
+ const data = get(dataItem, column);
37
+ const content = useMemo(() => {
38
+ if (isDate(data)) return dayjs(data).format('YYYY-MM-DD HH:mm:ss');
39
+
40
+ switch (typeof data) {
41
+ case 'object': {
42
+ return JSON.stringify(data);
43
+ }
44
+
45
+ case 'boolean': {
46
+ return data ? 'True' : 'False';
47
+ }
48
+
49
+ default: {
50
+ return data;
51
+ }
52
+ }
53
+ }, [data]);
54
+
55
+ return (
56
+ <td key={column} onDoubleClick={() => console.log('Edit cell:', rowIndex, column)}>
57
+ <Text
58
+ className={styles.cell}
59
+ ellipsis={{
60
+ tooltip: {
61
+ arrow: false,
62
+ classNames: { body: styles.tooltip },
63
+ title: <TooltipContent>{content}</TooltipContent>,
64
+ },
65
+ }}
66
+ >
67
+ {content}
68
+ </Text>
69
+ </td>
70
+ );
71
+ };
72
+
73
+ export default TableCell;
@@ -0,0 +1,39 @@
1
+ import { Highlighter } from '@lobehub/ui';
2
+ import Link from 'next/link';
3
+ import { ReactNode, memo } from 'react';
4
+ import { Flexbox } from 'react-layout-kit';
5
+
6
+ const TooltipContent = memo<{ children: ReactNode }>(({ children }) => {
7
+ if (typeof children !== 'string') return children;
8
+
9
+ if (children.startsWith('data:image')) {
10
+ return <img src={children} style={{ height: 'auto', maxWidth: '100%' }} />;
11
+ }
12
+
13
+ if (children.startsWith('http'))
14
+ return (
15
+ <Link href={children} target={'_blank'}>
16
+ {children}
17
+ </Link>
18
+ );
19
+
20
+ const code = children.trim().trimEnd();
21
+
22
+ if ((code.startsWith('{') && code.endsWith('}')) || (code.startsWith('[') && code.endsWith(']')))
23
+ return (
24
+ <Highlighter
25
+ language={'json'}
26
+ style={{
27
+ maxHeight: 400,
28
+ overflow: 'auto',
29
+ }}
30
+ type={'pure'}
31
+ >
32
+ {JSON.stringify(JSON.parse(code), null, 2)}
33
+ </Highlighter>
34
+ );
35
+
36
+ return <Flexbox>{children}</Flexbox>;
37
+ });
38
+
39
+ export default TooltipContent;
@@ -1,9 +1,10 @@
1
+ import { Icon } from '@lobehub/ui';
1
2
  import { createStyles } from 'antd-style';
3
+ import { Loader2Icon } from 'lucide-react';
2
4
  import React from 'react';
3
5
  import { Center } from 'react-layout-kit';
4
6
  import { TableVirtuoso } from 'react-virtuoso';
5
7
 
6
- import { usePgTable, useTableColumns } from '../usePgTable';
7
8
  import TableCell from './TableCell';
8
9
 
9
10
  const useStyles = createStyles(({ token, css }) => ({
@@ -88,24 +89,21 @@ const useStyles = createStyles(({ token, css }) => ({
88
89
  }));
89
90
 
90
91
  interface TableProps {
91
- tableName?: string;
92
+ columns: string[];
93
+ dataSource: any[];
94
+ loading?: boolean;
92
95
  }
93
96
 
94
- const Table = ({ tableName }: TableProps) => {
97
+ const Table = ({ columns, dataSource, loading }: TableProps) => {
95
98
  const { styles } = useStyles();
96
99
 
97
- const tableColumns = useTableColumns(tableName);
100
+ if (loading)
101
+ return (
102
+ <Center height={'100%'}>
103
+ <Icon icon={Loader2Icon} spin />
104
+ </Center>
105
+ );
98
106
 
99
- const tableData = usePgTable(tableName);
100
-
101
- const columns = tableColumns.data?.map((t) => t.name) || [];
102
- const isLoading = tableColumns.isLoading || tableData.isLoading;
103
-
104
- if (!tableName) return <Center height={'80%'}>Select a table to view data</Center>;
105
-
106
- if (isLoading) return <Center height={'80%'}>Loading...</Center>;
107
-
108
- const dataSource = tableData.data?.data || [];
109
107
  const header = (
110
108
  <tr>
111
109
  {columns.map((column) => (
@@ -1,12 +1,36 @@
1
- 'use client';
1
+ import { BookText, DatabaseIcon, FlagIcon, GlobeLockIcon } from 'lucide-react';
2
2
 
3
- import FloatPanel from './FloatPanel';
3
+ import CacheViewer from './CacheViewer';
4
+ import FeatureFlagViewer from './FeatureFlagViewer';
5
+ import MetadataViewer from './MetadataViewer';
4
6
  import PostgresViewer from './PostgresViewer';
7
+ import FloatPanel from './features/FloatPanel';
5
8
 
6
9
  const DevPanel = () => (
7
- <FloatPanel>
8
- <PostgresViewer />
9
- </FloatPanel>
10
+ <FloatPanel
11
+ items={[
12
+ {
13
+ children: <PostgresViewer />,
14
+ icon: <DatabaseIcon size={16} />,
15
+ key: 'Postgres Viewer',
16
+ },
17
+ {
18
+ children: <MetadataViewer />,
19
+ icon: <BookText size={16} />,
20
+ key: 'SEO Metadata',
21
+ },
22
+ {
23
+ children: <CacheViewer />,
24
+ icon: <GlobeLockIcon size={16} />,
25
+ key: 'NextJS Caches',
26
+ },
27
+ {
28
+ children: <FeatureFlagViewer />,
29
+ icon: <FlagIcon size={16} />,
30
+ key: 'Feature Flags',
31
+ },
32
+ ]}
33
+ />
10
34
  );
11
35
 
12
36
  export default DevPanel;
@@ -26,7 +26,6 @@ import {
26
26
  ModelProvider,
27
27
  } from '@/libs/agent-runtime';
28
28
  import { LobeStepfunAI } from '@/libs/agent-runtime/stepfun';
29
- import LobeWenxinAI from '@/libs/agent-runtime/wenxin';
30
29
  import { createTraceOptions } from '@/server/modules/AgentRuntime';
31
30
 
32
31
  import { AgentChatOptions } from './AgentRuntime';
@@ -47,6 +47,7 @@ import {
47
47
  TextToSpeechPayload,
48
48
  } from './types';
49
49
  import { LobeUpstageAI } from './upstage';
50
+ import { LobeWenxinAI } from './wenxin';
50
51
  import { LobeXAI } from './xai';
51
52
  import { LobeZeroOneAI } from './zeroone';
52
53
  import { LobeZhipuAI } from './zhipu';
@@ -167,6 +168,7 @@ class AgentRuntime {
167
168
  taichu: Partial<ClientOptions>;
168
169
  togetherai: Partial<ClientOptions>;
169
170
  upstage: Partial<ClientOptions>;
171
+ wenxin: Partial<ClientOptions>;
170
172
  xai: Partial<ClientOptions>;
171
173
  zeroone: Partial<ClientOptions>;
172
174
  zhipu: Partial<ClientOptions>;
@@ -370,6 +372,11 @@ class AgentRuntime {
370
372
  runtimeModel = new LobeDoubaoAI(params.doubao);
371
373
  break;
372
374
  }
375
+
376
+ case ModelProvider.Wenxin: {
377
+ runtimeModel = new LobeWenxinAI(params.wenxin);
378
+ break;
379
+ }
373
380
  }
374
381
  return new AgentRuntime(runtimeModel);
375
382
  }
@@ -1,107 +1,10 @@
1
- import { ChatCompletion } from '@baiducloud/qianfan';
2
-
3
- // 如果引入了这个类型,那么在跑 type-check 的 tsc 检查中就会抛错,大无语
4
- // import type QianFanClient from '@baiducloud/qianfan/src/ChatCompletion/index';
5
- import { safeParseJSON } from '@/utils/safeParseJSON';
6
-
7
- import { LobeRuntimeAI } from '../BaseAI';
8
- import { AgentRuntimeErrorType } from '../error';
9
- import { ChatCompetitionOptions, ChatStreamPayload } from '../types';
10
- import { AgentRuntimeError } from '../utils/createError';
11
- import { debugStream } from '../utils/debugStream';
12
- import { StreamingResponse } from '../utils/response';
13
- import { convertIterableToStream } from '../utils/streams';
14
- import { WenxinStream } from '../utils/streams/wenxin';
15
- import { ChatResp } from './type';
16
-
17
- interface ChatErrorCode {
18
- error_code: number;
19
- error_msg: string;
20
- }
21
-
22
- export interface LobeWenxinAIParams {
23
- accessKey?: string;
24
- baseURL?: string;
25
- secretKey?: string;
26
- }
27
-
28
- export class LobeWenxinAI implements LobeRuntimeAI {
29
- private client: any;
30
- baseURL?: string;
31
-
32
- constructor({ accessKey, baseURL, secretKey }: LobeWenxinAIParams = {}) {
33
- if (!accessKey || !secretKey)
34
- throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidProviderAPIKey);
35
-
36
- this.client = new ChatCompletion({
37
- QIANFAN_ACCESS_KEY: accessKey,
38
- QIANFAN_SECRET_KEY: secretKey,
39
- });
40
- this.baseURL = baseURL;
41
- }
42
-
43
- async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
44
- try {
45
- const result = await this.client.chat(
46
- { messages: payload.messages as any, stream: true, user_id: options?.user },
47
- payload.model,
48
- );
49
-
50
- const wenxinStream = convertIterableToStream(result as AsyncIterable<ChatResp>);
51
-
52
- const [prod, useForDebug] = wenxinStream.tee();
53
-
54
- if (process.env.DEBUG_WENXIN_CHAT_COMPLETION === '1') {
55
- debugStream(useForDebug).catch();
56
- }
57
-
58
- const stream = WenxinStream(prod, options?.callback);
59
-
60
- // Respond with the stream
61
- return StreamingResponse(stream, { headers: options?.headers });
62
- } catch (e) {
63
- const err = e as Error;
64
-
65
- const error: ChatErrorCode | undefined = safeParseJSON(err.message);
66
-
67
- if (!error) {
68
- throw AgentRuntimeError.createError(AgentRuntimeErrorType.AgentRuntimeError, {
69
- message: err.message,
70
- name: err.name,
71
- });
72
- }
73
-
74
- // 文心一言错误码
75
- // https://cloud.baidu.com/doc/WENXINWORKSHOP/s/tlmyncueh
76
- switch (error.error_code) {
77
- // Invalid API key or access key
78
- case 100:
79
- case 13:
80
- case 14: {
81
- throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidProviderAPIKey, error);
82
- }
83
-
84
- // quota limit
85
- case 4:
86
- case 17:
87
- case 18:
88
- case 19:
89
- case 336_501:
90
- case 336_502:
91
- case 336_503:
92
- case 336_504:
93
- case 336_505:
94
- case 336_507: {
95
- throw AgentRuntimeError.createError(AgentRuntimeErrorType.QuotaLimitReached, {
96
- errorCode: error.error_code,
97
- message: `${error.error_msg} | you can visit https://cloud.baidu.com/doc/WENXINWORKSHOP/s/tlmyncueh for more information about the error code`,
98
- });
99
- }
100
- }
101
-
102
- throw AgentRuntimeError.createError(AgentRuntimeErrorType.ProviderBizError, error);
103
- }
104
- }
105
- }
106
-
107
- export default LobeWenxinAI;
1
+ import { ModelProvider } from '../types';
2
+ import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';
3
+
4
+ export const LobeWenxinAI = LobeOpenAICompatibleFactory({
5
+ baseURL: 'https://qianfan.baidubce.com/v2',
6
+ debug: {
7
+ chatCompletion: () => process.env.DEBUG_WENXIN_CHAT_COMPLETION === '1',
8
+ },
9
+ provider: ModelProvider.Wenxin,
10
+ });
@@ -296,26 +296,6 @@ export default {
296
296
  tooltip: '更新服务商基础配置',
297
297
  updateSuccess: '更新成功',
298
298
  },
299
- wenxin: {
300
- accessKey: {
301
- desc: '填入百度千帆平台的 Access Key',
302
- placeholder: 'Qianfan Access Key',
303
- title: 'Access Key',
304
- },
305
- checker: {
306
- desc: '测试 AccessKey / SecretAccess 是否填写正确',
307
- },
308
- secretKey: {
309
- desc: '填入百度千帆平台 Secret Key',
310
- placeholder: 'Qianfan Secret Key',
311
- title: 'Secret Key',
312
- },
313
- unlock: {
314
- customRegion: '自定义服务区域',
315
- description: '输入你的 AccessKey / SecretKey 即可开始会话。应用不会记录你的鉴权配置',
316
- title: '使用自定义文心一言鉴权信息',
317
- },
318
- },
319
299
  zeroone: {
320
300
  title: '01.AI 零一万物',
321
301
  },