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