如何使用Server-Sent Events流式传输JSON数据

cdmah0mi  于 2023-08-08  发布在  其他
关注(0)|答案(1)|浏览(158)

设置服务器发送事件相对简单-特别是使用FastAPI -您可以这样做:

def fake_data_streamer():
for i in range(10):
    yield "some streamed data"
    time.sleep(0.5)

@app.get('/')
async def main():
    return StreamingResponse(fake_data_streamer())

字符串
在HTTP GET时,连接将每0.5秒返回“一些流数据”。
如果我想流一些结构化数据,比如JSON,该怎么办?
例如,我希望数据是JSON,所以类似于:

def fake_data_streamer():
    for i in range(10):
        yield json.dumps({'result': 'a lot of streamed data', "seriously": ["so", "much", "data"]}, indent=4)
        time.sleep(0.5)


这是一个正确的服务器端实现吗?这是否会造成客户端接收部分形成的有效载荷的风险-这在明文情况下是可以的,但使JSON不可解析?
如果这是好的,你将如何从客户端读取它?大概是这样的:

async def main():
async with aiohttp.ClientSession() as session:
    async with session.get(url) as resp:
        while True:
            chunk = await resp.content.readuntil(b"\n")
            await asyncio.sleep(1)
            if not chunk:
                break
            print(chunk)


虽然我不确定什么样的分隔符/阅读模式才能确保客户端总是接收到完全格式的JSON事件。
或者,这是一种完全不恰当的方式来完成完整的JSON事件的流。
作为参考,OpenAI在其API中实现了完整JSON对象的流式传输:https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb

6g8kf2rb

6g8kf2rb1#

为了澄清和提供一些上下文,OpenAI的客户端API post处理服务器发送的事件,使它们变成漂亮的JSON。但是,“原始”事件是按照 data: only 规范发送的服务器发送事件,如下所示:https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events。您提到的ipython notebook中有指向此规范的链接,以及notebook介绍中的其他资源。
您可以查询开放的AI端点来查看原始服务器事件:
https://asciinema.org/a/TKDYxqh6pgCNN0hX6tdcSgfzU
我使用curl命令:

curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY  -H 'Content-Type: application/json' -d '{"stream": true,"model": "gpt-3.5-turbo-0613", "messages": [ {"role": "user", "content": "Summarize Othello by Shaekspeare in a one line"}]}'

字符串
现在回答你的问题。没有什么可以阻止你做你想要的事情,spec中的示例代码说,你可以非常简单地做到这一点,只需在data:事件的末尾放置一个"\n\n",然后让客户端解析器解析它(在它看到相关的头"Content-Type: text/event-stream"之后)。python中的Requests库实际上使用response_obj.iter_lines()函数为您自动完成此操作。Python还有一个SSE客户端library,它很容易阅读,可以解析此事件并给予完整的data:行。

相关问题