ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

结合知识图谱与大模型:智能出题系统的闭环设计与实现

结合知识图谱与大模型:智能出题系统的闭环设计与实现 每到毕业设计季总有不少人把“智能出题系统”当成一个相对稳妥的方向觉得不外乎是建一张题库表再调用一个大模型API把题目“生成”出来。真到答辩现场才发现老师追问的往往不是“你调用的是哪个模型”而是“题目生成之后质量怎么保证和已有题目重复了怎么办学生做错的题系统能不能在后续出题时避开同一个坑”如果你也想做一个类似的项目——接通AI大模型结合知识图谱和错题分析做一个智能生成题目系统那这篇文章值得看完。我的核心判断是这类项目的价值不在于“接入了Qwen-Plus”而在于你用知识图谱组织题目、用大模型生成题目、用错题数据反向校正出题策略最终形成一个可解释、可控制、可演示的闭环。没有这个闭环你做的只是一个“随机出题器”而不是“智能出题系统”。1. 先搞清楚这个项目真正要解决的是什么问题1.1 单次调用大模型API撑不起一个毕设如果把“智能出题系统”简单理解成“输入一个知识点让大模型返回一道题”那这个项目的工作量大概只值一个周末。因为大模型本身就会做题、会出题你只需要写一个prompt把知识点填进去就能得到看起来还不错的题目。但问题是毕业设计答辩不会只看你能不能调通API。老师会继续追问你的题目是“生成”的还是从题库里“查询”的两者有什么区别如果两个老师输入同一个知识点会不会生成两道一模一样的题你怎么保证生成题目的难度符合教学要求错题分析的数据从哪里来它和出题环节是如何联动的这些问题没有一个能靠“模型能力强”来回答。它们考察的是你有没有把“出题”这件事当成一个完整的业务流程来设计。1.2 知识图谱不是为了好看而是给生成加约束在这个项目里知识图谱承担的角色非常关键。它不是一个花哨的可视化页面而是整条出题流水线里所有结构化信息的来源。你可以把知识图谱理解为一张“知识地图”。每个知识点是一个节点节点之间有前置关系、后置关系、属于哪个章节、常考哪种题型。比如“二叉树中序遍历”这个知识点它的前置知识可能是“树的基本概念”它的后置知识可能是“二叉树的遍历应用”它常考的题型可能是“选择题”和“算法题”。有了这张地图大模型就不是凭空生成题目而是在一张有序、有边界的网络里生成题目。它能知道当前应该围绕哪个知识点出题这个知识点适合什么难度的题哪些知识点是复习过的哪些是新学的某个学生经常做错的是哪些知识点下次出题要不要优先覆盖。如果只是给大模型一句话“帮我出一道二叉树的题”你得到的题目是随机的、孤立的。而接入了知识图谱之后每次出题都变成了一次有依据、可追溯的业务操作。这才是“系统”和“脚本”的本质区别。2. 理解这套系统的架构它是一条内容生产流水线2.1 知识图谱是“食材和菜单”大模型是“厨师”用一个容易理解的类比知识图谱就像厨房里的食材清单和菜单它规定了有哪些原料、哪些菜可以按什么顺序做。Qwen-Plus这样的生成大模型就像厨师负责把原料加工成一道成品菜。错题分析则是顾客吃完之后的反馈告诉后厨哪道菜偏咸了、哪个食材下次要少用。这三部分缺一不可。没有知识图谱厨师只能靠经验随机发挥出什么菜全凭感觉没有大模型知识图谱只是一份静态文档没法动态生成新题目没有错题分析整个系统只负责“出题”不负责“优化出题”它就不是一个完整的闭环。所以你在设计系统的时候要先把这三条链路理清楚而不是一上来就写代码调模型。2.2 一条核心生产链路从知识图谱到题目再到反馈完整的流程可以拆成四条子链路内容组织链路把教材、课程大纲、章节结构整理成知识图谱定义知识点节点和关系。智能生成链路根据当前出题需求知识点、难度、题型把结构化的知识点数据拼进prompt调用大模型生成题目。题目沉淀链路生成的题目经过解析、校验、去重之后存入题库并关联到对应知识点。错题反馈链路学生答题后记录错误信息映射到知识点维度计算薄弱点再反向调节下一轮出题的知识点权重。这四条链路合在一起才是“智能出题系统”的完整架构。单独拿出来任何一条都只是一个小工具。2.3 中间可以放一个“题目生成服务”在实际工程结构上我建议把大模型相关的逻辑单独抽成一个服务不要散落在业务代码里。这个服务只做一件事接收结构化的出题参数返回结构化的题目JSON。这样做的好处有三个后续如果要换模型比如从Qwen-Plus换成其他模型只需要改这一个服务方便加缓存、限流、重试、日志等工程能力答辩时可以说清楚“模型层和业务层是解耦的”这是一个很加分的工程亮点。很多学生容易犯的错是直接在Controller里写一段调用大模型API的代码前端一请求就直接同步等待。这在演示Demo时能跑通但一旦涉及批量出题、并发请求、超时重试就会暴露问题。后面我会专门讲这个坑。3. 从零实现四个关键链路如何落地3.1 第一步构建课程知识图谱先声明一点知识图谱不一定要用Neo4j。如果你的数据量不大用MySQL或者JSON文件也可以关键是先把“节点”和“关系”这两个基本概念建模清楚。一个最小可用的知识图谱至少包含三类信息类型说明示例知识点节点最小的知识单元二叉树中序遍历、快速排序、HTTP状态码关系知识点之间的语义关联前置知识、后置知识、属于章节属性每个节点的业务信息所属章节、难度等级、错误次数在落地时可以先用JSON定义一张小规模的图谱{ node_id: kp_001, name: 二叉树中序遍历, type: knowledge_point, chapter: 树, difficulty: 3, relations: [ { target: kp_000, type: 前置知识 }, { target: kp_002, type: 后置知识 } ] }如果只是毕设这种结构已经够用。如果你想展示“图数据库”的能力也可以把这份JSON导入Neo4j通过Cypher语句查询一个知识点的前驱和后继。答辩时现场展示一下图谱可视化比只讲概念有说服力得多。但要注意知识图谱里的数据才是整个系统的灵魂。如果图谱里只有三五个知识点生成题目就容易撞题错题分析也没有意义。建议从真实教材里选一个章节整理20个以上的知识点并尽量把关系建全。3.2 第二步设计题目的数据结构生成出来的题目不能是一段自由文本必须按固定结构存储。这样后续才能做检索、去重、错题分析。一个常见的题目结构包含这些字段字段类型说明idstring题目唯一IDstemstring题干typestring题型如single_choice、true_false、short_answerdifficultyint难度1到5knowledge_pointsarray关联的知识点ID列表optionsarray选项选择题必填answerstring标准答案analysisstring答案解析保持JSON格式存储可以这样设计{ id: q_1001, stem: 对于一棵非空二叉树中序遍历的最后一个节点是, type: single_choice, difficulty: 3, knowledge_points: [kp_001], options: [A. 根节点, B. 最左叶子节点, C. 最右叶子节点, D. 最后一个访问的节点], answer: D, analysis: 中序遍历的顺序是左-根-右所以最后一个节点是整棵树中最右且最后被访问的节点。 }这里有一个容易被忽略的点题目的数据结构要和知识图谱打通。每道题必须关联一个或多个知识点ID否则错题分析无法把学生的错误映射回知识点。3.3 第三步接入Qwen-Plus并设计出题Prompt接入大模型的细节不值得展开太多因为不同平台的API会在不断调整建议以平台最新文档为准。现在不少大模型服务商提供了OpenAI兼容的接口Qwen-Plus也可以通过类似方式调用。常见写法类似下面这样from openai import OpenAI client OpenAI( api_keyyour-api-key, base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1 ) resp client.chat.completions.create( modelqwen-plus, messages[ {role: system, content: 你是一个专业出题助手只输出JSON不要输出多余内容。}, {role: user, content: build_prompt(...)} ], temperature0.7 )真正容易出问题的是prompt设计。很多人的prompt是“请出一道关于二叉树的题目”这样的结果是不可控的。更稳妥的做法是把知识图谱里已有的结构化信息填进prompt并要求模型按固定JSON格式返回。举个例子一个比较保守的出题prompt结构是请根据以下信息出一道选择题。 知识点名称二叉树中序遍历 所属章节树 前置知识树的基本概念 难度要求31到55最难 题目要求考察中序遍历的规则 请严格按以下JSON格式返回 { stem: 题干, type: single_choice, options: [A..., B..., C..., D...], answer: 正确选项字母, analysis: 解析 }为什么要这样做传入知识点和前置知识模型生成的题目会更有针对性限定返回JSON格式后续解析才稳定约束题型和难度让生成结果符合教学预期。这里最重要的经验是不要相信大模型第一次返回的结果。在大模型真正返回数据之后必须加一层校验和兜底逻辑这也是后面要讲的工程化处理。3.4 第四步建立错题分析闭环错题分析是整个系统里最能体现“智能”的部分也是答辩时最值得展开讲的部分。它的核心逻辑是学生在系统里做题如果答错了系统把这道题关联的知识点记下来。累积一定数据后就能知道某个学生在哪个知识点上薄弱然后在下一次出题时提高薄弱知识点的出题权重。一张简单的错题记录表可以这样设计学生ID题目ID关联知识点是否答对答题时间stu_01q_1001kp_001否2025-06-01 10:30:00stu_02q_1002kp_003是2025-06-01 10:31:00有了这张表之后可以做一个简单的统计每个学生的知识点错误次数全局知识点错误率某个知识点最近是否频繁出错。然后把这个统计结果反馈到“出题策略”里。比如某个知识点错误次数超过阈值下一轮出题时系统可以自动把该知识点的出题权重提高。这一步可以和知识图谱结合如果“二叉树中序遍历”错误率很高那系统可以提示先复习“树的基本概念”因为它们在知识图谱里是前置关系。错题分析最重要的价值是让整个系统从“单向出题”变成“双向反馈”。答辩时如果能把这个闭环讲清楚评委通常会觉得你的系统是完整的设计而不是东拼西凑的Demo。4. 最容易踩坑的四个工程问题4.1 题目重复生成10道题可能有3道高度相似大模型生成有随机性。同一个知识点反复调用几次可能得到结构类似、甚至选项顺序都差不多的题目。这在题库量小的时候尤其明显。解决思路是“先查库再生成”和“生成后再去重”生成之前先查一下题库里这个知识点下已经有哪些题目把已有题目的题干摘要或知识点字段传进prompt提示模型不要重复生成之后再做一次相似度判断。可以用简单的方法比如把题干去掉空格后计算字符串相似度如果数据量大可以接一个向量化embedding计算两个题干的余弦相似度。毕设阶段用字符串相似度就够了重点是让评委看到你有“去重”的意识。4.2 输出格式不稳定大模型偶尔会“不听话”不管prompt里怎么强调“只输出JSON”模型总有小概率返回多余文字、缺字段、甚至选项重复。如果代码里直接用json.loads()解析很可能会抛异常。推荐做法是加一层“解析兜底”先尝试直接json.loads()失败则用正则提取大括号包裹的JSON片段还失败则判断为生成失败走重试逻辑重试次数建议限制在2到3次避免浪费接口调用。这层逻辑虽然不起眼但在实际演示时非常管用。因为你不知道什么时候模型会突然“抽风”有了兜底系统至少不会直接在用户面前报错。4.3 并发和超时不要在前端请求里同步等待大模型返回这是一个很典型的工程问题。如果你在前端页面上点击“生成题目”后端直接同步调用大模型API等待时间可能从几秒到几十秒不等。如果请求一多接口很容易超时。更稳妥的方案是异步化前端提交出题任务后端立即返回一个任务ID后端通过任务队列或线程池处理出题请求前端轮询任务状态生成完成后再展示结果。针对大模型接口调用还要设置超时时间和重试策略。第一次失败可能是因为网络波动或服务端限流重试一两次能显著提高成功率。但重试也要有上限否则成本会失控。4.4 知识图谱空有形式没有真实数据就没有说服力很多学生花时间学会了Neo4j导入了一堆示例数据但那些节点和关系是从网上复制来的和实际课程完全不匹配。答辩时老师随便问一个“这个知识点为什么是另一个知识点的前置”就答不上来。知识图谱的数据必须和你的出题场景一致。如果你做的是《数据结构》的出题系统就应该整理“栈与队列”“二叉树”“图”这些章节的真实知识点关系。规模不要贪大20到30个知识点足够支撑一轮演示但关系一定要合理。如果你不知道怎么建有一个简单的路径从课程的章节目录出发把每章拆成小节每节提炼2到3个核心知识点然后标注知识点之间的依赖关系。这个工作看起来费时间但它会直接决定你后面出题和错题分析的质量。5. 答辩时怎么讲才能从“功能演示”变成“系统设计”5.1 先讲“要解决什么问题”再讲“我做了什么”很多学生一上来就演示页面讲自己用了哪些技术栈这其实不是最好的方式。更好的顺序是先讲清楚“传统出题方式有什么问题”——题库建设成本高、题目复用率低、无法定位学生薄弱点。再说“我的系统怎么解决” —— 用知识图谱组织知识点用大模型动态生成题目用错题分析形成反馈。最后才是技术架构和界面演示。这个顺序能让评委先理解你的设计意图再去评判你的实现是否合理。5.2 演示时重点展示闭环而不是单点功能如果时间有限优先演示这条闭环链路进入出题页面选择知识点“二叉树中序遍历”点击生成题目展示大模型返回的JSON和前端渲染结果故意答错一道题进入错题记录查看错题分析展示该知识点已经被标记为薄弱点再次出题时展示系统提高了该知识点的出题权重。这一套走下来评委看到的不只是一个“调大模型API”的工具而是一个有数据流动、有策略调整、有反馈机制的系统。5.3 提前准备好高频追问的答案以下问题建议提前准备好表述“大模型生成错了怎么办”可以回答生成结果会经过JSON解析校验、相似度去重不合格会触发重试同时预留了人工审核入口可以人工下架错误题目。“知识图谱和普通的标签分类有什么区别”可以回答标签分类只是扁平化的标记知识图谱保存了知识点之间的语义关系比如前置、后置、属于系统能根据关系做更合理的出题策略。“如果换一个模型还能跑吗”可以回答模型调用被封装在独立的生成服务里业务层只依赖统一接口换模型只改一个适配层。这几个问题都答得上来答辩表现基本不会差。6. 这个项目真正的长期价值在哪里6.1 适合谁不适合谁这个方向适合有Java或Python后端基础对Spring Boot、Flask这类框架有了解又想在毕设里体现“AI应用能力”的人。它不要求你做模型训练但要求你把业务逻辑、数据结构、接口设计理清楚。如果你对知识图谱完全没兴趣或者只是想做一个纯前端展示页那这个项目的复杂度可能比你想的高。知识图谱的构建和错题分析的前后端联动都需要投入不少时间。如果是想研究大模型底层机制、做模型训练和微调这类“应用型毕设”也不适合你它更偏工程而不是算法。6.2 如果想继续往生产环境走还差哪些能力毕设阶段的系统通常还缺少这些模块用户体系与权限目前默认是单用户或少量测试用户生产环境需要登录、角色、权限控制题库审核流大模型生成的题目不能直接上架需要人工审核或规则校验日志与监控需要记录每次生成的耗时、失败率、模型返回异常方便追踪问题成本控制大模型调用按次计费批量出题时要设计额度限制和预警人工反馈学生可以对题目质量进行“吐槽”让低质量题目进入回收站。这些不是毕设必须做的但如果答辩时提到“这是后续可以完善的”会让评委觉得你对工程落地的理解不止停留在Demo层面。6.3 回到最开始的主判断这套系统的核心价值不是“调用了Qwen-Plus”而是用知识图谱给大模型生成加上了约束用错题分析让出题策略有了反馈依据。大模型是其中的生成引擎而不是整个系统。如果你的毕设目前还停留在“能调用API生成题目”的阶段不妨先停下来画一张数据流图知识图谱怎么提供输入题目怎么生成错题数据怎么回流。把这条链路跑通之后你会发现系统真正的难点和亮点都不是“调模型”这一步。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进