@lobehub/chat 1.90.1 → 1.90.2

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,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.90.2](https://github.com/lobehub/lobe-chat/compare/v1.90.1...v1.90.2)
6
+
7
+ <sup>Released on **2025-06-01**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Support `web_search` tool for MiniMax & Zhipu.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Support `web_search` tool for MiniMax & Zhipu, closes [#7980](https://github.com/lobehub/lobe-chat/issues/7980) ([28cdafb](https://github.com/lobehub/lobe-chat/commit/28cdafb))
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
+
5
30
  ### [Version 1.90.1](https://github.com/lobehub/lobe-chat/compare/v1.90.0...v1.90.1)
6
31
 
7
32
  <sup>Released on **2025-06-01**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Support web_search tool for MiniMax & Zhipu."
6
+ ]
7
+ },
8
+ "date": "2025-06-01",
9
+ "version": "1.90.2"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "fixes": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.90.1",
3
+ "version": "1.90.2",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -4,6 +4,7 @@ const minimaxChatModels: AIChatModelCard[] = [
4
4
  {
5
5
  abilities: {
6
6
  functionCall: true,
7
+ search: true,
7
8
  vision: true,
8
9
  },
9
10
  contextWindowTokens: 1_000_192,
@@ -19,11 +20,15 @@ const minimaxChatModels: AIChatModelCard[] = [
19
20
  output: 8,
20
21
  },
21
22
  releasedAt: '2025-01-15',
23
+ settings: {
24
+ searchImpl: 'params',
25
+ },
22
26
  type: 'chat',
23
27
  },
24
28
  {
25
29
  abilities: {
26
30
  functionCall: true,
31
+ search: true,
27
32
  vision: true,
28
33
  },
29
34
  contextWindowTokens: 245_760,
@@ -37,6 +42,9 @@ const minimaxChatModels: AIChatModelCard[] = [
37
42
  input: 1,
38
43
  output: 1,
39
44
  },
45
+ settings: {
46
+ searchImpl: 'params',
47
+ },
40
48
  type: 'chat',
41
49
  },
42
50
  {
@@ -236,6 +236,26 @@ export const openaiChatModels: AIChatModelCard[] = [
236
236
  releasedAt: '2024-07-18',
237
237
  type: 'chat',
238
238
  },
239
+ {
240
+ abilities: {
241
+ search: true,
242
+ },
243
+ contextWindowTokens: 128_000,
244
+ description:
245
+ 'GPT-4o mini 搜索预览版是一个专门训练用于理解和执行网页搜索查询的模型,使用的是 Chat Completions API。除了令牌费用之外,网页搜索查询还会按每次工具调用收取费用。',
246
+ displayName: 'GPT-4o mini Search Preview',
247
+ id: 'gpt-4o-mini-search-preview',
248
+ maxOutput: 16_384,
249
+ pricing: {
250
+ input: 0.15,
251
+ output: 0.6,
252
+ },
253
+ releasedAt: '2025-03-11',
254
+ settings: {
255
+ searchImpl: 'internal',
256
+ },
257
+ type: 'chat',
258
+ },
239
259
  {
240
260
  abilities: {
241
261
  functionCall: true,
@@ -244,14 +264,34 @@ export const openaiChatModels: AIChatModelCard[] = [
244
264
  contextWindowTokens: 128_000,
245
265
  description:
246
266
  'ChatGPT-4o 是一款动态模型,实时更新以保持当前最新版本。它结合了强大的语言理解与生成能力,适合于大规模应用场景,包括客户服务、教育和技术支持。',
247
- displayName: 'GPT-4o 1120',
248
- id: 'gpt-4o-2024-11-20',
267
+ displayName: 'GPT-4o',
268
+ id: 'gpt-4o',
249
269
  pricing: {
250
270
  cachedInput: 1.25,
251
271
  input: 2.5,
252
272
  output: 10,
253
273
  },
254
- releasedAt: '2024-11-20',
274
+ releasedAt: '2024-05-13',
275
+ type: 'chat',
276
+ },
277
+ {
278
+ abilities: {
279
+ search: true,
280
+ },
281
+ contextWindowTokens: 128_000,
282
+ description:
283
+ 'GPT-4o 搜索预览版是一个专门训练用于理解和执行网页搜索查询的模型,使用的是 Chat Completions API。除了令牌费用之外,网页搜索查询还会按每次工具调用收取费用。',
284
+ displayName: 'GPT-4o Search Preview',
285
+ id: 'gpt-4o-search-preview',
286
+ maxOutput: 16_384,
287
+ pricing: {
288
+ input: 2.5,
289
+ output: 10,
290
+ },
291
+ releasedAt: '2025-03-11',
292
+ settings: {
293
+ searchImpl: 'internal',
294
+ },
255
295
  type: 'chat',
256
296
  },
257
297
  {
@@ -262,14 +302,14 @@ export const openaiChatModels: AIChatModelCard[] = [
262
302
  contextWindowTokens: 128_000,
263
303
  description:
264
304
  'ChatGPT-4o 是一款动态模型,实时更新以保持当前最新版本。它结合了强大的语言理解与生成能力,适合于大规模应用场景,包括客户服务、教育和技术支持。',
265
- displayName: 'GPT-4o',
266
- id: 'gpt-4o',
305
+ displayName: 'GPT-4o 1120',
306
+ id: 'gpt-4o-2024-11-20',
267
307
  pricing: {
268
308
  cachedInput: 1.25,
269
309
  input: 2.5,
270
310
  output: 10,
271
311
  },
272
- releasedAt: '2024-05-13',
312
+ releasedAt: '2024-11-20',
273
313
  type: 'chat',
274
314
  },
275
315
  {
@@ -12,7 +12,16 @@ export const LobeMinimaxAI = LobeOpenAICompatibleFactory({
12
12
  baseURL: 'https://api.minimax.chat/v1',
13
13
  chatCompletion: {
14
14
  handlePayload: (payload) => {
15
- const { max_tokens, temperature, top_p, ...params } = payload;
15
+ const { enabledSearch, max_tokens, temperature, tools, top_p, ...params } = payload;
16
+
17
+ const minimaxTools = enabledSearch
18
+ ? [
19
+ ...(tools || []),
20
+ {
21
+ type: 'web_search',
22
+ },
23
+ ]
24
+ : tools;
16
25
 
17
26
  return {
18
27
  ...params,
@@ -20,6 +29,7 @@ export const LobeMinimaxAI = LobeOpenAICompatibleFactory({
20
29
  max_tokens: max_tokens !== undefined ? max_tokens : getMinimaxMaxOutputs(payload.model),
21
30
  presence_penalty: undefined,
22
31
  temperature: temperature === undefined || temperature <= 0 ? undefined : temperature / 2,
32
+ tools: minimaxTools,
23
33
  top_p: top_p !== undefined && top_p > 0 && top_p <= 1 ? top_p : undefined,
24
34
  } as any;
25
35
  },
@@ -21,6 +21,8 @@ export const LobeOpenAI = LobeOpenAICompatibleFactory({
21
21
  }
22
22
 
23
23
  if (model.includes('-search-')) {
24
+ const oaiSearchContextSize = process.env.OPENAI_SEARCH_CONTEXT_SIZE; // low, medium, high
25
+
24
26
  return {
25
27
  ...payload,
26
28
  frequency_penalty: undefined,
@@ -28,7 +30,12 @@ export const LobeOpenAI = LobeOpenAICompatibleFactory({
28
30
  stream: payload.stream ?? true,
29
31
  temperature: undefined,
30
32
  top_p: undefined,
31
- };
33
+ ...(oaiSearchContextSize && {
34
+ web_search_options: {
35
+ search_context_size: oaiSearchContextSize,
36
+ },
37
+ }),
38
+ } as any;
32
39
  }
33
40
 
34
41
  return { ...payload, stream: payload.stream ?? true };
@@ -99,16 +99,87 @@ export const transformOpenAIStream = (
99
99
  if (item.finish_reason) {
100
100
  // one-api 的流式接口,会出现既有 finish_reason ,也有 content 的情况
101
101
  // {"id":"demo","model":"deepl-en","choices":[{"index":0,"delta":{"role":"assistant","content":"Introduce yourself."},"finish_reason":"stop"}]}
102
-
103
102
  if (typeof item.delta?.content === 'string' && !!item.delta.content) {
103
+ // MiniMax 内建搜索功能会在第一个 tools 流中 content 返回引用源,需要忽略
104
+ // {"id":"0483748a25071c611e2f48d2982fbe96","choices":[{"finish_reason":"stop","index":0,"delta":{"content":"[{\"no\":1,\"url\":\"https://www.xiaohongshu.com/discovery/item/66d8de3c000000001f01e752\",\"title\":\"郑钦文为国而战,没有理由不坚持🏅\",\"content\":\"·2024年08月03日\\n中国队选手郑钦文夺得巴黎奥运会网球女单比赛金牌(巴黎奥运第16金)\\n#巴黎奥运会[话题]# #郑钦文[话题]# #人物素材积累[话题]# #作文素材积累[话题]# #申论素材[话题]#\",\"web_icon\":\"https://www.xiaohongshu.com/favicon.ico\"}]","role":"tool","tool_call_id":"call_function_6696730535"}}],"created":1748255114,"model":"abab6.5s-chat","object":"chat.completion.chunk","usage":{"total_tokens":0,"total_characters":0},"input_sensitive":false,"output_sensitive":false,"input_sensitive_type":0,"output_sensitive_type":0,"output_sensitive_int":0}
105
+ if (typeof item.delta?.role === 'string' && item.delta.role === 'tool') {
106
+ return { data: null, id: chunk.id, type: 'text' };
107
+ }
108
+
104
109
  return { data: item.delta.content, id: chunk.id, type: 'text' };
105
110
  }
106
111
 
112
+ // OpenAI Search Preview 模型返回引用源
113
+ // {"id":"chatcmpl-18037d13-243c-4941-8b05-9530b352cf17","object":"chat.completion.chunk","created":1748351805,"model":"gpt-4o-mini-search-preview-2025-03-11","choices":[{"index":0,"delta":{"annotations":[{"type":"url_citation","url_citation":{"url":"https://zh.wikipedia.org/wiki/%E4%B8%8A%E6%B5%B7%E4%B9%90%E9%AB%98%E4%B9%90%E5%9B%AD?utm_source=openai","title":"上海乐高乐园","start_index":75,"end_index":199}}]},"finish_reason":"stop"}],"service_tier":"default"}
114
+ if ((item as any).delta?.annotations && (item as any).delta.annotations.length > 0) {
115
+ const citations = (item as any).delta.annotations;
116
+
117
+ return [
118
+ {
119
+ data: {
120
+ citations: citations.map(
121
+ (item: any) =>
122
+ ({
123
+ title: item.url_citation.title,
124
+ url: item.url_citation.url,
125
+ }) as CitationItem,
126
+ ),
127
+ },
128
+ id: chunk.id,
129
+ type: 'grounding',
130
+ },
131
+ ];
132
+ }
133
+
134
+ // MiniMax 内建搜索功能会在最后一个流中的 message 数组中返回 4 个 Object,其中最后一个为 annotations
135
+ // {"id":"0483bf14ba55225a66de2342a21b4003","choices":[{"finish_reason":"tool_calls","index":0,"messages":[{"content":"","role":"user","reasoning_content":""},{"content":"","role":"assistant","tool_calls":[{"id":"call_function_0872338692","type":"web_search","function":{"name":"get_search_result","arguments":"{\"query_tag\":[\"天气\"],\"query_list\":[\"上海 2025年5月26日 天气\"]}"}}],"reasoning_content":""},{"content":"","role":"tool","tool_call_id":"call_function_0872338692","reasoning_content":""},{"content":"","role":"assistant","name":"海螺AI","annotations":[{"text":"【5†source】","url":"https://mtianqi.eastday.com/tianqi/shanghai/20250526.html","quote":"上海天气预报提供上海2025年05月26日天气"}],"audio_content":"","reasoning_content":""}]}],"created":1748274196,"model":"MiniMax-Text-01","object":"chat.completion","usage":{"total_tokens":13110,"total_characters":0,"prompt_tokens":12938,"completion_tokens":172},"base_resp":{"status_code":0,"status_msg":"Invalid parameters detected, json: unknown field \"user\""}}
136
+ if ((item as any).messages && (item as any).messages.length > 0) {
137
+ const citations = (item as any).messages.at(-1).annotations;
138
+
139
+ return [
140
+ {
141
+ data: {
142
+ citations: citations.map(
143
+ (item: any) =>
144
+ ({
145
+ title: item.url,
146
+ url: item.url,
147
+ }) as CitationItem,
148
+ ),
149
+ },
150
+ id: chunk.id,
151
+ type: 'grounding',
152
+ },
153
+ ];
154
+ }
155
+
107
156
  if (chunk.usage) {
108
157
  const usage = chunk.usage;
109
158
  return { data: convertUsage(usage), id: chunk.id, type: 'usage' };
110
159
  }
111
160
 
161
+ // xAI Live Search 功能返回引用源
162
+ // {"id":"8721eebb-6465-4c47-ba2e-8e2ec0f97055","object":"chat.completion.chunk","created":1747809109,"model":"grok-3","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":"stop"}],"system_fingerprint":"fp_1affcf9872","citations":["https://world.huanqiu.com/"]}
163
+ if ((chunk as any).citations) {
164
+ const citations = (chunk as any).citations;
165
+
166
+ return [
167
+ {
168
+ data: {
169
+ citations: citations.map(
170
+ (item: any) =>
171
+ ({
172
+ title: item,
173
+ url: item,
174
+ }) as CitationItem,
175
+ ),
176
+ },
177
+ id: chunk.id,
178
+ type: 'grounding',
179
+ },
180
+ ];
181
+ }
182
+
112
183
  return { data: item.finish_reason, id: chunk.id, type: 'stop' };
113
184
  }
114
185
 
@@ -146,7 +217,9 @@ export const transformOpenAIStream = (
146
217
  // in Hunyuan api, the citation is in every chunk
147
218
  ('search_info' in chunk && (chunk.search_info as any)?.search_results) ||
148
219
  // in Wenxin api, the citation is in the first and last chunk
149
- ('search_results' in chunk && chunk.search_results);
220
+ ('search_results' in chunk && chunk.search_results) ||
221
+ // in Zhipu api, the citation is in the first chunk
222
+ ('web_search' in chunk && chunk.web_search);
150
223
 
151
224
  if (citations) {
152
225
  streamContext.returnedCitation = true;
@@ -154,13 +227,10 @@ export const transformOpenAIStream = (
154
227
  return [
155
228
  {
156
229
  data: {
157
- citations: (citations as any[]).map(
158
- (item) =>
159
- ({
160
- title: typeof item === 'string' ? item : item.title,
161
- url: typeof item === 'string' ? item : item.url,
162
- }) as CitationItem,
163
- ),
230
+ citations: (citations as any[]).map((item) => ({
231
+ title: typeof item === 'string' ? item : item.title,
232
+ url: typeof item === 'string' ? item : item.url || item.link,
233
+ })).filter(c => c.title && c.url), // Zhipu 内建搜索工具有时会返回空 link 引发程序崩溃
164
234
  },
165
235
  id: chunk.id,
166
236
  type: 'grounding',
@@ -22,6 +22,9 @@ export const LobeZhipuAI = LobeOpenAICompatibleFactory({
22
22
  type: 'web_search',
23
23
  web_search: {
24
24
  enable: true,
25
+ result_sequence: 'before', // 将搜索结果返回顺序更改为 before 适配最小化 OpenAIStream 改动
26
+ search_engine: process.env.ZHIPU_SEARCH_ENGINE || 'search_std', // search_std, search_pro
27
+ search_result: true,
25
28
  },
26
29
  },
27
30
  ]