Neuron Stavový automat relace
Tento vzor se hodí, když se to, co vytváříte, podobá spíše relaci než jednorázovému běhu.
Stavové automaty Queuety řídí životní cyklus relace, workflow Queuety zajišťují práci na pozadí, která těží z opakování pokusů, režimů dokončení pro každou položku a agregace, a Neuron zajišťuje samotná volání agenta a paměť konverzace.
Toto rozdělení se hodí pro asistenty podpory, interní výzkumné asistenty, redakční agenty, kteří mohou čekat na lidské posouzení, i chatová vlákna, která přecházejí mezi fázemi plánování, čekání a odpovídání.
Průběh životního cyklu
V tomto příkladu prochází jedna relace podpory stavy awaiting_user, planning, waiting_on_research a responding. Automat zachovává tento životní cyklus přehledný, zatímco workflow na pozadí shromažďuje podklady a po dokončení o tom relaci informuje.
Stavový automat
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',
] );
Když uživatel odešle zprávu:
Queuety::machine_event(
$session_id,
'user_message',
[
'session_machine_id' => $session_id,
'message' => 'Can you compare our pricing to the main competitors?',
]
);
Automat přejde do stavu planning, zařadí svou akci do fronty a spustí výzkumné workflow.
Plánovací akce: spuštění workflow
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',
];
}
}
Tato stavová akce se nepokouší provádět výzkum sama. Spustí workflow a uloží jeho ID do stavu automatu.
Krok workflow: informování automatu o dokončení výzkumu
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 [];
}
}
Po dokončení workflow odešle do automatu událost research_completed a připojí syntetizovaný souhrn jako její data.
Akce odpovědi: volání Neuron s pamětí relace
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',
];
}
}
Po vytvoření odpovědi se automat vrátí do stavu awaiting_user s aktualizovanou odpovědí ve veřejném stavu. Stejná relace pak může přijmout další událost user_message a pokračovat.
Proč je to přehlednější než jedno velké workflow
Náročná část má stále podobu workflow, protože výzkum vyžaduje plánování, běhy specialistů, agregaci a syntézu. Dlouhodobá konverzace podpory má podobu stavového automatu, protože relace musí sledovat, zda čeká na vstup uživatele, na výsledky výzkumu, nebo zda může odeslat odpověď.
Toto rozdělení zpřehledňuje běh a jasně vymezuje model relace.