| 277 | } |
| 278 | |
| 279 | function accumulateChatCompletion( |
| 280 | chunks: OpenAI.ChatCompletionChunk[] |
| 281 | ): OpenAI.ChatCompletion { |
| 282 | if (chunks.length === 0) { |
| 283 | throw new Error('No chunks provided'); |
| 284 | } |
| 285 | |
| 286 | // Assuming the id, created, and model fields are consistent across chunks, |
| 287 | // we use the first chunk to initialize these values. |
| 288 | const firstChunk = chunks[0]; |
| 289 | |
| 290 | // Initialize the response |
| 291 | const response: OpenAI.ChatCompletion = { |
| 292 | id: firstChunk.id, |
| 293 | object: 'chat.completion', |
| 294 | created: firstChunk.created, |
| 295 | model: firstChunk.model, |
| 296 | choices: [ |
| 297 | { |
| 298 | index: 0, |
| 299 | message: { |
| 300 | content: null, |
| 301 | role: 'assistant', // or other roles as per your logic |
| 302 | }, |
| 303 | finish_reason: 'stop', |
| 304 | }, |
| 305 | ], |
| 306 | }; |
| 307 | |
| 308 | // we need to accumulate tools separatly as we need an object to do this.. |
| 309 | const toolCalls: Record<string, OpenAI.ChatCompletionMessageToolCall> = {}; |
| 310 | |
| 311 | // Accumulate the content from the first choice of each chunk |
| 312 | // TODO: in the future we can easily accumulate from each choice with a loop |
| 313 | const choice = chunks.reduce( |
| 314 | (previous, chunk) => { |
| 315 | const choiceIdx = 0; |
| 316 | if (chunk.choices[choiceIdx]?.delta?.content) { |
| 317 | if (previous.message.content) { |
| 318 | previous.message.content += chunk.choices[choiceIdx].delta.content; |
| 319 | } else { |
| 320 | previous.message.content = chunk.choices[choiceIdx].delta |
| 321 | .content as string; |
| 322 | } |
| 323 | } |
| 324 | previous.message.role = |
| 325 | (chunk.choices[choiceIdx]?.delta |
| 326 | ?.role as OpenAI.ChatCompletionMessage['role']) || |
| 327 | previous.message.role; |
| 328 | previous.finish_reason = |
| 329 | chunk.choices[choiceIdx]?.finish_reason || previous.finish_reason; |
| 330 | for (const tc of chunk.choices[choiceIdx].delta?.tool_calls || []) { |
| 331 | // initialize toolCalls if it doesn't exist |
| 332 | const tcnew = toolCalls[tc.index] || { |
| 333 | id: '', |
| 334 | type: 'function', |
| 335 | function: { |
| 336 | name: '', |