خطوة Neuron للبث
يعرض هذا المثال تقسيمًا واضحًا. يبث Neuron استجابة الوكيل جزءًا تلو الآخر، بينما يحفظ Queuety كل جزء بشكل دائم عبر StreamingStep. وهذا يتيح لـUI تلقي مسودة مباشرة، مع استمرار سير العمل رغم تعطل العامل أو إعادة المحاولة.
متى يفيد هذا النمط
استخدمه عندما تكون المسودة أو الاستجابة طويلة بما يكفي لتبثها مباشرة، وعندما لا تريد فقدان المخرجات الجزئية إذا توقف العامل، وعندما ينبغي أن يبقى الناتج النهائي في حالة سير العمل بعد اكتمال البث.
وكيل Neuron
namespace App\Neuron;
use NeuronAI\Agent\Agent;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\OpenAI\Responses\OpenAIResponses;
use NeuronAI\SystemPrompt;
final class DraftMemoAgent extends Agent
{
protected function provider(): AIProviderInterface
{
return new OpenAIResponses(
key: $_ENV['OPENAI_API_KEY'],
model: $_ENV['OPENAI_MODEL'],
);
}
public function instructions(): string
{
return (string) new SystemPrompt(
background: [
'You write crisp internal strategy memos.',
'Prefer short sections and operationally useful language.',
],
);
}
}
خطوة البث في Queuety
namespace App\Workflow\Steps;
use App\Neuron\DraftMemoAgent;
use NeuronAI\Chat\Messages\UserMessage;
use Queuety\Contracts\StreamingStep;
use Queuety\Heartbeat;
final class StreamMemoDraftStep implements StreamingStep
{
public function stream(array $state, array $existing_chunks = []): \Generator
{
if (! empty($existing_chunks)) {
return;
}
$handler = (new DraftMemoAgent())->stream(
new UserMessage(sprintf(
"Write a strategy memo about %s for account %d.",
$state['topic'],
$state['account_id'],
))
);
foreach ($handler->events() as $i => $chunk) {
Heartbeat::beat(['chunks' => $i + 1]);
// This example assumes the agent has no tools attached, so
// Neuron will stream text/reasoning chunks only.
yield $chunk->content;
}
}
public function on_complete(array $chunks, array $state): array
{
return [
'draft_markdown' => implode('', $chunks),
];
}
public function config(): array
{
return [
'max_attempts' => 3,
];
}
}
استخدامه في سير عمل
use Queuety\Queuety;
Queuety::workflow('memo_drafting')
->then(BuildDraftBriefStep::class)
->then(StreamMemoDraftStep::class)
->then(StoreMemoStep::class)
->dispatch([
'account_id' => 10,
'topic' => 'pricing changes for enterprise accounts',
]);
لماذا تستخدم Queuety بدلًا من محولات بث Neuron وحدها
تفيد محولات البث في Neuron لبروتوكولات الواجهة الأمامية ووسائل النقل. ويضيف Queuety ميزة مختلفة: يُحفظ كل جزء مُنتج، ويمكن استئناف المحاولات باستخدام الأجزاء المحفوظة سابقًا، وتُدمج المسودة المكتملة مجددًا في حالة سير العمل، ويصبح البث خطوة دائمة واحدة ضمن تنسيق أكبر.
يجعل ذلك هذا النمط مناسبًا عندما يكون البث جزءًا من عملية أعمال متعددة الخطوات، وليس مجرد UI طلب واستجابة.
تنبيه واحد
إذا كان وكيل Neuron يستخدم أدوات أثناء البث، فتعامَل صراحةً مع أنواع الأجزاء المتدفقة. تصف مستندات البث الحالية في Neuron الأنواع TextChunk وReasoningChunk وToolCallChunk وToolResultChunk. وفي سير عمل صياغة خلفي، غالبًا ما يكون أبسط نهج هو إبقاء نص وكيل البث فقط.