Repository: openai/openai-python

Issue:
Json parsing issue when using openai.Completion.acreate(stream=True)
See the last line, looks like the stream iterator might be breaking up parts where it shouldn't? Unless it's an API issue. cc @ddeville 

```
Traceback (most recent call last):
  File "/Users/nuno/Library/Caches/pypoetry/virtualenvs/platform-api-30l3Kv3P-py3.10/lib/python3.10/site-packages/openai/api_requestor.py", line 670, in _interpret_response_line
    data = json.loads(rbody)
  File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 191 (char 190)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/nuno/dev/concat/server-py/concat/conversation.py", line 87, in handle_conversation
    await run
  File "/Users/nuno/dev/concat/server-py/concat/agent/openai/openai.py", line 122, in __call__
    msg, _ = await asyncio.gather(
  File "/Users/nuno/dev/concat/server-py/concat/tools/multi_prompt.py", line 87, in __call__
    return await self.call(prompt["prompt"], examples, input, ctx)
  File "/Users/nuno/dev/concat/server-py/concat/tools/sql/__init__.py", line 59, in call
    async for key, msg in ctx.stream_multi_message_async(
  File "/Users/nuno/dev/concat/server-py/concat/context/context.py", line 419, in stream_multi_message_async
    async for text in iterator:
  File "/Users/nuno/dev/concat/server-py/concat/utils/openai.py", line 37, in openai_completion_stream
    async for chunk in cast(
  File "/Users/nuno/Library/Caches/pypoetry/virtualenvs/platform-api-30l3Kv3P-py3.10/lib/python3.10/site-packages/openai/api_resources/abstract/engine_api_resource.py", line 230, in <genexpr>
    return (
  File "/Users/nuno/Library/Caches/pypoetry/virtualenvs/platform-api-30l3Kv3P-py3.10/lib/python3.10/site-packages/openai/api_requestor.py", line 320, in wrap_resp
    async for r in resp:
  File "/Users/nuno/Library/Caches/pypoetry/virtualenvs/platform-api-30l3Kv3P-py3.10/lib/python3.10/site-packages/openai/api_requestor.py", line 635, in <genexpr>
    self._interpret_response_line(
  File "/Users/nuno/Library/Caches/pypoetry/virtualenvs/platform-api-30l3Kv3P-py3.10/lib/python3.10/site-packages/openai/api_requestor.py", line 672, in _interpret_response_line
    raise error.APIError(
openai.error.APIError: HTTP code 200 from API ({"id": "cmpl-6YxjgLI6W6XwRj8hqhDZ6aCFz19Hp", "object": "text_completion", "created": 1673790796, "choices": [{"text": "sche", "index": 0, "logprobs": null, "finish_reason": null}], "model": ")
```


Discussion:
Huh, that's weird. Any chance you have a command to recreate it? 
 No, this was only once, out of many similar requests. The same request (or
as close to same as I could) repeated after didn’t trigger this error.


On Sun, Jan 15 2023 at 4:31 pm, hallacy ***@***.***> wrote:

> Huh, that's weird. Any chance you have a command to recreate it?
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/openai/openai-python/issues/184#issuecomment-1383193806>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAAN4RSOMLYQSZF5QSWDSN3WSQQ4LANCNFSM6AAAAAAT34ET6M>
> .
> You are receiving this because you authored the thread.Message ID:
> ***@***.***>
>

I just got this exact error and seems like an isolated case. I noticed it was taking long to get the response, like 2min, and eventually it raised that exception. This is the python code I used with v0.26.1:

```python
response = openai.Image.create(
  prompt='a kitten splashing on an aquarium full of candy´,
  n=10,
  size="1024x1024",
  response_format='b64_json'
)
```

Resolving patch:
diff --git a/openai/api_requestor.py b/openai/api_requestor.py
--- a/openai/api_requestor.py
+++ b/openai/api_requestor.py
@@ -96,8 +96,10 @@ def parse_stream_helper(line: bytes) -> Optional[str]:
             # and it will close http connection with TCP Reset
             return None
         if line.startswith(b"data: "):
-            line = line[len(b"data: ") :]
-        return line.decode("utf-8")
+            line = line[len(b"data: "):]
+            return line.decode("utf-8")
+        else:
+            return None
     return None
 
 
@@ -109,13 +111,10 @@ def parse_stream(rbody: Iterator[bytes]) -> Iterator[str]:
 
 
 async def parse_stream_async(rbody: aiohttp.StreamReader):
-    async for chunk, _ in rbody.iter_chunks():
-        # While the `ChunkTupleAsyncStreamIterator` iterator is meant to iterate over chunks (and thus lines) it seems
-        # to still sometimes return multiple lines at a time, so let's split the chunk by lines again.
-        for line in chunk.splitlines():
-            _line = parse_stream_helper(line)
-            if _line is not None:
-                yield _line
+    async for line in rbody:
+        _line = parse_stream_helper(line)
+        if _line is not None:
+            yield _line
 
 
 class APIRequestor:


Test patch: