fix: stream return EOF when openai return error (#184)
* fix: stream return EOF when openai return error * perf: add error accumulator * fix: golangci-lint * fix: unmarshal error possibly null * fix: error accumulator * test: error accumulator use interface and add test code * test: error accumulator add test code * refactor: use stream reader to re-use stream code * refactor: stream reader use generics
This commit is contained in:
@@ -2,11 +2,7 @@ package openai
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ChatCompletionStreamChoiceDelta struct {
|
||||
@@ -30,52 +26,7 @@ type ChatCompletionStreamResponse struct {
|
||||
// ChatCompletionStream
|
||||
// Note: Perhaps it is more elegant to abstract Stream using generics.
|
||||
type ChatCompletionStream struct {
|
||||
emptyMessagesLimit uint
|
||||
isFinished bool
|
||||
|
||||
reader *bufio.Reader
|
||||
response *http.Response
|
||||
}
|
||||
|
||||
func (stream *ChatCompletionStream) Recv() (response ChatCompletionStreamResponse, err error) {
|
||||
if stream.isFinished {
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
|
||||
var emptyMessagesCount uint
|
||||
|
||||
waitForData:
|
||||
line, err := stream.reader.ReadBytes('\n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var headerData = []byte("data: ")
|
||||
line = bytes.TrimSpace(line)
|
||||
if !bytes.HasPrefix(line, headerData) {
|
||||
emptyMessagesCount++
|
||||
if emptyMessagesCount > stream.emptyMessagesLimit {
|
||||
err = ErrTooManyEmptyStreamMessages
|
||||
return
|
||||
}
|
||||
|
||||
goto waitForData
|
||||
}
|
||||
|
||||
line = bytes.TrimPrefix(line, headerData)
|
||||
if string(line) == "[DONE]" {
|
||||
stream.isFinished = true
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(line, &response)
|
||||
return
|
||||
}
|
||||
|
||||
func (stream *ChatCompletionStream) Close() {
|
||||
stream.response.Body.Close()
|
||||
*streamReader[ChatCompletionStreamResponse]
|
||||
}
|
||||
|
||||
// CreateChatCompletionStream — API call to create a chat completion w/ streaming
|
||||
@@ -98,9 +49,13 @@ func (c *Client) CreateChatCompletionStream(
|
||||
}
|
||||
|
||||
stream = &ChatCompletionStream{
|
||||
emptyMessagesLimit: c.config.EmptyMessagesLimit,
|
||||
reader: bufio.NewReader(resp.Body),
|
||||
response: resp,
|
||||
streamReader: &streamReader[ChatCompletionStreamResponse]{
|
||||
emptyMessagesLimit: c.config.EmptyMessagesLimit,
|
||||
reader: bufio.NewReader(resp.Body),
|
||||
response: resp,
|
||||
errAccumulator: newErrorAccumulator(),
|
||||
unmarshaler: &jsonUnmarshaler{},
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user