(w http.ResponseWriter, r *http.Request, chunks <-chan OpenAIChunk)
| 320 | } |
| 321 | |
| 322 | func writeChatCompletionsStreaming(w http.ResponseWriter, r *http.Request, chunks <-chan OpenAIChunk) { |
| 323 | w.Header().Set("Content-Type", "text/event-stream") |
| 324 | w.Header().Set("Cache-Control", "no-cache") |
| 325 | w.Header().Set("Connection", "keep-alive") |
| 326 | w.WriteHeader(http.StatusOK) |
| 327 | |
| 328 | flusher, ok := w.(http.Flusher) |
| 329 | if !ok { |
| 330 | http.Error(w, "streaming not supported", http.StatusInternalServerError) |
| 331 | return |
| 332 | } |
| 333 | |
| 334 | for { |
| 335 | var chunk OpenAIChunk |
| 336 | var ok bool |
| 337 | select { |
| 338 | case <-r.Context().Done(): |
| 339 | log.Printf("writeChatCompletionsStreaming: request context canceled, stopping stream") |
| 340 | return |
| 341 | case chunk, ok = <-chunks: |
| 342 | if !ok { |
| 343 | _, _ = fmt.Fprintf(w, "data: [DONE]\n\n") |
| 344 | flusher.Flush() |
| 345 | return |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | choicesData := make([]map[string]interface{}, len(chunk.Choices)) |
| 350 | for i, choice := range chunk.Choices { |
| 351 | choiceData := map[string]interface{}{ |
| 352 | "index": choice.Index, |
| 353 | } |
| 354 | if choice.Delta != "" { |
| 355 | choiceData["delta"] = map[string]interface{}{ |
| 356 | "content": choice.Delta, |
| 357 | } |
| 358 | } |
| 359 | if len(choice.ToolCalls) > 0 { |
| 360 | // Tool calls come in the delta |
| 361 | if choiceData["delta"] == nil { |
| 362 | choiceData["delta"] = make(map[string]interface{}) |
| 363 | } |
| 364 | delta, ok := choiceData["delta"].(map[string]interface{}) |
| 365 | if !ok { |
| 366 | delta = make(map[string]interface{}) |
| 367 | choiceData["delta"] = delta |
| 368 | } |
| 369 | delta["tool_calls"] = choice.ToolCalls |
| 370 | } |
| 371 | if choice.FinishReason != "" { |
| 372 | choiceData["finish_reason"] = choice.FinishReason |
| 373 | } |
| 374 | choicesData[i] = choiceData |
| 375 | } |
| 376 | |
| 377 | chunkData := map[string]interface{}{ |
| 378 | "id": chunk.ID, |
| 379 | "object": chunk.Object, |
no test coverage detected