Ügynökök összehangolása
A(z) Queuety jól illik az ügynökrendszerekhez, ha alkalmazkodó munkát szeretne, de meg akarja tartani a tartós állapotot, az újrapróbálkozásokat, a vizsgálhatóságot és a kifejezett várakozási szemantikát.
A legtöbb ügynökfolyamathoz nincs szüksége futás közben szerkeszthető DAG-motorra. A gyakorlatban a legtöbb rendszer modellezhető néhány tartós összehangolási művelettel. A(z) for_each() egy munkafolyamat-futáson belül bontja ki a munkát. A(z) start_agents() és wait_for_agents() a futás közben felfedezett feladatokat önálló, legfelső szintű munkafolyamatoknak adja át. A(z) wait_for_decision() és wait_for_input() emberi beavatkozásig szüneteltet. A(z) wait_for_workflow(), wait_for_workflows() és wait_for_agent_group() lehetővé teszi, hogy egy legfelső szintű futás megvárjon egy másikat vagy egy elindított kvórumot.
Hasznos gondolkodási modell
Az ügynökök összehangolása rétegekben átlátható a legkönnyebben. A tervező meghatározza, milyen munka van. A(z) Queuety ezt a munkát tartós feladatokká vagy munkafolyamatokká alakítja. A specializált futások eredményeket hoznak létre, és műtermékeket tárolnak. Egy felügyelő szakasz összesíti ezeket az eredményeket, és eldönti, mi történjen ezután. A futás bármely pontján egy ember jóváhagyhatja, elutasíthatja vagy korrigálhatja a folytatás előtt.
A fontos különbség az, hogy az ügynök dönti el, milyen munkát végezzen, de a(z) Queuety továbbra is azt szabályozza, hogyan történik a munka mentése, újrapróbálása, folytatása és összesítése. Ha az összehangolás célja egy hosszú életű munkamenet, nem pedig egy behatárolt futás, párosítsa ezt az Állapotgépek megoldással.
1. minta: Tervező/végrehajtó önálló ügynökfutásokkal
Használja a(z) start_agents() megoldást, ha egy tervezőlépés futás közben fedez fel feladatokat, és mindegyikből önálló, legfelső szintű munkafolyamatnak kell lennie.
use Queuety\Enums\WaitMode;
use Queuety\Queuety;
$agent_run = Queuety::workflow( 'agent_run' )
->then( FetchSourcesStep::class )
->then( DraftFindingStep::class );
Queuety::workflow( 'brief_research' )
->version( 'brief-research.v1' )
->idempotency_key( 'brief:42:research' )
->max_transitions( 20 )
->then( PlanResearchTasksStep::class )
->start_agents( 'agent_tasks', $agent_run, group_key: 'researchers' )
->wait_for_agent_group( 'researchers', WaitMode::Quorum, 2, 'agent_results' )
->then( SynthesizeBriefStep::class )
->dispatch( [ 'brief_id' => 42 ] );
Ebben a mintában a(z) PlanResearchTasksStep a futás közben felfedezett elemeket a(z) $state['agent_tasks'] helyre írja, a(z) start_agents() feladatonként egy tartós munkafolyamatot indít el, a(z) wait_for_agent_group() pedig parkolópályára teszi a szülőt a választott befejezési feltétel teljesüléséig. Ezután a(z) SynthesizeBriefStep a befejezett gyermekállapotokat a(z) $state['agent_results'] alatt kapja meg.
Ez a legjobb kiindulópont a tervező/végrehajtó rendszerekhez, mert minden ügynökfutás önállóan megvizsgálható és újrapróbálható marad.
2. minta: Emberi felülvizsgálat a futás folytatása előtt
Akkor használja a(z) wait_for_decision() megoldást, ha a munkafolyamatnak meg kell állnia egy tényleges igen/nem döntéshez, a(z) wait_for_input() megoldást pedig akkor, ha a kezelő strukturált visszajelzést szeretne küldeni a futásba.
use Queuety\Queuety;
$workflow_id = Queuety::workflow( 'brief_review' )
->then( DraftBriefStep::class )
->wait_for_decision( result_key: 'review' )
->then( HandleReviewDecisionStep::class )
->wait_for_input( result_key: 'revision_notes' )
->then( ApplyRevisionNotesStep::class )
->dispatch( [ 'brief_id' => 42 ] );
Ha a felülvizsgáló jóváhagyja:
Queuety::approve_workflow(
$workflow_id,
[
'reviewer' => 'editor@example.com',
'notes' => 'Looks good, publish after legal check',
],
'approved'
);
Ha a felülvizsgáló elutasítja:
Queuety::reject_workflow(
$workflow_id,
[
'reviewer' => 'editor@example.com',
'reason' => 'Needs citations and a stronger conclusion',
],
'rejected'
);
A(z) wait_for_decision() után a munkafolyamat strukturált adattartalmat kap, amely tartalmazza a végső eredményt, a futást folytató jelzést és a felülvizsgáló által mellékelt adatokat. Ez valódi emberi ellenőrzési pontot biztosít anélkül, hogy a futás várakozása alatt nyitva kellene tartani egy PHP folyamatot.
3. minta: Egy legfelső szintű munkafolyamat megvár egy másikat
Néha nem egyetlen óriási munkafolyamat a legtisztább modell. Az egyik munkafolyamat befejezheti a kutatást, egy másik pedig megvárhatja ezt, mielőtt elindítaná a következő szakaszt.
use Queuety\Enums\WaitMode;
use Queuety\Queuety;
$research_id = Queuety::workflow( 'research_brief' )
->then( PlanResearchTasksStep::class )
->start_agents( 'agent_tasks', $agent_run )
->wait_for_agents( mode: WaitMode::All, result_key: 'agent_results' )
->then( SynthesizeBriefStep::class )
->dispatch( [ 'brief_id' => 42 ] );
Queuety::workflow( 'publish_brief' )
->wait_for_workflow( $research_id, 'research' )
->wait_for_decision( result_key: 'editor_review' )
->then( PublishBriefStep::class )
->dispatch( [ 'brief_id' => 42 ] );
Így tartós határ jön létre a kutatási és a publikálási szakasz között. Minden futásnak saját működési életciklusa van, a második munkafolyamat mégis automatikusan folytatódik, amikor a függőség teljesül.
A megfelelő alapvető építőelem kiválasztása
A(z) for_each() a megfelelő eszköz, ha a munka egy munkafolyamat-futáson belül marad, az elágazások pedig valójában csak lépésszintű párhuzamos végrehajtást jelentenek egy közös állapottárolón.
A(z) start_agents() jobb választás, ha minden felfedezett feladatból önálló, tartós, legfelső szintű futásnak kell lennie, és ezeket külön szeretné megvizsgálni, újrapróbálni vagy exportálni.
A(z) wait_for_workflow() és wait_for_workflows() akkor illik a feladathoz, ha az egyik legfelső szintű munkafolyamat egy másiktól függ, és tartós, aszinkron összehangolást szeretne az összehangolási rétegek között.
A(z) wait_for_decision() és wait_for_input() ott hasznos, ahol egy embernek jóvá kell hagynia, el kell utasítania vagy irányítania kell a futást, miközben a munkafolyamat szünetel, de nem foglal feldolgozói kapacitást.
Javasolt állapotkonvenciók
Az ügynökrendszerek hibakeresése könnyebb, ha az állapotkulcsok kiszámíthatók. A gyakorlatban a(z) agent_tasks jól használható a tervező kimenetéhez, a(z) agent_workflow_ids az elindított legfelső szintű futásokhoz, a(z) agent_results a befejezett gyermek-munkafolyamat állapotához, a(z) review vagy decision pedig a jóváhagyási vagy elutasítási adattartalomhoz. A nagyobb kimenetek, például a vázlatok, hivatkozások vagy kutatási jegyzékek általában inkább a műterméktárolóba valók, nem a fő munkafolyamat állapottárolójába.
Ajánlott védőkorlátok az ügynökfutásokhoz
Az ügynökmunkafolyamatoknak szinte minden más felhasználási esetnél nagyobb szükségük van védőkorlátokra, mivel természetüknél fogva dinamikusak.
Queuety::workflow( 'agent_research' )
->version( 'agent-research.v2' )
->idempotency_key( 'brief:42:agent-research' )
->max_transitions( 20 )
->max_for_each_items( 12 )
->max_state_bytes( 32768 );
Ezek a vezérlők a gyakorlatban fontos éles üzemi kérdésekre adnak választ: melyik definícióverzió hozott létre egy futást, előfordulhat-e, hogy ismétlődő külső kérések kétszer indítják el, létrehozhat-e a tervező túl sok elágazást, illetve korlátlanul növekedhet-e a munkafolyamat állapota. A legtöbb ügynökrendszernél ezeket a védőkorlátokat érdemes beállítani, mielőtt a feldolgozók számát vagy a sorok topológiáját hangolná.