2026春SDU软件创新实训第10周工作总结
本博客对应工作时间为2026.5.6-2026.5.10。目前项目已经达到中期阶段,项目的骨架以及基础功能已经基本完成,接下来就是将原先完成的诸多后端接口集成到前端并成为对应的功能即可。
本周的工作相对较少,主要包含:
- 将原始的AI解析题目功能集成到具体的题目,成为一个方便实用的插件。具体的功能包括首轮知识库检索解析、多轮追问和个性化回答
- 基于现有题目、用户追问记录和对应的知识库信息实现个性化的新题目生成,并加入用户个性题库。
- 集成相似度检索算法进入交通标志识别功能,实现模型识别(单标志)+推荐识别(多候选标志)结合
题目解析插件实现
注意到我们在先前的问答助手中已经实现了“智能解析”模式,考虑到了偏题目问答的情况,它的逻辑是这样的:
- 如果输入只有文本,我们从纯文本知识库进行检索相关片段作为知识库,输入给文本模型
- 如果输入的包含图片(多模态输入),则优先将输入的图片和现有的图库进行多维相似度匹配并排序推荐,如果相似度高于阈值就采用top-1结果的元数据,调用文本模型进行整合回答;低于阈值就调用视觉模型,对输入的图像进行解析。
注意到,由于实际驾考题目里面一个题目最多只有一个题目,因此这一套对于题目解析同样适用!我们只需要对接口略作修改,能够适应前端的实际需求即可。
在正式进入接口修改之前,我们先对数据的持久化方式做了一些变更,原先的问答记录都存放在mysql中,不同模式都混在一起。这里如果我们是在题目插件里面调用接口,我们需要对同一道题目进行多轮问答,那么不同题目、不同用户的对话内容都需要进行隔离。这样mysql的方式不利于快速的查找。深思熟虑之后我选择改用mongo存储题目插件里面产生的问答信息,现有的接口不再修改而是写出来新的接口。我们将自己思考的结构给到LLM,由他参考并进行修改:
其中,首轮问答(产生的默认解析)所传递的结构如下:
{ "user_id": "123", "question_id": "题目唯一id", "question_data": { "question": "题干", "type": "single_choose", "options": ["A、...", "B、..."], "key": "B", "analysis": "原有硬编码解析", "label": ["标签"], "subject": 1, "img": null }, "top_k": 4 }后续的多轮问答部分,对应调用的json结构:
{ "mode": "专业解析", "user_id": "123", "question_id": "mongo_object_id_or_frontend_unique_id", "question": { "...": "题目结构" }, "query": "我为什么选错了?" }这样就完成了对应的实现解析和多轮问答的后端逻辑,对应实际使用的数据库结构如下:
这样我们首先按照用户名称进行编号,用户内部按照题目编号进行区分,对于同一个用户的同一道题,分为两部分:第一个是初始的默认解析,可支持重新生成,包含了调用的知识库等附带信息;第二个是针对题目的多轮问答追问回复对话,是一个序列信息,每个元素表示一轮问答的结果。
后端完成后,我们让LLM生成对应的功能的接口文档,说明清楚有哪些接口,调用的方式和结构格式、可选参数等,这样我们在本地的Android Studio里面使用的时候也可以让本地的LLM“看到”后端实际服务器的写法:
生成的md文档大致如下:
我们利用filezilla将服务器上面的Md文件传输到本地,并且调用 本地的LLM,在Android Studio中进行前端的修改,让LLM根据接口文档的内容补充功能:
效果预览:
个性化题目生成插件
这一部分是一块相对新颖且有意思的功能,属于是本组的原创功能(之前从未在其他任何APP或者网站上看到过)。我们的总体思路就是:从一个单个的题目出发,生成与之比较在知识点上相似的题目。我们的核心输入是:
- 原始的题目信息(题干、选项、答案和解析)
- 搜集获得的知识库条目信息
- 用户的问答记录
原始的题目信息限定了生成结果的核心主题,不能随意生成,风格上必须与既定的题目信息自洽(如科目一只能生成单选和判断题,但是科目四还可以另外生成多选题);知识库条目信息保证了考察知识点的科学性和合理性,不能天马星空,而是有确定的可信知识来源的;用户的问答记录展现了个性化的成分,模型将优先针对用户的疑问生成切合实际薄弱点的个性化结果。三者三位一体,在不同方面约束输出的结果,尽可能将黑盒输出的不稳定性降到最低。
我们首先将自己的需求给到LLM,让它进行细化,变为规范的表述,得到的需求文档如下:
实际功能需求主要包括:
- 个性化新题目生成(包含题干、选项、解析和参考答案等)
- 确认/否决添加到个性化题库
- 获取当前所有的个性化题目
- 删除个性化题库中的某些题目
接着我们将需求文档作为提示词传入,让LLM检查当前系统是否有了类似的功能,如果没有就开始细化:
初始的默认的数据存储形式非常零散,一个用户+一个题目的做成单独的一个文档,缺乏整合性和层次度。我们再次要求他改成按照用户聚类,内部按照题号区分的优化版逻辑:
最终生成个性化题目的所用提示词如下:
sections = [ "你是驾驶员考试题库命题专家。请基于原题、知识库检索结果和用户追问方向,生成新的相似练习题。", "只支持纯文字题,不要生成图片题、视频题或需要看图才能作答的题。", f"必须生成 {count} 道题,输出必须是严格 JSON 数组,不要添加任何解释文字。", f"subject 必须固定为 {subject}。", "允许题型:" + "、".join(allowed_types), "可用标签只能从下列标签选择,优先 1 个,最多 2 个:\n" + "、".join(labels), "考察内容优先级:知识库检索结果 > 用户提问方向 > 原题。不要简单复述原题。", "每道题必须包含 question、type、options、key、analysis、label、subject。", "single_choose 和 judge 的 key 是单个大写字母;multi_choose 的 key 是多个大写字母按字母顺序拼接。", "【原始题目信息】\n" + _question_payload_to_prompt(question_payload), ]测试无误后,生成对应的接口文档,供前端调用:
我们按照之前类似的思路,前端看到这个md说明,并且部署相应的个性化生成接口功能:
随后我们再对现有的界面进行优化,增加了交互模式信息,生成过程有转圈提示等:
最终效果展示:
交通标志检索添加相似度检索逻辑
这一部分是对队友做的交通标志检测的优化,yolo模型虽然识别很准,但是一旦出错,可用性就会迅速归0。这种非黑即白的模式显然无法完全适用于实际。考虑到之前在智能解析模块做过图像相似度检索的算法,或许可以在原有的纯yolo模型识别的基础上再进一步添加基于图像相似度的检索逻辑,这样即使yolo模型识别错误,只要返回的相似的图像数量足够多,仍然能够基本能找到对应的真实的结果(即使top-1不一定就是真实的结果,但是只要前几名是包含真实对应的结果的仍然可用!),这一操作可以极大提升功能的容错率,理论上只要我们图库扩充的足够完备,那么总是可以匹配到对应的真实结果的,通过元数据就可以获取信息了。相似度检索的算法作用就是将原有的超大范围的查找(不方便人工)压窄变为少量的几个候选的结果,支持人工的匹配。这就已经能够达到真实需求的功能了!
这里的主要思路就是:原始的yolo检测可以拆解为两部分(虽然实际上,这两部分似乎是模型内部一起完成的,但是结果上可以分离):第一步是定位出所有标志在图中的位置,第二步是对于每个识别出来的位置(切分出来的子图),独立判断这个标志是什么。显然我们可以将第二步进行替换,替换为基于图像的相似度(视觉+语义)的推荐系统类型的版本。我们直接将切出来的子图作为相似度检索模块的输入即可,输出匹配程度最高的若干个标准图以及对应的元数据(标准图包含的图像名称),只要这个top-k里面能够包含真实的对应图像就是成功!
我们对需求的表述如下:
生成相应的接口说明文档、给到前端,让它基于这个文档生成修改集成双向判断识别结果后的结果:
最终又修复了图片显示异常等问题,得到下面的预览效果:
