main: 引入 AgentProvider 流式事件与 OpenAI 兼容适配
- 增加流式事件流支持,Provider 输出 `message.delta` 等事件 - 实现 OpenAI 兼容适配器,包括 RequestBuilder、ApiClient 等模块 - 更新 Agent Run 逻辑,支持流式增量写入与模型完成状态管理 - 扩展配置项 `agent.openai.*`,支持模型、密钥等配置 - 优化文档,完善流式事件与消息类型说明 - 增加单元测试,覆盖 Provider 和 OpenAI 适配相关逻辑 - 更新环境变量与配置示例,支持新功能
This commit is contained in:
75
app/Services/Agent/OpenAi/OpenAiStreamParser.php
Normal file
75
app/Services/Agent/OpenAi/OpenAiStreamParser.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Agent\OpenAi;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
class OpenAiStreamParser
|
||||
{
|
||||
public function __construct(private readonly int $chunkSize = 1024)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses SSE data lines into payload strings.
|
||||
*
|
||||
* @return \Generator<int, string>
|
||||
*/
|
||||
public function parse(StreamInterface $stream, ?callable $shouldStop = null): \Generator
|
||||
{
|
||||
$buffer = '';
|
||||
$eventData = '';
|
||||
|
||||
while (! $stream->eof()) {
|
||||
if ($shouldStop && $shouldStop()) {
|
||||
break;
|
||||
}
|
||||
|
||||
$chunk = $stream->read($this->chunkSize);
|
||||
|
||||
if ($chunk === '') {
|
||||
usleep(10000);
|
||||
continue;
|
||||
}
|
||||
|
||||
$buffer .= $chunk;
|
||||
|
||||
while (($pos = strpos($buffer, "\n")) !== false) {
|
||||
$line = substr($buffer, 0, $pos);
|
||||
$buffer = substr($buffer, $pos + 1);
|
||||
$line = rtrim($line, "\r");
|
||||
|
||||
if ($line === '') {
|
||||
if ($eventData !== '') {
|
||||
yield $eventData;
|
||||
$eventData = '';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_starts_with($line, 'data:')) {
|
||||
$data = ltrim(substr($line, 5));
|
||||
if ($eventData !== '') {
|
||||
$eventData .= "\n";
|
||||
}
|
||||
$eventData .= $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($buffer !== '') {
|
||||
$line = rtrim($buffer, "\r");
|
||||
if (str_starts_with($line, 'data:')) {
|
||||
$data = ltrim(substr($line, 5));
|
||||
if ($eventData !== '') {
|
||||
$eventData .= "\n";
|
||||
}
|
||||
$eventData .= $data;
|
||||
}
|
||||
}
|
||||
|
||||
if ($eventData !== '') {
|
||||
yield $eventData;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user