072403101_陈海滨_软件工程实践第二次作业

Astrix74 2026-09-24 23:55:22

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

这个作业属于哪个课程https://bbs.csdn.net/forums/2601_CS_SE_FZU?spm=1001.2014.3001.6685
这个作业要求在哪里https://bbs.csdn.net/topics/620526318
这个作业的目标与 AI 结对完成需求分析、原型设计、编码实现与云部署,做一个可验证的 CVPR/ICCV/ECCV 顶会热词统计平台
其他参考文献《构建之法》第 3、4、8 章;Node.js / React / ECharts 官方文档;CVF Open Access、ECVA 官网

目录

  1. Git 仓库、代码规范与 AI 工具说明
  2. PSP 表格
  3. NABCD 需求分析
  4. 原型设计与原型链接
  5. 成品展示
  6. 结对(人机)讨论过程描述
  7. 设计实现过程
  8. 代码说明
  9. 心路历程、收获
  10. 对 AI 结对伙伴的评价
  11. 交付链接与已知限制

1. Git 仓库、代码规范与 AI 工具说明

AI 工具说明

工具模型主要用途
Codex—(初始化会话)工程骨架、pnpm workspace、文档与验收表初始化
DeepSeek Harness(命令行代理框架,主会话+子代理并行)deepseek-v4.1-flash数据源实测、API 全量实现(论文 CRUD/抓取/统计)、Figma 原型程序化生成、前端五页、真实数据采集
ZCode(命令行,含子智能体调度)GLM-5.3-flash会话恢复与核验、缺陷修复与回归、测试重写、外网验收、部署收尾
ego-browser / playwright浏览器自动化人工式目检、原型 Present 模式验证、重复性截图与导出脚本

工程规范实践

这一节先讲清楚本项目能在一个晚上保持质量的工程手段,后面代码说明会反复用到它们:

  1. mise 统一工具链:.mise.toml + .node-version 双文件锁定 Node 24.18.1 / pnpm 11.18.0,mise exec 后所有机器(本机、CI、部署服务器)版本一致,engines 告警归零。部署服务器装的就是同版本 Node 24.18.1。
  2. 共享契约包防前后端类型漂移:packages/contracts 同时被 API 与前端引用,导出 CONFERENCES、isHeldIn、全部 DTO 与 KEYWORD_METHOD_VERSION;根脚本在 dev/build/typecheck 前自动先构建它。接口改动只改一处,前后端同时被类型检查约束。
  3. 统一检查门:pnpm check = typecheck → lint → test → build 四步全绿才算完成;测试独立成 tests/ 包(API 用 supertest,Web 用 jsdom + React Testing Library),与生产代码物理隔离,共 36 个测试。
  4. AI 代码必须过人工核验与真实提交:每次 commit 对应一个可解释的能力切分;规范与仓库规则都禁止事后伪造提交时间(作业要求"commit 记录应该符合项目实情")。

2. PSP 表格

实际耗时按三次真实 AI 协作会话的记录归属统计(会话日志可核对),博客提交前可根据自己的计时微调。

PSP阶段/任务预估(分钟)实际(分钟)
Planning计划:作业阅读、需求拆解、估计3520
Analysis需求分析:NABCD、竞品核查4045
Design Spec架构、数据与 API 设计3530
Design Review设计复审(人工复核 AI 方案)2015
Coding Standard代码规范制定1015
Design学习工具与五页原型(Figma 两版)75160
Coding数据库/爬取/清洗9095
Coding统计 API/图谱/趋势7070
Coding五页前端与联动7590
Code Review人工检查 AI 代码2530
Test功能/浏览器/边界测试4055
Reporting云部署/验收4045
Reporting博客/截图/总结4060
合计595710

偏差分析(最大的三项):

  1. 原型超时(75→160):第一版 Figma 原型人工复核时发现中文普遍溢出、图谱节点不可见、折线偏离数据点等 6 类问题,按"先测量再排版"重做了第二版——这一轮返工换来的是后面前端开发可以照稿直接写,没有再返工。
  2. 测试超时(40→55):测试独立成包后踩到 pnpm 依赖不提升导致 react-router-dom 在 tests 包解析失败的问题,重写了 4 条旧断言并新增 API client 错误码测试。
  3. 预估整体偏乐观(595→710):实际是压缩交付(一晚完成 F1–F5+部署),真实开销比"理想排期"多约 19%,主要花在缺陷修复与两轮关键词抽取迭代上——这也验证了预估必须给返工留余量。

3. NABCD 需求分析

N · Need 需求

主要用户是想快速了解计算机视觉研究方向的学生(作业场景中的"小刚")。CVPR 一年录取近 3000 篇论文,靠人工逐篇阅读总结热点不可行。他的核心诉求是:先看方向、再看证据、再读原文——从"哪些方向热"下钻到"哪些论文支撑这个结论",并能比较不同会议、不同年份的变化。次要用户是助教/研究生:需要核查某个趋势的数据来源与统计口径,确认它是不是"编出来的"。

A · Approach 做法(重点)

  • 发现层用官方目录:实测发现 DBLP 检索 API 与数据集下载被 Anubis 反爬拦截(robots.txt: Disallow: /),且 DBLP 官方 FAQ 明确不提供摘要。因此发现层改用 CVF Open Access(CVPR/ICCV)与 ECVA(ECCV)官方目录:目录缓存 8903 条(CVPR 2024 共 2715 条、ICCV 2023 共 2156 条、ECCV 2022/2024 共 1645/2387 条),论文页再抓摘要与原文链接。
  • 可解释的关键词抽取(v1):官方论文页没有关键词字段,因此关键词由规则算法提取并**如实标注 extracted**:子句切段防伪短语 → 停用词/学术泛词过滤 → 1–3 词短语打分(题名命中按词数加权 + 摘要频次 + 短语长度奖励)→ 贪心选择互不包含。方法版本号进库,改规则可整库重算。
  • **统计单位 = "提到该关键词的不同论文数"**,一篇重复出现只算一次;总览、图谱、趋势共用同一统计结果,每个热词都能回查论文。
  • 缺失值语义明确:ECCV 奇数年不举办输出 null 并显示"不举办",未采集的年份显示"无数据"——两者都不画成 0。

B · Benefit 收益

用户 2 分钟内可以从一个热词找到支撑论文(实测路径:总览点词 → 列表 → 详情/原文);批量导入把逐篇打开网页的时间压缩成一次粘贴;公开覆盖矩阵让跨会议比较可解释、可信任。

C · Competitors 竞争(重点,均经现场核查)

替代方式核查结论(2026-09-24 实测)差异
会议官网 / CVF / ECVA权威论文入口,逐届可浏览,但没有跨年三会的热词聚合视图我们补的就是聚合与下钻
DBLP检索 API 被反爬拦截(Anubis 挑战页),且官方 FAQ 说明不提供摘要只能做书目,做不了摘要/关键词层
人工 Excel / 脚本灵活但无界面、难共享、口径易漂移我们把口径写进代码并版本化(v1)

竞争策略:不追求取代学术搜索引擎,而是把范围收窄到三大顶会,做"热词 → 论文证据"的真实闭环,并公开覆盖率与缺失情况——数据上绝不冒充全量。

D · Delivery 交付

原型用专用工具(Figma)制作并发布网页链接;正式产品部署在云服务器(本作业部署在阿里云 ECS · 杭州,源码与版本管理在华为云 CodeArts);博客提供可访问链接、数据来源、动画截图与 AI 协作记录。


4. 原型设计与原型链接

  • 原型工具:Figma(浏览器版)。协作方式是"AI 程序化生成初稿 + 人工复核修改":AI 通过浏览器自动化驱动 Figma,用 Scripter 插件脚本直接在文件里生成设计系统与页面(等价于 MCP 式的工具调用),人工在 Present 模式逐页复核并修改。
  • 原型文件:「CV Scope 原型 · 顶会热词统计」 → 【待你填:把 Figma 文件移到 Drafts 后的公开链接】
  • 原型规模:00 设计系统(13 色板、8 级文字、19 个真实 Figma Component)、01–08 共 8 个版块、12 个导出 Frame、30 个交互热区 + 1 个原型起点(Present 模式实测跳转)。
  • 交互定义:页面跳转(总览↔走势/列表/详情/导入/关于)、弹窗(在线查询候选、删除确认、论文编辑)、查询联动(点击 Top10 行/图谱节点 → 带关键词筛选的论文列表)、空/错/加载态。

第一版 → 第二版的修复(AI 协作案例 A 的人工复核部分):

现象根因修复
中文普遍溢出用"字符数×常数"估宽,中文全角宽度≈字号改为 measure() 先量文本真实宽度再定尺寸
图谱只见连线、气泡不可见节点缺颜色字段补充颜色并重排为力导向式布局
折线整体比数据点高约 16px误判 Figma rotation 旋转锚点改用 relativeTransform 显式仿射变换
详情摘要压住关键词标题resize(w,10) 后读到的是换行前高度改为 resize(w, t.height) 按真实高度推进

原型关键帧(12 张导出图之一,与最终实现对照):

img

img


02-热度走势对比.png

注意:原型由专用原型工具制作并发布;apps/ 里的正式实现是独立手写代码,没有导入任何原型工具生成的代码。


5. 成品展示

以下截图全部来自部署后的线上站点 http://116.62.81.154/ (浏览器实测)。

5.1 首页:热门方向总览(功能 3 + 功能 4)

进入首页即看到数据范围(样本数、会议年、关键词版本、关键词总数四张统计卡)、Top 10 热门方向榜单(计数/占比/条形)与关键词图谱(节点大小=论文数、连线=共现)。点击任一行或节点会跳到带关键词筛选的论文列表。

img

5.2 热度走势对比(功能 5 · 动图)

走势页按年份逐帧播放三大会议的热度折线:有播放/暂停、速度控制、"减少动态效果"开关、当前帧读数卡(每会显示"占比 · N 篇",不举办显示"—(不举办)"),下方提供等价的逐帧数字表格(无障碍与键盘可达)。

img

img

5.3 论文列表管理(功能 2)

搜索框支持精确查询(题目正规化后全等)与模糊查询(编号/题目/关键词),可按会议、年份过滤;表格支持分页(每页 10 条)、行内"查看/编辑/删除",删除有二次确认弹窗;移动端自动切换为卡片布局。

img

5.4 论文详情

详情页展示摘要、关键词(带来源标签:原文关键词 / 算法提取 / 手工录入)、字段来源与抓取时间(sourceName/sourceUrl/fetchedAt)、相关论文;点击可直接打开原文。

img

5.5 论文抓取与批量导入(功能 1)

单个题目支持"查询预览 / 在线查找候选"——本地未命中时联网查询官方目录返回候选,用户确认后才入库;批量导入支持文本粘贴与 .txt/.csv 文件,单批 ≤200 条,任务按 1.5s 轮询返回逐条成功/重复/失败结果,失败可重试。

img

5.6 关于与统计口径(附加功能:了解更多)

公开覆盖矩阵(真实数字:四会议年 × 50 篇抽样、200 篇全部含摘要)、统计口径 6 条规则、三大会议背景与已知限制——把"数据可信度"做成产品的一部分。

img

5.7 移动端

≤760px 断点下导航横向滚动、统计卡单列、论文列表变卡片布局,全部功能可操作。

img

img

img

5.8 部署验证

  • curl http://116.62.81.154/api/health → {"status":"ok"}
  • 重启 API 进程后再次请求 /api/papers 数据完整读回(SQLite 持久化在 /var/lib/cvscope/,由 systemd 管理 cvscope-api 服务,Nginx 同源反向代理 80 端口)。

6. 结对(人机)讨论过程描述

本项目由 DeepSeek Harness(deepseek-v4.1-flash)+ ZCode(GLM-5.3-flash)双 AI 结对完成,全程保留会话记录,以下三个案例均给出真实 Prompt/输出截图。

案例 A · AI 辅助需求分析与原型设计

协作方式:我先让 AI 通读作业与已有代码库,冻结接口契约(packages/contracts),再授权它通过浏览器自动化直接操作 Figma(类似 MCP 的工具调用),程序化生成设计系统与五页原型;原型定了交互与信息架构,再照稿手写实现。

img

img

采纳:AI 提出的"发现层改用 CVF/ECVA 官方目录、关键词标注算法提取"(因 DBLP 被反爬拦截且无摘要)经我用 curl 逐条实测后采纳;脚本程序化生成设计系统 + 热区接线的方案被采纳并复用两版。
拒绝/修改:AI 最初用"字符数×常数"估文本宽度,中文全角普遍溢出——我要求改为先测量再排版;Figma API 的三处用法错误(textAlignHorizontal 枚举大小写、OVERLAY 必须顶层 Frame、reaction 参数限制)在人工复核中修正。

案例 B · AI 辅助编码实现

协作方式:主会话冻结契约后并行开工——主线程做 API(Express + node:sqlite + 抓取解析),同时派一个前端子代理按 Figma 导出帧实现五页。前端产出了统一 API client(错误码映射/Abort/INVALID_RESPONSE 兜底)、路由级懒加载(ECharts 不进首屏包)、走势逐帧读数卡等。

img

人工核验:typecheck/lint 过后逐条修掉 9 个 React Compiler 警告;发现前端 graph 请求传 limit 而服务端契约是 nodeLimit/edgeLimit 的类型漂移,改为正确参数——这正是"契约包 + 双端类型检查"要防的问题,AI 仍会犯,必须靠检查门兜住。

案例 C · AI 辅助调试与修复(真实 Bug)

Bug 1(会话中断留下的脏行):DeepSeek Harness 会话在 replaceKeywords 中断时误删了一行 DELETE FROM paper_keywords WHERE paper_id = ?。恢复现场时用 git diff 定位:编辑论文传 keywords 时旧关键词只增不删。修复后做真实回归:创建 → PATCH 换关键词 → 确认旧词被替换 → 删除 → 404,全链路通过。

Bug 2(测试包依赖解析):测试独立成包后 tests/ 里解析不到 react-router-dom。AI 的分析是正确的:pnpm 不做依赖提升,依赖只存在于 apps/web/node_modules,从 tests/ 出发解析不到;按此结论给 tests 包补依赖、用路由型 mock 重写 4 条测试并新增 client 错误码测试,36 个测试全绿。

Bug 3(关键词质量):真实数据入 200 篇后,Top 10 里出现 benchmark、data、simple 这类泛词,还有跨标点拼出的伪短语("compared memory speed")。修复方案:n-gram 不跨子句标点、弱名词只允许参与短语、题名修辞性词(simple/worth/closer look 等)进泛词表;随后跑重算脚本(先自动备份 DB)重建全部关键词,复测 Top 10 全部变为真实研究方向(3d human pose / point clouds / 3d object detection…)。

可解释性声明

  • AI 生成的部分:工程骨架初稿、API 各模块初稿、前端页面初稿、Figma 生成脚本、部署脚本初稿。
  • 本人编写/修改的部分:需求取舍与验收口径(哪些字段必须如实标注)、缺陷的确认与修复决策(上述三个案例)、关键词抽取规则的人工复核与样本核对、部署步骤执行与验证、文档与提交审查。
  • 本人验证:所有功能都在真实环境验证过(curl 实测、浏览器逐页操作、36 个自动化测试、外网验收),博客中每个数字都来自实测或真实会话记录,没有编造。

7. 设计实现过程

7.1 功能结构

flowchart LR
  U[浏览器 React 19 + Vite 8] -->|同源 /api| P[Nginx 反向代理]
  P --> A[Express 5 API]
  P --> S[静态产物 dist]
  A --> D[(SQLite node:sqlite\n迁移/WAL/备份)]
  A --> I[抓取与清洗 ingestion]
  I --> C1[CVF 目录 CVPR/ICCV]
  I --> C2[ECVA 目录 ECCV]
  I -.被反爬拦截.-> DBLP[DBLP 书目]
  A --> K[关键词抽取 v1 + 统计]
  K --> D
  • 技术栈:TypeScript 6 全栈 + pnpm workspace(apps/web React 19 / apps/api Express 5 / packages/contracts 共享类型);数据库用 Node 24 内置 node:sqlite(免原生编译,部署友好);图表 ECharts(按路由懒加载,首屏不载图表库)。
  • 部署:systemd 管理常驻 API(127.0.0.1:3000),Nginx 把 /api/ 反代到 API、其余路径到静态产物并做 SPA 回退;SQLite 置于 /var/lib/cvscope/ 持久目录。

7.2 数据来源与覆盖矩阵(如实公开)

会议年官方目录条数已入库含摘要
CVPR 2024271550(抽样)50
ICCV 2023215650(抽样)50
ECCV 2022164550(抽样)50
ECCV 2024238750(抽样)50
  • 目录合计 8903 条已缓存;入库为限量限速的真实抽样(每会议年 50 篇,0 失败),不冒充全量;应用"关于"页公开同一张矩阵与生成时间。
  • 官方论文页没有关键词字段,因此关键词全部标注"算法提取 v1",规则可解释、可重算。
  • 逐篇保留来源(sourceName/sourceUrl/fetchedAt/字段来源),canonical_key = 会议+年份+正规化题名 保证重复导入幂等。

7.3 统计口径

  • Top 10 / 图谱 / 趋势共用同一过滤集合;统计单位是"提到该词的不同论文数",一篇重复出现只算一次。
  • 走势的每帧同时呈现:计数、样本量、占比;ECCV 奇数年 held=false 输出 null(断线显示"不举办"),未采集年份 rate 为空(显示"无数据")——绝不把缺失画成 0。

7.4 遇到的问题与解决(节选)

问题原因解决方式
DBLP 全站被 Anubis 拦截反爬 + robots 全站禁抓不绕过;发现层改走 CVF/ECVA 官方目录,博客与关于页如实说明
编辑论文关键词只增不删会话中断误删 DELETE 行git diff 定位恢复 + 真实链路回归(增→改→删→404)
tests 包解析不到 react-router-dompnpm 不做依赖提升tests 包补开发依赖 + 测试统一走别名引用源码
Top 10 出现 benchmark/data 等泛词抽取器初版无弱名词过滤v1 修订(子句切段/弱名词/泛词/题名加权)+ 全库重算(重算前自动备份 DB)
服务器 apt install nginx 找不到包Ubuntu 源列表过期apt-get update 后安装成功

8. 代码说明

以下均为仓库中的真实代码(节选),按调用链组织:契约 → 存储 → 抽取 → 统计 → 错误处理 → 前端。

8.1 契约包:会议节奏与"是否举办"(packages/contracts)

前端图表与后端统计共用这一份真值,避免"前后端各自判断 ECCV 奇数年"的类型漂移:

export const CONFERENCE_CADENCE: Record<Conference, 'annual' | 'odd' | 'even'> = {
  CVPR: 'annual',
  ICCV: 'odd',
  ECCV: 'even',
};

export function isHeldIn(conference: Conference, year: number): boolean {
  const cadence = CONFERENCE_CADENCE[conference];
  if (cadence === 'annual') return true;
  return cadence === 'odd' ? year % 2 === 1 : year % 2 === 0;
}

8.2 数据层:版本化迁移与约束(apps/api/src/db/index.ts)

SQLite 表结构在迁移里集中管理,重复迁移不破坏数据;会议字段用 CHECK 约束而不是靠前端自觉:

CREATE TABLE papers (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  canonical_key TEXT NOT NULL UNIQUE,
  title TEXT NOT NULL,
  normalized_title TEXT NOT NULL,
  conference TEXT NOT NULL CHECK (conference IN ('CVPR','ICCV','ECCV')),
  year INTEGER NOT NULL,
  abstract TEXT,
  paper_url TEXT,
  ...
);

8.3 关键词抽取 v1 的打分核心(apps/api/src/analysis/keywords.ts)

设计思路:先切段、再组短语、按信息量打分、贪心去重。题名命中的短语按词数放大,避免高频弱词 "diffusion" 挤掉更具体的 "diffusion models";单字泛名词(model/image/data)不单独成词但可参与短语:

const scored: Candidate[] = [];
for (const candidate of candidates.values()) {
  const words = candidate.text.split(' ');
  const inTitle = titleSpans.has(candidate.text);
  const lengthBonus = words.length === 2 ? 1.5 : words.length === 3 ? 1 : 0;
  // 题名命中的短语比单词更有信息量,按词数放大,避免 "diffusion" 挤掉 "diffusion models"
  const score = (inTitle ? 4 * words.length : 0) + Math.min(candidate.score, 4) + lengthBonus;
  if (words.length === 1) {
    if (WEAK_UNIGRAM.has(candidate.text)) continue; // 单字泛名词不当关键词
    if (!inTitle && candidate.score < 2) continue; // 只在摘要里出现一次的单词太弱
  }
  scored.push({ ...candidate, score });
}

scored.sort((a, b) => b.score - a.score || b.text.length - a.text.length || a.text.localeCompare(b.text));

const chosen: Candidate[] = [];
for (const candidate of scored) {
  if (chosen.length >= limit) break;
  // 不重叠:避免同时输出 "diffusion" 与 "diffusion models"
  const overlaps = chosen.some((picked) => candidate.text.includes(picked.text) || picked.text.includes(candidate.text));
  if (overlaps) continue;
  chosen.push(candidate);
}

8.4 论文写入:幂等替换关键词(apps/api/src/papers/index.ts)

这是案例 C 修复的方法:先清空旧关联再写新集合,并清理不再被引用的词,保证统计不被旧词污染;重复词在一篇内只算一次:

replaceKeywords(paperId: number, keywords: KeywordInput[]): void {
  // 先清空旧关联再写新集合,否则编辑传 keywords 时旧词只增不删
  this.db.prepare('DELETE FROM paper_keywords WHERE paper_id = ?').run(paperId);
  const seen = new Set<string>();
  for (const keyword of keywords) {
    const normalized = normalizeKeyword(keyword.label);
    if (!normalized || seen.has(normalized)) continue; // 一篇里重复出现的词只算一次
    seen.add(normalized);
    const keywordId = existing?.id ?? insertKeyword(normalized, keyword.label);
    this.db
      .prepare('INSERT OR REPLACE INTO paper_keywords (paper_id, keyword_id, origin, weight) VALUES (?, ?, ?, ?)')
      .run(paperId, keywordId, keyword.origin, keyword.weight ?? 1);
  }
}

8.5 趋势接口的缺失值口径(apps/api/src/analysis/index.ts)

"不举办"与"没采到数据"是两种不同的缺失,都不能画成 0——这是本产品统计可信度的底线:

const held = isHeldIn(conference, year);
if (!held) {
  // 不举办:缺失值,不能画成 0
  points.push({ year, conference, held: false, count: null, sampleCount: null, rate: null });
  continue;
}
// …统计该会议年的样本量与命中论文数后:
points.push({
  year, conference, held: true,
  count: hit.total,
  sampleCount: sample.total,
  rate: sample.total > 0 ? hit.total / sample.total : null,
});

8.3 统一错误体(apps/api/src/http/errors.ts)

所有业务错误都是 {error:{code,message}},内部堆栈绝不返回给客户端:

export function sendError(response: Response, error: unknown): void {
  if (error instanceof ApiError) {
    response.status(error.status).json({ error: { code: error.code, message: error.message } });
    return;
  }
  // 不把内部堆栈返回给客户端
  console.error('[api] unexpected error', error);
  response.status(500).json({ error: { code: 'INTERNAL', message: '服务内部错误' } });
}

8.4 前端 API client:错误码映射与取消(apps/web/src/api/client.ts)

全站唯一的 HTTP 入口,网络层失败、非 JSON 响应、服务端错误体、用户取消四类情况都有明确归宿:

async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {
  const url = `${API_PREFIX}${path}${buildQuery(options.query)}`;
  let response: Response;
  try {
    response = await fetch(url, { method: options.method ?? 'GET', signal: options.signal, /* … */ });
  } catch (cause) {
    if (isAbortError(cause)) throw new ApiError('ABORTED', CODE_TO_MESSAGE.ABORTED, 0);
    throw new ApiError('NETWORK', CODE_TO_MESSAGE.NETWORK, 0);
  }
  // …读取文本并 JSON.parse,非 JSON 兜底 INVALID_RESPONSE…
  if (!response.ok) throw toApiError(response.status, payload);
  if (payload === null) throw new ApiError('INVALID_RESPONSE', CODE_TO_MESSAGE.INVALID_RESPONSE, response.status);
  return payload as T;
}

8.5 关键词归一化:检索与去重共用一份规则(apps/api/src/papers/index.ts)

export function normalizeKeyword(label: string): string {
  return label
    .normalize('NFKC')
    .toLowerCase()
    .replace(/[^a-z0-9\u4e00-\u9fff+#.]+/g, ' ')
    .trim()
    .replace(/\s+/g, ' ');
}

9. 心路历程、收获

这次结对作业和我以往写课程作业最大的不同:写代码的时间变短了,"审查 AI"的时间变长了。三次真实会话里,AI 在几分钟内给出的 API 骨架、解析器和前端页面,我过去要写一整天;但 AI 也会把接口参数写漂移(limit vs nodeLimit/edgeLimit)、会留下被截断的半成品代码、会在真实数据上暴露抽取规则的漏洞——如果照单全收,这些问题全部会流到演示现场才爆发。

我最后的做法是把"人的位置"固定在四件事上:冻结契约(接口先于实现,双 AI 并行也不漂)、跑真实数据(Top 10 一出现泛词立刻暴露抽取器问题)、外网验收(部署后用无痕浏览器逐页走查)、只提交真实的东西(22 个 commit 每个都能讲清楚做了什么)。AI 给的是初稿和速度,判断与责任仍然是人的——这也正是《构建之法》第 4 章里结对编程"驾驶员-领航员"关系的AI版:AI 是不知疲倦的驾驶员,但我必须始终坐在领航员的位置上。

最大的教训是一次时间管理:低估了"真实数据闭环"的复杂度(数据源被拦截、目录解析、抽样限速),导致最后压缩交付。PSP 表 595→710 的偏差说明:预估必须给"返工"和"环境踩坑"留出 20% 余量,这个 19% 的偏差本身就是本次作业教给我的最贵一课。

10. 对 AI 结对伙伴的评价

deepseek-v4.1-flash(DeepSeek Harness):产出密度极高,且子代理并行编排(主会话做 API、子代理照 Figma 写前端)真实地压缩了关键路径。局限也很典型:中断恢复时会留下半成品(正是案例 C 的 Bug 1 来源),对"估宽度"这类看似简单的操作会给出系统性错误方案,需要人工给出"先测量再排版"的硬约束。它最大的优点是在被指出后能给出准确的根因分析——pnpm 依赖提升、Figma API 锚点语义,都一次讲透。

GLM-5.3-flash(ZCode):擅长"接手烂摊子":从会话日志恢复现场、只读侦察并行铺开、把恢复出的缺陷逐个修复并做实景回归;在收尾核验阶段用双端截图与 curl 逐条对验收,把"文档说了"和"系统真的会"区分开。不足是它同样不能代替人的判断:比如它明确提出"不能伪造提交时间戳",最终是我确认了这个决定——AI 能把风险讲清楚,但守规矩的最终决定仍是人的责任。

与传统人人结对的异同:AI 结对没有情绪、没有时区、随叫随到,产出速度极快;但它不会主动质疑需求,也会自信地写错——所以"持续 Code Review + 真实测试门"必须由人搭好。人人结对的价值在相互提醒与共同担责,AI 结对里"担责"完全落在人这边,因此人的审查纪律比传统结对更重要,而不是更不重要。

11. 交付链接与已知限制

  • 线上站点:http://116.62.81.154/ (重启后数据读回已验证)
  • CodeArts 仓库:见第 1 节;dev 分支与 v1.0.0 标签已推送
  • 原型公开链接:【待你填:Figma 文件移到 Drafts 后的分享链接】
  • 已知限制(如实公开):
    1. 论文数据为四会议年 × 50 篇的真实抽样,覆盖矩阵已在应用内公开,不代表会议全量;
    2. 关键词为算法提取 v1(官方论文页无关键词字段),方法版本可重算;
    3. DBLP 因反爬拦截不参与必须路径,未绕过其访问规则;
    4. 走势页建议配合 GIF/视频展示动图效果(截图已含播放中帧)。
...全文
47 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

88

社区成员

发帖
与我相关
我的任务
社区描述
计算机-软件工程
软件工程 高校 福建省·福州市
社区管理员
  • FZU_SE_LQF
  • *奈落*
  • 助教李烨
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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