Neuron Sesijos būsenų mašina
Šis šablonas naudingas, kai kuriama sistema labiau primena sesiją nei vienkartinį vykdymą.
Queuety būsenų mašinos valdo sesijos gyvavimo ciklą, Queuety darbo eigos atlieka foninius darbus, kuriems naudingi pakartotiniai bandymai, ciklinio vykdymo užbaigimo režimai ir rezultatų apibendrinimas, o Neuron tvarko pačius agento iškvietimus ir pokalbio atmintį.
Toks atskyrimas tinka pagalbos tarnybos kopilotams, vidiniams tyrimų asistentams, redagavimo agentams, kurie gali pristabdyti darbą žmogaus peržiūrai, ir pokalbiams, pereinantiems planavimo, laukimo bei atsakymo etapus.
Gyvavimo ciklo struktūra
Šiame pavyzdyje viena pagalbos sesija pereina per awaiting_user, planning, waiting_on_research ir responding būsenas. Mašina aiškiai valdo šį gyvavimo ciklą, o foninė darbo eiga surenka tyrimo medžiagą ir praneša sesijai, kai darbas baigtas.
Būsenų mašina
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',
] );
Kai naudotojas siunčia pranešimą:
Queuety::machine_event(
$session_id,
'user_message',
[
'session_machine_id' => $session_id,
'message' => 'Can you compare our pricing to the main competitors?',
]
);
Mašina pereina į planning, įtraukia veiksmą į eilę ir paleidžia tyrimo darbo eigą.
Planavimo veiksmas: paleiskite darbo eigą
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',
];
}
}
Šis būsenos veiksmas pats tyrimo neatlieka. Jis paleidžia darbo eigą ir įrašo jos ID į mašinos būseną.
Darbo eigos žingsnis: praneškite mašinai, kai tyrimas paruoštas
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 [];
}
}
Pasibaigusi darbo eiga grąžina į mašiną research_completed ir perduoda apibendrintą medžiagos paketą kaip įvykio duomenis.
Atsakymo veiksmas: iškvieskite Neuron su sesijos atmintimi
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',
];
}
}
Sugeneravus atsakymą, mašina grįžta į awaiting_user ir į viešąją būseną įrašo atnaujintą atsakymą. Tada ta pati sesija gali priimti kitą user_message įvykį ir tęsti darbą.
Kodėl tai paprasčiau nei viena didelė darbo eiga
Sudėtingą darbą vis dar geriausia atlikti darbo eigoje, nes tyrimo daliai reikia planavimo, specialistų vykdymo, rezultatų apibendrinimo ir sintezės. Ilgai veikiantį pagalbos pokalbį geriau valdyti būsenų mašina, nes sesija turi sekti, ar laukia naudotojo pranešimo, tyrimo rezultatų, ar gali pateikti atsakymą.
Taip vykdymo logika išlieka suprantama, o sesijos modelis – aiškus.