
1. 为什么在线考试系统需要一块AI拼图做了几年的在线考试系统我最大的感受是市面上大多数系统其实只能算题库答题卡成绩单的电子化替代品。出题靠人工从题库里翻组卷靠随机算法拼凑主观题要么人工判、要么直接不做考后分析就是统计个平均分和及格率。学生刷完题拿到分数并不知道自己到底弱在哪老师拿到成绩也说不清下节课该重点讲什么。所以我一直在想一件事能不能把AI能力真正嵌到考试系统的业务流程里而不是只挂一个智能问答的入口当摆设这个念头最终变成了一个具体项目——基于SpringAI的在线考试系统给传统的考、练、评、析四个环节做智能化拓展。这篇文章就把我在这套系统里的完整思路拆开来讲技术选型为什么落到SpringAI、智能出题和批改怎么做、上线之后踩了哪些坑、以及最终的效果量化。适合两类人看一是想搞毕业设计或项目实训的同学可以参考这个题目从0到1的完整落地方案二是企业内部要做考试培训平台的Java工程师里面的模块拆解和降级策略可以直接借鉴。先说结论SpringAI这套东西本质上是给Java生态开了一扇通往大模型能力的大门它把和LLM对话这件事变成了一套标准化的Spring风格接口。你不需要自己写HTTP客户端、不用管Prompt拼接的脏活、也不用手动解析模型返回的JSON串——这些痛点它都处理掉了。往下我会一步步还原整个项目是怎么从零搭起来的。2. 技术选型的底层逻辑SpringAI到底解决了我哪几个痛点2.1 为什么不用直连大模型API这种看似更简单的方案动手之前我其实先试过一条更粗暴的路线在Service层里直接用RestTemplate或OkHttp发HTTP请求去调用大模型接口把Prompt作为参数传过去返回结果再手动解析。这套方案在小规模测试时完全能跑甚至代码量看起来更少。但一旦进入真实项目问题就暴露了。第一个痛点是Prompt管理。考试系统里至少会有十几种Prompt场景——单选生成、多选生成、填空生成、主观题评分、学习路径推荐、知识点图谱分析。每个场景的Prompt模板都不一样有的还带few-shot示例就是给模型几个标准样例让它照着写。如果全部用字符串拼接散落在Service代码里改一次Prompt就要重新编译代码而且整个项目里到处都是magic string维护成本直接失控。第二个痛点是结构化和容错。大模型接口返回的是纯文本模型偶尔会JSON格式不对、字段名不一致、甚至直接输出一段解释性的废话。这些脏数据在考试系统里是致命的——一道客观题如果解析出错整份试卷的考题就废了。直连方案下我要为每个场景单独写一套解析重试容错的胶水代码这个工作量比调用本身都要大。第三个痛点是流式输出和对话上下文管理。考试系统的AI答疑场景希望答案像ChatGPT一样一个字一个字蹦出来给用户思考中的感知同时如果学生追问还要把前面的对话历史带进去。这些如果自己写要做SSE协议封装、会话窗口维护、Token超限截断全是细节活。所以当我注意到SpringAI这个项目时几乎没怎么犹豫——它把我上面说的三个痛点用Spring生态熟悉的套路全给解掉了。2.2 SpringAI的架构并不复杂理解这四点就够了如果只抓主干SpringAI可以概括成四层能力第一层是Client抽象。不管底层接的是OpenAI、通义千问还是DeepSeek在SpringAI里统一封装成一个ChatClient或ChatModel的Bean。你在业务代码里只跟这个接口打交道换模型供应商时只需要改application.yml里的配置业务代码一行不动。第二层是Prompt模板机制。它提供了类似Thymeleaf的PromptTemplate可以用{placeholder}占位符把动态参数填进Prompt里。加上SpringEL表达式支持模板里甚至可以做简单的循环、条件判断、正则提取。这一层让我把出题、评分的Prompt从Java代码里彻底解放了出来全部外置到resource/prompts/目录下改Prompt不动代码。第三层是结构化输出。SpringAI提供了BeanOutputConverter配合JsonDescription注解可以定义Java类描述期望的JSON结构。模型返回的文本会直接被转换成Java对象解析错误的场景由框架帮你兜底。这就是我前面说的解决脏数据问题的关键设计——我用完之后感觉结构化输出功能应该算SpringAI全项目里面最值得优先用熟的一个组件。第四层是Advisor的横切能力。消息上下文、日志审计、Prompt安全过滤、Token用量统计都可以通过Advisor以拦截器的方式来挂载。比如我不想让AI回答跟考试无关的问题就可以写一个简单的Advisor在模型输出前加一段系统限定词或者检测用户输入是否触发了敏感词表。下面这张表是我在项目里用到的核心组件清单方便初次接触SpringAI的人建立坐标系组件对应能力我实际用到的场景ChatClient统一的大模型调用入口所有出题、评分、答疑请求都通过它走ChatModel底层模型Bean封装配置了全局模型和评分专用模型两个实例PromptTemplatePrompt模板渲染按题型拆了8个模板文件全部外置BeanOutputConverter模型JSON转Java对象把选题结果、评分报告转成强类型对象Advisor横切拦截上下文集成、敏感信息过滤、日志记录对没接触过SpringAI的人来说你暂时不需要深入每层的源码先把它帮你解决了跨模型切换、Prompt管理、结构化解析这三个问题记在心里就够了——因为后面的模块设计全是围绕这三件事展开的。3. 智能化模块的整体架构和核心数据流3.1 六个AI能力点和传统考试流程的一一映射传统考试系统的业务链路无非五段出题、组卷、考试、批改、学情分析。我的智能化改造思路是给其中四段都插入AI能力点并额外加了一段考后的个性化对话流程环节传统做法AI智能化能力点具体的用户场景出题人工编辑或随机抽题AI智能生成试题老师输入生成10道关于Spring事务传播机制的单选题批改客观题自动判主观题人工或跳过AI辅助主观题评分简答题、论述题自动评阅并生成评语学情分析及格率、平均分统计AI学情洞察报告考试结束后自动生成班级薄弱知识点清单个性化学习无AI学习路径推荐学生主动提问我SQL老错接下来该怎么练这四个能力点对应了四个核心业务模块智能出题模块、智能评分模块、学情分析模块、AI答疑助手。再加上一个贯穿全局的Prompt管理服务和模型调用日志服务就构成了完整的AI拓展面。你可能注意到我没提智能组卷——不是不想做而是出于稳妥考虑组卷的结果直接决定试卷难度和公平性容错率极低。我的判断是AI适合做生成候选素材也就是出题而从候选池里挑题组合这种约束优化问题让传统规则引擎来做更可靠。一味的什么环节都塞AI不一定是加分反而会引入不稳定因素。3.2 关键数据流一次AI出题请求的完整旅程只看模块清单不容易建立体感我拿一次典型的智能生成单选题请求来串一下数据流这样你就能看清SpringAI在整个链路里的位置请求进入老师在前端页面填写出题表单——题目数量、知识点范围、难度系数。后端收到请求校验参数并读取当前学期的知识点树。解析结构化入参系统先查询知识点树拿到事务传播机制下属的子知识点列表作为出题覆盖范围的约束。组装Prompt从prompts/multi-choice-gen.st模板文件加载出题模板用知识列表、题目数量、难度要求填充模板占位符。这一步在SpringAI里就是一行promptTemplate.render(params)。调用模型通过ChatClient发出请求并传入BeanOutputConverter指示模型必须按我预定义的QuestionBean结构返回JSON。清洗与入库框架将模型返回的文本自动转为ListQuestionBean我再做一次业务规则校验——比如选项是否重复、知识点是否匹配、题目是否和已有题库冲突。校验通过的题目写入题库状态为待审核。反馈结果把生成的题目列表回传给前端老师可以逐题确认、修改后发布。这个流程里面SpringAI的Concrete贡献主要在第三步和第四步——把如何跟模型对话给标准化了。我在改造前的直连方案里第4步之后还要写一大堆解析和容错代码现在一个注解加一个Converter就搞定了。4. 智能出题模块的完整实现Prompt模板和结构化输出的组合拳4.1 一次成功的Prompt是喂出来的不是一次写出来的出题模块是整个系统里最早开发的功能因为在考试系统里题是源头没有题就什么都谈不上。但真正动手后我发现大模型出题有几个绕不开的问题一是太容易生成一眼假的题目——选项一看就是凑数的二是容易超出指定范围擅自引入我没要求的知识点三是偶尔会输出以上都对这种无效选项。这些问题靠调代码是修不好的只能从Prompt层面去压制。我踩了很多轮之后沉淀出一个相对稳定的出题模板结构下面这个文件简化后只有单选题部分你是资深课程出题专家擅长根据给定的知识点范围生成客观题。 要求如下 1. 题目必须严格限定在知识点列表以内不得超范围 2. 每道题的四个选项中必须有且仅有一个正确项其余三个为高分干扰项 3. 干扰项必须看起来合理不能出现明显错误或语义重复 4. 难度系数为 {difficulty}其中1表示基础识记3表示综合应用5表示扩展提高 5. 输出JSON数组每个元素包含字段 questionContent(题干), optionA, optionB, optionC, optionD, correctAnswer(选项字母), knowledgePoint(命中的知识点), difficulty(难度系数) 知识点列表 {knowledgePoints} 请生成 {questionCount} 道题目。你注意第2和第3条这是从多次失败中总结出来的关键约束。第一次我写的模板只说了生成单选题结果模型自己编了一堆选项长短完全不齐、答案一看就是最短那个的题目加上高分干扰项这个词并给出定义之后质量明显上了一个台阶。由此你会发现Prompt工程本质上是在用自然语言给模型立规矩每一句规则都要能对应到可观察、可检验的输出表现上。我把不同题型的Prompt模板全部放在了src/main/resources/prompts/目录下单选、多选、判断、填空各一个文件。这样后续要调整出题策略只需要改文本文件不用重新部署代码。4.2 用BeanOutputConverter把模型输出钉死成Java对象Prompt写得再严谨模型偶尔也会不听话地多输出一段解释性文字或者少一个字段。为了把系统的健壮性握在自己手里我做了一层强约束在调用ChatClient的时候传入一个BeanOutputConverter。RestController RequestMapping(/api/ai/questions) public class AiQuestionController { Resource private ChatClient chatClient; Resource private BeanOutputConverterQuestionGenResult questionConverter; PostMapping(/single-choice) public ResultListQuestionBean generateSingleChoice(RequestBody GenRequest req) { PromptTemplate pt new PromptTemplate( loadPromptTemplate(single-choice-gen) ); MapString, Object params new HashMap(); params.put(knowledgePoints, req.getKnowledgePoints()); params.put(questionCount, req.getQuestionCount()); params.put(difficulty, req.getDifficulty()); String rendered pt.render(params); // BeanOutputConverter会把输出的JSON文本转成Java对象 String output chatClient.prompt(rendered) .options(OpenAiChatOptions.builder() .withModel(deepseek-chat) .withTemperature(0.7) .build()) .call() .content(); QuestionGenResult result; try { result questionConverter.convert(output); } catch (Exception e) { // 解析失败时降级方案提示重新生成不直接报错 throw new BizException(AI解析失败请点击重新生成); } return Result.ok(businessValidateAndSave(result.getQuestions())); } }代码里的QuestionGenResult是一个专门定义输出结构的类核心部分长这样public class QuestionGenResult { private ListQuestionBean questions; // getter/setter省略 public static class QuestionBean { JsonDescription(题干内容) private String questionContent; JsonDescription(选项A的内容) private String optionA; JsonDescription(选项B的内容) private String optionB; JsonDescription(选项C的内容) private String optionC; JsonDescription(选项D的内容) private String optionD; JsonDescription(正确答案对应的选项字母只能是A/B/C/D中的一个) private String correctAnswer; JsonDescription(命中的知识点名称) private String knowledgePoint; JsonDescription(难度系数取值1到5) private Integer difficulty; // getter/setter省略 } }这里面的JsonDescription很关键它会随Prompt一起发送给模型。换句话说这个注解不只是给程序员看的注释它是在提示模型请按这个字段的意思来生成数据。相比只靠Prompt文本描述输出结构这种双保险方式能把结构化解析的成功率从90%提到99%左右——这是我做了50多次自测实验后的数据。4.3 生成题目之后的业务验尸报告SpringAI帮我解决了模型输出到Java对象的转换问题但AI生成的题能不能直接进题库还需要一道业务层面的守门员。我在模块里写了一个QuestionBusinessValidator专门做这几件事检查题干、选项是否为空选项之间是否有明显重复校验correctAnswer是否在合法范围内校验题目命中的知识点是否在传入的知识点清单内用相似度算法简单排查是否与已有题库重复本地先用编辑距离粗筛确保难度系数落在1到5之间。通过校验的题目状态标记为PENDING_REVIEW不会直接发布上线。老师在前端审核界面看到的是一批AI草稿可以逐题编辑、标记删除、一键通过。我始终坚持一个原则AI可以做80分的初稿但最终决定权必须留在人手里。这不是不信任AI而是考试场景的特殊性决定了——一道错题直接浪费的是几百个学生的考试时间这个风险不值得冒。5. 评分和学情分析AI不是替你判断是帮你放大判断力5.1 主观题AI评分的思路和实现要点对于客观题传统系统早就实现了自动判分不需要AI插手。真正有价值的地方在主观题——简答题、论述题、应用题。这里我做了两个档位的设计供教师选择第一档叫辅助评分。系统把学生答案和参考答案一起交给模型模型给出一个建议得分区间和一个评分理由摘要教师再做最终裁决。以一道10分的简答题为例模型输出类似建议给7-8分学生答出了核心机制但缺少边界条件说明这样的结构化结果。第二档叫全自动评分。适用于那些答案相对规范的题型比如写出SQL语句、填写代码输出结果。模型直接给分但命中下面的条件时会自动转人工得分和班级平均分偏差超过30%、模型自身的置信度字段低于阈值、或者答案长度异常。实现上评分请求需要并发送模型两个东西评分标准rubric和待评分的学生答案。Prompt模板里我用Markdown表格来表达评分标准实验证明这种格式对大模型理解规则是最友好的请根据以下评分标准对学生的答案进行评分。 | 得分点 | 分值 | 评分细则 | |---|---|---| | 事务概念准确 | 4分 | 准确描述事务ACID特性得4分遗漏一个特性扣1分 | | 传播行为理解 | 3分 | 正确解释REQUIRED和REQUIRES_NEW区别得3分 | | 代码示例 | 3分 | 提供可运行的代码示例得3分有明显错误扣1分 | 学生答案{studentAnswer} 参考答案{referenceAnswer}运行下来我的感受是这种结构化评分标准分数档位描述的方式比直接丢一句请给这个答案打分稳定得多。评分结果用JSON返回包含suggestedScore、confidence、comment三个字段。其中confidence字段是我特别加上的——当模型自己都觉得拿不准的时候系统就自动把这张卷标记为待人工复核。5.2 从班级平均分到班级能力画像的跨越传统的考试成绩分析核心输出物就三张表分数分布表、知识点得分率表、名次表。老师看得出来某个知识点得分率是60%但说不清楚为什么这个班在这个知识点上集体失分。AI学情分析模块做的就是把这个模糊的结论沉淀为可执行的洞察。我在每次考试结束、批改完成后触发一次学情分析异步任务第一步从数据库汇总班级全体学生的答题数据按知识点维度计算得分率第二步找出得分率低于60%的薄弱知识点作为分析的核心输入第三步调用模型生成针对性分析报告包括薄弱点成因推测、典型错误类型归纳、下一阶段教学建议。报告最后会以结构化数据存储下来而不是一股脑塞进AI的回复里。我一直很反对那种AI输出了一整段漂亮话然后直接抛给用户的设计——因为这种内容没有沉淀价值老师根本没法二次利用。我做的是让模型按固定JSON结构返回问题清单原因建议存库后前端再渲染成报告卡片。这样老师可以把建议逐条勾选为已采纳后续还能统计采纳率。6. 上线前必须优化好的几个细节性能、降级、成本6.1 异步化改造绝不让等AI卡住主流程AI模型的单次响应时间通常在3到10秒之间有的甚至更长。如果在考生交卷时同步去调用模型做主观题评分用户体验将直接崩掉——交卷转圈3分钟谁也接受不了。解决思路是老生常谈但极其有效异步化 任务队列。我在评分模块里做了如下设计考生交卷后客观题立即自动判分响应时间保持在200ms内主观题评分任务写入本地任务表状态为PENDING由定时任务每隔5秒捞取并调用AI评分完成后通过WebSocket主动推送评分完成通知给学生如果AI调用失败任务状态保留为RETRYABLE最多重试3次最终还是失败的话降级为人工评分待办。这套设计让我想到了多年前做秒杀系统的限流削峰——AI调用就是一种慢服务比例虽然是1:1的但它天然就是异步场景。考试系统里几乎所有AI调用点都应该遵循这个原则只有AI答疑助手需要保持同步流式响应因为那是用户主动触发的交互场景。6.2 缓存和降级策略AI不可用的时候系统不能跟着躺平在线考试系统是典型的教学生产力工具对可用性的要求其实是很高的。我不能因为大模型供应商的一次服务抖动就让全校的在线考试瘫痪。所以从第一天起我就设计了三级降级路径第一级正常路径调用AI模型返回智能化结果。第二级缓存路径针对学情分析和出题请求如果检测到同样的知识点维度、相似的参数组合在近期已经生成过直接返回历史结果。我用了Guava Cache做本地缓存缓存时间为24小时。在实际运行中期末考试这样的高频请求命中率大概在15%左右——不算高但省下的调用钱是真的。第三级降级路径AI调用连续失败超过5次触发熔断出题模块自动切换到随机抽题模式主观题评分切换到仅展示参考答案不评分模式。这个降级逻辑用Spring Cloud CircuitBreaker实现熔断打开后30秒内不再尝试调用AI保护模型服务不被压垮也不让系统空转。这三级路径现在已经成为我所有AI功能模块的基础框架。我认为AI功能可以做成锦上添花但不能变成系统运转的致命单点——能用永远排在智能前面。6.3 成本控制你猜一次全年级数学考试的分析要花多少钱很多人在做AI项目时有意无意忽略成本问题但真实项目里这是躲不开的。我把三个核心场景的Token消耗做了量化结果如下场景每次调用的输入Token均值输出Token均值单次成本按最低档模型单题生成约1200约300约0.01元10题批量生成约2500约3500约0.03元主观题评分单题约900约160约0.005元学情分析报告单班约8000约1200约0.06元单看单价确实便宜但折算到全校规模一个月轻松跑掉几万次调用账单就会变得很难看。所以我做了三层成本控制一是上面说的缓存路径减少重复请求二是在模型选型上区分主模型和轻量模型——出题和答疑用上下文理解力更强的模型客观题数据清理、关键词提取这类简单任务用便宜模型三是全链路Token用量打点每次调用都记录input/output token数在后台给管理员展示今日AI消费曲线让成本变成可观测、可追踪的数据。说实话这一步在展示项目时未必有人问你但真正上线运营时每一分钱都是你老板会关心的。7. 踩坑实录我在开发中遇到并解决的几个真实问题7.1 结构化输出偶尔会姿势不对容错不能只靠一次转换我最开始天真地以为BeanOutputConverter能给结构化输出上双重保险实际跑起来才知道模型偶尔输出格式会有小瑕疵。有一次我连续测试200次单选题生成发现大约有2%的比例返回的JSON字段名从questionContent变成了questioncontent还有几次模型输出的数组前面多了一段以下是生成的题目这样的前缀文字。BeanOutputConverter.convert()对这个问题的处理我认为不够激进它抛异常了事。所以我在项目里包了一层AiOutputResolver专门做三级修复第一级直接在convert()前面跑一个JSON清理器把多余的说明文字截断、把单引号修正成双引号第二级修复失败就用正则从文本里提取最接近的JSON片段第三级才是交给convert()去解析。这套修复之后200次测试的成功率从98%提到了99.8%。这种问题你在官方文档里是学不到的只有在真跑数据时才会暴露出来。我建议所有用SpringAI做生产功能的人都要留一套AI输出清洗管道不要过度信任任何框架的结构化解析能力。7.2 模型幻觉出的选项和知识点靠Prompt管不住靠业务规则管Prompt可以约束模型应该生成什么但没办法约束它不该生成什么。我的出题模块曾经出现过一个很滑稽的问题我要求知识点范围限定在Spring事务传播机制AI却生成了一道关于Redis持久化的题——它自己认为这两个知识点有强关联擅自把范围扩大了。业务校验器在这里发挥了作用。我在保存到题库前会做知识点映射校验如果模型中带出来的knowledgePoint字段不在本次请求的知识点ID清单里就拒绝入库并重新生成。经过十几次迭代后这个超范围的比例从最初的7%降到了0.5%以下。另外一个更隐蔽的问题是重复生成。AI在生成多选题时经常生成两道本质相同、只换了数字的题目。我引入了一层相似度检测用SimHash加编辑距离双重判断相似度超过85%的题目直接被标记为疑似重复。在人工审核界面上这些疑似重复题会用黄色标签标出来方便老师快速处理。把能生成题目变成能生成不重复、不超纲、可审核的题目才是出题模块真正能用的标志。7.3 长对话的上下文衰减问题AI答疑模块的隐形大坑AI答疑模块上线后用户很快反馈一个问题聊到第五六轮之后AI开始忘记一开始的问题背景。比如学生最开始问的是Spring事务失效的场景有哪些连续追问几轮之后AI的回答却跑偏到了数据库连接池配置上。分析了一下发现无状态的每次一个新Prompt发出去在长对话场景必然出现这种问题。解决思路是我在SpringAI的Advisor里实现了对话历史的滚动窗口把所有历史消息组成一个消息队列超过3000字符时自动丢弃最早的对话同时把最开始的那个原始问题固定在Prompt的最前方——这样即使中间对话被裁剪模型也能始终记得最初的上下文锚点。这个设计一开始我并没有想得很复杂但上线后被这个问题反复抽打最后才形成这样的机制。现在答疑模块能稳定支撑连续15轮以上的对话不跑题记忆锚点加滚动窗口这招功不可没。8. 学习路径推荐功能的实现逻辑从考完拉倒到考完有下一步做完出题、评分、学情分析之后我一直在想一件事考试系统如果只把学生考趴下却不告诉他下一步怎么走那考试就失去了最重要的教育价值。于是最后一个模块我做了AI学习路径推荐。核心逻辑并不复杂。系统汇总学生历次考试的知识点得分率数据形成一张个人薄弱点热力图——哪些知识点反复失分、哪些知识点最近刚刚开始下滑。然后把这些数据交给模型让它生成个性化的学习路径输出结果是一个结构化的JSON{ studentId: 2024001234, targetKnowledgePoint: Spring事务传播机制, weaknessAnalysis: 在REQUIRES_NEW场景下理解偏差明显建议先掌握嵌套事务的独立回滚语义, learningPath: [ {step: 1, action: 观看基础概念视频, resourceType: video, estimatedMinutes: 15}, {step: 2, action: 完成专项练习5题, resourceType: quiz, estimatedMinutes: 20}, {step: 3, action: 阅读典型反例文档并分析, resourceType: article, estimatedMinutes: 10} ] }设计这个模块时我专门加了一个前置门槛如果学生在某个知识点上的失分次数少于2次AI不会强行推荐学习路径而是提醒本次波动可能属于偶发性失误建议先重做错题。这一条过滤规则避免了AI在数据量不足时过度解读大幅降低了一刀切推荐的荒谬感。现在这个模块上线后学生端学习路径的点击转化率明显高于其他内容推荐位说明这个方向是真实有价值的。9. 项目上线四周后的效果和数据项目上线后我统计了最初四周的使用数据虽然样本不算大但也足以说明智能化模块的实际效果。智能出题方面老师一共发起了112次出题请求生成题目486道审核通过394道通过率约81%。相比人工出题出题准备时间从平均2小时缩短到了15分钟这个提升幅度是实打实的。主观题评分方面共处理了约3600道主观题答案模型给分和教师复核给分的相关性约在0.89左右。这个分数已经算相当可观但距离完全自动化仍有一段距离——不少教师仍然习惯先看AI评语再去核分把它当作一个草稿助手。学情分析模块生成的分析报告老师采纳建议的比例接近75%。最受欢迎的输出是薄弱知识点原因分析和下阶段教学建议这说明老师并不缺数据缺的是把数据转化成行动结论的洞察。这恰好就是AI在这个系统里的定位——不是取代人而是在数据分析到教学决策的最后一公里搭一座桥。10. 关于这个项目我最后想说的几件事项目做到这里回头看其实一开始的很多担忧都显得多余了。SpringAI的成熟度比我最初预想的高不少它在Prompt管理、结构化输出、流式交互这些方向上已经形成了非常完整的工具链。真正需要你多花心思的反而不是框架本身而是业务规则的兜底、降级策略的设计、Token成本的控制——这些才是把一个AI Demo变成一个AI产品的最厚壁垒。我个人在实际操作中的体会是不要试图让AI包办一切也不要因为一次效果不好就全盘否定。你要做的是把AI放在它最擅长的地方——生成初稿、归纳总结、发现问题——然后把最终决策权握在业务层手里。这种人机协作的架构既是这个考试系统能稳定跑下去的根因也是我建议每个做AI落地项目的人优先参考的实践思路。最后分享一个小技巧如果你的项目也打算引入AI能力特别建议把所有的Prompt外置成模板文件并且从第一天就给每个Prompt写版本号。我统计过在项目迭代过程中出题模板的修改次数至少是代码修改次数的两倍——Prompt是活的它是项目里最值得持续打磨的资产。