آلة حالات جلسة Neuron
يفيد هذا النمط عندما يشبه ما تبنيه جلسة أكثر من كونه تشغيلًا لمرة واحدة.
تتولى آلات حالات Queuety دورة حياة الجلسة، وتنجز مسارات عمل Queuety المهام الخلفية التي تستفيد من إعادة المحاولة وأوضاع الإكمال لكل عنصر وتجميع النتائج، بينما يتولى Neuron استدعاءات الوكيل الفعلية وذاكرة المحادثة.
يناسب هذا التقسيم مساعدين للدعم، ومساعدي أبحاث داخليين، ووكلاء تحرير قد يتوقفون للمراجعة البشرية، وسلاسل محادثة تنتقل بين مراحل التخطيط والانتظار والرد.
شكل دورة الحياة
في هذا المثال، تنتقل جلسة دعم واحدة بين awaiting_user وplanning وwaiting_on_research وresponding. تحافظ الآلة على وضوح دورة الحياة، بينما يجمع سير عمل في الخلفية الأبحاث ويرسل إشارة إلى الجلسة عند انتهائه.
آلة الحالات
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',
] );
عندما يرسل المستخدم رسالة:
Queuety::machine_event(
$session_id,
'user_message',
[
'session_machine_id' => $session_id,
'message' => 'Can you compare our pricing to the main competitors?',
]
);
تنتقل الآلة إلى planning، وتضع الإجراء في قائمة الانتظار، وتبدأ سير عمل البحث.
إجراء التخطيط: أرسل سير العمل
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',
];
}
}
لا يحاول إجراء هذه الحالة إجراء البحث بنفسه. بل يرسل سير عمل ويسجل معرّفه في حالة الآلة.
خطوة سير العمل: أرسل إشارة إلى الآلة عند جهوز البحث
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 [];
}
}
عند انتهاء سير العمل، يرسل research_completed إلى الآلة، ويضمّن الحزمة المركبة في حمولة الحدث.
إجراء الرد: استدعِ Neuron مع ذاكرة الجلسة
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',
];
}
}
بعد إنشاء الرد، تعود الآلة إلى awaiting_user مع الرد المحدّث في الحالة العامة. ويمكن للجلسة نفسها عندئذٍ استقبال حدث user_message آخر ومتابعة العمل.
لماذا يعد هذا أوضح من سير عمل واحد كبير
تظل المهام الثقيلة مناسبة لمسارات العمل، لأن جانب البحث يحتاج إلى التخطيط وتشغيل المتخصصين وتجميع النتائج وتركيبها. أما محادثة الدعم طويلة الأمد فتناسب آلة الحالات، لأن الجلسة يجب أن تتعقب ما إذا كانت تنتظر دور المستخدم أو انتهاء البحث أو السماح بإرسال رد.
يجعل هذا التقسيم بيئة التشغيل أسهل قراءةً، ويحافظ على وضوح نموذج الجلسة.