main: 引入 AgentProvider 流式事件与 OpenAI 兼容适配
- 增加流式事件流支持,Provider 输出 `message.delta` 等事件 - 实现 OpenAI 兼容适配器,包括 RequestBuilder、ApiClient 等模块 - 更新 Agent Run 逻辑,支持流式增量写入与模型完成状态管理 - 扩展配置项 `agent.openai.*`,支持模型、密钥等配置 - 优化文档,完善流式事件与消息类型说明 - 增加单元测试,覆盖 Provider 和 OpenAI 适配相关逻辑 - 更新环境变量与配置示例,支持新功能
This commit is contained in:
50
app/Services/Agent/OpenAi/OpenAiEventNormalizer.php
Normal file
50
app/Services/Agent/OpenAi/OpenAiEventNormalizer.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Agent\OpenAi;
|
||||
|
||||
use App\Services\Agent\ProviderEvent;
|
||||
|
||||
class OpenAiEventNormalizer
|
||||
{
|
||||
/**
|
||||
* Normalizes a single SSE payload into ProviderEvent values.
|
||||
*
|
||||
* @return array<int, ProviderEvent>
|
||||
*/
|
||||
public function normalize(string $payload): array
|
||||
{
|
||||
if (trim($payload) === '[DONE]') {
|
||||
return [ProviderEvent::done('done')];
|
||||
}
|
||||
|
||||
$decoded = json_decode($payload, true);
|
||||
|
||||
if (! is_array($decoded)) {
|
||||
return [ProviderEvent::error('INVALID_JSON', 'Agent provider returned invalid JSON', [
|
||||
'raw' => $payload,
|
||||
])];
|
||||
}
|
||||
|
||||
$events = [];
|
||||
$choices = $decoded['choices'] ?? [];
|
||||
$firstChoice = is_array($choices) ? ($choices[0] ?? null) : null;
|
||||
$delta = is_array($firstChoice) ? ($firstChoice['delta'] ?? null) : null;
|
||||
|
||||
if (is_array($delta)) {
|
||||
$content = $delta['content'] ?? null;
|
||||
if (is_string($content) && $content !== '') {
|
||||
$events[] = ProviderEvent::messageDelta($content);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($firstChoice) && array_key_exists('finish_reason', $firstChoice) && $firstChoice['finish_reason'] !== null) {
|
||||
$events[] = ProviderEvent::done((string) $firstChoice['finish_reason']);
|
||||
}
|
||||
|
||||
if (isset($decoded['usage']) && is_array($decoded['usage'])) {
|
||||
$events[] = ProviderEvent::usage($decoded['usage']);
|
||||
}
|
||||
|
||||
return $events;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user