Pereiti prie turinio

Neuron Atminties ir peržiūros būsenų mašina

Šis šablonas naudingas, kai agentas turi išlaikyti pokalbio kontekstą per kelis žmogaus atliekamus peržiūros etapus, o visą gyvavimo ciklą ir toliau turi orkestruoti Queuety.

Queuety valdo peržiūros būsenų mašiną, o Neuron – agento juodraščio kūrimo gijos atmintį.

Kodėl čia praverčia Neuron atmintis

Jei peržiūrintysis atmeta juodraštį ir paprašo jį pataisyti, kitą kartą iškviestam agentui neturėtų tekti iš naujo atkurti viso konteksto.

Neuron SQLChatHistory tam puikiai tinka, nes agentas gali toliau dirbti toje pačioje pokalbio gijoje, o Queuety nukreipia peržiūrėtojo sprendimus ir taisymų etapus.

Agentas Neuron su SQL paremta istorija

PHP
namespace App\Neuron;

use NeuronAI\Agent\Agent;
use NeuronAI\Chat\History\ChatHistoryInterface;
use NeuronAI\Chat\History\SQLChatHistory;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\Anthropic\Anthropic;
use NeuronAI\SystemPrompt;

final class EditorAgent extends Agent
{
    public function __construct(
        private readonly string $threadId,
        private readonly \PDO $pdo,
    ) {}

    protected function provider(): AIProviderInterface
    {
        return new Anthropic(
            key: $_ENV['ANTHROPIC_API_KEY'],
            model: $_ENV['ANTHROPIC_MODEL'],
        );
    }

    protected function chatHistory(): ChatHistoryInterface
    {
        return new SQLChatHistory(
            thread_id: $this->threadId,
            pdo: $this->pdo,
            table: 'neuron_chat_history',
            contextWindow: 50000,
        );
    }

    public function instructions(): string
    {
        return (string) new SystemPrompt(
            background: [
                'You are an editorial agent for long-form product briefs.',
                'Apply reviewer notes without losing the original intent.',
            ],
        );
    }
}

Pirmasis juodraštis ir jo taisymas toje pačioje atminties gijoje

PHP
namespace App\StateMachines\Actions;

use App\Neuron\EditorAgent;
use NeuronAI\Chat\Messages\UserMessage;
use Queuety\Contracts\StateAction;

final class DraftBriefAction implements StateAction
{
    public function handle(array $state, ?string $event = null, array $event_payload = [], array $payload = []): array|string
    {
        // Queuety creates actions with `new DraftBriefAction()`, so build dependencies here.
        $pdo = new \PDO($_ENV['NEURON_DB_DSN'], $_ENV['NEURON_DB_USER'], $_ENV['NEURON_DB_PASSWORD']);

        $threadId = $state['neuron_thread_id'] ?? sprintf(
            'brief:%d:editor',
            $state['brief_id'],
        );

        $prompt = "Write the first draft for brief {$state['brief_id']}.";

        if ('reject' === $event) {
            $prompt = sprintf(
                'Revise the draft using these review notes: %s',
                $event_payload['reason'] ?? 'Tighten the draft and address reviewer concerns.',
            );
        }

        $agent = new EditorAgent($threadId, $pdo);
        $message = $agent->chat(
            new UserMessage($prompt)
        )->getMessage();

        return [
            'neuron_thread_id' => $threadId,
            'draft_markdown' => $message->getContent(),
            'review_round' => (int) ($state['review_round'] ?? 0) + 1,
            '_event' => 'draft_ready',
        ];
    }
}

Queuety būsenų mašina

PHP
use Queuety\Enums\StateMachineStatus;
use Queuety\Queuety;

$machine_id = Queuety::machine('brief_review_session')
    ->version('brief-review-session.v1')
    ->state('drafting')
    ->action(DraftBriefAction::class)
    ->on('draft_ready', 'awaiting_review')
    ->state('awaiting_review')
    ->on('approve', 'completed')
    ->on('reject', 'drafting')
    ->state('completed', StateMachineStatus::Completed)
    ->dispatch([
        'brief_id' => 42,
    ]);

// Later, once the draft action has finished and the machine waits in `awaiting_review`:
Queuety::machine_event(
    $machine_id,
    'reject',
    [ 'reason' => 'Tighten the introduction and add pricing context.' ]
);

Queuety::machine_event(
    $machine_id,
    'approve',
    [ 'reviewer' => 'editor@example.com' ]
);

Pirmasis bandymas pereina į drafting, įvykdo eilėje esančią veiksmą ir pereina į awaiting_review.

Jei peržiūrintysis juodraštį atmeta, mašina grįžta į drafting. Kadangi įvykio reject duomenys perduodami į DraftBriefAction, kitame juodraštyje galima panaudoti peržiūrėtojo pastabas ir išsaugoti pradinę Neuron gijos istoriją.

Kodėl tai paprasčiau nei kartoti darbo eigą

Ši problema susijusi su gyvavimo ciklu. Juodraštis laukia žmogaus peržiūros, peržiūrintysis gali jį patvirtinti arba atmesti, atmetus sesija grįžta prie juodraščio kūrimo, o patvirtinus sesija baigiama. Tai tiesiogiai atitinka būsenų mašiną, o ne linijinę darbo eigą su grįžtamuoju ryšiu.

Darbo eigos būsena puikiai tinka orkestravimo duomenims, pavyzdžiui, peržiūros etapų skaičiui, artefaktų ID, darbo eigos ID ir maršrutizavimo sprendimams. Neuron atmintis geriau tinka pokalbio kontekstui, pavyzdžiui, ankstesnėms užklausoms, nuosekliems taisymams ir modelio atsakymams, kurie turi likti juodraščio kūrimo gijos dalimi.

Naudojant abi sistemas, kiekviena atlieka tai, ką moka geriausiai.

Kada geriau palikti tai darbo eiga

Darbo eigą rinkitės, kai peržiūros procesas yra aiškiai apibrėžtas ir orientuotas į vykdymą, pavyzdžiui:

Sukurkite vieną juodraštį, palaukite vieno patvirtinimo ir paskelbkite.

Būsenų mašiną rinkitės, kai sesija gali kelis kartus grįžti į tas pačias būsenas, o jos gyvavimo ciklą lemia išoriniai įvykiai.