Prompt 状态机:AI 面试越级率 0% 的工程化
做 AI 模拟面试,最大的技术难点不是流式、不是计费,是让 LLM 老老实实按流程走:开场 → 自我介绍 → 基础题 → 追问 → 评分,一步都不能跳。
初版产品被用户吐槽最多的就是:面试官(LLM)聊着聊着突然跳到"恭喜你通过面试"——流程越级。我们把越级率从 20% 压到 0%,靠的不是调参,是 Prompt 状态机。
一、为什么 LLM 会越级
LLM 没有"程序计数器",它是按概率生成下一个 token。长对话里:
- 上下文漂移:聊了 20 轮后,模型忘了现在在第几步
- 用户诱导:用户说"我觉得我答得不错,是不是该给我过了?",模型容易顺着答
- 指令稀释:Prompt 里写了 10 条规则,越靠后的越容易被忽略(注意力衰减)
解决思路:把流程状态"焊死"在每一轮对话里,而不是让模型自己记。
二、三层 Prompt 结构
第 1 层:System 强元规则(会话级)
|
|
关键:把规则写成"命令式约束",并且给一个可验证的格式要求(每轮输出 [STATE: STEPn])——让模型自己每轮"汇报"自己在哪一步,漂移能被立即发现。
第 2 层:User 变量(每轮注入)
每轮对话,后端把当前状态拼进 User 消息:
|
|
状态不在 System 里躺着,而是在每轮 User 消息里刷新——模型的注意力永远能看到最新的状态行。
第 3 层:Assistant 预填开场(Prefill Injection)
这层最关键也最容易被忽略。不要等模型自己想下一句,后端预填 Assistant 的开头:
|
|
模型在预填内容后面续写,很难推翻已经"说出口"的状态。预填 = 给模型一个"既成事实",让它顺着走。
三、校验层:输出必须可验证
三层 Prompt 是"引导",校验层是"兜底":
|
|
越级不是"接受"或"忽略",是直接拦截重写——模型输出到了 STEP5,我们就截掉那部分,重新生成或提示用户继续。这就是越级率 0% 的机制来源。
四、实战效果
| 指标 | 初版(单层 Prompt) | 三层状态机 |
|---|---|---|
| 流程越级率 | ~20% | 0% |
| 用户中途"求通过" | 部分被模型顺走 | 100% 拦截 |
| 每轮状态可追踪 | 无 | [STATE] 标记可入日志 |
| 面试完整完成率 | 60% | 92% |
五、踩坑记录
坑 1:别把"下一步"写死在 System
初版把流程描述写进 System 让模型"记住",20 轮后全忘。状态必须每轮刷新(User 变量),System 只放不变的规则。
坑 2:预填会"抢话"
预填如果写了完整的问句,模型可能直接开始"自问自答"。预填只写状态标记 + 半句话,留一半给模型续,既焊死状态又不抢戏。
坑 3:评分步骤要独立会话
评分总结时如果还在同一会话,模型会受前面对话影响。评分用新会话,只传"完整问答记录",让模型基于记录评分,不基于"聊天情绪"。
坑 4:中文状态下状态标记要统一
[STATE: STEP3] 的括号形式必须固定,解析器才稳。格式是协议,不是文案——模型可能输出全角/半角括号混用,解析器要做归一化。
总结
AI 应用里的流程控制,本质是把状态从模型的记忆里搬到系统的数据里:
- System 放不变的规则 + 输出格式约束(状态标记)
- User 每轮刷新当前状态,对抗注意力衰减
- Assistant 预填 用既成事实焊死下一步
- 校验层 解析状态标记,越级直接拦截
不要指望模型"自觉"遵守流程——把流程变成可校验的协议,0% 才可能。