Zum Inhalt springen

Neuron-Streaming-Schritt

Dieses Beispiel zeigt eine klare Aufgabenteilung: Neuron streamt die Agentenantwort Stück für Stück, während Queuety jedes Stück über StreamingStep zuverlässig speichert. So kann UI einen Entwurf live empfangen, während der Workflow auch nach Worker-Abstürzen oder Wiederholungen fortgesetzt werden kann.

Wann dieses Muster nützlich ist

Verwende es, wenn ein Entwurf oder eine Antwort lang genug ist, um live gestreamt zu werden, wenn Teilausgaben bei einem Worker-Ausfall nicht verloren gehen sollen und wenn das fertige Ergebnis nach dem Stream weiterhin im Workflow-Zustand verfügbar sein soll.

Der Neuron-Agent

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

Der Queuety-Streaming-Schritt

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

In einem Workflow verwenden

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

Warum Queuety statt alleiniger Neuron-Stream-Adapter verwenden

Die Stream-Adapter von Neuron sind für Frontend-Protokolle und Übertragungswege nützlich. Queuety ergänzt etwas anderes: Jedes ausgegebene Stück wird gespeichert, Wiederholungen können mit den zuvor gespeicherten Stücken fortfahren, der fertige Entwurf wird wieder in den Workflow-Zustand übernommen, und der Stream wird zu einem dauerhaften Schritt in einer größeren Orchestrierung.

Dieses Muster eignet sich daher gut, wenn der Stream Teil eines mehrstufigen Geschäftsprozesses ist und nicht nur einer Anfrage-Antwort-UI.

Ein Hinweis

Wenn dein Neuron-Agent beim Streamen Tools verwendet, verarbeite die gestreamten Elementtypen ausdrücklich. Die aktuellen Streaming-Dokumente von Neuron beschreiben TextChunk, ReasoningChunk, ToolCallChunk und ToolResultChunk. Für einen Workflow zur Hintergrund-Erstellung ist es meist am einfachsten, den Streaming-Agenten auf reinen Text zu beschränken.