Skip to content

Commit e70b7e9

Browse files
[azopenai] If the scanner reaches the end of stream and we haven't gotten the '[done]' token then return an error instead of silently failing. (Azure#21323)
Also: - Fixing casing of error message - shouldn't have a leading uppercase letter. - Fixing misspelled comment
1 parent c705b7c commit e70b7e9

File tree

4 files changed

+30
-4
lines changed

4 files changed

+30
-4
lines changed

sdk/ai/azopenai/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
### Bugs Fixed
1313

14+
- EventReader, used by GetChatCompletionsStream and GetCompletionsStream for streaming results, would not return an
15+
error if the underlying Body reader was closed or EOF'd before the actual DONE: token arrived. This could result in an
16+
infinite loop for callers. (PR#)
17+
1418
### Other Changes
1519

1620
## 0.1.1 (2023-07-26)

sdk/ai/azopenai/custom_models_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func TestParseResponseError(t *testing.T) {
5555

5656
contentFilterResults := contentFilterErr.ContentFilterResults
5757

58-
// thsi comment was considered violent, so it was filtered.
58+
// this comment was considered violent, so it was filtered.
5959
require.Equal(t, &ContentFilterResultsViolence{
6060
Filtered: to.Ptr(true),
6161
Severity: to.Ptr(ContentFilterSeverityMedium)}, contentFilterResults.Violence)

sdk/ai/azopenai/event_reader.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,19 @@ func (er *EventReader[T]) Read() (T, error) {
4747
err := json.Unmarshal([]byte(tokens[1]), &data)
4848
return data, err
4949
default: // Any other event type is an unexpected
50-
return data, errors.New("Unexpected event type: " + tokens[0])
50+
return data, errors.New("unexpected event type: " + tokens[0])
5151
}
5252
// Unreachable
5353
}
5454
}
55-
return *new(T), er.scanner.Err()
55+
56+
scannerErr := er.scanner.Err()
57+
58+
if scannerErr == nil {
59+
return *new(T), errors.New("incomplete stream")
60+
}
61+
62+
return *new(T), scannerErr
5663
}
5764

5865
// Close closes the EventReader and any applicable inner stream state.

sdk/ai/azopenai/event_reader_test.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestEventReader_InvalidType(t *testing.T) {
2424

2525
firstEvent, err := eventReader.Read()
2626
require.Empty(t, firstEvent)
27-
require.EqualError(t, err, "Unexpected event type: invaliddata")
27+
require.EqualError(t, err, "unexpected event type: invaliddata")
2828
}
2929

3030
type badReader struct{}
@@ -35,8 +35,23 @@ func (br badReader) Read(p []byte) (n int, err error) {
3535

3636
func TestEventReader_BadReader(t *testing.T) {
3737
eventReader := newEventReader[ChatCompletions](io.NopCloser(badReader{}))
38+
defer eventReader.Close()
3839

3940
firstEvent, err := eventReader.Read()
4041
require.Empty(t, firstEvent)
4142
require.ErrorIs(t, io.ErrClosedPipe, err)
4243
}
44+
45+
func TestEventReader_StreamIsClosedBeforeDone(t *testing.T) {
46+
buff := strings.NewReader("data: {}")
47+
48+
eventReader := newEventReader[ChatCompletions](io.NopCloser(buff))
49+
50+
evt, err := eventReader.Read()
51+
require.Empty(t, evt)
52+
require.NoError(t, err)
53+
54+
evt, err = eventReader.Read()
55+
require.Empty(t, evt)
56+
require.EqualError(t, err, "incomplete stream")
57+
}

0 commit comments

Comments
 (0)