历阶 Helix-α冲刺Day4

历阶 历阶 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

历阶 Helix-α冲刺Day4

这个作业属于哪个课程202601福大-软件工程实践-W班
这个作业要求在哪里软件工程实践团队作业-站立式会议+α冲刺
这个作业的目标完成 α 冲刺 Day4:接入 Mem0 用户长期记忆、FSRS 复习调度与正文检索,代码签入团队仓库 dev
其他参考文献《构建之法》;千问 qwen-flash;Mem0

目录

  • 历阶 Helix-α冲刺Day4
  • 一、站立式会议
  • 二、项目燃尽图
  • 三、昨日至今进展总览
  • 四、成员进展
  • 五、代码签入与测试结果记录
  • 六、程序/模块最新运行效果
  • 七、下一步计划

一、站立式会议

参会成员:周蔚琳、刘嘉奕、柳钰舒、黄奕、郑聪凌、刘锐清、林彩华、汤文琪
会议照片:

img

二、项目燃尽图

燃尽图:

img

三、昨日至今进展总览

Day3 把大模型接到服务端、甘特按计划动态渲染。今天把 AI 从「只会起草」推进到「能记住你、能复习、能找资料」,同时补齐 FSRS 复习调度闭环和正文检索第一步。

  • 用户长期记忆:汤文琪接入 Mem0,本机 pgvector 持久化(helix 库 mem0_memories 表,dim=1024),只在 helix 一个库内扩展,未另开 Qdrant/Milvus。对话和新建计划前,用当前这句话做向量检索,取 top5、截约 500 字拼进提示词;回答后再用一次短模型调用做门控,只在用户陈述稳定偏好、习惯、约束时才写入 Mem0,闲聊不写。未登录用浏览器 guest-xxx 作为 user_id,登录后切真实 id。聊天超过 10 轮时把旧对话 compact 压成一句。

  • 向量模型:周蔚琳在百炼北京地域给原来那把 Key 开通 text-embedding-v3,用兼容接口试调返回 200、向量长度 1024,供记忆检索使用。对话继续用 qwen-flash,Key 不进 Git,写进 web/.env.local。

  • FSRS 复习调度:郑聪凌接入独立 Python py-fsrs 服务,实现复习评分、下一次复习日计算和 FSRS 状态保存;复习重新做题流程把题目判分关联到 Good/Again;服务失败时进入「待计算」状态,到期复习任务排在今日列表第一条;前端不能直接改掌握状态和复习日期,复习接口加了幂等提交处理。

  • 正文检索:柳钰舒完成正文检索 Day1——新增 web/src/server/analysis/(types.ts 契约类型 + retrieval.ts 检索模块),新建计划时模型只出检索词,服务端用 Tavily 把检索词换成真实链接,逐条做存活检查(HEAD 优先、405 回退 GET),再按 Content-Type / 后缀分类(url/pdf/word/ppt),替换 composeDraft 里的检索词占位接入 analyze 最小链路;新增 readers/ 正文读入骨架(trafilatura 2.3.1 + read_web.py + venv + README),单链接实测可读出正文。

  • 前端体验:黄奕修复天梯弹层互斥(层级测试弹窗与抽屉叠开不可点击),甘特新增「撤回/复原初始排期」(撤销栈 + 排期快照);周蔚琳按测试反馈修了层级测试弹窗——未点亮时不再在 useEffect 里同步改状态,已推到 dev。

  • 测试:今天对 web 工程做了一轮功能测试(访客演示模式、Chrome、1440×900),发现 4 个问题:今日面板步骤详情弹窗漏传回调按钮无反应、甘特「今天之前」任务难改期且误拖不可撤销、双栏页面右栏吸顶、任务列表进度条标签重叠,详见第五部分。

  • 约定保持不变:密钥不进 Git、每人写进 web/.env.local 后重启;开发阶段未登录时,完成、归档、删除、导入、通关和记忆都落在本机/guest 标识下,登录注册和共用数据库留到部署。

四、成员进展

成员从昨天站立式会议到现在的进展存在的问题/遇到的困难从现在到明天站立式会议的安排心得体会今日成果
周蔚琳(152401221)在百炼北京地域给原来那把 Key 加上 text-embedding-v3,并用兼容接口试调,返回 200,向量长度 1024。按测试反馈修了层级测试弹窗:未点亮时不再在 useEffect 里同步改状态,已推到 dev。出题是否发出、图片是否换成 next/image 这两条没有改对话模型和向量模型要分开授权,只开通千问时记忆写不进去。向量还要有地方放,接记忆的同学要安装并启动 py-fsrs 服务,完成正常评分、失败重试、固定日期复现和重复提交测试。根据测试结果完善异常提示、日志记录和部署说明,确保 FSRS 服务能够稳定支持复习流程。用现有 PostgreSQL 的 pgvector,不能只放内存。开发阶段大多没登录,没有稳定用户 id,换电脑对不上同一个人。种子数据未点亮时,通关出题请求仍不会发出等接记忆的同学用这把 Key 接入 Mem0:对话继续 qwen-flash,向量用 text-embedding-v3,只在用户说出习惯时写入,检索 3 到 5 条填进现有 memory。Key 不用换,也不进 Git向量模型只负责把一句话变成数,记得住靠落库。计划、分数、复习日仍走系统记录,不放进向量。只改会挡住提交的那一处,避免和别人正在改的甘特、夜幕撞在一起向量模型已开通并试调成功。层级测试的 lint 已修并推到 dev(ecf4ccf)
郑聪凌(102400309)完成 FSRS 复习调度功能:接入独立 Python py-fsrs 服务,实现复习评分、下一次复习日计算和 FSRS 状态保存。补充复习重新做题流程,将题目判分结果关联到 FSRS 的 Good/Again。增加 FSRS 服务失败时的“待计算”状态,并保证到期复习任务排在今日列表第一条。同时限制前端直接修改掌握状态和复习日期,增加复习接口幂等提交处理。Python 服务依赖需要单独安装和启动,前后端联调还需要数据库和 FSRS 服务同时运行。部分固定日期、服务异常和重复提交场景还需要在完整运行环境中继续验证。安装并启动 py-fsrs 服务,完成正常评分、失败重试、固定日期复现和重复提交测试。根据测试结果完善异常提示、日志记录和部署说明,确保 FSRS 服务能够稳定支持复习流程。FSRS 的复习日期不能由前端直接修改,应该由服务端统一计算并保存。复习结果必须来源于用户重新完成题目后的判分,掌握状态、完成状态和复习状态也需要分开处理,才能符合说明书中的业务要求。完成 FSRS 复习调度主流程、复习重新做题流程、阶段测试联动、服务异常“待计算”处理、今日列表优先排序、复习日期只读和接口幂等控制;前端 TypeScript 检查和生产构建已通过。
汤文琪(102400305)完成 Mem0 用户长期记忆接入:本机 pgvector 持久化(helix 库 mem0_memories 表,dim=1024),只在 helix 一个库内扩展,未另开 Qdrant/Milvus。对话 / 新建计划前用当前这句话做向量检索,取 top5、截约 500 字拼进提示词;回答后用一次短模型调用做门控,只在用户陈述稳定偏好 / 习惯 / 约束时才写入 Mem0,闲聊不写;未登录用浏览器 guest-xxx 作为 user_id,登录后切真实 id。聊天超 10 轮时把旧对话 compact 压成一句。修补了助手回答满屏 Markdown 符号和回答过长两个体验问题。① qwen-flash 用 response_format=json_object 时要求 messages 里出现字面 "json",初次分类调用 400,被 catch 吞掉表现为 shouldMemorize 永远 false;②分类门控初版提示词漏了 "学习时间段 / 作息习惯" 这一类,"我习惯晚上学" 被误判 false,补例子后通过;③Mem0 会把助手视角的建议(如 "早点睡")也存成记忆,有少量噪声,待二期清理。补聊天记录 localStorage 持久化(刷新后历史对话丢失);二期做登录后把 guest 记忆搬到真实 user id 的合并逻辑,并清理 Mem0 把助手建议也入库的噪声。向量持久化不能图省事用内存库,一重启记忆就没;模型分类门控要把例子写全,少一类 qwen-flash 就会误判;加一行 [mem0] 调试日志比瞎猜快得多 —— 今天卡在 shouldMemorize=false 半小时,加日志后立刻定位到是 400 报错被静默吞了。Mem0 用户长期记忆端到端跑通,pgvector 持久化、模型门控、compact 压缩全部落地;完成 5 项自测:新偏好刷新后带出、闲聊不入库、无痕窗口记忆隔离、dev 重启后记忆仍在、中文问法命中英文记忆。
黄奕 (102400203)修复天梯弹层互斥(层级测试弹窗与抽屉叠开不可点击);甘特新增「撤回/复原初始排期」(撤销栈 + 排期快照);甘特提示语修正并移位;访客 cookie 下拖拽改期 500:演示 id(p1)非 UUID,数据库主键是 UUID,需与组员对齐;复习日"用户可调度"与 FSRS 服务端独占冲突,暂缓改动;DevTools 注入属性产生 hydration 噪音,易误判为 bug斥;与组员对齐演示数据 id 与数据库主键格式;跟进复习日用户调度方案(等 py-fsrs 协议);继续后续工作安排撤销栈记录旧日期 + 复用 markStep 回写,登录/访客态自动同步;弹层互斥(开新弹窗前关旧弹层)比调 z-index 更治本;改期前记录状态比改后记录更容易实现撤回完成甘特「撤回/复原初始排期」、天梯弹层互斥修复、甘特提示语修正,已提交 dev 分支;本地环境已更新到 dev 最新并成功启动。
柳钰舒(102400205)完成正文检索 Day1:新增 web/src/server/analysis/(types.ts 契约类型 + retrieval.ts 检索模块),新建计划时模型只出检索词,服务端用 Tavily 把检索词换成真实链接,逐条做存活检查(HEAD 优先、405 回退 GET),再按 Content-Type / 后缀分类(url/pdf/word/ppt),替换 composeDraft 里的检索词占位接入 analyze 最小链路;新增 readers/ 正文读入骨架(trafilatura 2.3.1 + read_web.py + venv + README),单链接实测可读出正文;把百炼与 Tavily 密钥配进本机 web/.env.local;端到端验证 analyze 产出 6 条真实链接资源(linkState=ok)、自检脚本分类/存活/降级 4 项全过、tsc / lint 归零;3 个提交已推 dev本机 PostgreSQL 首次安装折腾:EDB 安装器对中文用户路径会调PowerShell 脚本失败,要拷到纯 ASCII 路径静默安装;tsx 直跑脚本不加载 .env.local,给自检脚本补了手动加载;Tavily 是外部服务,失败路径一律自动降级为检索词,不编造链接明天(Day5)做正文读入 Day2:FastAPI POST /read 服务(端口 8765,trafilatura 读网页正文)+ Next.js 侧 readers.ts 客户端(超时/降级)+ 落库 body_ready/body_ref;PDF/Word/PPT 用 Docling,先验证 Python 3.13 兼容性,不行用 pypdf / python-docx / python-pptx 兜底检索模块坚持「降级优先」:无 key、读不出正文一律退回检索词,绝不编造链接,整体不报错中断;契约类型(types.ts)先定死,Day2 读入服务和模型侧都不会跑偏;端到端验证比单测更接近验收,死链过滤和降级路径都要进回归完成正文检索 Day1:Tavily 真实链接检索、存活检查与类型分类接入 analyze 流水线,替换检索词占位;正文读入骨架(trafilatura)就位并实测可读;百炼与 Tavily 密钥配置到本机;端到端验证 analyze 产出真实链接资源(linkState=ok),tsc / lint 归零。3 个提交已推 dev:feat(retrieval) 787f158、chore(readers) e6aeb96、chore(deps) c4f16bc。

AI 技术员工作情况

AI 技术员角色今日任务对团队效率的具体帮助
程序员(周蔚琳)改层级测试弹窗的出题状态:能不能出题改为渲染时计算,请求结束后再改状态这个文件再提交不会被 set-state-in-effect 拦住,出题规则和页面表现保持原样
对接说明(周蔚琳)核对 Key 已能调用 text-embedding-v3,并写明记忆接在现有 memory 参数上,向量存在同一套 PostgreSQL 的 pgvector 里接记忆的同学不用再改 Key,也不用另买向量库;以后上云时跟这台数据库一起走
程序员(郑聪凌)完成 FSRS 服务适配层和复习接口,将复习评分、题目判分、掌握状态、复习日期和异常状态串联起来;同时移除了甘特图中拖动修改 FSRS 复习日期的功能保证复习日期只能由服务端 FSRS 计算,避免前端绕过业务规则直接修改复习状态
测试与质量保障(郑聪凌)对正常复习、复习失败、固定日期、重复提交、前端构建和 TypeScript 类型进行检查提前发现服务依赖和运行环境问题,降低提交后联调失败的风险
文档对接(郑聪凌)根据需求规格说明书和系统设计说明书补充 FSRS 适配器、异常处理、“待计算”状态和复习流程说明使实现结果与说明书中的复习重新做题、阶段测试和复习日只读要求保持一致
程序员(汤文琪)实现 server/ai/memory.ts(Mem0 单例 + pgvector 配置 + searchRelevant + shouldMemorize + addTurn),改写 chat/draft 路由接入记忆检索与门控写入,新增 compact 接口压缩旧对话,前端按 guest id 传 userId。记忆不重复塞计划正文 / 笔记全文,只带和当前这句话相关的 3~5 条短句,控制 token 成本,避免共用 Key 被很快耗尽。
测试与质量保障(汤文琪)写 scripts/probe-mem0.ts 做端到端探针;跑通 5 项自测(正向记忆、闲聊反向、无痕隔离、dev 重启持久化、中文问法跨语言检索)写 scripts/probe-mem0.ts 做端到端探针;跑通 5 项自测(正向记忆、闲聊反向、无痕隔离、dev 重启持久化、中文问法跨语言检索)
程序员(黄奕)实现甘特撤回/复原初始排期(撤销栈 20 步 + 排期快照);修复天梯弹层互斥;修正甘特提示语把"拖错排期逐条改回"和"弹层叠开不可点"两类交互缺陷一次改完,提交前验收
测试员(黄奕)每项改动 lint 归零 + 浏览器实测(拖拽→撤回→复原全流程、弹层互斥、提示语布局);定位"拖拽改期 500"根因为演示 id 非 UUID(环境问题非代码 bug)提交前闭环验证,并避免团队把环境问题误当代码 bug 返工
程序员(柳钰舒)完成正文检索 Day1:Tavily 真实链接检索、存活检查、类型分类接入 analyze,替换检索词占位;新增正文读入骨架(trafilatura + read_web.py + venv + README);配好百炼与 Tavily 密钥到本机 .env.local;3 个提交已推 dev队友拉取 dev 并填入密钥即可复现「检索词 → 真实链接」效果,不再只看到灰色检索词;检索词占位被替换后,Day2 读入服务只需按已定死的契约类型对接,不用返工接口
测试员(柳钰舒)自检脚本覆盖 classifyKind 分类(url/pdf/word/ppt)、liveness 存活/失效、无 key 降级 4 项;npx tsc --noEmit 与 eslint 归零;走 Next.js 运行时端到端:guest 建任务 → analyze,验证 resources 出现 6 条真实 url(linkState=ok)、校验 100 分提交前闭环验证,把「无 key 降级」和「死链过滤」两条路径都纳入回归,避免联调阶段才暴露检索链路问题

五、代码签入与测试结果记录

代码签入记录

以下为 2026-10-25 远程 dev 上的提交。

提交人提交说明提交链接/截图
周蔚琳(152401221)fix(web): 层级测试出题不再在 effect 里同步改状态ecfeccfc
郑聪凌(102400309)fix(web): 修改了独立 Python py-fsrs 服务4e8a74cf
汤文琪(102400305)feat (ai): 接入 Mem0 用户长期记忆(pgvector 持久化 + 模型门控)5c98169
黄奕(102400203)feat(web): 甘特图撤回/复原排期与天梯弹层互斥修复5cde0d5f
柳钰舒(102400205)feat(retrieval): 接入 Tavily 真实链接检索与存活检查,替换 analyze 检索词占位787f158d
柳钰舒(102400205)chore(readers): 新增正文读入骨架(trafilatura 脚本 + 依赖清单 + README)e6aeb966
柳钰舒(102400205)chore(deps): 同步 package-lockc4f16bc2

提交记录总览:今日 dev 上有 8 次提交。接入Mem0用户长期记忆,初步完成FSRS复习调度功能,修复层级测试、甘特图等问题,接入Tavily真实链接检索与存活检查,新增正文读入骨架。

提交记录截图:

img

工作项(Issue)

工作项列表:https://devcloud.cn-north-4.huaweicloud.com/projectman/scrum/08ad145e89cd43d89513e75bf09dd94e/workitem/backlog

工作项列表截图:

img

测试等其他工作结果

2026-10-26 对 web 工程做了一轮功能测试。测试环境:本地 npm run dev(localhost:3000),访客演示模式(未登录,前端回退 mock 数据),Chrome,视口 1440×900。本轮共发现 4 个问题,分别位于今日面板回调缺失、甘特改期与撤销、双栏吸顶、任务列表进度条排版。

问题优先级 / 类型现象状态
今日看板步骤详情弹窗内按钮无反应功能缺陷除关闭 / 标记已完成 / 打开资源外,改期、复制 Prompt、做练习、去层级测试、去任务详情 5 个按钮点击无响应且不报错待修(今日面板漏传 5 个回调)
甘特「今天之前」任务难改期、误拖无法撤销交互缺陷跨周任务找不到合法落点无法改期;误拖后改动无法还原待修(落点守卫 + 跨周投放 + 撤销)
两栏页面右栏吸顶不动CSS 交互缺陷右栏内容超一屏被留在视口外,需左栏滚到底才看得到待修(补 max-height + overflow)
「我的任务」列表进度条标签与统计重叠排版缺陷L1–L6 标签绝对定位溢出,与统计行叠压待修(加大 margin)

问题一(中优先级,功能缺陷):今日看板「步骤详情」弹窗内,除「标记已完成」和「打开资源」外,其余按钮全部无反应 —— 没有弹窗、没有 toast、没有跳转,控制台也不报错。根因不是某个按钮单独的问题:StepDetailModal 内部所有交互按钮都采用「回调存在才执行」的写法(如改期是 onClick={() => (onReschedule ? onReschedule(step) : undefined)}),而 TodayPanel.tsx 渲染该组件时只传入了 step、plan、onClose、onToggle 四个参数,漏传 onReschedule、onCopyPrompt、onPractice、onGoTest、onJumpTask 五个交互回调,回调缺失就静默不响应,所以既无报错也无视觉反馈。对照验证:同样的弹窗在历阶天梯页和任务详情页表现完全正常,因为这两处父组件把回调都传齐了,证明缺陷只出在今日面板这一处调用点。修复:在 TodayPanel.tsx 渲染 StepDetailModal 的位置参照 Ladder.tsx 补齐五个回调即可,无需改动组件本身;onCopyPrompt 照抄 Ladder 的 copyPrompt(组装学习提示词写入剪贴板并 toast「学习 Prompt 已复制」),onPractice 复用面板已有的 setReviewPractice 通道。修完按按钮清单逐个回归,重点确认弹窗内八个交互点全部有响应。

问题二(中优先级,交互缺陷):甘特图里「今天之前」的任务大多没有改期途径,且误拖后的改动无法撤销。这不是单一 bug,而是两道限制叠加出的设计盲区:其一,落点守卫(GanttTimeline.tsx 对 day < today 的列设置 dropEffect='none' 且不调用 preventDefault,光标显示禁止)防止把任务排进过去日期,本身合理;其二,拖拽只能发生在当前显示的 7 列之内、不支持跨周投放 —— 演示「今天」固定 10 月 15 日,本周视图右侧还有 10/15–10/18 四个合法落点,所以 10/13、10/14 的任务能后移;但更早一周切过去后 7 列全是过去日期,一个合法落点都找不到,自然无法改期。带锁条形(mastery=fuzzy 且有复习日)学习日设为 draggable=false 是预期设计(FSRS 复习日由服务端计算、只读),非缺陷。次生问题:误拖后 markStep 已真实修改排期数据,想拖回原日期又被同一个守卫拦截,界面上没有任何撤销入口,只能靠「历史与成就」页的「重置演示数据」整体还原。修复建议:给普通任务条增加不依赖拖拽的改期入口(点击任务条弹出日期选择器,选过去日期给确认提示而非直接禁止),或支持拖起任务后翻周投放、放宽守卫为「允许落到过去列但需二次确认」,并把改期撤销做成 toast 上的「撤销」按钮。此问题与问题一存在连锁:问题一修好后详情弹窗的「改期」会把用户指去甘特图,而甘特图对老任务又拖不动,改期闭环仍是断的,建议两处一起规划。

img

问题三(低优先级,CSS 交互缺陷):页面出现两栏时(任务详情页步骤列表 + 右侧检查器,今日看板主列 + 右侧统计栏同理),向下滚动页面,最右边那栏始终吸顶不动,要等左边栏的内容全部滚完、页面触底后右栏才跟着下移,导致右栏超出一屏的部分(如「掌握状态」面板)被留在视口之外。根因是 CSS 粘性定位的使用方式:两个右栏都设置了 position: sticky; top: 96px,但没有限制 max-height、没有设置 overflow,吸顶后底部内容落在视口外,而页面滚动又完全由左栏内容主导。修复:给两个右栏容器补 max-height: calc(100vh - 96px) 与 overflow-y: auto,让右栏内容超一屏时在栏内部独立滚动,与左栏滚动进度解耦;内容不长时外观没有任何变化。若产品上希望右栏完全随文档流,也可直接去掉 sticky,但考虑到右栏承担「随时可见的检查器」职责,推荐前者。

img

问题四(低优先级,排版缺陷):「我的任务」页切换到「列表」视图后,每张计划卡片的六段层级进度条下方,L1–L6 层级标签文字与下一行「完成 9/14 级・10 月 15 日 起・共 10 天・优先级 64」的统计文字叠在一起,难以阅读。根因:层级标签不是独立文字节点,而是进度条分段的绝对定位伪元素(.level-segment:after { position: absolute; top: 12px; }),绝对定位不占布局高度,进度条容器预留高度(分段 8px + margin-bottom 12px = 20px)不够,标签从分段顶部往下 12px 起、自身约 14px 高,底沿到达容器顶部以下约 26px,超出预留高度,于是与统计行叠在同一条基线。修复:把 .level-progress 的 margin: 24px 0 12px 调大为 margin: 24px 0 28px(或等效加 padding-bottom: 18px),给悬空标签留出空间,统计行自然下移不再重叠;改完需确认「卡片」视图与甘特图等其他用到该进度条的页面没有因此出现多余空隙。更彻底的做法是把标签从绝对定位伪元素改为正常文档流内的元素(分段下方套一行六列文字),可作为二期优化。

img

img

六、程序/模块最新运行效果

  • FSRS 复习调度:接入 py-fsrs 后,复习评分、判分关联、下一次复习日计算与「待计算」处理均已生效;到期复习任务排在今日列表第一条,前端复习日期只读。
  • Mem0 用户记忆:对话 / 新建计划前按当前这句话向量检索,取 top5 拼进提示词;只在用户陈述稳定偏好时写入,闲聊不入库;超 10 轮自动 compact。

img

  • 正文检索:新建计划时模型只出检索词,服务端用 Tavily 换成真实链接并做存活检查与内容分类,analyze 产出 6 条真实链接资源(linkState=ok)。

img

  • 甘特撤回/复原:甘特新增「撤回/复原初始排期」,撤销栈记录旧日期并复用 markStep 回写,登录/访客态自动同步。

img

  • 天梯弹层互斥:层级测试弹窗与右侧抽屉不再叠开,开新弹窗前关旧弹层,关闭按钮与背景可正常点击。

img

七、下一步计划

记忆已能写入并带出,复习闭环与检索链路已初步完成,下一步将继续:1、正文读入 Day2(FastAPI /read + Next.js readers.ts 客户端 + 落库 body_ready/body_ref,PDF/Word/PPT 用 Docling 或兜底库)。2、补聊天记录 localStorage 持久化、登录后把 guest 记忆合并到真实 user id、清理 Mem0 把助手建议入库的噪声。3、对齐演示数据 id 与数据库主键格式,跟进复习日用户调度方案(等 py-fsrs 协议),并在数据库 + FSRS 服务完整环境下补完固定日期、服务异常与重复提交的联调验证。

...全文
评论
收藏 已收藏
分享
返回顶部