软件工程实践第二次作业——与 AI 结对编程(顶会热词统计)

102400320林明阳 2026-09-24 22:05:20

软件工程实践第二次作业:与 AI 结对完成“顶会热词统计平台”

项目内容
这个作业属于哪个课程202601福大-软件工程实践-W班
学号-姓名102400320_林明阳
这个作业要求在哪里顶会热词统计作业要求
这个作业的目标使用 AI 结对完成需求分析、墨刀原型、Web 编码、测试、部署和过程反思,分析 CVPR、ICCV、ECCV 的专业研究方向变化
其他参考文献DBLP Search API、《构建之法》第 3、4、8 章、课程附录 14 论文清单

目录

  • 软件工程实践第二次作业:与 AI 结对完成“顶会热词统计平台”
  • 一、三个访问链接
  • 二、AI 编程助手说明
  • 三、作业描述
  • 四、项目范围与确认内容
  • 4.1 已确认的页面信息架构
  • 4.2 已确认的数据策略
  • 4.3 本次不纳入范围
  • 五、PSP 表格
  • 5.1 偏差分析
  • 六、NABCD 需求分析
  • 6.1 N:Need——用户需求与痛点
  • 角色一:小刚,计算机视觉初学者
  • 角色二:论文研究者
  • 6.2 A:Approach——解决方案与核心流程
  • 核心流程
  • 页面解决问题的方式
  • 关键词与热度口径
  • 6.3 B:Benefit——用户价值与项目优势
  • 对小刚的价值
  • 对论文研究者的价值
  • 项目优势
  • 6.4 C:Competition——替代方案、竞争方式与差异化
  • 6.5 D:Delivery——数据来源、实现范围、交付方式与限制
  • 数据来源
  • 实现范围
  • 交付方式
  • 限制
  • 七、功能范围与验收标准
  • 7.1 本次必须实现
  • 7.2 后续可选扩展
  • 7.3 可执行验收标准
  • 八、墨刀原型设计
  • 8.1 原型工具与链接
  • 8.2 六个页面的原型职责
  • 1. 数据总览
  • 2. 论文导入
  • 3. 论文列表管理
  • 4. 热门方向与关键词图谱
  • 5. 热度走势
  • 6. 关于与使用说明
  • 8.3 原型截图位置
  • 九、系统设计与实现过程
  • 9.1 技术架构
  • 9.2 论文数据字段
  • 9.3 关键实现步骤
  • 十、成品功能展示
  • 数据总览页正常状态
  • 论文批量导入文件预览
  • 论文导入成功
  • 字段校验失败
  • 论文列表管理
  • 编辑和删除确认
  • 论文详情和原文链接
  • Top 10 专业研究方向
  • 关键词图谱和关联论文
  • 热度走势动画
  • 关于与使用说明
  • 空数据、加载和失败状态
  • 自动化测试和部署验证
  • 十一、结对(人机)讨论过程描述:AI 结对协作记录
  • 11.1 协作方式
  • 11.2 案例 A:需求分析与原型调整
  • 我的提示词
  • AI 输出摘要
  • 我的修改与理由
  • 这一轮协作的结果
  • 11.3 案例 B:论文导入、专业方向分析与趋势实现
  • 我的提示词
  • AI 输出摘要
  • 我的修改与理由
  • 11.4 案例 C:发现并修复原文链接、热词和图谱问题
  • 我提出的问题
  • AI 输出摘要
  • 我做的修改
  • 验证结果
  • 11.5 可解释性声明
  • 十二、代码说明:关键代码与实现思路
  • 12.1 数据源和 DBLP 条件检索
  • 12.2 专业方向清洗和热度统计
  • 12.3 关键词图谱和趋势数据
  • 12.4 Flask 接口中的失败处理
  • 12.5 前端原文链接和趋势动画
  • 十三、测试、Git 提交与部署
  • 13.1 自动化测试
  • 13.2 CodeArts 提交情况
  • 13.3 腾讯云部署
  • 十四、心路历程、收获与结对开发反思
  • 14.1 与传统人人结对的相同点
  • 14.2 AI 结对的优势
  • 14.3 AI 结对的局限
  • 14.4 对 AI 结对伙伴的评价
  • 十五、项目不足与后续计划
  • 已知不足
  • 后续计划
  • 十六、参考资料

一、三个访问链接

类型访问地址检查结果
CodeArts 项目代码仓库102400320-2已检查,仓库页面可访问
CodeArts 代码规范codestyle.md已检查,代码规范文件位于仓库根目录
项目部署网站https://hotwords.43-128-25-27.sslip.io/已检查,HTTPS 返回 200
墨刀原型在线链接顶会热词统计平台-102400320-分享已检查,分享页面可访问

项目部署服务器公网 IP 也可以直接访问:http://43.128.25.27/。

部署平台说明:本项目实际部署在腾讯云服务器上;CodeArts 用于代码仓库和提交记录管理。当前 dev、远程 main 已同步到 e9854b7,共 39 次提交,并保留 v1.0.0 标签。

二、AI 编程助手说明

本项目使用的 AI 编程助手是 ChatGPT / Codex(GPT-5 系列)。

主要用途如下:

  1. 协助完成角色分析、NABCD 需求分析和验收标准梳理;
  2. 协助讨论墨刀原型的信息架构、页面职责、异常状态和跳转关系;
  3. 协助设计 Flask、SQLite、前端页面和数据处理模块的初稿;
  4. 协助生成测试思路、定位原文链接、年份范围、热词质量和关键词图谱布局问题;
  5. 协助整理博客结构和代码说明。

AI 输出只作为候选方案和结对讨论材料。最终页面划分、数据口径、异常处理、代码修改、测试结果和部署检查均由我审核、修改并验证。

三、作业描述

本项目面向对计算机视觉研究方向感兴趣的初学者、需要整理论文数据的研究者以及负责检查课程作业的助教,设计并实现一个“顶会热词统计平台”。

系统以 CVPR、ICCV、ECCV 三大计算机视觉顶会为范围,使用附录 14 论文清单作为标题、会议和年份的主要来源,再通过 DBLP 等公开接口,在本地没有结果且数据源可访问时补充摘要和原文链接。系统不承诺稳定爬取所有会议官网,也不把自动提取的关键词冒充成论文官方关键词。

平台目前包含六个独立页面:

  1. 数据总览;
  2. 论文导入;
  3. 论文列表管理;
  4. 热门方向与关键词图谱;
  5. 热度走势;
  6. 关于与使用说明。

已验证的当前数据规模为:

  • 论文记录:1120 篇;
  • 会议:CVPR、ICCV、ECCV;
  • 年份范围:2018—2025;
  • 会议分布:CVPR 640 篇、ICCV 320 篇、ECCV 160 篇;
  • 热词分析:使用清洗后的系统提取专业方向进行论文计数;
  • 自动化测试:31 项通过。

这里的热度表示清洗后的系统提取方向在论文中的出现频次或论文覆盖数,不等同于严格的学术影响力、引用量或研究质量评价。

四、项目范围与确认内容

4.1 已确认的页面信息架构

页面页面职责
数据总览展示论文总数、会议分布、年份覆盖、Top 10 摘要和最近导入记录
论文导入区分单篇查询与批量导入,提供文件预览、字段校验、重复论文提示和结果反馈
论文列表管理提供搜索、筛选、论文详情、编辑、删除和无结果后的条件远程检索
热门方向与关键词图谱展示 Top 10 专业研究方向、关键词关系和关键词关联论文
热度走势按会议、年份和关键词筛选,以图表动画展示多年变化,并同步展示文字数据
关于与使用说明说明数据来源、原始关键词、系统提取关键词、统计口径和数据限制

4.2 已确认的数据策略

  • 附录 14 论文清单作为标题、会议和年份的主要来源;
  • 课程数据集和本地 SQLite 数据作为优先数据;
  • DBLP 公开检索接口作为本地无结果时的备用检索来源;
  • 远程查询只有在数据源可访问时才尝试;
  • 远程接口失败、超时、无结果或字段不完整时,向用户返回明确提示;
  • 论文原始关键词和系统提取关键词分开保存;
  • 原始关键词用于论文详情展示;
  • 系统提取方向用于 Top 10、关键词图谱和热度走势;
  • 原文链接优先使用公开论文页面或 DBLP 返回的链接,不能使用 example.com 等演示占位地址。

4.3 本次不纳入范围

本次没有把登录、收藏、复杂个性化推荐、微服务拆分、全文 PDF 下载、引用网络分析和商业化权限系统列为必须功能。这些可以作为后续扩展,不影响本次基础功能验收。

五、PSP 表格

以下表格沿用本次作业过程中确认的分钟记录。实际耗时用于课程实践复盘,不把时间记录解释为系统功能完成的证明。

阶段预计耗时(分钟)实际耗时(分钟)偏差
计划与需求分析130195+65
原型与交互设计190312+122
数据库和 API 设计130183+53
代码规范与设计评审60108+48
后端编码380605+225
前端编码380650+270
测试与缺陷修复190312+122
文档与截图240432+192
Git 提交与发布100180+80
合计18002977+1177

5.1 偏差分析

  1. 原型阶段实际花费较多,主要原因是页面从“功能堆叠”重新调整为六个独立页面,并补充了空数据、加载、重复论文、字段错误、无结果和网络失败状态;
  2. 后端和前端耗时增加,主要原因是增加了附录 14 标题优先、DBLP 条件补充、原始关键词与系统提取关键词分离、专业方向清洗、原文链接跳转和多年趋势数据;
  3. 测试阶段增加了真实错误路径检查,而不是只验证理想流程;
  4. 文档和截图阶段需要同时整理墨刀原型、AI 对话、CodeArts 提交记录、测试结果和部署页面,因此实际耗时高于最初估计;
  5. Git 提交阶段需要按功能拆分并完成编译、测试后再提交,不能把所有改动一次性提交。

六、NABCD 需求分析

本节中的“已确认”是项目约束;“候选建议”是结合需求分析得到的可执行方案,不表示所有扩展已经实现。

6.1 N:Need——用户需求与痛点

角色一:小刚,计算机视觉初学者

痛点:

  • 不清楚 CVPR、ICCV、ECCV 近几年关注哪些专业方向;
  • 论文数量多,逐篇阅读并手工统计耗时;
  • 不容易理解英文论文标题中的研究术语;
  • 希望同时看到论文标题、摘要、原始关键词和原文链接;
  • 希望通过 Top 10、关键词图谱和趋势图建立整体认识。

使用场景:

小刚在数据总览页查看论文规模和会议分布,在热门方向页查看“视频理解、扩散模型、视觉-语言、多模态、视觉 Transformer、自监督学习”等专业方向,再点击关键词查看相关论文,最后在热度走势页观察某个方向在不同会议和年份中的变化。

角色二:论文研究者

痛点:

  • 需要按会议、年份、题目和关键词查询论文;
  • 需要批量导入论文清单,减少逐条录入;
  • 需要修改不完整字段并删除错误记录;
  • 需要区分论文原始关键词和系统自动提取方向;
  • 需要知道数据来自哪里,避免把统计结果误认为官方研究结论。

使用场景:

研究者在论文导入页上传课程数据或输入单篇题目,先预览字段和重复项,再确认导入;之后在论文列表管理页按会议和年份筛选,打开详情查看摘要、原始关键词、系统提取方向和原文链接。

6.2 A:Approach——解决方案与核心流程

核心流程

附录14标题清单
        |
        v
本地清洗、去重、字段校验
        |
        v
SQLite 论文库
        |
        +--> 本地精确/模糊查询
        |        |
        |        +--> 有结果:展示论文详情
        |        |
        |        +--> 无结果:数据源可访问时尝试 DBLP
        |                         |
        |                         +--> 成功:提示来源并允许保存
        |                         +--> 失败:说明失败原因,不伪装成功
        |
        v
系统提取专业方向
        |
        +--> Top 10 方向
        +--> 关键词图谱
        +--> 多会议多年趋势动画

页面解决问题的方式

  1. 数据总览:把论文规模、会议分布、年份覆盖和热门方向放在一个入口,但不放论文增删改查;
  2. 论文导入:单篇查询与批量导入分开,批量导入先预览再确认,避免错误文件直接写入;
  3. 论文列表管理:把搜索区、筛选区、列表区和操作区分开,编辑和删除都有确认步骤;
  4. 热门方向与关键词图谱:Top 10 列表、图谱和关联论文在同一个分析页面中协同展示,但不放热度走势;
  5. 热度走势:只负责会议、年份、关键词筛选和动态图表,不重复放导入和管理功能;
  6. 关于与使用说明:把数据来源、字段含义、统计口径和限制单独写清楚,帮助初学者和助教理解结果。

关键词与热度口径

  • 论文官方原始关键词:若数据中存在,则原样保存并在详情页标注为“原始关键词”;
  • 系统提取方向:从标题和摘要中经过大小写归一、停用词过滤、词组识别和专业词表映射得到,明确标注为“系统提取方向”;
  • 热度基础指标:清洗后的系统提取专业方向覆盖论文数;
  • 同一论文在某一方向的统计中只计一次,避免同一论文重复计数;
  • 该指标用于课程项目中的统计展示,不等同于论文引用量、学术影响力或研究质量。

6.3 B:Benefit——用户价值与项目优势

对小刚的价值

  • 用 Top 10 代替逐篇浏览,先形成计算机视觉研究方向的整体认识;
  • 通过中文方向名和英文术语对照,降低理解门槛;
  • 点击关键词可以查看关联论文,便于从概念进入原文;
  • 通过趋势动画观察研究方向在不同会议和年份中的变化。

对论文研究者的价值

  • 用批量导入减少重复录入;
  • 支持精确查询和模糊查询;
  • 提供原始关键词与系统提取方向的分层展示;
  • 通过编辑、删除和来源字段维护本地论文列表。

项目优势

  • 范围收敛到 CVPR、ICCV、ECCV,不承诺不稳定的全网爬取;
  • 附录 14 作为标题主来源,DBLP 只作为有条件补充,数据来源边界清楚;
  • 原始关键词和系统提取方向不混淆;
  • 统计、图谱和趋势使用同一套清洗后的专业方向;
  • 不只设计理想流程,补充了加载、空数据、重复论文、字段校验和远程失败状态。

6.4 C:Competition——替代方案、竞争方式与差异化

替代方案能解决什么局限本项目的差异化
CVF 或会议官网查看论文标题、摘要和原文更适合逐篇浏览,不直接提供课程作业要求的导入、维护、Top 10 和趋势整合将课程数据、论文管理和统计分析组合起来
DBLP公开检索论文元数据不保证所有论文都有完整摘要、关键词或原文链接只在本地无结果时条件查询,并显示失败和字段不完整
Google Scholar、Semantic Scholar搜索论文和引用信息数据范围、接口限制和统计口径不完全受本项目控制项目范围固定为三大顶会,结果可解释、可复现
VOSviewer、CiteSpace适合复杂文献计量分析使用门槛较高,不是面向初学者的六页 Web 平台用较少操作展示 Top 10、图谱和趋势
只做静态页面的课程项目能展示界面常缺少真实导入、异常状态和可操作查询以可操作验收为中心,保留真实数据链路和失败提示

本项目不是要替代专业文献计量软件,而是针对课程需求,强调“数据来源透明、功能链路完整、初学者能看懂、助教能验收”。

6.5 D:Delivery——数据来源、实现范围、交付方式与限制

数据来源

  1. 附录 14:标题、会议和年份的主要种子来源;
  2. DBLP Search API:本地没有结果且接口可访问时的备用查询来源;
  3. 公开论文页面:用于原文跳转,例如 CVF Open Access 页面;
  4. 不下载论文全文,不把远程检索失败伪装成成功。

实现范围

  • Flask 后端;
  • SQLite 嵌入式数据库;
  • HTML、CSS、JavaScript 前端;
  • ECharts 图表和时间轴动画;
  • Gunicorn 运行 Web 服务;
  • systemd 管理服务;
  • Caddy 反向代理和 HTTPS;
  • CodeArts 管理源代码和提交记录。

交付方式

  • CodeArts 代码仓库;
  • 腾讯云公网部署网站;
  • 墨刀只用于手工原型设计;
  • 博客提供截图、测试证据、代码片段和访问链接。

限制

  • DBLP 字段可能为空、延迟或受接口限制;
  • 远程检索依赖网络,不保证每次都能返回结果;
  • 课程数据不是三大会议全部官方论文全集;
  • 热度是清洗后方向覆盖数,不等同于学术影响力;
  • 系统提取方向不是论文官方关键词;
  • 当前不包括登录、收藏、复杂推荐和全文 PDF 下载。

七、功能范围与验收标准

7.1 本次必须实现

编号必须功能
F1单篇论文查询
F2批量导入论文列表,先预览后确认
F3标题、摘要、原始关键词、系统提取方向、原文链接展示
F4论文新增、修改、删除和查询
F5精确查询、模糊查询和无结果时的条件远程检索
F6Top 10 专业研究方向统计
F7关键词图谱,点击关键词显示关联论文
F8CVPR、ICCV、ECCV 多年份热度走势和前端动画
F9空数据、加载、网络失败、重复论文、字段校验失败、无搜索结果、图表加载失败提示
F10六个独立页面和清晰跳转
F11CodeArts 提交记录、自动化测试和腾讯云部署

7.2 后续可选扩展

  • 账号登录和权限管理;
  • 收藏和个人阅读清单;
  • 引用量或被引趋势;
  • 论文 PDF 阅读和笔记;
  • 更复杂的语义聚类;
  • 多语言方向解释;
  • 导出 CSV;
  • 定时更新公开数据;
  • 论文相似度推荐;
  • 微服务拆分。

7.3 可执行验收标准

功能操作步骤成功判断
单篇查询打开“论文导入”,输入一个已有论文标题并查询返回标题、会议、年份、摘要、原始关键词、系统提取方向和原文链接
单篇无结果输入本地不存在的题目页面明确显示“本地无结果”,只有数据源可访问时才出现远程查询入口
远程失败让备用数据源不可访问或等待超时显示“远程查询失败/超时”,给出“重试”和“返回本地查询”,不显示伪造论文
批量预览选择包含合法行、缺字段行和重复行的文件先显示预览、合法数、错误数、重复数,未点击确认前数据库数量不变
批量成功在预览页点击确认导入只写入合法且不重复的记录,显示成功数和失败数
字段校验提交空标题、非法年份或不支持会议阻止提交并在对应字段下方显示错误原因
重复论文导入与已有记录标题和会议年份相同的论文标记为重复,默认不重复写入,并说明可跳过或返回修改
列表搜索在管理页输入完整题目搜索只返回匹配论文,并能打开详情
模糊搜索输入编号、关键词或部分标题返回包含查询词的记录
编辑点击编辑,修改摘要后提交显示明确确认步骤,确认后列表显示新摘要
删除点击删除先显示包含论文标题的确认框,取消不删除,确认后刷新列表并提示成功
Top 10打开热门方向页显示 10 个专业方向的中文名、英文名、论文数和占比
图谱点击图谱中的一个方向节点节点高亮,并在下方或右侧显示相关论文
图谱防重叠调整窗口或刷新页面主要节点和标签可辨识,不出现所有标签重叠在一个圆内
趋势筛选在热度走势页选择会议、年份范围和专业方向图表和文字数据同步更新
趋势动画点击播放或重播时间轴按年份推进,能比较 CVPR、ICCV、ECCV 的变化
空数据清空或使用无数据数据源进入页面显示空状态说明和“去导入论文”按钮,不显示空白图表
加载状态首次进入或点击刷新显示加载提示,加载完成后替换为统计内容
图表失败让分析接口返回错误保留页面标题和筛选条件,显示“图表加载失败”和“重新加载”按钮
原文链接在列表中点击“查看原文”浏览器直接打开记录中的真实公开论文地址,而不是跳转到 example.com
移动端手机访问部署链接并依次打开六页导航可折叠,表格可横向滚动,按钮和文字不被裁切
部署使用外网打开部署 URL首页返回 200,六个页面和核心 API 可访问
代码提交查看 CodeArts 提交记录能看到按功能划分的多次中文提交记录,并能定位对应代码变更
测试在项目环境执行测试命令输出 31 passed 或不低于当前测试数量的通过结果

八、墨刀原型设计

8.1 原型工具与链接

原型使用墨刀手工绘制,没有使用原型工具生成代码。

在线原型:顶会热词统计平台-102400320-分享

8.2 六个页面的原型职责

1. 数据总览

展示五张统计卡片:论文总数、会议数量、年份覆盖、系统提取方向数量、最近导入数量;下方放会议分布图、年份覆盖图、Top 10 摘要和最近导入记录。

按钮跳转:

  • “去导入论文” -> 论文导入;
  • “查看论文” -> 论文列表管理;
  • “查看 Top 10” -> 热门方向与关键词图谱;
  • “查看趋势” -> 热度走势;
  • “了解数据口径” -> 关于与使用说明。

2. 论文导入

页面上半部分是“单篇查询”,下半部分是“批量导入”。批量导入必须先显示文件名、字段预览、合法数、错误数和重复数,再由用户确认。

状态包括:输入为空、查询中、查询成功、本地无结果、远程成功、远程失败、文件格式错误、字段错误、重复论文、部分成功和全部失败。

3. 论文列表管理

分为搜索区、筛选区、列表区和操作区。列表中同时显示“原始关键词”和“系统提取方向”,并提供详情、编辑、删除和查看原文。

编辑流程为:点击编辑 -> 打开表单 -> 修改 -> 点击“保存修改” -> 显示修改确认 -> 确认后刷新列表。删除流程为:点击删除 -> 显示论文标题和风险提示 -> 点击“确认删除”或“取消”。

4. 热门方向与关键词图谱

上方是 Top 10 专业方向表格,中部是关键词图谱,下方或右侧是关联论文列表。点击节点后只刷新关联论文,不跳转到热度走势。

5. 热度走势

只保留会议筛选、年份筛选、专业方向筛选、播放、暂停、重播按钮、动态图表和文字统计。页面不放论文导入、删除和编辑操作。

6. 关于与使用说明

单独说明课程数据集、DBLP 备用检索、原始关键词、系统提取方向、热度统计口径、异常状态和数据限制。

8.3 原型截图位置

img

墨刀六个页面在同一画板中的整体布局

img

数据总览页的卡片、图表、Top 10 摘要和最近导入区域。

九、系统设计与实现过程

9.1 技术架构

浏览器
  |
  v
HTML / CSS / JavaScript / ECharts
  |
  v
Flask 路由与 JSON API
  |
  +--> 论文导入、列表管理、详情接口
  +--> 统计、Top 10、图谱、趋势接口
  +--> DBLP 条件远程检索
  |
  v
SQLite
  |
  +--> papers
  +--> import_records
  +--> keyword statistics

部署结构:

公网 HTTPS
    |
    v
Caddy 反向代理
    |
    v
Gunicorn(127.0.0.1:8001)
    |
    v
Flask 应用
    |
    v
SQLite 数据库

9.2 论文数据字段

字段含义
title论文标题
abstract摘要,可能为空
venue会议,限定 CVPR、ICCV、ECCV
year发表年份
original_keywords数据源提供的原始关键词,若有则保留
extracted_keywords系统从标题、摘要中提取的专业方向
url原文或公开论文页面链接
source数据来源,例如附录14或 DBLP
title_source标题来源说明
created_at导入时间

9.3 关键实现步骤

  1. 将附录 14 标题清单清洗为统一字段;
  2. 对标题、会议和年份进行去重;
  3. 对缺少摘要或原文链接的记录,按条件尝试公开接口;
  4. 将原始关键词与系统提取方向分开存储;
  5. 用专业方向词表、短语识别和停用词过滤替代无意义高频词;
  6. 统计论文覆盖数,生成 Top 10;
  7. 根据方向共现关系生成图谱;
  8. 用会议、年份和方向生成趋势时间轴;
  9. 为导入、管理、分析、趋势分别提供接口;
  10. 使用测试、CodeArts 提交和公网访问逐步验收。

十、成品功能展示

数据总览页正常状态

展示论文总数、会议分布、年份覆盖、Top 10 摘要和最近导入记录。

img

论文批量导入文件预览

展示文件名、字段列、合法记录数、错误记录数和重复记录数,说明确认前不会直接写入。

img

论文导入成功

展示批量导入完成后的成功数、跳过数、失败数,以及“查看论文列表”按钮。

img

字段校验失败

展示标题为空、年份不合法或会议不支持时的字段级错误提示。

img

论文列表管理

展示搜索区、会议筛选、年份筛选、原始关键词、系统提取方向和操作按钮。

img

编辑和删除确认

展示编辑表单、保存修改确认,或包含论文标题的删除确认框。

img

论文详情和原文链接

展示摘要、原始关键词、系统提取方向、来源字段和“查看原文”按钮。点击按钮后应打开真实公开论文地址。

img

img

Top 10 专业研究方向

展示方向中文名、英文名、论文数、占比、增长信息和“查看相关论文”。

img

关键词图谱和关联论文

展示节点间距、节点标签和点击某个专业方向后的关联论文列表,重点证明标签没有全部重叠。

img

点击“图像生成”的关键词节点的结果如下

img

热度走势动画

展示会议、年份和专业方向筛选,以及按年份推进的动态图表和文字数据。

img

img

关于与使用说明

展示课程数据集、DBLP 备用检索、原始关键词、系统提取方向和统计限制。

img

空数据、加载和失败状态

展示空数据提示、加载动画、统计数据加载失败和“重新加载”按钮。

img

自动化测试和部署验证

展示测试结果 31 passed 或当前实际测试结果,以及公网页面地址。

img

十一、结对(人机)讨论过程描述:AI 结对协作记录

11.1 协作方式

我的协作方式不是把整道题一次性交给 AI,而是把任务拆成需求分析、原型评审、数据处理、功能实现、测试修复和文档整理几个阶段。每个阶段都先提出约束,再检查 AI 输出,最后用页面操作、测试命令或公网接口验证。

AI 更像一个可以快速提出候选方案的搭档;我负责决定哪些内容符合题目、哪些内容需要删减,以及哪些代码必须通过测试后才能保留。

11.2 案例 A:需求分析与原型调整

我的提示词

请根据“顶会热词统计”作业要求,从小刚和论文研究者两个角色分析用户痛点、使用场景、必须功能、可选功能、数据来源风险和验收标准。请先提出候选方案,不直接写代码,也不要使用原型工具生成代码。

AI 输出摘要

AI 按两个角色整理了用户痛点、使用场景、功能优先级和验收方向,建议设置数据总览、导入、论文管理、分析、趋势和说明等页面。

我的修改与理由

  • 采纳角色划分和“先需求、后代码”的顺序;
  • 否定“所有功能放在一个页面”的建议,改为六个独立页面;
  • 补充空数据、加载失败、网络失败、重复论文、字段错误和无搜索结果;
  • 将 DBLP 限定为本地无结果且数据源可访问时的备用查询;
  • 明确区分原始关键词和系统提取方向;
  • 将热度口径改为清洗后的专业方向论文覆盖数;
  • 将登录、收藏、复杂推荐和微服务移到可选扩展。

这一轮协作的结果

这一轮没有直接产生代码,而是形成了墨刀手工原型的页面职责、状态设计和跳转关系。后续页面设计均以这版收紧后的需求为准。

img

需求分析提示词截图。

img


img

我对单页堆叠方案的否定和页面架构修改截图。

img

img

11.3 案例 B:论文导入、专业方向分析与趋势实现

我的提示词

请把已经确认的六页面需求落实为 Flask + SQLite 的最小可解释实现:批量导入必须先预览再写入;原始关键词和系统提取关键词分开保存;Top 10、关键词图谱和趋势只能使用系统提取关键词;DBLP 只在本地无结果时尝试。请先说明接口和测试点,不要把失败的远程查询伪装成成功。

AI 输出摘要

AI 建议将导入预览和确认写入分成两个动作,将论文字段、来源和两类关键词分开存储,并为统计接口增加明确的失败返回。

我的修改与理由

  • 采纳先预览后写入,避免错误文件直接污染数据库;
  • 采纳系统提取方向单独存储,避免把自动结果展示为官方关键词;
  • 采纳统计接口统一使用提取方向;
  • 将“DBLP 一定能补全”改为“可访问时尝试,失败则提示”;
  • 对论文时间范围扩展到 2018—2025,保证满足至少五年以上跨度;
  • 对热词结果加入专业方向词表和短语过滤,删除 data、show、however 等普通词;
  • 对图谱增加布局和节点间距处理,避免所有标签重叠。

img

专业方向 Top 10、图谱和趋势动画截图。

img

11.4 案例 C:发现并修复原文链接、热词和图谱问题

我提出的问题

点“查看原文”不能直接打开真实论文网址;热词中出现普通英文词;关键词图谱的节点和标签全部重叠。请定位问题并修复,同时保留失败状态提示,不要用 example.com 这类演示地址。

AI 输出摘要

AI 分析了原文链接字段、前端点击行为、关键词清洗和图谱布局几个位置,建议先检查数据源和接口返回,再检查前端按钮是否使用了真实 URL,最后增加专业词过滤和图谱布局约束。

我做的修改

  1. 将论文记录中的演示原文地址替换为公开论文页面或 DBLP 返回的真实地址;
  2. 前端“查看原文”使用记录中的 URL 直接打开,并在没有 URL 时显示明确提示;
  3. 将系统提取关键词限定为清洗后的专业研究方向;
  4. 调整关键词图谱的节点大小、间距和标签布局,避免节点重叠;
  5. 用测试检查至少一个原文链接返回成功;
  6. 在失败时保留重试或返回本地查询入口。

验证结果

  • 公开论文链接可访问;
  • /api/overview 返回 1120 篇、2018—2025 年和三大会议统计;
  • 图谱页面不再把所有普通词堆叠在同一节点上;
  • 自动化测试通过。

img

发现原文链接、专业热词和图谱重叠问题的调试截图。

11.5 可解释性声明

  • 需求分析和页面文案参考了 AI 的候选建议,但最终页面拆分和异常状态由我审核确定;
  • 部分代码骨架、接口命名和测试思路由 AI 协助生成,我逐段理解并根据项目数据源和实际报错修改;
  • 附录 14 数据清洗、字段取舍、专业方向词表、原文链接检查、测试和部署结果由我负责确认;
  • 墨刀原型采用手工绘制,没有使用原型工具生成代码;
  • 提交前不使用自己不能解释的 AI 生成代码。

十二、代码说明:关键代码与实现思路

以下代码用于说明关键思路,展示的是项目中与数据源、关键词分析、异常处理和前端交互有关的核心片段。为控制文章篇幅,重复的样式、模板和简单 CRUD 代码用省略号表示;个别局部变量为了便于阅读做了整理,接口路径按当前仓库版本书写,完整实现以 CodeArts 仓库为准,目标是展示约 300 行左右的关键代码。

12.1 数据源和 DBLP 条件检索

# hotwords/sources.py
from __future__ import annotations

import json
from urllib.parse import quote
from urllib.request import Request, urlopen

SUPPORTED_VENUES = {"CVPR", "ICCV", "ECCV"}


class SourceError(RuntimeError):
    """公开数据源不可用、超时或返回内容不完整时使用。"""


def _read_json(url: str, timeout: float = 8.0) -> dict:
    request = Request(
        url,
        headers={
            "Accept": "application/json",
            "User-Agent": "top-conference-hotwords-course-project/1.0",
        },
    )
    try:
        with urlopen(request, timeout=timeout) as response:
            body = response.read().decode("utf-8")
    except Exception as exc:
        raise SourceError(f"公开数据源请求失败:{exc}") from exc

    try:
        return json.loads(body)
    except json.JSONDecodeError as exc:
        raise SourceError("公开数据源返回的内容不是合法 JSON") from exc


def fetch_dblp(title: str) -> dict | None:
    """仅在本地无结果时被调用,找不到时返回 None。"""
    if not title.strip():
        return None

    url = (
        "https://dblp.org/search/publ/api"
        f"?q={quote(title)}&format=json&h=10"
    )
    payload = _read_json(url)
    hits = payload.get("result", {}).get("hits", {}).get("hit", [])

    for item in hits:
        info = item.get("info", {})
        venue = str(info.get("venue", "")).upper()
        if not any(name in venue for name in SUPPORTED_VENUES):
            continue

        result = {
            "title": info.get("title", ""),
            "abstract": info.get("abstract", ""),
            "url": info.get("ee", ""),
            "source": "DBLP",
        }
        if not result["title"] or not result["url"]:
            raise SourceError("DBLP 返回记录字段不完整")
        return result

    return None

这段代码的重点是:远程查询不是默认路径;只在本地没有结果时调用;接口失败、JSON 错误和字段不完整都会转成可解释的错误。

12.2 专业方向清洗和热度统计

# hotwords/analyzer.py
from collections import Counter
import re

STOP_WORDS = {
    "the", "and", "for", "with", "from", "that", "this",
    "data", "show", "however", "which", "both", "novel",
}

PROFESSIONAL_TOPICS = {
    "video understanding": "视频理解",
    "diffusion models": "扩散模型",
    "vision-language": "视觉-语言多模态",
    "vision transformer": "视觉 Transformer",
    "self-supervised learning": "自监督与表征学习",
    "image generation": "图像生成",
    "semantic segmentation": "语义分割",
    "object detection": "目标检测",
    "3d vision": "三维视觉",
    "efficient inference and compression": "高效推理与模型压缩",
}


def normalize_text(value: str) -> str:
    value = value.lower().replace("_", " ")
    return re.sub(r"\s+", " ", value).strip()


def extract_professional_topics(title: str, abstract: str) -> list[str]:
    text = normalize_text(f"{title} {abstract}")
    found = []
    for english_name in PROFESSIONAL_TOPICS:
        if english_name in text:
            found.append(english_name)
    return sorted(set(found))


def count_topics(papers: list[dict]) -> list[dict]:
    counts = Counter()
    paper_total = len(papers)

    for paper in papers:
        topics = paper.get("extracted_keywords", [])
        for topic in set(topics):
            counts[topic] += 1

    result = []
    for rank, (topic, count) in enumerate(
        counts.most_common(10), start=1
    ):
        result.append(
            {
                "rank": rank,
                "topic": topic,
                "name_zh": PROFESSIONAL_TOPICS.get(topic, topic),
                "paper_count": count,
                "share": round(count / paper_total * 100, 2)
                if paper_total else 0,
            }
        )
    return result

这段代码把普通高频词过滤在专业方向集合之外,并用“覆盖论文数”计数。set(topics) 保证一篇论文在同一方向只统计一次。

12.3 关键词图谱和趋势数据

def build_keyword_graph(papers: list[dict]) -> dict:
    node_counts = Counter()
    edge_counts = Counter()

    for paper in papers:
        topics = sorted(set(paper.get("extracted_keywords", [])))
        for topic in topics:
            node_counts[topic] += 1
        for index, left in enumerate(topics):
            for right in topics[index + 1:]:
                edge_counts[(left, right)] += 1

    nodes = []
    for topic, count in node_counts.most_common(12):
        nodes.append(
            {
                "id": topic,
                "name": PROFESSIONAL_TOPICS.get(topic, topic),
                "value": count,
                "symbolSize": 26 + min(count, 80) * 0.45,
            }
        )

    links = [
        {"source": left, "target": right, "value": count}
        for (left, right), count in edge_counts.most_common(24)
    ]

    return {"nodes": nodes, "links": links}


def trend_series(
    papers: list[dict],
    venues: list[str],
    years: list[int],
    topic: str,
) -> list[dict]:
    result = []
    for year in years:
        row = {"year": year}
        for venue in venues:
            row[venue] = sum(
                1
                for paper in papers
                if paper.get("year") == year
                and paper.get("venue") == venue
                and topic in set(paper.get("extracted_keywords", []))
            )
        result.append(row)
    return result

图谱使用共现关系,不是把所有关键词都画成一个大圆。前端还会对节点间距、布局和标签位置进行约束,避免用户看到重叠文字。趋势接口按会议和年份返回数字,前端用 ECharts 时间轴动画展示。

12.4 Flask 接口中的失败处理

# hotwords/__init__.py(核心逻辑节选)
@app.get("/api/papers")
def list_papers():
    query = request.args.get("q", "").strip()
    venue = request.args.get("venue", "").strip()
    year = request.args.get("year", "").strip()

    try:
        items = repository.search(
            query=query,
            venue=venue,
            year=int(year) if year else None,
        )
    except ValueError:
        return jsonify({
            "ok": False,
            "message": "年份必须是数字",
        }), 400

    return jsonify({
        "ok": True,
        "items": items,
        "total": len(items),
    })


@app.post("/api/papers/import/preview")
def preview_import():
    upload = request.files.get("file")
    if upload is None or not upload.filename:
        return jsonify({
            "ok": False,
            "message": "请选择论文文件",
        }), 400

    preview = importer.preview(upload)
    return jsonify({
        "ok": True,
        "valid_count": preview.valid_count,
        "duplicate_count": preview.duplicate_count,
        "error_count": preview.error_count,
        "rows": preview.rows,
    })


@app.post("/api/papers/import")
def confirm_import():
    payload = request.get_json(silent=True) or {}
    token = payload.get("preview_token", "")
    if not token:
        return jsonify({
            "ok": False,
            "message": "请先完成文件预览",
        }), 400

    try:
        result = importer.confirm(token)
    except DuplicateError as exc:
        return jsonify({
            "ok": False,
            "message": str(exc),
        }), 409
    except ValidationError as exc:
        return jsonify({
            "ok": False,
            "message": str(exc),
        }), 400

    return jsonify({"ok": True, "result": result})

当前仓库还提供 /api/papers/fetch 和 /api/papers/lookup 作为远程检索入口;接口把输入错误、远程失败、重复错误和字段校验错误返回成不同状态,前端可以据此显示不同文案,而不是全部显示“操作失败”。

12.5 前端原文链接和趋势动画

function openPaperSource(url) {
  if (!url) {
    showToast("该论文暂未返回可访问的原文链接");
    return;
  }

  const target = String(url).trim();
  if (!/^https?:\/\//i.test(target)) {
    showToast("原文链接格式异常,请先检查论文来源");
    return;
  }

  window.open(target, "_blank", "noopener,noreferrer");
}


async function loadTrend() {
  setLoading("#trend-panel", "正在加载趋势数据……");

  const params = new URLSearchParams({
    venue: getValue("#venue-filter"),
    year_from: getValue("#year-from"),
    year_to: getValue("#year-to"),
    topic: getValue("#topic-filter"),
  });

  try {
    const response = await fetch("/api/analysis/trends?" + params);
    if (!response.ok) {
      throw new Error("HTTP " + response.status);
    }

    const payload = await response.json();
    if (!payload.ok) {
      throw new Error(payload.message || "趋势数据加载失败");
    }

    renderTrendChart(payload.series);
    renderTrendTable(payload.series);
  } catch (error) {
    showError(
      "#trend-panel",
      "趋势数据加载失败,请检查网络后重试",
      loadTrend,
    );
  }
}


function renderTrendChart(series) {
  const chart = echarts.init(
    document.querySelector("#trend-chart"),
  );

  chart.setOption({
    timeline: {
      axisType: "category",
      autoPlay: false,
      playInterval: 1200,
      data: series.map(item => item.year),
    },
    options: series.map(item => ({
      title: { text: item.year + " 年专业方向热度" },
      xAxis: {
        type: "category",
        data: ["CVPR", "ICCV", "ECCV"],
      },
      yAxis: { type: "value" },
      series: [{
        type: "bar",
        data: [item.CVPR, item.ICCV, item.ECCV],
      }],
    })),
  });
}

这里把“打开真实 URL”和“展示趋势动画”分开处理。原文地址缺失或格式错误时不打开空白页;趋势加载失败时保留重试按钮。

十三、测试、Git 提交与部署

13.1 自动化测试

在项目环境中执行:

python -m pytest -q

当前验证结果:

31 passed in 5.54s

测试覆盖了论文查询、导入预览、重复处理、原文链接、统计接口、图谱、趋势和部分异常状态。

13.2 CodeArts 提交情况

项目在 CodeArts 的 dev 分支进行开发,当前可核验的提交数量为 39 个,远程 main 与 dev 已同步到提交 e9854b7,并保留 v1.0.0 标签。

提交按功能阶段拆分,示例包括:

  • 补齐2025论文数据与年份趋势;
  • 修复原文链接直接跳转;
  • 修正热词提取与图谱节点布局;
  • 扩充三大顶会论文数据并规范专业方向;
  • 增加移动端 IP 访问入口;
  • 修正云服务器部署端口并接入 Caddy。
  • 补充产品测试与交付验收记录。

每次提交前先完成对应功能、编译或启动检查,再提交代码;没有把所有功能一次性提交。

13.3 腾讯云部署

部署结构为:

  • 腾讯云公网 IP:43.128.25.27;
  • HTTPS 域名:https://hotwords.43-128-25-27.sslip.io/;
  • Gunicorn 监听本机 127.0.0.1:8001;
  • systemd 负责进程管理;
  • Caddy 负责反向代理和 HTTPS;
  • SQLite 数据库已经初始化为 1120 条论文记录。

已验证接口:

  • /api/overview 返回 200;
  • /api/papers?page=1&page_size=3 返回论文列表;
  • /overview、/import、/papers、/analysis、/trends、/about 均可访问;
  • 论文原文链接指向公开 CVF 页面,不再使用 example.com 占位链接。

十四、心路历程、收获与结对开发反思

14.1 与传统人人结对的相同点

人机结对和传统两人结对都需要:

  • 明确需求和共同目标;
  • 一边提出方案,一边检查方案;
  • 及时发现错误并修改;
  • 通过测试和演示确认结果;
  • 对提交内容负责,而不是只看代码数量。

本项目中,我先提出需求约束,AI 给出候选结构;我再指出“不能所有功能堆在一个页面”“不能把普通英文词当热词”“不能把 DBLP 失败写成成功”,这种往返和传统结对中的驾驶员、观察员协作比较接近。

14.2 AI 结对的优势

  1. 反馈速度快,适合在需求、原型、接口、测试之间反复比较;
  2. 可以从初学者、研究者和助教多个角色补充遗漏点;
  3. 能快速生成表格、验收标准和异常状态清单;
  4. 对常见 Flask、SQLite、JavaScript 和 ECharts 写法有较多候选经验;
  5. 可以帮助把报错转成具体排查步骤。

14.3 AI 结对的局限

  1. AI 可能把不存在的接口、字段或链接说得很确定;
  2. AI 可能生成能运行但不符合题意的普通词统计;
  3. AI 不会自动知道课程数据集的真实字段,需要我提供并核对;
  4. AI 可能忽略部署环境、端口、权限和移动端网络问题;
  5. AI 输出的代码如果不经过理解和测试,容易形成不可维护的黑盒;
  6. 远程数据源存在接口限制、超时和字段缺失,不能把 AI 的“应该可以”当成实际保证。

14.4 对 AI 结对伙伴的评价

AI 适合作为高响应速度的方案讨论者、代码草稿助手和测试清单生成器,但不适合替代需求判断、数据核验和最终验收。

这次协作中,AI 最有价值的地方是帮助我把一个较宽泛的“统计热词平台”收紧为六页、可操作、可验收的系统;最需要警惕的地方是它可能默认理想网络、理想数据和理想用户流程。因此我把“提出建议”和“证明完成”分开:前者可以让 AI 加快,后者必须由代码、测试、截图和公网访问共同证明。

十五、项目不足与后续计划

已知不足

  • 课程数据规模和会议官方全部论文规模不是同一个概念;
  • DBLP 的摘要、关键词和原文链接不保证完整;
  • 目前热度指标是论文覆盖数,不包含引用量、作者影响力和论文质量;
  • 关键词图谱是基于方向共现的可视化,不等于严格的知识图谱;
  • 当前没有登录、收藏、全文阅读和复杂推荐;
  • 腾讯云部署与作业原文“华为云服务器”的平台要求存在差异,需要向助教确认。

后续计划

  1. 增加数据源状态和最后更新时间;
  2. 增加 CSV 导出,方便助教复核;
  3. 引入更稳定的专业术语词表和人工审核入口;
  4. 为趋势图增加会议对比说明和数据缺失标记;
  5. 根据助教意见决定是否迁移到课程指定云平台。

十六、参考资料

  1. 软件工程实践作业要求:顶会热词统计
  2. DBLP Search API 使用说明
...全文
85 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

102

社区成员

发帖
与我相关
我的任务
社区描述
202601福大-软件工程实践-W班
软件工程 高校 福建省·福州市
社区管理员
  • 202601福大-软件工程实践-W班
  • 李之尹
  • 123
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧