Django HttpStreamingResponse Not Streaming

У меня возникла очень интересная проблема с Django HttpStreamingResponse. Наш сервер вызывает OpenAI Text Completion API в потоковом режиме, после получения фрагментов от OpenAI, мы инкрементально разбираем фрагменты и передаем полные JSON объекты обратно нашим клиентам. Ниже приведены некоторые фрагменты кода:

views.py

class StreamViewSet(ModelViewSet):
    ...
    def stream(self, request):
       ...
       json_stream = agent.get_json_objects()
       return StreamingHttpResponse(json_stream, content_type="application/json")

agents.py

    def stream(self):
        yield from self.json_agent.get_json_stream()

json_agent.py

def get_data_stream(self):
    # This calls OpenAI text completion API with stream=True
    stream_response = self.get_text_completion(user_preference, stream=True)

    # Create an incremental json parser
    json_stream_parser = JsonStreamParser()

    for chunk in stream_response:
        if chunk.choices and chunk.choices[0].delta.content is not None:
            json_stream_parser.feed(chunk.choices[0].delta.content)
            yield from json_stream_parser.parse()

json_parser.py

class JsonStreamParser:
    """A simple JSON stream parser that can parse a stream of JSON objects.
    Note it only works for an array of JSON objects, which means the input
    must contain a valid JSON array, at any point of the stream, that starts with '[' and ends with ']'.
    It will parse the JSON objects in the array and ignores anything outside of the array.
    """
    def __init__(self):
        self.buffer = ""
        self.index = 0
        self.open_braces = 0
        self.start_index = -1
        self.array_started = False

    def feed(self, data):
        self.buffer += data

    def parse(self):
        parsed = []
        while self.index < len(self.buffer):
            if self.buffer[self.index] == '[':
                self.array_started = True

            if self.buffer[self.index] == '{' and self.array_started:
                # If the start_index is -1, then we have found the start of a json object
                if self.start_index == -1:
                    self.start_index = self.index
                self.open_braces += 1

            elif self.buffer[self.index] == '}':
                self.open_braces -= 1
                # If the open_braces is 0, then we have found a complete json object
                if self.open_braces == 0 and self.start_index != -1:
                    j_obj = self.buffer[self.start_index:self.index+1]
                    parsed.append(j_obj)
                    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    # However, it will not work with
                    # parsed.append(json.loads(j_obj))
                    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                    # Reset the start_index and the buffer
                    self.start_index = -1
                    self.buffer = self.buffer[self.index:]
                    self.index = 0
            self.index += 1

        return parsed

    def flush(self):
        self.buffer = ""
        self.index = 0

Промежуточное ПО и приложения, которые я установил на сервер django, следующие:


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework.authtoken',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ]
}

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Этот код отлично работает, передавая текст нашим клиентам, пока я не добавлю json.loads() в json_parser.py, где я хочу, чтобы он возвращал json-объект вместо текста. В чем может быть проблема, которая блокирует потоковую передачу и буферизует все данные перед отправкой в ответ?

Я пытался удалить некоторые промежуточные программы, но они, похоже, не связаны между собой. Я пробовал писать код генератора разными способами, но это не помогло.

Вернуться на верх