機詳解:從 INIT 到 DONE,每一輪 Turn 如何被「管住」)
AI 家教狀態(tài)機詳解從 INIT 到 DONE每一輪 Turn 如何被「管住」標(biāo)簽狀態(tài)機LLM應(yīng)用架構(gòu)Spring Boot教育科技Agent系列接《別再「套個大模型」了》技術(shù)深挖可控講題的編排實現(xiàn)。寫在前面接上大模型不等于接上「會教的老師」。模型會寫話術(shù)卻管不住「審題 → 分步 → 復(fù)述 → 收尾」的課堂節(jié)奏。本文講 AI 家教里的狀態(tài)機編排INIT→DONE各狀態(tài)職責(zé)、一輪Turn的前后端契約、冪等與后處理閘門、多問誤拆怎么防。一句話——狀態(tài)機控權(quán)模型負(fù)責(zé)怎么說后處理防止說崩。適合已接 LLM、卻被跳步 / 卡死 / 串學(xué)科折磨過的同學(xué)對照落地。1. 為什么必須上狀態(tài)機大模型擅長「寫得像老師」不擅長「嚴(yán)格服從課堂流程」。如果完全交給模型決定「講到哪了」常見后果是一步講完整題破壞分步 Reveal語文題突然教列方程只有一題卻不斷「下一問」收尾輪沒有出口學(xué)生無法結(jié)束所以我們把狀態(tài)推進(jìn)權(quán)放在后端編排器把話術(shù)生成權(quán)交給模型再用后處理校正 Turn 的 UI/選項/下一狀態(tài)。一句話狀態(tài)機控權(quán)模型負(fù)責(zé)怎么說后處理防止說崩。2. 狀態(tài)一覽VIP 主路徑狀態(tài)職責(zé)學(xué)生常見動作典型下一狀態(tài)INIT審題 考查點 第一步提問打字回答THINKUNDERSTAND對齊理解 / 情緒與卡點處理選項或文本THINKTHINK題目解構(gòu)、進(jìn)入第一步選項或文本STEPSTEP一步一問可多輪選項 / 文本 / 下一步STEP或CHECKCHECK復(fù)述自檢按學(xué)科換話術(shù)打字復(fù)述SUMMARY/ 補講SUMMARY結(jié)構(gòu)化總結(jié)看解析 / 結(jié)束 / 下一問EXTENDEXTEND收尾選擇區(qū)同上DONE或下一問重開DONE終態(tài)無互動DONE說明會話創(chuàng)建時會固化flow_typeVIP / Legacy后續(xù)turns:next只按該值路由。狀態(tài)在實現(xiàn)里多為字符串常量讀代碼時先確認(rèn)鏈路再進(jìn) Handler。3. Turn 協(xié)議前后端的「一輪課」每一輪后端返回結(jié)構(gòu)化 JSON示意{state:CHECK,message:做個復(fù)述自檢……語文設(shè)問→依據(jù)→收束,question:請用自己的話復(fù)述這題的賞析思路,options:[],ui:{allowTextInput:true,showNextButton:false},next_state:CHECK}字段含義字段含義message老師說的話氣泡主文question本輪向?qū)W生提的問題options可點選項空數(shù)組表示不靠選項推進(jìn)ui.allowTextInput是否開放底部輸入ui.showNextButton是否顯示「下一步」next_state本輪結(jié)束后會話應(yīng)落到的狀態(tài)三條鐵律建議寫進(jìn)單測 / 后處理有question且無options→ 必須allowTextInputtrue并關(guān)閉孤立的「下一步」。進(jìn)入 SUMMARY / 收尾→ 必須有可點出口查看解析 / 結(jié)束練習(xí) / 多問時的下一問。禁止死鎖輪無選項 不可輸入 無下一步且非 DONE。這三條比「把 Prompt 寫得更長」可靠得多。4. 編排主流程偽代碼以下為 VIP「下一輪」的骨架邏輯示意非某一文件逐行拷貝function nextTurn(userId, explanationId, req): e loadOwnedExplanation(userId, explanationId) // —— 守衛(wèi) —— if turn : findByClientTurnId(req.clientTurnId): return replay(turn) // 冪等弱網(wǎng)連點不重復(fù)計分/不重復(fù)生成 if e.currentState DONE: return terminalDoneTurn() // 已結(jié)束不再寫庫 if req.currentState ! e.currentState and not isExitAction(req): // 結(jié)束/下一問等收口動作可放行 return softResyncTurn(e) // 并發(fā)提示帶回服務(wù)端當(dāng)前態(tài) // —— 多問誤拆糾正 / 懶加載拆分示意—— reconcileMisSplitIfStatementEnum(e) // ①②③「以上說法正確個數(shù)」→ 單問 // —— 按狀態(tài)分發(fā) —— switch e.currentState: case CHECK: turn runCheck(req, e) // 空輸入→按學(xué)科發(fā)復(fù)述題有輸入→掌握判定 case SUMMARY: turn handleSummaryOption(req, e) // 僅處理選項類事件更穩(wěn) case EXTEND: turn handleExtend(req, e) case THINK: turn llmGenerate(buildCtx(e, req)) case STEP: maybeStepPaceNudge(e, req) // 輪次偏多催促而非硬砍死 turn llmGenerate(buildCtx(e, req)) default: turn llmGenerate(buildCtx(e, req)) // —— 后處理閘門比 Prompt 更硬—— postProcess(e, turn) // —— 落庫并推進(jìn) —— saveExplanationTurn(...) e.currentState turn.nextState updateExplanation(e) return turn4.1 CHECK掌握檢測學(xué)科感知function runCheck(req, e): if blank(req.userInput): return checkAskTurn(e.subject) // 語文設(shè)問→意象/詞句→收束 // 數(shù)學(xué)已知所求→關(guān)系/列式→代回核對 // 英語/史地政各自話術(shù) if not masteryPass(req.userInput, e.question, e.subject): return masteryFailSummary(...) // 標(biāo)準(zhǔn)答案方向 薄弱點 收尾選項 return masteryPassSummary(...) // 同一輪給總結(jié)選項禁止「空橋接輪」空橋接輪是典型事故只說「接下來給你結(jié)構(gòu)化總結(jié)」卻不給內(nèi)容、不給選項、不給輸入——前端必卡死。正確做法是通過后同一輪交付總結(jié)與出口。4.2 postProcess最后一道閘function postProcess(e, turn): if turn.state INIT: turn.options [] ensureFirstStepAsk(turn) // 去掉全科通用卡點問卷 if hasQuestion(turn): allowInput(turn); hideNext(turn) if turn.state SUMMARY or turn.nextState SUMMARY: turn.nextState EXTEND ensureExitOptions(turn) // 查看解析 / 結(jié)束 / 下一問 injectNextSubQuestionIfNeeded(e, turn) if turn.state EXTEND: sanitizeExtendOptions(turn) forbidInteractiveDeadEnd(turn) // 非 DONE 不得死鎖5. 多問大題怎么推進(jìn)又如何防誤拆5.1 數(shù)據(jù)模型sub_questions_json子問列表sub_question_index/sub_question_total當(dāng)前問與總數(shù)Prompt 側(cè)優(yōu)先喂「當(dāng)前子問」附帶原題片段避免多問混講。5.2 下一問if user picks NEXT_SUB_Q and hasNext(e): advanceIndex(e) reset stepIndex return buildFirstTurnAsInit() // 下一問重新開場5.3 誤拆防護(hù)實戰(zhàn)結(jié)論中文試卷編號語義不統(tǒng)一形態(tài)常見含義(1)(2)(3)/第1問真·多問設(shè)問①②③④ 「以上說法正確的個數(shù)」說法枚舉 單題選擇規(guī)則上要強信號才拆說法枚舉強制單問歷史誤拆可 reconcile。6. 與 LLM 層如何協(xié)作簡圖編排器 buildCtx(狀態(tài)/題干/歷史摘要/學(xué)科/學(xué)段) │ ▼ TutorEngineRouter │ ├─ LangChainTutorEngine ──? LlmGateway │ ├─ TEXT │ └─ NATIVE FC多輪 tool loop硬上限 ├─ DeepSeek 降級路徑 ────────? LlmGateway.chatText └─ RuleBased 兜底 ───────────? 無外網(wǎng)也能走完主路徑工具側(cè)建議白名單 服務(wù)端執(zhí)行如當(dāng)前子問、步驟摘要、KB 檢索、錯因模式。定量驗算如雞兔更適合后置校驗流水線不一定要做成 Function Calling以免打亂引導(dǎo)式教學(xué)。Prompt 運行時讀庫可熱更新倉庫 Markdown 用于規(guī)范與引導(dǎo)入庫——改文件后記得同步庫表否則線上仍是舊約束。7. 客戶端只需做好三件事每輪帶上explanationId、currentState、eventType、clientTurnId嚴(yán)格按options/allowTextInput/showNextButton渲染不在前端「猜」業(yè)務(wù)連點防護(hù)穩(wěn)定的clientTurnId服務(wù)端冪等不要用前端補丁修復(fù)后端死鎖。死鎖是編排/后處理的責(zé)任前端兜底只會掩蓋問題。8. 落地檢查清單可當(dāng) Code Review 列表INIT 是否還在甩全科通用「卡點問卷」有提問無選項時是否強制開放輸入CHECK 話術(shù)是否按subject分支掌握通過是否同一輪給出總結(jié)出口SUMMARY/EXTEND 是否必定能結(jié)束會話說法枚舉題是否不會被拆成多問clientTurnId是否真正冪等大模型失敗時 Rule/兜底是否仍能講完9. 小結(jié)AI 家教的狀態(tài)機本質(zhì)是在回答一個問題開放生成與封閉流程之間如何做出穩(wěn)定、可測、可運營的教學(xué)體驗我們的實踐答案是用狀態(tài)機定義「課怎么上」用 Turn 協(xié)議定義「這一分鐘師生怎么互動」用后處理定義「模型越界時系統(tǒng)怎么拉回來」用學(xué)科分支定義「同一流程下話術(shù)如何不同」下一篇AI 家教實戰(zhàn)Function Calling RAG增強講題卻不搶教學(xué)節(jié)奏。歡迎評論區(qū)交流你們的狀態(tài)劃分方式或「死鎖 / 串臺 / 誤拆」的真實案例。