@@ -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,21 +217,20 @@ 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 ;
153
226
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' ,
0 commit comments