nomid2 commited on
Commit
5cdca7f
·
verified ·
1 Parent(s): ba27085

Upload chat.js

Browse files
Files changed (1) hide show
  1. src/router/chat.js +137 -87
src/router/chat.js CHANGED
@@ -7,6 +7,7 @@ const accountManager = require('../lib/manager')
7
  const imageUploader = require('../lib/uploader')
8
  const logger = require('../lib/logger')
9
  const ErrorHandler = require('../lib/errorHandler')
 
10
 
11
  const router = express.Router()
12
 
@@ -121,130 +122,179 @@ async function convertOpenAIToMammouth(openaiRequest, requestId = null) {
121
  let hasProcessedText = false // 标记是否已处理文本
122
  let normalImageCount = 0 // 普通图片计数
123
 
124
- // 处理每个图片
125
- console.log(`[图片处理开始] 共${imageParts.length}张图片待处理`)
126
- for (let imagePartIndex = 0; imagePartIndex < imageParts.length; imagePartIndex++) {
127
- const imagePart = imageParts[imagePartIndex]
128
- console.log(`[图片处理] 开始处理第${imagePartIndex + 1}张图片 (全局索引: ${currentImageIndex + 1})`)
129
 
130
- try {
131
- // 获取图片数据
132
- let imageUrl = imagePart.image_url
133
- if (typeof imageUrl === 'object' && imageUrl.url) {
134
- imageUrl = imageUrl.url
135
- }
136
 
137
- console.log(`[图片处理] 图片${currentImageIndex + 1}类型: ${imageUrl.startsWith('data:image') ? 'Base64' : 'URL'}`)
138
-
139
- // 使用智能上传方法处理图片(支持长图)
140
- // 启用preserveOrder=true来确保图片顺序正确
141
- let uploadedUrls = []
142
- if (imageUrl.startsWith('data:image')) {
143
- uploadedUrls = await imageUploader.uploadFromBase64Smart(
144
- imageUrl,
145
- null,
146
- requestId,
147
- currentImageIndex,
148
- true // preserveOrder = true,禁用缓存优化以保持顺序
149
- )
150
- } else {
151
- uploadedUrls = await imageUploader.uploadFromUrlSmart(
152
- imageUrl,
153
- null,
154
- requestId,
155
- currentImageIndex,
156
- true // preserveOrder = true,禁用缓存优化以保持顺序
157
- )
158
- }
159
 
160
- console.log(`[图片处理] 图片${currentImageIndex + 1}上传完成,获得${uploadedUrls.length}个URL`)
161
 
162
- // 如果是长图(多个片段),为每个片段创建单独的消息
163
- if (uploadedUrls.length > 1) {
164
- console.log(`[长图处理] 图片${currentImageIndex + 1}被切割为${uploadedUrls.length}个片段,将按顺序发送`)
 
165
 
166
- if (requestId) {
167
- logger.logMessageSegmentation(requestId, currentImageIndex, uploadedUrls.length)
 
 
 
168
  }
169
 
170
- uploadedUrls.forEach((url, segmentIndex) => {
171
- // 只在第一个长图的第一个片段包含原始文本
172
- const includeOriginalText = !hasProcessedText && segmentIndex === 0 && combinedText
173
- const segmentText = includeOriginalText
174
- ? `${combinedText}\n\n[长图片段 ${segmentIndex + 1}/${uploadedUrls.length}]`
175
- : `[长图片段 ${segmentIndex + 1}/${uploadedUrls.length}]`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
- processedMessages.push({
178
- content: segmentText || '.',
179
- imagesData: [url],
180
- documentsData: []
181
- })
182
 
183
- console.log(`[消息生成] 长图片段${segmentIndex + 1}: "${segmentText.substring(0, 50)}..."`)
 
 
184
 
185
- if (includeOriginalText) {
186
- hasProcessedText = true
187
- }
188
- })
189
- } else {
190
- // 普通图片,按顺序存储到结果数组中
191
- const imageResult = {
192
- index: imagePartIndex, // 在消息中的位置索引
193
- urls: uploadedUrls,
194
- originalIndex: currentImageIndex, // 全局图片索引
195
- processOrder: normalImageCount // 处理顺序
196
  }
 
 
 
 
 
197
 
198
- normalImageResults.push(imageResult)
199
- normalImageCount++
 
 
200
 
201
- console.log(`[图片收集] 普通图片${currentImageIndex + 1}已收集`)
202
- console.log(` - 消息位置索引: ${imagePartIndex}`)
203
- console.log(` - 全局图片索引: ${currentImageIndex}`)
204
- console.log(` - 处理顺序: ${normalImageCount}`)
205
- console.log(` - 当前普通图片总数: ${normalImageCount}`)
206
- }
207
 
208
- currentImageIndex++
209
- console.log(`[图片处理] 图片${currentImageIndex}处理成功,继续下一张`)
 
 
210
 
211
- } catch (error) {
212
- console.error(`[图片处理错误] 图片${currentImageIndex + 1}处理失败: ${error.message}`)
213
- console.log(`[图片处理错误] 跳过图片${currentImageIndex + 1},继续处理下一张`)
 
 
 
 
 
 
214
 
215
  if (requestId) {
216
- logger.logError(requestId, 'IMAGE_PROCESSING_ERROR', error.message, {
217
- imageIndex: currentImageIndex,
218
- imagePartIndex: imagePartIndex,
219
- imageUrl: typeof imagePart.image_url === 'string' ? imagePart.image_url.substring(0, 100) : 'object'
 
 
 
 
 
 
 
 
 
 
220
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  }
222
 
223
- // 即使处理失败,也要增加索引以保持一致性
224
- currentImageIndex++
 
 
 
 
 
 
 
 
225
  }
226
  }
227
 
 
 
 
228
  console.log(`[图片处理完成] 共处理${imageParts.length}张图片,成功收集${normalImageResults.length}张普通图片`)
229
 
230
  // 如果有普通图片,按原始顺序创建一个包含所有普通图片的消息
231
  if (normalImageResults.length > 0) {
232
- console.log(`[排序前验证] 收集到${normalImageResults.length}张普通图片`)
233
  normalImageResults.forEach((result, idx) => {
234
- console.log(` 图片${idx + 1}: 消息位置=${result.index}, 全局索引=${result.originalIndex}, 处理顺序=${result.processOrder}`)
235
  })
236
 
237
  // 按照imagePartIndex排序,确保严格按客户端上传顺序
238
- console.log(`[开始排序] 按消息中的位置索引排序...`)
 
 
 
 
 
239
  normalImageResults.sort((a, b) => {
240
  const result = a.index - b.index
241
- console.log(` 比较: 位置${a.index}(图片${a.originalIndex + 1}) vs 位置${b.index}(图片${b.originalIndex + 1}) = ${result}`)
242
  return result
243
  })
244
 
245
- console.log(`[排序后验证] 最终图片顺序:`)
246
  normalImageResults.forEach((result, idx) => {
247
- console.log(` 第${idx + 1}位: 消息位置=${result.index}, 全局索引=${result.originalIndex}, 处理顺序=${result.processOrder}`)
248
  })
249
 
250
  // 验证排序是否正确(检查index是否连续递增)
 
7
  const imageUploader = require('../lib/uploader')
8
  const logger = require('../lib/logger')
9
  const ErrorHandler = require('../lib/errorHandler')
10
+ const ImageProcessingQueue = require('../lib/imageQueue')
11
 
12
  const router = express.Router()
13
 
 
122
  let hasProcessedText = false // 标记是否已处理文本
123
  let normalImageCount = 0 // 普通图片计数
124
 
125
+ // 处理每个图片 - 使用严格的顺序处理机制
126
+ console.log(`[图片处理开始] 共${imageParts.length}张图片待处理,开始时间: ${new Date().toISOString()}`)
 
 
 
127
 
128
+ // 创建图片处理队列,确保严格按顺序处理
129
+ const imageQueue = new ImageProcessingQueue()
130
+ const imageProcessingPromises = []
 
 
 
131
 
132
+ // 为每张图片创建处理任务
133
+ for (let imagePartIndex = 0; imagePartIndex < imageParts.length; imagePartIndex++) {
134
+ const imagePart = imageParts[imagePartIndex]
135
+ const imageGlobalIndex = currentImageIndex + imagePartIndex
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
 
137
+ console.log(`[队列任务] 创建第${imagePartIndex + 1}张图片的处理任务 (全局索引: ${imageGlobalIndex + 1})`)
138
 
139
+ // 创建图片处理任务
140
+ const imageProcessor = async () => {
141
+ const processingStartTime = Date.now()
142
+ console.log(`[队列执行] 开始处理图片${imageGlobalIndex + 1},时间: ${new Date().toISOString()}`)
143
 
144
+ try {
145
+ // 获取图片数据
146
+ let imageUrl = imagePart.image_url
147
+ if (typeof imageUrl === 'object' && imageUrl.url) {
148
+ imageUrl = imageUrl.url
149
  }
150
 
151
+ console.log(`[队列执行] 图片${imageGlobalIndex + 1}类型: ${imageUrl.startsWith('data:image') ? 'Base64' : 'URL'}`)
152
+ console.log(`[队列执行] 图片${imageGlobalIndex + 1}URL长度: ${typeof imageUrl === 'string' ? imageUrl.length : 'N/A'}`)
153
+
154
+ // 记录处理前的状态
155
+ const beforeProcessTime = Date.now()
156
+ console.log(`[队列执行] 图片${imageGlobalIndex + 1}开始上传处理,时间: ${new Date().toISOString()}`)
157
+
158
+ // 使用智能上传方法处理图片(支持长图)
159
+ // 启用preserveOrder=true来确保图片顺序正确
160
+ let uploadedUrls = []
161
+ if (imageUrl.startsWith('data:image')) {
162
+ uploadedUrls = await imageUploader.uploadFromBase64Smart(
163
+ imageUrl,
164
+ null,
165
+ requestId,
166
+ imageGlobalIndex,
167
+ true // preserveOrder = true,禁用缓存优化以保持顺序
168
+ )
169
+ } else {
170
+ uploadedUrls = await imageUploader.uploadFromUrlSmart(
171
+ imageUrl,
172
+ null,
173
+ requestId,
174
+ imageGlobalIndex,
175
+ true // preserveOrder = true,禁用缓存优化以保持顺序
176
+ )
177
+ }
178
 
179
+ const afterProcessTime = Date.now()
180
+ const processingDuration = afterProcessTime - beforeProcessTime
 
 
 
181
 
182
+ console.log(`[队列执行] 图片${imageGlobalIndex + 1}上传完成,获得${uploadedUrls.length}个URL`)
183
+ console.log(`[队列执行] 图片${imageGlobalIndex + 1}处理耗时: ${processingDuration}ms`)
184
+ console.log(`[队列执行] 图片${imageGlobalIndex + 1}完成时间: ${new Date().toISOString()}`)
185
 
186
+ return {
187
+ imagePartIndex,
188
+ imageGlobalIndex,
189
+ uploadedUrls,
190
+ processingDuration,
191
+ processingStartTime,
192
+ completedTime: afterProcessTime
 
 
 
 
193
  }
194
+ } catch (error) {
195
+ console.error(`[队列执行] 图片${imageGlobalIndex + 1}处理失败: ${error.message}`)
196
+ throw error
197
+ }
198
+ }
199
 
200
+ // 将任务添加到队列
201
+ const promise = imageQueue.addTask(imagePartIndex, imageProcessor)
202
+ imageProcessingPromises.push(promise)
203
+ }
204
 
205
+ console.log(`[队列管理] 所有${imageParts.length}个图片任务已添加到队列`)
 
 
 
 
 
206
 
207
+ // 等待所有图片处理完成
208
+ console.log(`[队列管理] 开始等待所有图片处理完成...`)
209
+ const imageResults = await Promise.all(imageProcessingPromises)
210
+ console.log(`[队列管理] 所有图片处理完成,共${imageResults.length}个结果`)
211
 
212
+ // 处理队列返回的结果
213
+ for (const result of imageResults) {
214
+ const { imagePartIndex, imageGlobalIndex, uploadedUrls, processingDuration } = result
215
+
216
+ console.log(`[结果处理] 处理图片${imageGlobalIndex + 1}的结果,位置索引: ${imagePartIndex}`)
217
+
218
+ // 如果是长图(多个片段),为每个片段创建单独的消息
219
+ if (uploadedUrls.length > 1) {
220
+ console.log(`[长图处理] 图片${imageGlobalIndex + 1}被切割为${uploadedUrls.length}个片段,将按顺序发送`)
221
 
222
  if (requestId) {
223
+ logger.logMessageSegmentation(requestId, imageGlobalIndex, uploadedUrls.length)
224
+ }
225
+
226
+ uploadedUrls.forEach((url, segmentIndex) => {
227
+ // 只在第一个长图的第一个片段包含原始文本
228
+ const includeOriginalText = !hasProcessedText && segmentIndex === 0 && combinedText
229
+ const segmentText = includeOriginalText
230
+ ? `${combinedText}\n\n[长图片段 ${segmentIndex + 1}/${uploadedUrls.length}]`
231
+ : `[长图片段 ${segmentIndex + 1}/${uploadedUrls.length}]`
232
+
233
+ processedMessages.push({
234
+ content: segmentText || '.',
235
+ imagesData: [url],
236
+ documentsData: []
237
  })
238
+
239
+ console.log(`[消息生成] 长图片段${segmentIndex + 1}: "${segmentText.substring(0, 50)}..."`)
240
+
241
+ if (includeOriginalText) {
242
+ hasProcessedText = true
243
+ }
244
+ })
245
+ } else {
246
+ // 普通图片,按顺序存储到结果数组中
247
+ const collectTime = Date.now()
248
+ const imageResult = {
249
+ index: imagePartIndex, // 在消息中的位置索引
250
+ urls: uploadedUrls,
251
+ originalIndex: imageGlobalIndex, // 全局图片索引
252
+ processOrder: normalImageCount, // 处理顺序
253
+ collectTime: collectTime, // 收集时间戳
254
+ processingDuration: processingDuration // 处理耗时
255
  }
256
 
257
+ normalImageResults.push(imageResult)
258
+ normalImageCount++
259
+
260
+ console.log(`[图片收集] 普通图片${imageGlobalIndex + 1}已收集,收集时间: ${new Date(collectTime).toISOString()}`)
261
+ console.log(` - 消息位置索引: ${imagePartIndex}`)
262
+ console.log(` - 全局图片索引: ${imageGlobalIndex}`)
263
+ console.log(` - 处理顺序: ${normalImageCount}`)
264
+ console.log(` - 处理耗时: ${processingDuration}ms`)
265
+ console.log(` - 当前普通图片总数: ${normalImageCount}`)
266
+ console.log(` - 第一个URL: ${uploadedUrls[0] ? uploadedUrls[0].substring(uploadedUrls[0].lastIndexOf('/') + 1) : 'N/A'}`)
267
  }
268
  }
269
 
270
+ // 更新全局图片索引
271
+ currentImageIndex += imageParts.length
272
+
273
  console.log(`[图片处理完成] 共处理${imageParts.length}张图片,成功收集${normalImageResults.length}张普通图片`)
274
 
275
  // 如果有普通图片,按原始顺序创建一个包含所有普通图片的消息
276
  if (normalImageResults.length > 0) {
277
+ console.log(`[排序前验证] 收集到${normalImageResults.length}张普通图片,验证时间: ${new Date().toISOString()}`)
278
  normalImageResults.forEach((result, idx) => {
279
+ console.log(` 图片${idx + 1}: 位置=${result.index}, 全局=${result.originalIndex}, 顺序=${result.processOrder}, 耗时=${result.processingDuration}ms, 收集时间=${new Date(result.collectTime).toISOString()}`)
280
  })
281
 
282
  // 按照imagePartIndex排序,确保严格按客户端上传顺序
283
+ console.log(`[开始排序] 按消息中的位置索引排序,排序时间: ${new Date().toISOString()}`)
284
+
285
+ // 记录排序前的顺序
286
+ const beforeSort = normalImageResults.map(r => ({pos: r.index, global: r.originalIndex, order: r.processOrder}))
287
+ console.log(`[排序前顺序] ${beforeSort.map(r => `位置${r.pos}(全局${r.global},顺序${r.order})`).join(' -> ')}`)
288
+
289
  normalImageResults.sort((a, b) => {
290
  const result = a.index - b.index
291
+ console.log(` 比较: 位置${a.index}(全局${a.originalIndex + 1}) vs 位置${b.index}(全局${b.originalIndex + 1}) = ${result}`)
292
  return result
293
  })
294
 
295
+ console.log(`[排序后验证] 最终图片顺序,完成时间: ${new Date().toISOString()}`)
296
  normalImageResults.forEach((result, idx) => {
297
+ console.log(` 第${idx + 1}位: 位置=${result.index}, 全局=${result.originalIndex}, 顺序=${result.processOrder}, 耗时=${result.processingDuration}ms`)
298
  })
299
 
300
  // 验证排序是否正确(检查index是否连续递增)