Neuron Sessionstillståndsmaskin
Det här mönstret är användbart när det du bygger fungerar mer som en session än som en engångskörning.
Queuety-tillståndsmaskiner hanterar sessionens livscykel, Queuety-arbetsflöden utför bakgrundsarbetet som gynnas av omförsök, for-each-slutförandelägen och aggregering, och Neuron hanterar själva agentanropen och konversationsminnet.
Den här uppdelningen passar bra för supportassistenter, interna researchassistenter, redaktionella agenter som kan pausas för mänsklig granskning och chatttrådar som växlar mellan planering, väntan och svar.
Livscykelns förlopp
I det här exemplet går en supportsession igenom awaiting_user, planning, waiting_on_research och responding. Maskinen håller livscykeln tydlig, medan ett bakgrundsarbetsflöde samlar in research och signalerar till sessionen när det är klart.
Tillståndsmaskinen
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 användare skickar ett meddelande:
Queuety::machine_event(
$session_id,
'user_message',
[
'session_machine_id' => $session_id,
'message' => 'Can you compare our pricing to the main competitors?',
]
);
Maskinen övergår till planning, köar sin åtgärd och startar researcharbetsflödet.
Planeringsåtgärd: skicka iväg arbetsflödet
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',
];
}
}
Den här tillståndsåtgärden utför inte researchen själv. Den skickar iväg ett arbetsflöde och sparar arbetsflödes-ID:t i maskinens tillstånd.
Arbetsflödessteg: signalera till maskinen när researchen är 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 arbetsflödet är klart skickar det research_completed tillbaka till maskinen och inkluderar det sammanställda underlaget som händelsenyttolast.
Svarsåtgärd: anropa Neuron med sessionsminnet
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 har skapats övergår maskinen tillbaka till awaiting_user med det uppdaterade svaret i det offentliga tillståndet. Samma session kan sedan ta emot ytterligare en user_message-händelse och fortsätta.
Därför är detta enklare än ett stort arbetsflöde
Det omfattande arbetet följer fortfarande arbetsflödesmodellen eftersom researchdelen kräver planering, specialistsessioner, aggregering och sammanställning. Den långlivade supportkonversationen följer tillståndsmaskinsmodellen eftersom sessionen måste hålla reda på om den väntar på användaren, väntar på research eller får skicka ett svar.
Den här uppdelningen gör körningen lättare att följa och håller sessionsmodellen tydlig.