十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

码道 · 用结构化提示词,把大模型打磨成一名「错题教练」——AI 错题解析助手从想法到落地的全记录

码道 · 用结构化提示词,把大模型打磨成一名「错题教练」——AI 错题解析助手从想法到落地的全记录 项目仓库https://atomgit.com/gcw_vdwXc6Cs/aicuotijiexi 分支main 技术栈HTML5 · CSS3 · JavaScript零依赖文章性质个人技术博客 · 课程大作业展示仓库地址https://gitcode.com/gcw_vdwXc6Cs/aicuotijiexi.git—码道生成项目目录一、写在开头为什么会有这个项目二、从错题本到错题教练需求拆解与产品定位三、技术选型为什么坚持零依赖纯前端四、整体架构一个文件的小而美五、核心设计上如何用系统提示词约束大模型输出 JSON六、核心设计中错题解析的数据契约 —— JSON Schema七、核心设计下SSE 流式输出与思考过程的取舍八、容错设计让坏掉的 JSON也能优雅展示九、前端如何把 JSON 变成病历 处方十、视觉设计深蓝科技风的落地细节十一、样式本地化为什么最终交付是一个单文件十二、测试与验证不只能跑还要能看十三、踩坑记录与工程经验十四、安全、局限与边界十五、展望从解题工具到学习教练十六、结语写代码之外的三点收获一、写在开头为什么会有这个项目每一个认真读书的人大概都经历过同一个过程考试结束翻开试卷对着一个红叉发呆——明明感觉会做怎么就错了呢翻开标准答案“过程很简单”可再遇到类似的题还是错。问题出在哪里答案往往不在这道题而在我为什么做错了这道题。题目的正确解法是果而做错的原因才是因。可惜的是绝大多数学生的错题本只记了果没记因。抄一道题五分钟看一遍答案一分钟然后随手一合——错题本成了抄题本。这个项目想解决的就是这个问题。我想做一个工具你只需要把做错的题目粘贴进来它就能像一名细心的私人教练那样帮你把这道题拆开来看——你错在哪一步、为什么错、这道题背后的考点是什么、以后再遇到同类题该怎么防。它不是把答案丢给你而是陪你把因找出来。当然如果这个工具只是又一个能回答问题的聊天机器人那就毫无意义了。真正让我兴奋的是另一件事前端能不能拿到结构化的、可以直接排版的解析结果也就是说我希望 AI 不仅会说话还能按格式工作把结果自动组织成错因分析、解题步骤、考点归纳、提升建议这样层次清晰的信息块。这引出了整个项目最核心的一个问题——如何让一个基于概率的大模型稳定地输出我规定的数据结构。二、从错题本到错题教练需求拆解与产品定位在写任何代码之前我先花了一晚上做需求拆解。我把一个理想中的错题解析工具拆成了四个核心能力这也是后来页面功能区那四张卡片的由来能力要回答的问题对学生的价值定位错因我到底为什么错把粗心这种空话翻译成具体的行为诊断拆解步骤正确的解题路径是什么给出一套可以跟练的动作清单归纳考点这道题考的是哪个知识点把一道题放进知识地图里提升建议我下一步该做什么给出能够执行的学习动作这四件事说难不难但有一个前提它们之间存在清晰的信息分层。错因是诊断步骤是处方考点是背后的机理建议是康复计划。如果 AI 把四件事混在一大段话里说出来学生要自己在一堆文字里做信息抽取——这恰恰是机器应该替人做的事。于是产品形态逐渐清晰AI 按结构说话前端按结构展示。整个项目的技术设计都是围绕这句话展开的。三、技术选型为什么坚持零依赖纯前端课程大作业有它独特的生存法则。很多作业死在答辩现场翻车——不是功能不行而是环境不行昨天还能跑今天依赖装不上这台机器行换台机器就白屏。所以我给自己立了三条硬约束零依赖。只用原生 HTML5、CSS3、JavaScript。不引 Vue、不引 React、不引 jQuery更不用 webpack、vite 这类构建工具。项目里连一张图片资源都没有图标全部用内联 SVG。不写后端。纯前端直接调用大模型的开放接口。接口是 HTTP SSE 流式浏览器原生fetch就能处理不需要自制代理服务。双击即用。最终交付物要尽可能小、尽可能单。理想状态下把仓库里那个 HTML 文件拷贝到任何一台电脑上双击就能跑出完整页面。这三条约束听起来佛系实际上对设计提出了很高要求没有框架意味着状态管理和 DOM 操作全靠手写没有构建意味着每一条 CSS 都必须自己斟酌没有后端意味着 API Key 的存放、跨域策略这些都要考虑清楚。而约束本身也带来好处——可控。每一个字节都是我写出来的出了问题我知道去哪找。四、整体架构一个文件的小而美经过反复打磨项目最终以单个index.html的形式交付CSS 全部内联在head的style里JavaScript 全部内联在页尾的script里favicon 是一个 data URI 的内联 SVG页面不请求任何本地静态资源。页面的结构可以分成四个区域来理解顶部标题栏居中放置蓝紫渐变发光标题与副标题左侧是「清空会话」按钮右侧是模型徽章整体走科技感、对称感路线。欢迎/功能区页面初次加载时展示欢迎卡片与四张功能特性卡片告诉使用者这个工具能干什么降低上手成本。对话区整个页面的主体承载用户消息与 AI 回复。用户的消息是右侧的蓝色渐变气泡AI 的解析结果渲染成分区结构化的解析卡片。这也是全项目视觉工作量最大的部分。输入区底部固定包含学科胶囊按钮、示例快捷填入、输入文本框与发送按钮支持回车发送。在数据层面对话历史通过localStorage持久化刷新页面后上下文仍然保留用户可以对同一道题持续追问——比如这道题有没有更快的解法、“换一道同类题给我练练”。代码的组织方式也很朴素一个CONFIG常量对象放接口地址、模型名、密钥、参数一个SYS_PROMPT模板字符串放系统提示词其余的对话、流式解析、JSON 渲染、历史管理都封装成若干明显的函数。没有模块化框架但目录清晰、职责分明——这正是原生 JavaScript 的魅力所在。五、核心设计上如何用系统提示词约束大模型输出 JSON这是我认为整个项目最值得写一笔的地方。直接问大模型这道题怎么做它会给你一大段自然语言。这段话说得再对前端也很难排版它哪里是重点用户想知道错因答案却先写了三步解题。用户想看考点答案却沉浸在大段推导里。信息是有的但结构是乱的。要让输出结构化最朴素也最有效的思路是在系统提示词里把输出协议定义清楚并反复强调这是一个硬性要求。我把它写成了一份输出规范要点如下给模型一个明确的角色定义“你是一位经验丰富的中小学全科错题解析教练”——角色的作用很大它会调动模型在教育场景下的语料经验。定义输出的 JSON 结构并明确说明必须始终以严格的 JSON 对象输出不要输出任何多余的说明文字、不要用 markdown 代码块包裹、不要带前后缀。约定字段的内容腔调解题步骤要求分点、并用【】标出每一步的易错点common_mistakes和knowledge_points必须用数组即使只有一项也要是数组。做最坏情况预案提示词里明确写出如果题目信息严重缺失要在question字段注明缺失并在error_analysis里说明还需要哪些信息——避免模型面对残缺输入时直接摆烂或者瞎编。这条系统提示词在项目开发早期就写好并做了端到端验证。我用一个真实错题二次函数在闭区间上的最值问题去测模型的返回严格符合 Schemasubject、question、七个字段一个不少两个数组字段类型正确解题步骤里甚至真的用了【步骤1】这样的结构化写法。那一刻我很确定这条技术路线走对了。这里有一个值得分享的经验约束性提示词有三个要素——给格式定义、给反面示例、给兜底约定缺一不可。只给格式定义模型可能偶尔叛逆加上不要输出多余内容这类反面约束稳定性会好很多而兜底约定则是保证产品在极端输入下仍然体面。六、核心设计中错题解析的数据契约 —— JSON Schema既然约定要输出 JSON那就要把契约写得足够明确。项目的契约如下{subject:学科名称如数学,question:重新整理后的完整题目原文,error_analysis:错因分析定位做错的根本原因,correct_solution:正确解法分步骤解题过程用【】标注易错点,common_mistakes:[常见错误1,常见错误2,常见错误3],knowledge_points:[核心考点1,核心考点2,核心考点3],study_advice:针对性的学习建议与避坑策略}七个字段的设计是有讲究的subject与question是基本信息用于回显和归档error_analysis是诊断结论直接回应用户最关心的问题——我为什么错correct_solution是标准动作给出可跟练的步骤用【】做易错点强调common_mistakes是反面清单把最容易踩的坑提前暴露出来knowledge_points是概念外延把一道具体的题接到知识网络里去study_advice是行动建议给出可执行的下一步。前端拿到这个 JSON 之后渲染逻辑也变成了声明式的——每个字段对应一种视觉组件错因用红色圆点点缀、步骤配绿色强调、考点渲染成胶囊标签、建议放进青色提示框。数据契约一旦定义好前端代码其实就是一遍遍摆组件。七、核心设计下SSE 流式输出与思考过程的取舍对话接口采用text/event-stream分块传输也就是大家常说的 SSE。与一次性返回不同SSE 让模型每生成一段内容就推给客户端体验上是边生成边显示的打字机效果——比干等十来秒然后啪地弹出一大段要舒服得多也更符合对话的直觉。前端的实现是fetchReadableStreamconstresawaitfetch(CONFIG.API_URL,{method:POST,headers:{Content-Type:application/json,Authorization:Bearer${CONFIG.API_KEY}},body:JSON.stringify({model:CONFIG.MODEL,messages,stream:true,...params})});constreaderres.body.getReader();// 用缓冲区按 \n 切分 SSE 帧逐行解析 data: 前缀的内容有一个必须处理的工程细节SSE 帧可能被 TCP 拆成半个 JSON。如果每次read()都立刻JSON.parse往往会撞上Unexpected end of JSON input。正确的做法是维护一个累积缓冲区先按换行符把完整行剥出来再逐行解析——这是流式开发最容易翻车、也最值得记住的坑之一。调试时我还发现了一个有意思的现象模型的每个分片里既包含reasoning_content思考过程也包含content正式回答。思考过程在流式阶段会先于内容出现体现为发送请求后先安静一两秒然后文字开始蹦出来。我选择只消费content把思考过程留在后台——它不属于用户想要的信息也就不该出现在界面上。八、容错设计让坏掉的 JSON也能优雅展示大模型是概率性输出哪怕提示词写得再死也保不齐某一次返回前多了一行好的以下是详细解析或者把结果包进了 markdown 代码围栏。如果前端不处理这些情况用户就会在页面上看到一坨看不懂的原始 JSON。所以我在解析端做了三层降级第一层用正则提取json ... 代码块里的内容优先按围栏内的文本来JSON.parse第二层提取不到围栏时把模型完整返回做 trim 后直接JSON.parse第三层如果前面都失败就放弃 JSON 渲染把原始内容按 Markdown 转成可读的 HTML 展示。三层兜底的意义在于无论模型怎么发挥用户永远不会看到一行裸 JSON 或一片报错。产品是可以降级运行的——数据好的时候精美呈现数据差的时候保底能看。这种优雅降级的思维在工程上往往比一刀切更体现产品素养。九、前端如何把 JSON 变成病历 处方如果把错题解析看作一次就诊那error_analysis是诊断、correct_solution是处方、knowledge_points是病因机理、study_advice是康复计划。前端就负责把这些信息做成一张结构清晰的病历卡。渲染层我写了一个buildAnswerCard(json)函数专门把 JSON 转成 DOM。卡片分头部和若干内容区块头部是蓝紫渐变横幅左侧标题错题深度解析、右侧学科标签内容区块则按刚才说的对应关系逐个渲染。答题步骤会用有序列表展示考点渲染成一组彩色胶囊标签常见错误用✗符号做项目符号学习建议则放进一个有左边框强调的提示框里。这里值得一提的是section这个小组件函数我给每个内容区块传入标题 颜色 内容 HTML由它统一生成带彩色圆点的小标题 内容区的结构。所有模块复用同一套模板视觉上就非常统一。这种先定义组件、再组装页面的思路即使不引入 UI 框架也能写出结构清爽的代码。十、视觉设计深蓝科技风的落地细节如果说结构化数据是项目的里子那怎么把这套东西做得好看就是面子。课程大作业要能拿出来讲视觉上必须能打。我围绕深蓝科技教育风做了整套设计核心手段如下背景纵深主体用linear-gradient从深蓝到藏蓝的渐变营造宇宙般的纵深感背景里叠加一张极淡的网格线background-image用两个方向的linear-gradient拼出再撒 16 个纯 CSS 动画的星光粒子——粒子用animation做上下缓浮和透明度呼吸位置、时长、透明度都各不相同看起来活但绝不抢戏更不会遮挡文字。标题发光大标题用 CSSbackground-clip: text做蓝紫渐变文字再配filter: drop-shadow做柔和发光视觉重心一上来就立住了。毛玻璃材质欢迎卡片、输入区都用backdrop-filter: blur()做磨砂毛玻璃效果配合半透明描边让页面看起来通透、现代。微交互功能卡片 hover 时轻微上浮并向外晕开一层蓝紫光晕学科胶囊点击后从浅底切换成渐变蓝底、文字变白全程有 0.3 秒平滑过渡发送按钮 hover 时scale(1.05)轻微放大并增强发光。细节打磨自定义了渐变圆角滚动条移动端把 9 个学科胶囊改成单行横向滚动、隐藏滚动条在 390px 宽度的手机上实测无横向溢出。做视觉我最大的感受是高级感来自细节密度而不是堆料。一个阴影、一条描边、一处圆角单独看都不起眼但组合起来就是这套页面用心了的感觉。十一、样式本地化为什么最终交付是一个单文件项目早期样式和脚本分别放在css/style.css和js/app.js里结构很标准——但实际使用中出了岔子某些预览环境加载外链资源失败、某些浏览器命中旧缓存不更新样式于是出现了HTML 跑起来了但页面是白板/旧皮肤的尴尬局面。排查到最后我做了个干脆的决定把所有样式彻底内联进 HTML让页面完全自包含。于是index.html变成了一个一碰就响的单文件不再请求任何本地资源唯一的网络请求就是对话接口本身。这对课程展示的意义是决定性的无论是拷贝到新电脑、发邮件给老师、还是放进在线 HTML 预览器打开就是完整页面再也不用解释你要把 css 和 js 放到对应目录。连 favicon 都做成了内联的 data URI SVG —— 一个解字放在渐变圆角色块上。实测浏览器在加载该页面时零外部资源请求、零控制台报错这才是我心目中交付完毕的标准。十二、测试与验证不只能跑还要能看代码写完不算完我给它做了一轮完整验证覆盖三个层面接口层用真实错题调用模型验证返回严格符合 JSON Schema、数组字段类型正确两层都必须是 list不能变成字符串。页面层用无头浏览器打开页面断言——深蓝背景生效body计算样式非白色、功能卡片数量为 4、学科胶囊数量为 9、隐藏的下拉框select仍然存在于 DOM 且与胶囊联动正常。交互层点击语文胶囊后select的 value 正确变为语文且 active 状态正确互斥输入题目点击发送后用户气泡出现、页面无 JS 报错AI 的真实解析结果能在若干秒内完整渲染成结构化卡片。其中胶囊与 select 联动是一个有意思的细节既有逻辑读取的是select.value但我需要的是胶囊按钮的视觉形态。我选择了保留隐藏下拉框作为数据载体 胶囊按钮做视觉与值同步的方案——用一个十几行的小脚本桥接两者没有改动原有逻辑一行。这种不动老代码、只做适配层的做法在接手维护他人代码时尤其实用。十三、踩坑记录与工程经验把开发过程中踩过的坑和沉淀的经验集中记下来供后来者参考“为什么样式没生效”——外链 CSS 在部分预览环境和缓存策略下不可靠的教训换来了全内联交付以后凡是给人看的项目我都倾向于先确认资源是否会丢。流式解析的边界——SSE 分帧可能把 JSON 从中截断必须用缓冲区攒行再解析这是一个和网络搏斗养成的肌肉记忆。组件与既有逻辑的耦合——胶囊按钮与下拉框的故事说明前端做视觉重构时最稳妥的方式是给旧逻辑留数据后门而不是粗暴替换。上下文长度的心智模型——对话历史会越滚越长需要做截断策略本项目截取最近约 16 条否则提示词膨胀会越来越贵、越来越慢。流式与思考的先后——了解模型reasoning_content与content的流动顺序才不会把用户等得心焦也不会误把思考塞进对话气泡。十四、安全、局限与边界诚实地讲这个项目存在明确的边界。API Key 明文纯前端必然要在代码里写 Key这等于把钥匙挂在大门口。课程演示可以接受但绝不能直接上生产。可靠的做法是加一个轻量后端做转发Key 只存在服务端。内容可信度大模型有幻觉风险解析内容仅供参考。项目一直保留着内容由 AI 生成仅供参考的提示这也是一份产品责任感。只能处理文本目前不支持拍照识题。图片类错题几何图、手写过程是真实使用中的高频场景也是计划中要补的能力。依赖外部接口可达离线环境、校园网络受限时功能不可用。可以在仓库里放一份示例 JSON 作为演示模式属于易做且有价值的小改进。十五、展望从解题工具到学习教练下一步的设想是在不破坏零依赖基因的前提下逐步进化错题本归档把每次解析结果存入localStorage按学科归档支持检索与复习——这本身就是艾宾浩斯遗忘曲线的最佳实践场景。薄弱点画像累计一定数量的错题后按knowledge_points做统计输出你的知识薄弱点雷达图。这一步能让产品从一题一解升级为全局诊断。同类题练习让 AI 基于当前错题现场生成同考点的练习题并附答案学习闭环从看懂跨到练会。图片识别引入 OCR 或支持上传图片直接交给多模态模型补齐几何题、手写题等高频场景。十六、结语写代码之外的三点收获回顾这个项目代码之外有三件事让我觉得最值得第一让 AI 按结构工作。大模型不是只能聊天通过好的提示词设计它可以变成一个守规矩的结构化数据生产者。这种模型的确定性是可以被工程手段驯化的——提示工程是 AI 时代最基本的工程能力。第二优雅降级的设计哲学。三层 JSON 兜底教会我一个成熟的产品不但要考虑正常时多好看更要考虑异常时不难看。容错才是工程成熟度的分水岭。第三约束带来美感。零依赖、单文件、双击即用这几个约束让项目最终长成了它该有的样子。有时候把选择变少反而更容易把事做成做透。如果你也在做一个大模型 前端的小项目希望这篇博客能给你一些启发别急着堆功能先把输出契约定下来别怕模型不稳定把兜底层做厚别小看视觉和交付体验看起来高级这件事本身就是作业的一部分。本文由「码道」撰写 · AI 错题解析助手 · HTML5 CSS3 JavaScript · Zero Dependencies
返回列表