Ga naar de inhoud

Neuron Streamingstap

Dit voorbeeld laat een heldere taakverdeling zien. Neuron streamt het agentantwoord deel voor deel, terwijl Queuety elk deel duurzaam opslaat via StreamingStep. Daardoor kan UI een live concept ontvangen, terwijl de workflow bestand blijft tegen crashes van workers en nieuwe pogingen.

Wanneer dit patroon handig is

Gebruik dit patroon wanneer een concept of antwoord lang genoeg is om live te streamen, wanneer je gedeeltelijke uitvoer niet wilt verliezen als de worker uitvalt en wanneer het uiteindelijke resultaat na afloop van de stream in de workflowstatus moet blijven staan.

De agent van Neuron

PHP
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.',
            ],
        );
    }
}

De streamingstap van Queuety

PHP
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,
        ];
    }
}

Gebruiken in een workflow

PHP
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',
    ]);

Waarom Queuety gebruiken in plaats van alleen streamadapters van Neuron

De streamadapters van Neuron zijn handig voor frontendprotocollen en transporten. Queuety doet iets anders: elk vrijgegeven deel wordt opgeslagen, nieuwe pogingen kunnen verdergaan met eerder opgeslagen delen, het voltooide concept wordt teruggezet in de workflowstatus en de stream wordt één duurzame stap in een grotere orkestratie.

Dat maakt dit patroon geschikt wanneer de stream deel uitmaakt van een proces met meerdere stappen, en niet alleen van een aanvraag-antwoord-UI.

Eén aandachtspunt

Als je agent van Neuron tijdens het streamen tools gebruikt, verwerk dan de typen gestreamde delen expliciet. De huidige streamingdocumentatie van Neuron beschrijft TextChunk, ReasoningChunk, ToolCallChunk en ToolResultChunk. Voor een workflow die op de achtergrond concepten opstelt, is het meestal het eenvoudigst om de streamende agent alleen tekst te laten produceren.