Neuron Sessionstilstandsmaskine
Dette mønster er nyttigt, når det, du bygger, minder mere om en session end en enkeltstående kørsel.
Queuety-tilstandsmaskiner styrer sessionens livscyklus, Queuety-workflows udfører baggrundsarbejde, der drager fordel af nye forsøg, færdiggørelsestilstande for hver iteration og sammenlægning, og Neuron håndterer selve agentkald og samtalehukommelse.
Denne opdeling passer godt til supportcopiloter, interne forskningsassistenter, redaktionelle agenter, der kan afvente menneskelig gennemgang, og chattråde, der bevæger sig mellem planlægning, ventetid og svarfaser.
Livscyklusforløb
I dette eksempel bevæger én supportsession sig gennem awaiting_user, planning, waiting_on_research og responding. Maskinen holder livscyklussen tydelig, mens et baggrundsworkflow indsamler research og giver sessionen besked, når det er færdigt.
Tilstandsmaskinen
use Queuety\Queuety;
$session_id = Queuety::machine( 'support_session' )
->version( 'support-session.v1' )
->state( 'awaiting_user' )
->on( 'user_message', 'planning' )
->state( 'planning' )
->action( DispatchResearchWorkflowAction::class )
->on( 'research_dispatched', 'waiting_on_research' )
->state( 'waiting_on_research' )
->on( 'research_completed', 'responding' )
->state( 'responding' )
->action( RespondWithNeuronAction::class )
->on( 'response_ready', 'awaiting_user' )
->dispatch( [
'thread_id' => 'support:customer-42',
] );
Når en bruger sender en besked:
Queuety::machine_event(
$session_id,
'user_message',
[
'session_machine_id' => $session_id,
'message' => 'Can you compare our pricing to the main competitors?',
]
);
Maskinen går over i planning, sætter sin handling i kø og starter researchworkflowet.
Planlægningshandling: Send workflowet videre
namespace App\StateMachines\Actions;
use Queuety\Contracts\StateAction;
use Queuety\Enums\WaitMode;
use Queuety\Queuety;
final class DispatchResearchWorkflowAction implements StateAction
{
public function handle( array $state, ?string $event = null, array $event_payload = [], array $payload = [] ): array|string
{
$message = trim( (string) ( $event_payload['message'] ?? '' ) );
$agent_workflow = Queuety::workflow( 'support_research_agent' )
->then( ResearchTopicStep::class );
$research_workflow = Queuety::workflow( 'support_research_packet' )
->then( PlanResearchTasksStep::class )
->start_agents( 'agent_tasks', $agent_workflow )
->wait_for_agents( mode: WaitMode::All, result_key: 'agent_results' )
->then( SynthesizeResearchPacketStep::class )
->then( NotifySessionResearchReadyStep::class );
$workflow_id = $research_workflow->dispatch( [
'machine_id' => $state['session_machine_id'],
'thread_id' => $state['thread_id'],
'customer_prompt' => $message,
] );
return [
'latest_user_message' => $message,
'research_workflow_id' => $workflow_id,
'_event' => 'research_dispatched',
];
}
}
Denne tilstandshandling forsøger ikke selv at udføre researchen. Den sender et workflow videre og registrerer workflow-id'et i maskinens tilstand.
Workflowtrin: Giv maskinen besked, når researchen er klar
namespace App\Workflow\Steps;
use Queuety\Queuety;
use Queuety\Step;
final class NotifySessionResearchReadyStep implements Step
{
public function handle( array $state ): array
{
Queuety::machine_event(
$state['machine_id'],
'research_completed',
[
'research_packet' => $state['research_packet'],
]
);
return [];
}
public function config(): array
{
return [];
}
}
Når workflowet er færdigt, sender det research_completed tilbage til maskinen og inkluderer den syntetiserede pakke som hændelsens payload.
Svarhandling: Kald Neuron med sessionens hukommelse
namespace App\StateMachines\Actions;
use App\Neuron\SupportAgent;
use NeuronAI\Chat\Messages\UserMessage;
use Queuety\Contracts\StateAction;
final class RespondWithNeuronAction implements StateAction
{
public function handle( array $state, ?string $event = null, array $event_payload = [], array $payload = [] ): array|string
{
// Queuety creates actions with `new RespondWithNeuronAction()`, so build dependencies here.
$pdo = new \PDO( $_ENV['NEURON_DB_DSN'], $_ENV['NEURON_DB_USER'], $_ENV['NEURON_DB_PASSWORD'] );
$agent = new SupportAgent(
threadId: $state['thread_id'],
pdo: $pdo,
);
$message = $agent->chat(
new UserMessage(
sprintf(
"Answer the user message '%s' using this research packet:\n\n%s",
$state['latest_user_message'],
json_encode( $state['research_packet'] ?? [], JSON_PRETTY_PRINT )
)
)
)->getMessage();
return [
'assistant_reply' => $message->getContent(),
'_event' => 'response_ready',
];
}
}
Når svaret er genereret, går maskinen tilbage til awaiting_user med det opdaterede svar i den offentlige tilstand. Den samme session kan derefter modtage endnu en user_message-hændelse og fortsætte.
Hvorfor dette er enklere end ét stort workflow
Det tunge arbejde udføres stadig i et workflow, fordi researchdelen kræver planlægning, specialistkørsler, sammenlægning og syntese. Den langvarige supportsamtale styres af en tilstandsmaskine, fordi sessionen skal holde styr på, om den venter på en brugerbesked, venter på research eller må sende et svar.
Denne opdeling gør kørselstidskoden overskuelig og holder sessionsmodellen tydelig.