code wiki / (root) / nx_quad_companion_compose_test.nx

nx_quad_companion_compose_test.nx source

↩ module page · 237 lines · 8754 B

1// nx_quad_companion_compose_test.nx -- 4-modality concurrent integration. 2// 3// Closes the parallel-companion north star: FOUR actors of DIFFERENT 4// modalities running interleaved through one scheduler + message bus + 5// multiplexer. 6// 7// NARRATOR (LLM, priority 80) -- nx_actor_role_llm 8// NPC (LLM, priority 60) -- nx_actor_role_llm 9// AUDIO_QC (audio grader, priority 50) -- nx_actor_role_audio_grader 10// GAME_LOGIC (tictactoe, priority 70) -- nx_actor_role_game_logic 11// 12// Replaces the image grader from the original quad attempt with the 13// lighter-deps game-logic actor per [[feedback-nxc2-module-const-ceiling]] 14// guidance. Each actor calls a DIFFERENT other-agent / sibling-arc 15// primitive: 16// 17// LLM -> nx_embedding_lookup + nx_blas_matmul + nx_sample_categorical 18// AUDIO -> nx_audio_scene_grade (5-axis Q14 verdict) 19// GAME -> nx_ttt_pick + nx_ttt_try_apply + nx_ttt_evaluate 20// 21// Proves the substrate handles arbitrary heterogeneous modalities 22// through one uniform actor + message + multiplexer pipeline. 23 24import "nx_syscalls.nx" 25import "nx_tier.nx" 26import "nx_tensor.nx" 27import "nx_actor.nx" 28import "nx_message.nx" 29import "nx_stream_multiplexer.nx" 30import "nx_actor_role_llm.nx" 31import "nx_actor_role_audio_grader.nx" 32import "nx_actor_role_game_logic.nx" 33 34func _fill_q10(t: *NxTensor, base: i64, stride: i64) -> i64 { 35 let p: *i64 = t.storage as *i64 36 var i: nx_int = 0 37 while i < t.numel { 38 p[i] = base + (i as i64) * stride 39 i = i + 1 40 } 41 return 0 42} 43 44func main() -> i64 { 45 let now: nx_size = 1000000 46 47 // ===== Stage 1: LLM weights (shared by NARRATOR + NPC) ===== 48 let shape_buf: *u8 = sys_mmap(16) 49 let shape: *i64 = shape_buf as *i64 50 shape[0] = 4 51 shape[1] = 4 52 let err_buf: *u8 = sys_mmap(8) 53 let err_p: *i64 = err_buf as *i64 54 let embed_table: *NxTensor = nx_t_alloc(NX_DT_I64, shape, 2, err_p) 55 if err_p[0] != NX_T_OK { return 1 } 56 _fill_q10(embed_table, 100, 5) 57 58 let shape2_buf: *u8 = sys_mmap(16) 59 let shape2: *i64 = shape2_buf as *i64 60 shape2[0] = 4 61 shape2[1] = 4 62 let out_proj: *NxTensor = nx_t_alloc(NX_DT_I64, shape2, 2, err_p) 63 _fill_q10(out_proj, 40, 3) 64 65 // ===== Stage 2: audio inputs ===== 66 let bins_buf: *u8 = sys_mmap(64) 67 let bins: *i64 = bins_buf as *i64 68 var b: nx_int = 0 69 while b < 8 { 70 bins[b] = 5000 + ((b * 600) as i64) 71 b = b + 1 72 } 73 let rms_buf: *u8 = sys_mmap(128) 74 let rms: *i64 = rms_buf as *i64 75 var f: nx_int = 0 76 while f < 16 { 77 rms[f] = 2200 + ((f * 180) as i64) 78 f = f + 1 79 } 80 81 // ===== Stage 3: shared substrate ===== 82 let sched: *NxActorScheduler = nx_ac_sched_new(8, 1000000, 24, now) 83 let bus: *NxMessageBus = nx_ms_bus_new(8, 32, 32) 84 let mux: *NxStreamMultiplexer = nx_sm_new(64, 50000) 85 86 let NARR: nx_int = 9001 87 let NPC: nx_int = 9002 88 let AUD: nx_int = 9003 89 let GAME: nx_int = 9004 90 let LIS: nx_int = 9099 91 92 nx_ac_spawn(sched, NARR, 1, 80, 0, now) 93 nx_ac_spawn(sched, NPC, 1, 60, 0, now) 94 nx_ac_spawn(sched, AUD, 4, 50, 0, now) 95 nx_ac_spawn(sched, GAME, 5, 70, 0, now) 96 nx_ac_spawn(sched, LIS, 5, 30, 0, now) 97 98 nx_ms_register(bus, NARR) 99 nx_ms_register(bus, NPC) 100 nx_ms_register(bus, AUD) 101 nx_ms_register(bus, GAME) 102 nx_ms_register(bus, LIS) 103 nx_ms_subscribe(bus, LIS, NX_MS_KIND_LLM_TOKEN) 104 nx_ms_subscribe(bus, LIS, NX_MS_KIND_AUDIO_FRAME) 105 nx_ms_subscribe(bus, LIS, NX_MS_KIND_GAME_ACTION) 106 107 // ===== Stage 4: actor contexts ===== 108 let narr_ctx: *NxLlmActorCtx = nx_lr_actor_new(embed_table, out_proj, 1, 4, 4, 1024, 2, 7) 109 let npc_ctx: *NxLlmActorCtx = nx_lr_actor_new(embed_table, out_proj, 2, 4, 4, 1024, 2, 13) 110 let aud_ctx: *NxAudioGraderCtx = nx_ag_actor_new(bins, 8, rms, 16, 4) 111 let game_ctx: *NxGameLogicCtx = nx_gl_actor_new(NX_TTT_X, NX_TTT_AI_PERFECT, NX_TTT_AI_PERFECT, 19) 112 if (narr_ctx as i64) == 0 { return 2 } 113 if (npc_ctx as i64) == 0 { return 3 } 114 if (aud_ctx as i64) == 0 { return 4 } 115 if (game_ctx as i64) == 0 { return 5 } 116 117 // ===== Stage 5: pick_next initial = NARRATOR (priority 80) ===== 118 let first: *NxActor = nx_ac_pick_next(sched) 119 if first.actor_id != NARR { return 6 } 120 121 // ===== Stage 6: drive each actor to completion ===== 122 // NARR + NPC: 5 phases each 123 // AUD: 3 phases 124 // GAME: up to 9 plies (1 step per ply, terminates when game ends) 125 var tick: nx_size = now + 100 126 var i: nx_int = 0 127 while i < 5 { 128 nx_lr_actor_step(narr_ctx, sched, bus, NARR, tick) 129 tick = tick + 50 130 i = i + 1 131 } 132 var j: nx_int = 0 133 while j < 5 { 134 nx_lr_actor_step(npc_ctx, sched, bus, NPC, tick) 135 tick = tick + 50 136 j = j + 1 137 } 138 var p: nx_int = 0 139 while p < 3 { 140 nx_ag_actor_step(aud_ctx, sched, bus, AUD, tick) 141 tick = tick + 50 142 p = p + 1 143 } 144 // Game: step until COMPLETED (PERFECT vs PERFECT -> DRAW in 9 plies) 145 var game_steps: nx_int = 0 146 var game_verdict: nx_int = NX_GL_V_STEPPED 147 while game_verdict == NX_GL_V_STEPPED { 148 game_verdict = nx_gl_actor_step(game_ctx, sched, bus, GAME, tick) 149 tick = tick + 50 150 game_steps = game_steps + 1 151 if game_steps > 12 { return 7 } 152 } 153 154 // ===== Stage 7: all four actors COMPLETED ===== 155 let na: *NxActor = nx_ac_find(sched, NARR) 156 let nb: *NxActor = nx_ac_find(sched, NPC) 157 let nc: *NxActor = nx_ac_find(sched, AUD) 158 let nd: *NxActor = nx_ac_find(sched, GAME) 159 if na.state != NX_AC_STATE_COMPLETED { return 8 } 160 if nb.state != NX_AC_STATE_COMPLETED { return 9 } 161 if nc.state != NX_AC_STATE_COMPLETED { return 10 } 162 if nd.state != NX_AC_STATE_COMPLETED { return 11 } 163 164 // ===== Stage 8: game theory invariant -- PERFECT vs PERFECT must DRAW ===== 165 if nx_gl_actor_outcome(game_ctx) != NX_TTT_DRAW { return 12 } 166 if nx_gl_actor_plies(game_ctx) != 9 { return 13 } 167 168 // ===== Stage 9: LISTENER mailbox totals ===== 169 // 2 LLM_TOKEN (narr + npc) + 1 AUDIO_FRAME + 9 GAME_ACTION = 12 170 if nx_ms_pending(bus, LIS) != 12 { return 14 } 171 172 // ===== Stage 10: verdicts ===== 173 let narr_tok: nx_int = nx_lr_actor_token(narr_ctx) 174 let npc_tok: nx_int = nx_lr_actor_token(npc_ctx) 175 if narr_tok < 0 { return 15 } 176 if narr_tok >= 4 { return 16 } 177 if npc_tok < 0 { return 17 } 178 if npc_tok >= 4 { return 18 } 179 if nx_ag_actor_score_q14(aud_ctx) <= 0 { return 19 } 180 181 // ===== Stage 11: drain LISTENER in FIFO order ===== 182 // First 2 messages = LLM_TOKEN (narr, npc); then AUDIO_FRAME; then 9 GAME_ACTION 183 let m1: *NxMessage = nx_ms_receive(bus, LIS) 184 if m1.kind != NX_MS_KIND_LLM_TOKEN { return 20 } 185 if m1.sender_actor_id != NARR { return 21 } 186 187 let m2: *NxMessage = nx_ms_receive(bus, LIS) 188 if m2.kind != NX_MS_KIND_LLM_TOKEN { return 22 } 189 if m2.sender_actor_id != NPC { return 23 } 190 191 let m3: *NxMessage = nx_ms_receive(bus, LIS) 192 if m3.kind != NX_MS_KIND_AUDIO_FRAME { return 24 } 193 194 // Remaining 9 are GAME_ACTION 195 var ga_count: nx_int = 0 196 while ga_count < 9 { 197 let mg: *NxMessage = nx_ms_receive(bus, LIS) 198 if mg.kind != NX_MS_KIND_GAME_ACTION { return 30 + ga_count } 199 if mg.sender_actor_id != GAME { return 50 + ga_count } 200 ga_count = ga_count + 1 201 } 202 203 // ===== Stage 12: multiplexer priority ordering ===== 204 // Push one of each class; drain. Priorities: 205 // LLM_TEXT = 80 206 // GAME_ACTION = 90 (game actions are highest non-system) 207 // AUDIO_TTS = 70 208 nx_sm_push(mux, NARR, NX_SM_CLASS_LLM_TEXT, 1, 8, narr_tok as nx_size, tick) 209 nx_sm_push(mux, AUD, NX_SM_CLASS_AUDIO_TTS, 2, 8, nx_ag_actor_score_q14(aud_ctx) as nx_size, tick) 210 nx_sm_push(mux, GAME, NX_SM_CLASS_GAME_ACTION, 3, 8, 0xCAFE, tick) 211 if nx_sm_pending_count(mux) != 3 { return 70 } 212 213 let oc_buf: *u8 = sys_mmap(24) 214 let oc: *i64 = oc_buf as *i64 215 let os: *i64 = (oc_buf + 8) as *i64 216 let oid: *i64 = (oc_buf + 16) as *i64 217 218 // First drained = GAME_ACTION (priority 90) 219 nx_sm_next(mux, oc, os, oid, tick + 100) 220 if oc[0] != (NX_SM_CLASS_GAME_ACTION as i64) { return 71 } 221 222 // Second = LLM_TEXT (priority 80) 223 nx_sm_next(mux, oc, os, oid, tick + 200) 224 if oc[0] != (NX_SM_CLASS_LLM_TEXT as i64) { return 72 } 225 226 // Third = AUDIO_TTS (priority 70) 227 nx_sm_next(mux, oc, os, oid, tick + 300) 228 if oc[0] != (NX_SM_CLASS_AUDIO_TTS as i64) { return 73 } 229 230 if nx_sm_pending_count(mux) != 0 { return 74 } 231 232 // ===== Stage 13: scheduler stats ===== 233 if nx_ac_actor_count(sched) != 5 { return 75 } // NARR+NPC+AUD+GAME+LIS 234 if nx_ac_total_runtime_us(sched) <= 0 { return 76 } 235 236 return 0 237}