Към съдържанието

Neuron Машина на състоянията на сесия

Този модел е полезен, когато изгражданата от вас система прилича повече на сесия, отколкото на еднократно изпълнение.

Машините на състоянията Queuety управляват жизнения цикъл на сесията, работните процеси Queuety вършат фоновата работа, за която са полезни повторните опити, режимите за завършване при обработка на всеки елемент и обединяването, а Neuron обработва самите извиквания на агента и паметта на разговора.

Това разделение е подходящо за асистенти за поддръжка, вътрешни изследователски асистенти, редакционни агенти, които може да изчакват човешки преглед, и чат нишки, които преминават през етапи на планиране, изчакване и отговор.

Форма на жизнения цикъл

В този пример една сесия за поддръжка преминава през awaiting_user, planning, waiting_on_research и responding. Машината поддържа този жизнен цикъл изричен, а фонов работен процес събира проучвания и уведомява сесията, когато приключи.

Машината на състоянията

PHP
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',
    ] );

Когато потребител изпрати съобщение:

PHP
Queuety::machine_event(
    $session_id,
    'user_message',
    [
        'session_machine_id' => $session_id,
        'message' => 'Can you compare our pricing to the main competitors?',
    ]
);

Машината преминава в planning, поставя действието си на опашка и стартира работния процес за проучване.

Действие за планиране: изпращане на работния процес

PHP
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',
        ];
    }
}

Това действие на състоянието не извършва самото проучване. То изпраща работен процес и записва неговия ID в състоянието на машината.

Стъпка на работния процес: сигнализиране на машината, когато проучването е готово

PHP
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 с паметта на сесията

PHP
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 и да продължи.

Защо това е по-ясно от един голям работен процес

Тежката работа все още е под формата на работен процес, защото проучването изисква планиране, изпълнения от специалисти, обединяване и синтез. Дълготрайният разговор за поддръжка е под формата на машина на състоянията, защото сесията трябва да следи дали чака ход от потребител, чака проучване или може да изпрати отговор.

Това разделение прави изпълнението по-четимо и модела на сесията изричен.