/**
* @param $connection
* @param $options
* @param \Closure $dataHandler
* @return \support\Response
*/
private function handleStreamResponse($connection, $options, \Closure $dataHandler) {
try {
$messageId = uniqid('chatcmpl-');
$startTime = time();
$id = Timer::add(0.1, function () use ($connection, &$id, $messageId, $startTime, $options, $dataHandler) {
if ($connection->getStatus() !== TcpConnection::STATUS_ESTABLISHED) {
Timer::del($id);
return;
}
$dataHandler($connection, $messageId, $startTime, $options);
$endData = json_encode([
'id' => uniqid('chatcmpl-'),
'object' => 'chat.completion.chunk',
'created' => time(),
'model' => $options['model'],
'choices' => [[
'delta' => [],
'index' => 0,
'finish_reason' => 'stop'
]]
], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
$connection->send(new Chunk("data: {$endData}\n\n"));
$connection->send(new Chunk(""));
Timer::del($id);
});
} catch (\Throwable $e) {
$errorData = json_encode([
'error' => [
'message' => $e->getMessage(),
'type' => 'error',
'code' => $e->getCode()
]
]);
$connection->send(new Chunk("data: {$errorData}\n"));
}
return response()->withHeaders([
"Content-Type" => "application/json",
"Transfer-Encoding" => "chunked",
]);
}
使用方法(闭包函数是我这边的业务,实际自己看情况写):
if ($stream) {
return $this->handleStreamResponse($connection, $options, function($connection, $messageId, $startTime, $options) use($service, $messages) {
foreach ($service->chatStream($messages, $options) as $chunk) {
if (!empty($chunk)) {
$data = json_encode([
'id' => $messageId,
'object' => 'chat.completion.chunk',
'created' => $startTime,
'model' => $options['model'],
'choices' => [[
'delta' => [
'role' => 'assistant',
'content' => $chunk
],
'index' => 0,
'finish_reason' => null
]]
], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
echo "data: {$data}\n\n";
$connection->send(new Chunk("data: {$data}\n\n"));
}
}
});
}
在控制器中使用流式输出。
尝试了很多方法,在控制器中如果不使用Timer的话,无法正常即时输出。
分享出来我的方法,有更好的方法也希望兄弟们让我学习学习
为啥不用这种
我记得有这个啊
