Files
PlantAI-rag-new/docs/PRD.md
adminandClaude Fable 5 dea46402e8 docs(priv): 阶段0 私有资料问答文档先行——PRD §17 FR-PRIV-001~008 + UI_SPEC §9 + 原始测试计划 + 团队上下文 + A1/T1 任务书
用户需求:客户上传 PDF 等资料进行向量化并追加进向量库,且问答可检索。
决策:全局检索融合 / BFF 直连 DeepSeek 生成私有回答 / 两路并行展示(命中才显示) /
「我的资料」管理界面挂文档 TAB 空态。改动仅限本分支,QA 金标树与红线零改动。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-07 21:20:35 +08:00

41 KiB
Raw Permalink Blame History

PRD.md —— PlantAI-rag-new 产品需求文档

版本 1.0 | 作者 PM | 本文件由 PM 独占写入,所有开发/测试 agent 只读

本文件是全项目需求的唯一来源。 开发 agent 按此实现,测试 agent 按此写用例。 每个功能点有唯一编号 FR-<模块>-<序号>,测试用例必须在追溯矩阵中与之一一对应。 需求有歧义时,向 PM 提出,不要自行解释。


0. 产品定位

面向植物生物信息学研究者的文献知识问答工作台。用户提出关于植物基因家族的科学问题,系统从已构建的文献知识库(约 100 篇论文、44,595 条关系断言)中检索证据,生成有引用锚定的答案,并展示完整的检索过程、证据来源与知识图谱。同时提供论文抽取任务的管理入口。

使用场景:桌面深度研究为主,手机端随时查询为重要补充(实验室、会议、田间)。

不做什么:默认支持同会话上下文记忆(可在设置中关闭)(上游 max_rounds:1,每次提问独立检索);不做文献全文阅读器;(2026-09-05 起:生信流程执行经对话式编排进入,见 FR-BIO)。


1. 术语表

术语 含义
会话 Session 一组问答的容器,有标题、状态、时间。注意:会话是组织单位,不是上下文单位——同一会话内的多次提问互相独立
消息 Message 会话内的一条记录,role 为 user 或 assistant
块 Block 助手消息的内容单元,判别式联合类型(text/table/code/stream/pipeline/tool/sources/graph)
来源 Source 一条支撑答案的文献证据,含标题、片段、分数、PMID/DOI 等
证据链 Chain 知识图谱上的一条多跳推理路径,由若干 hop 组成
阶段 Stage 上游 QA 服务推送的细粒度检索步骤(十余个)
相位 Phase 前端展示用的五阶段归并(规划/检索/证据/生成/完成)
上游 Upstream 现有的三个后端服务:QA(7920)、抽取(8000/7900)、Neo4j
BFF 本项目的适配层后端,前端唯一直连对象

2. 全局约定

2.1 状态枚举

会话状态 idle | running | done | error

  • idle 排队中/新建未提问 —— 空心点,ink-subtle
  • running 有进行中的问答 —— 青色 #00D4FF 脉冲点
  • done 最近一次问答成功 —— success #2ED3A0 实心点
  • error 最近一次问答失败或中断 —— error #FF5C7A 实心点

消息状态 streaming | done | error

相位状态 waiting | running | done(对应字形 ◌ / ● / ✓)

2.2 错误处理原则

  • BFF 一切错误返回统一信封 {"ok":false,"error":{"code","message","degraded"}},HTTP 状态码语义正确。
  • 前端不显示原始异常堆栈,显示 error.message 的中文可读文案。
  • degraded:true 表示「上游不可用」而非「请求有误」,UI 用降级提示(横幅/离线态)而非错误弹窗。
  • 失败必须可见:任何静默吞掉错误的实现视为缺陷。

2.3 文案约定

用户可见文案统一走 src/i18n/labels.js。例外:后端返回的 error.message 直接展示(后端已中文化)。

2.4 数据不伪造原则

UI 只展示后端真实返回的数据。禁止:占位假数据流入生产路径、把空结果渲染成看起来有内容的样子、用动画暗示实际不存在的流式过程(客户端揭示动画是明示的视觉设计,允许,但不得声称是 token 流)。


3. 模块与编号

模块 前缀 范围
应用外壳 FR-SHELL 三栏布局、顶栏、状态栏、折叠、背景
主题与无障碍 FR-THEME 深浅主题、动效降级、焦点、对比度
会话管理 FR-SESSION 列表、分组、增删改查、搜索
对话与问答 FR-CHAT 消息渲染、作曲器、流式、流水线、持久化
检索过程 FR-RETRIEVAL 工作台 Tab1
文献来源 FR-SOURCE 工作台 Tab2
提取任务 FR-EXTRACT 工作台 Tab3
知识图谱 FR-KG 工作台 Tab4
响应式 FR-RESP 四档断点与移动端专项
健康与降级 FR-HEALTH 上游探活与降级行为
生信流程编排 FR-BIO 对话式生信编排(七项引导 / 面板 / 三形态 / 独立服务)

4. FR-SHELL 应用外壳

编号 功能点 业务逻辑与边界 验收要点
FR-SHELL-001 桌面三栏网格 grid-template-columns: 260px minmax(0,1fr) 380px;grid-template-rows: 48px minmax(0,1fr) 28px;区域 "top top top" / "side chat bench" / "status status status"。页面本身不滚动(body{overflow:hidden}),滚动发生在各栏内部 1440×900 下三栏宽度精确;缩放窗口不出现横向滚动条
FR-SHELL-002 顶栏 高 48px。左:9px 渐变发光圆点 + 「海古纪 PlantAI」渐变文字(background-clip:text)。中:当前会话标题(超长省略)+ 状态徽章。右:主题切换按钮。背景 color-mix(in srgb, var(--pa-canvas) 88%, transparent) + backdrop-filter: blur(14px),底部 1px hairline 无会话时中部显示「就绪」徽章;标题超长省略而非换行
FR-SHELL-003 底部状态栏 高 28px。左:4 个 7px agent 状态点(规划/检索/证据/生成),与流水线相位联动。右:PlantAI RAG v0.1 + mono 的 QA 版本号 + 会话数 + 上游健康标记 问答进行中四点按相位依次点亮;QA 版本号来自 /api/qa/info
FR-SHELL-004 左栏折叠 折叠后宽 64px 图标轨,显示 3 个 34×34 图标按钮(会话/图谱/设置),当前项左侧 2px 渐变竖条。折叠状态写入 localStorage pa-side-collapsed 折叠/展开过渡 300ms ease-out;刷新后保持
FR-SHELL-005 右栏折叠 折叠后保留 28px 手柄条(折叠 ≠ 隐藏),点击手柄重新展开。状态写入 localStorage pa-bench-collapsed 折叠后手柄可见可点;刷新后保持
FR-SHELL-006 Aurora 背景 固定层,z-index:0,pointer-events:none。两个 560/620px 渐变光斑,blur(120px),aurora-drift 16s 往复;叠加 48px 点阵,顶部渐隐遮罩。浅色主题下 --pa-aurora-opacity:.08 不遮挡任何交互;浅色下明显衰减
FR-SHELL-007 首屏初始化 顺序:读 localStorage 主题并写 documentElement.dataset.theme(必须在挂载前,避免闪白)→ 挂载应用 → 并行请求会话列表与 /api/health、/api/qa/info → 无会话则显示欢迎空态 深色主题下刷新无白屏闪烁;接口失败不阻塞渲染

5. FR-THEME 主题与无障碍

编号 功能点 业务逻辑与边界 验收要点
FR-THEME-001 双主题等价 深色为默认。浅色不是降级稿,是同一套语义的另一组令牌值。所有组件必须在两套主题下都正确 逐组件走查两套主题无失色、无对比度不足
FR-THEME-002 切换与持久化 顶栏按钮切换,写 localStorage['pa-theme'],同步 documentElement.dataset.theme。图标日/月互换并 rotate 180°(400ms) 切换即时生效;刷新保持
FR-THEME-003 浅色 glow 衰减 浅色下所有辉光乘 --pa-glow-opacity:.35——浅底上不衰减会糊 浅色下按钮悬停辉光明显弱于深色
FR-THEME-004 动效降级 @media (prefers-reduced-motion: reduce) 下关闭全部 animation/transition;状态改由静态符号表达(实心/空心/✓/✕),不依赖运动传达信息 开启系统「减少动态效果」后无任何动画,且状态仍可辨认
FR-THEME-005 焦点与键盘 :focus-visible 输出 2px rgba(94,106,210,.5) 焦点环,offset 1px。所有交互元素键盘可达,Tab 顺序符合视觉顺序 纯键盘可完成:新建会话→输入→发送→切换 tab
FR-THEME-006 对比度 深色 ink/canvas ≈15:1,ink-muted/canvas ≥4.5:1;浅色同标准 抽检主要文本对比度达标

6. FR-SESSION 会话管理

编号 功能点 业务逻辑与边界 验收要点
FR-SESSION-001 列表与分组 按 updated_at 倒序,分「今天 / 昨天 / 更早」三组,组标签 11px/500/字距0.6px。空列表显示引导文案 跨零点后分组正确迁移
FR-SESSION-002 状态点四态 见 §2.1。running 脉冲动画,其余静态 四种状态视觉可区分,且不仅靠颜色(形状:空心/实心 + 动/静)
FR-SESSION-003 新建会话 顶部渐变按钮(40px 高)。行为:调 POST /api/sessions 创建 → 切为活动会话 → 对话区显示欢迎空态。不预先落一条空消息 连点两次产生两个独立会话,不重复
FR-SESSION-004 选择与加载 点击会话 → GET /api/sessions/{id} 拉取消息 → 渲染历史。加载中显示骨架屏。切换会话时若有进行中的流,中断该流并把原会话置 error(标注「已中断」) 历史消息含表格/图谱块能正确重渲染
FR-SESSION-005 搜索过滤 搜索框对 title 做不区分大小写的子串匹配,实时过滤(前端过滤,不发请求)。无匹配显示「无匹配会话」 输入中文/英文均可过滤;清空恢复全量
FR-SESSION-006 重命名 双击标题或右键菜单进入编辑,回车提交 PATCH /api/sessions/{id},Esc 取消。空标题不允许提交 重命名后列表与顶栏标题同步更新
FR-SESSION-007 删除 需二次确认。确认后 DELETE /api/sessions/{id}(级联删消息)。若删的是当前会话,切到列表中最新一个;列表空则显示欢迎空态 删除后刷新不再出现;消息一并清除
FR-SESSION-008 标题自动生成 新会话首次提问后,用问题前 30 字符(超出加省略号)作为标题,调 PATCH 落库。用户手动改过标题的会话(meta.title_manual=true)不再自动覆盖 首问后标题自动变化;手动改名后再提问不被覆盖
FR-SESSION-009 活动态高亮 左侧 2px 渐变竖条 + color-mix(in srgb, var(--pa-g-to) 8%, transparent) 底 + 22% 内描边 活动项一眼可辨,与悬停态区分

7. FR-CHAT 对话与问答(核心模块)

7.1 基础渲染

编号 功能点 业务逻辑与边界 验收要点
FR-CHAT-001 欢迎空态 消息为空时显示:46px 渐变菱形(✧)+ 渐变标题「海古纪 PlantAI 知识工作台」+ 副标题 + 3 张建议卡(示例问题)。点击建议卡直接以该文本提问 卡片悬停上浮 2px + 青色微光;点击即发起真实提问
FR-CHAT-002 用户消息 右对齐,最大宽 70%,渐变底(深色 135deg,#2A2A3E,#1C1C2A;浅色 #E8ECFF,#F4FBFF)+ hairline-strong 边,r12,padding 10/15px 长文本正确换行不溢出
FR-CHAT-003 助手消息 无底色全文(Linear 式),左缘 2px 透明竖线悬停变渐变。头部:24px 渐变头像(✦)+ 「PlantAI 智能体」+ 时间。内容按块联合顺序渲染 多块混排顺序正确
FR-CHAT-004 Markdown 渲染 markdown-it 解析 → DOMPurify 消毒 → v-html。表格加 md-table 类:thead 用 2px 渐变下边框,数据格 mono(表头为「说明」的列除外,保持比例字体);代码块 code-bg + hairline + mono 12.5px LLM 输出的表格/列表/加粗正确渲染;注入脚本被消毒
FR-CHAT-014 自动滚动 新消息或流式更新时滚到底。例外:用户手动向上滚动后暂停自动滚动,并显示「回到最新」按钮;点击或用户滚回底部后恢复 阅读历史时不被强制拽到底
FR-CHAT-015 内联引用 答案文本中的引用标记渲染为可点 chip,点击滚动定位到工作台「文献来源」中对应条目并高亮 2s 引用 chip 与来源列表编号一致

7.2 作曲器

编号 功能点 业务逻辑与边界 验收要点
FR-CHAT-005 输入框 r16 surface-1 卡片,:focus-within 渐变描边 + 青色辉光。textarea 无边框透明,14px/1.6,min-height 46px,max-height 160px 后内部滚动。占位符提示示例问题 多行输入自动增高至上限后滚动
FR-CHAT-006 三种模式 pill 切换,参数集定义在 config/modes.js:
问答 {use_llm:true} → /api/qa/chat/stream
方案 {use_llm:true, native_chain_enabled:true, native_chain_max_hops:3, native_chain_top_k:5} → 同上,深证据链
检索 {use_llm:false} → /api/qa/search,只出来源不出答案
激活态渐变底 + 白字 + 青光
三种模式发出的请求体字段正确;检索模式不产生答案块
FR-CHAT-007 发送与快捷键 Enter 换行,⌘/Ctrl+Enter 发送。发送按钮渐变 pill,空输入或忙碌时 disabled(opacity .45)。底部提示文案说明快捷键 快捷键在中英文输入法下均生效;空输入不可发送
FR-CHAT-011 停止/中断 流式进行中,发送按钮变为「停止」。点击 → AbortController.abort() → 关闭 SSE → 当前消息置 error 并标注「已停止」→ 已收到的块保留不丢 停止后 BFF 侧上游连接也关闭(不留悬挂请求)

7.3 流式问答(最复杂的部分,详细说明)

FR-CHAT-008 流式问答主流程

业务逻辑,按时序:

  1. 用户发送 → 前端立即在界面追加用户消息气泡 → POST /api/sessions/{id}/messages 落库(role:user)
  2. 会话状态置 running,左栏状态点开始脉冲,底栏 agent 点复位
  3. 前端追加一条助手消息骨架(status:streaming),内含一个 pipeline 块,五相位全为 waiting
  4. fetch + ReadableStream 打开 POST /api/qa/chat/stream(不能用 EventSource——请求是带 JSON body 的 POST)
  5. 逐帧消费:
    • event: progress → 取 phase 字段(BFF 已计算好,前端不解析上游 stage 名)→ 更新 pipeline 块对应相位为 running,此前相位置 done;同时把该事件的 details 追加为工作台「检索过程」的一张阶段卡
    • event: complete → payload 即完整归一化响应 → 用 answer 生成 text 块(走揭示动画)、sources 生成 sources 块、图谱数据生成 graph 块;pipeline 全部置 done
    • event: error → 消息置 error,展示 error.message,保留已收到的块
    • event: timeout → 同 error,文案为「检索超时」
    • event: raw → 记入 raw,不渲染
    • : 注释帧(keepalive)→ 忽略
  6. 每 ~3s 调 PATCH /api/sessions/{id}/messages/{mid} 做检查点持久化
  7. 终态:消息置 done/error 落库,会话状态同步,底栏 agent 点定格

边界与异常:

  • 上游最长 240s:期间必须持续有视觉反馈(相位卡 + shimmer + 已耗时计数),不得让用户面对静止界面
  • 网络中断(移动端切网常见):fetch reject → 置 error,文案「连接中断」,提供「重试」按钮。不自动重连——每次 LLM 调用昂贵,自动重试会放大成本
  • 页面刷新中途:重载后显示最后检查点内容 + 「已中断」标注,会话状态 error
  • 同一会话并发提问:忙碌时发送按钮 disabled,从交互上杜绝

FR-CHAT-009 五阶段流水线卡

相位 颜色令牌 上游 stage(由 BFF 归并)
规划 --pa-t-planning #C0A8DD understanding_started、entities_identified、related_search_started
检索 --pa-t-execution #9FBBE0 concepts_found、subquestion_retrieved、agent_review_started、subquestion_retry_started
证据 --pa-t-knowledge #9FC9A2 evidence_accepted、evidence_review_completed
生成 --pa-t-validation #DFA88F answer_generation_started
完成 --pa-t-done #C08532 completed

渲染:纵向时间线,每相位 = 16px 状态点(✓ done / ● running / ◌ waiting)+ 2px 连接线 + 相位名 + 描述(取自最近一次该相位事件的摘要)+ 右侧状态文字;running 相位额外显示 11px 旋转 spinner。卡片头部「⚙ 检索流水线」+ 整体状态徽章(语义色)。

关键约束:相位色只回答「哪一步在做什么」,语义色只回答「整体成败」,两者不得混用。

FR-CHAT-010 答案揭示动画

上游不做 token 级流式,完整答案在 complete 一次到达。前端以 30ms/字符的速度揭示,尾部显示 8×15px 青色闪烁光标(blink 1s),下方显示 3px shimmer 进度线。揭示期间用户可点击「跳过」立即显示全文。揭示结束替换为最终 text 块。

边界:答案超过 2000 字符时,揭示速度自动加快(总时长上限 8s),避免长答案等待过久。

FR-CHAT-012 错误与重试

  • 上游返回 HTTP≥400 且 detail.error_code == "invalid_llm_citation":BFF 已自动重试一次;若仍失败,前端展示「引用校验失败,请重试」并提供重试按钮
  • 其他错误:展示 error.message,提供重试按钮
  • 重试 = 用相同问题与模式重新发起,在同一条助手消息位置替换,不新增用户消息

FR-CHAT-013 消息持久化与恢复

  • 块联合完整落库(stream 块为瞬态,不落库,落库时已转为 text)
  • raw 字段保存完整归一化响应,供排查与重渲染
  • 刷新后从 GET /api/sessions/{id} 恢复全部块,包括表格、来源、图谱

8. FR-RETRIEVAL 检索过程(工作台 Tab1)

编号 功能点 业务逻辑与边界 验收要点
FR-RETRIEVAL-001 阶段卡列表 每个 SSE progress 事件生成一张卡,沿用原型「工具调用卡」视觉:折叠头(相位色图标 + 阶段中文名 + 状态点 + 耗时 mono)+ 展开体(details 以 mono 参数块呈现 + 摘要行) 一次问答后卡片数量与收到的 progress 事件数一致
FR-RETRIEVAL-002 相位筛选 chip:全部/规划/检索/证据/生成。激活态实心 #5E6AD2 底 + 白字 筛选后仅显示对应相位卡片
FR-RETRIEVAL-003 展开折叠 点击头部切换,chevron 旋转 90°,展开体 fade-slide 200ms。运行中的卡默认展开,完成后自动折叠 展开状态互相独立
FR-RETRIEVAL-004 运行中效果 运行中卡片头部 shimmer 扫光 1.8s 循环 + 状态点脉冲 完成后动效停止
FR-RETRIEVAL-005 检索计划 若响应含 retrieval_plan,在列表顶部以只读信息块展示;另展示 /api/qa/info 的 12 段 pipeline 描述作为静态说明 无 plan 时该区域不显示(不留空框)
FR-RETRIEVAL-006 空态 未提问时显示「发起提问后,这里会实时展示检索过程」 空态不显示假卡片

9. FR-SOURCE 文献来源(工作台 Tab2)

编号 功能点 业务逻辑与边界 验收要点
FR-SOURCE-001 来源列表 沿用原型「产物文件」的 mono 列表视觉。每条:序号 + 标题(超长省略)+ mono 元信息行(PMID:xxx / DOI:xxx / 分数)+ 证据片段(默认 2 行截断,点击展开) 条目数与 source_count 一致
FR-SOURCE-002 字段展示 展示归一化后的 title / snippet / score / pmid / pmcid / doi / section / support_count。缺失字段不显示占位符,不显示 undefined/null 各字段缺失组合下渲染正常
FR-SOURCE-003 外链跳转 链接优先级:url > doi(拼 https://doi.org/{doi})> pmid(拼 PubMed)> pmcid(拼 PMC)。均无则不显示链接图标。新标签页打开,带 rel="noopener" 点击真实跳转到正确文献页
FR-SOURCE-004 证据链 chains 按 chain_id 分组,每组可展开为逐跳列表:源实体 —[关系]→ 目标实体,每跳附 paper_id/PMID。跳数以徽章显示 多跳链条展开顺序正确
FR-SOURCE-005 会话级聚合 顶部切换「本次回答 / 本会话全部」。后者调 GET /api/sessions/{id}/sources,按 paper_id 去重并累计出现次数 去重正确,计数准确
FR-SOURCE-006 空态 无来源时显示「本次检索未命中文献」,不显示空列表框 空结果不误导为加载中

10. FR-EXTRACT 提取任务(工作台 Tab3)

编号 功能点 业务逻辑与边界 验收要点
FR-EXTRACT-001 任务列表 GET /api/extraction/jobs。每条沿用原型进度条视觉:任务名 + mono 百分比 + 6px 轨道 + 渐变填充 + sweep 扫光;100% 转为纯 success 色且停止扫光。上游无 progress 数值,百分比由 BFF 按 stage 派生(queued=5 / mineru=35 / llm=75 / completed=100,failed 显示失败态不显示进度条) 列表与上游一致;派生数值正确;failed 任务呈现为错误态
FR-EXTRACT-002 任务详情 点击展开 GET /api/extraction/jobs/{id},展示状态、message(中文进度描述)、统计字段(stage/species/figure_table 计数)、plan(仅 completed 有,未完成置 null 不显示) 详情字段与上游一致;未完成任务不显示 plan 且不报错
FR-EXTRACT-003 运行日志 GET /api/extraction/run-log,mono 等宽展示,最大高度内滚动,自动贴底 长日志不撑破布局
FR-EXTRACT-004 论文上传 作曲器区域附件按钮 → 选 PDF → POST /api/extraction/upload(multipart)→ 显示上传进度 → 成功返回 job_id 并刷新列表。限制:仅 PDF,单文件 ≤50MB。上游当前环境 MinerU 二进制路径缺失会导致新任务 failed(历史 27 个 failed 任务同因)——若发生,展示上游 message 的明确错误文案 非 PDF 被拒;超限被拒;错误文案可读
FR-EXTRACT-005 轮询刷新 存在 running 状态任务时每 5s 轮询列表;全部终态则停止轮询。切到其他 tab 时暂停轮询 无进行中任务时不空转
FR-EXTRACT-006 离线降级 抽取上游不可用时显示离线提示与重试按钮,不影响其他 tab 8000/7900 全停时该 tab 优雅降级

11. FR-KG 知识图谱(工作台 Tab4)

双数据源策略(重要):

  • 答案图谱:来自当前消息的 graph 块(由 QA 响应的 knowledge_graph/native_graph_chains 归一化而来)。永远可用,Neo4j 挂了也不受影响。
  • 自由浏览:来自 GET /api/kg/*,BFF 用 Bolt 直连 Neo4j。上游 /api/v1/kg/* 已损坏(指向未运行的 7687),不可依赖。
编号 功能点 业务逻辑与边界 验收要点
FR-KG-001 答案图谱渲染 手写 SVG 力导向布局。节点圆点 + 标签,边为渐变线(#5E6AD2→#00D4FF)带关系名。节点数 >50 时自动降级为列表视图并提示 图谱与答案引用的实体一致
FR-KG-002 节点着色与图例 按实体 type 着色,用品牌色 + 辅助紫 + 五相位色构成调色板,底部图例。同一 type 在会话内颜色稳定 图例与节点颜色对应
FR-KG-003 节点详情 点击节点 → 侧滑详情面板,展示实体属性;若 Neo4j 可用,额外调 GET /api/kg/entities/{name} 拉全量属性 Neo4j 不可用时仍能显示消息内已有属性
FR-KG-004 实体搜索 搜索框 → GET /api/kg/entities?q= → 按 name_norm 精确/前缀匹配(走 name_norm 索引,0.1s 内返回)→ 选中渲染其邻域。注意上游无全文索引,搜索是精确/前缀匹配,非模糊全文检索 中英文实体名(精确或前缀)均可搜到;响应 <1s
FR-KG-005 邻域展开 GET /api/kg/entities/{name}/neighborhood?depth=&limit=。深度选择 1/2,默认 1(两跳实测约 13s,需提示较慢)。节点上限 200,每跳按 paper_count/support_count 降序截断防 hub 吃满预算 深度切换生效;超限有提示不卡死
FR-KG-006 缩放与平移 滚轮/双指缩放(0.3×–3×),拖拽平移,双击复位。触摸端必须支持双指缩放与单指拖拽 手机上可流畅缩放平移
FR-KG-007 离线降级 Neo4j 不可用时:搜索与邻域功能禁用并提示离线;答案图谱照常渲染(这是双数据源的意义) 断开 Neo4j 后 tab 不白屏
FR-KG-008 空态 本次回答无图谱数据时提示「本次检索未产生图谱关系」,并引导使用实体搜索 空态不显示空画布

12. FR-RESP 响应式(手机为一等公民)

12.1 断点

编号 档位 宽度 布局规则
FR-RESP-001 Desktop ≥1280px 完整三栏 260/1fr/380
FR-RESP-002 Laptop 1024–1279px 三栏保留;左栏自动折叠为 64px 轨;右栏收窄至 340px
FR-RESP-003 Tablet 768–1023px 对话单栏铺满;左栏改左抽屉(scrim 遮罩 + 滑入),顶栏加汉堡按钮;右栏改右抽屉,顶栏加工作台按钮并显示来源数角标
FR-RESP-004 Mobile <768px 单栏;顶栏 = 汉堡 + 标题 + 工作台按钮;对话铺满;作曲器吸底;工作台为全屏覆盖层 + 顶部 tab 条;底部状态栏隐藏,四个 agent 点合并为顶栏一枚聚合状态点

抽屉与覆盖层动效沿用 ease-out 300ms;打开时 scrim 淡入,点击 scrim 或按 Esc 关闭。

12.2 移动端专项

编号 功能点 业务逻辑与边界 验收要点
FR-RESP-005 viewport 与安全区 <meta viewport ... viewport-fit=cover>;作曲器 padding-bottom: env(safe-area-inset-bottom);顶栏 env(safe-area-inset-top) iPhone 刘海/Home 条不遮挡内容
FR-RESP-006 iOS 输入放大规避 <768px 时 textarea font-size:16px(低于 16px 必触发 iOS 自动缩放)。禁止用 maximum-scale=1 规避——伤害无障碍 iPhone Safari 聚焦输入框页面不放大
FR-RESP-007 悬停态触摸等价 所有 hover 样式包在 @media (hover: hover) 内。触摸设备下:来源外链图标常驻可见、助手消息左缘线常驻、会话条目去掉悬停底色改用点击反馈 手机上无「需要悬停才出现」的功能
FR-RESP-008 触控目标 <768px 下会话条目、bench tab、模式 pill、图标按钮 min-height:44px(iOS HIG 标准,高于 DESIGN.md 的 36px) 手机上不误触
FR-RESP-009 视口高度 用 100dvh,保留 100vh 回退,规避移动浏览器地址栏伸缩导致的高度跳变 滚动时布局不跳动
FR-RESP-010 虚拟键盘 监听 visualViewport 的 resize:键盘弹出时压缩消息区高度并保持贴底,作曲器始终可见 键盘弹出不遮挡输入框
FR-RESP-011 表格横向滚动 <768px 下答案内 md-table 包一层横向滚动容器,右侧加渐隐提示。不压缩字号(可读性优先) 宽表格可横滑查看完整内容
FR-RESP-012 移动端性能降级 <768px 下 aurora 模糊半径降低或 --pa-aurora-opacity:0;图谱节点数上限降至 30 中端手机滚动流畅无卡顿
FR-RESP-013 手势(可选) 左缘右滑开会话抽屉,右滑关工作台覆盖层。不作为验收门槛 实现则可用,不实现不算缺陷

13. FR-HEALTH 健康与降级

编号 功能点 业务逻辑与边界 验收要点
FR-HEALTH-001 健康轮询 挂载后请求 GET /api/health,此后每 30s 一次。结果写入 store,驱动状态栏标记与各降级态。轮询失败不弹窗,仅标记 上游恢复后 30s 内自动解禁
FR-HEALTH-002 QA 不可用 /api/qa/* 返 503 degraded:作曲器禁用并显示「知识问答服务当前不可用」,历史会话仍可浏览 停掉 7920 后 UI 明确提示而非静默失败
FR-HEALTH-003 Neo4j 不可用 图谱 tab 搜索/邻域禁用并提示离线;答案图谱不受影响 见 FR-KG-007
FR-HEALTH-004 抽取不可用 见 FR-EXTRACT-006 仅该 tab 降级
FR-HEALTH-005 网络中断 流式中断时提示「连接中断」+ 重试按钮;不自动重连(避免重复触发昂贵 LLM 调用) 手机切换网络后有明确提示

14. 非功能要求

项 要求
首屏可交互 桌面 <2s(本地网络),手机 <3s
长任务反馈 QA 最长 240s,期间必须持续有视觉反馈,无静止超过 5s 的状态
数据安全 Neo4j 凭据只存在于 BFF 配置,绝不下发到浏览器;LLM 输出必须经 DOMPurify 消毒后才 v-html
离线容忍 前端零外网请求(无 Google Fonts、无 CDN),符合 DESIGN.md 禁令
浏览器支持 Safari 16+(iOS)、Chrome 110+、Firefox 110+

15. FR 索引(供追溯矩阵使用)

SHELL: 001–007(7)|THEME: 001–006(6)|SESSION: 001–009(9)|CHAT: 001–015(15)|RETRIEVAL: 001–006(6)|SOURCE: 001–006(6)|EXTRACT: 001–006(6)|KG: 001–008(8)|RESP: 001–013(13)|HEALTH: 001–005(5)

合计 81 个功能点。 测试用例追溯矩阵必须覆盖全部 81 项(FR-RESP-013 标注为可选,仍需有用例但允许标记为 N/A)。


16. FR-BIO 生信流程编排(对话式)

模块范围:在对话界面用自然语言驱动 73 个生信分析阶段(基因家族 21 / RNA-seq 14 / WGS 14 / 群体 5 / GWAS 9+报告)的路径规划、数据文件引导、参数确认、执行过程展示、报告生成调整、任务存档与存档复用;新增「生信任务」「生信档案」两个工作台面板;流程文档知识库问答并入生信对话;三形态部署(只 rag / 只生信 / 同部署)。

FR-BIO-001 意图分流:仅当用户明确下达分析指令时才走生信流——「用 xxx 进行分析」「帮我分析 xxxxx」「帮我跑 xxx 鉴定」类指令(任务动词+家族/对象、前缀分析句式、分析链句式、存档复用句式四通道,词典与用例表见 docs/team/cases_bioflow_intent.md v1.1);其余一律走正常问答流程——「水稻 SPL 基因家族的最新研究进展有哪些?」等问答句不进生信流(疑问引导词与问答主题词两道拦截,漏判安全优先)。(验收:明确分析指令句进入生信流;问答句照旧走 qa 检索回答,不弹出生信路径卡)

FR-BIO-002 分析路径引导:系统先回复可用分析步骤路径候选(2-3 条,依据阶段目录+流程知识库生成),渲染为可点选路径卡;用户可点选或自然语言描述修改。(验收:SPL 询问 → 回复含 2-3 条候选路径卡,每条含阶段序列与用途)

FR-BIO-003 路径校验与前置补全:LLM 候选路径经阶段目录硬校验,未知阶段直接拒绝;缺失的前置阶段自动补全并在回复中明示。(验收:伪造阶段名被拒;跳过中间阶段时前置被补全且可见)

FR-BIO-004 路径确认卡:最终阶段链以确认卡展示(逐阶段名称/用途/预计耗时),用户确认后创建任务。(验收:确认卡逐阶段可读;确认后生信任务面板出现新任务)

FR-BIO-005 数据文件引导:阶段执行前检查输入文件;缺失时自然语言告知「请将 xxx 数据文件拖入窗口上传至服务器,或在聊天窗口中指定数据文件的具体路径」,附文件引导卡。(验收:起始阶段缺 fasta → 出现该提示与文件引导卡)

FR-BIO-006 拖拽上传:文件引导卡支持拖拽/点击上传;XHR 上传实时进度(百分比);支持大文件(≥456M 基因组)。(验收:拖入文件 → 进度条推进至 100%;大文件不断流)

FR-BIO-007 服务器路径登记:用户可直接在聊天里输入服务器文件路径字符串登记为阶段输入。(验收:输入合法路径 → 输入检查通过;非法路径 → 明确报错)

FR-BIO-008 参数确认表单:阶段执行前对话告知「XXXX 步骤,可调整参数如下,可按需调整,调整完毕后继续」,并显示可编辑参数表单卡(默认值带来源标注)。(验收:每个阶段执行前出表单卡;默认值=契约文档/参数预填值且来源可见)

FR-BIO-009 继续执行:用户编辑参数后点「继续」按钮,该阶段按表单值执行。(验收:改一个参数 → 执行命令使用新值)

FR-BIO-010 自动连续执行开关:开启后按推荐参数自动连续跑完全程;可随时暂停切回手动。(验收:开启后阶段间不等待表单确认自动推进;暂停后停在下一阶段前)

FR-BIO-011 阶段进度卡:阶段链确定后生成进度卡(与现有流水线卡同款视觉);随执行逐阶段流转(等待/运行/完成/失败/跳过);运行中阶段显示实时日志尾部。(验收:执行中进度卡逐阶段点亮、日志尾滚动更新)

FR-BIO-012 失败三选一:失败阶段标红,卡片内提供「重跑/跳过/改参数重跑」三按钮。(验收:注入失败阶段 → 标红 + 三按钮出现;三种处置各自生效)

FR-BIO-013 长链折叠:阶段超过 10 个自动折叠为分组视图,可展开。(验收:>10 阶段链显示分组折叠;展开可见全部)

FR-BIO-014 断线回放:SSE 断线重连后按任务快照整体回放进度卡状态。(验收:断网 30s 重连 → 卡片恢复当前状态,无进度丢失)

FR-BIO-015 报告生成:任务最后阶段运行报告链,生成图文并茂单文件 HTML(图 base64 内嵌 + 各阶段 manifest 事实数据)。(验收:报告含图与阶段结果汇总,浏览器可打开)

FR-BIO-016 报告预览:报告登记进文档工作台,DocPane 预览(白底)。(验收:任务完成后文档 TAB 出现报告,预览白底图文正常)

FR-BIO-017 报告编辑:可像公文一样就地编辑文字、用 prompt 调整排版(走现有编辑链路)。(验收:改文字落盘;prompt 排版指令生效)

FR-BIO-018 报告导出:导出 PDF/DOCX。(验收:两种格式下载成功且文件可打开)

FR-BIO-019 图表调整:图表类 prompt(如「xxx 图表颜色换成红色」)解析为绘图参数 → 重跑产生该图的阶段 → 新图回填报告并刷新预览;纯文字排版指令走 docgen 编辑。(验收:换色指令后报告图更新为新颜色)

FR-BIO-020 任务存档提示:任务完成后对话提示「本次生信任务已完成,是否存档?可按你的要求命名并描述」;用户可放弃。(验收:完成即出存档提示;放弃不存档无副作用)

FR-BIO-021 存档执行与状态回复:按用户要求存档(过程记录、中间文件、结果文件、报告),完成后回复存档状态(名称/位置/大小)。(验收:存档后回复含上述三要素;磁盘档案目录存在)

FR-BIO-022 档案回看:「生信档案」面板可找出历次任务回看(详情/产物/报告)。(验收:存档任务出现在档案列表,详情可看)

FR-BIO-023 存档方法复用:按名称匹配存档(精确优先,模糊给候选)→ 装载阶段链与参数 → 表单预填存档值 → 按确认参数发起新任务。(验收:「用 XXX 存档任务的方法帮我跑 yyy」→ 表单预填 XXX 参数 → 新任务按此执行)

FR-BIO-024 生信任务面板:「生信任务」面板:任务列表/阶段 DAG/进度/manifest 与日志浏览/重跑。(验收:多任务浏览流畅;manifest 与日志可读;重跑成功)

FR-BIO-025 探活显隐:启动时探测 /api/bioflow/health;不可达则隐藏生信 TAB 与块分支(只部署 rag 的前端自动退化为无生信界面)。(验收:停 8098 刷新 → 生信入口消失;恢复后出现)

FR-BIO-026 流程知识库问答:生信对话内流程咨询(如「identify 需要什么输入」),答案含引用原文,UI 可跳转原文。(验收:咨询回复含引用块且可跳转;评估集通过率 ≥90%)

FR-BIO-027 三形态部署:只部署 rag(BIOFLOW_ENABLED 默认关 → 反代不注册、前端无生信痕迹);只部署生信(8098 直连不依赖 BFF,报告降级为下载 HTML);同部署(反代启用+前端显形)。(验收:三形态各自冒烟通过)

FR-BIO-028 独立服务与数据:生信服务独立进程 8098 + 独立 SQLite bioflow.db;BFF 仅流式反代 /api/bioflow/*(BIOFLOW_ENABLED 开关)+ 报告登记端点。(验收:停 BFF 生信服务仍可直连工作;BFF 重启不影响生信任务)

FR-BIO-029 Docker 执行:每阶段以 docker run --rm 拉起对应镜像执行,--cpus/--memory 资源限制,--user 宿主机 uid,BIOFLOW_DATA 只读挂载。(验收:执行日志含资源参数;容器退出即清理)

FR-BIO-030 内核等价性:金标 SPL identify 输出 24 成员 ID 与 dev 预期输出集合全等。(验收:diff 命令输出为空)

FR-BIO-031 并发与恢复:全局并发信号量上限 3(可配);生信服务重启后从 DB 恢复 in-flight 任务并续跑。(验收:第 4 个并发任务排队;重启服务后任务续跑不重跑已完成阶段)

FR-BIO-032 发布与编译:生信服务 .so 编译流水线(compile_bioflow.sh)+ 内核 4 镜像构建(build_all.sh)+ rag 侧 BIOFLOW_ENABLED 装配开关。(验收:两条流水线各自产出;SHA256SUMS 与泄露门禁通过)

BIO: 001–032(32)|上述 81 + BIO 32 = 合计 113 个功能点。生信用例追溯必须覆盖全部 32 项 FR-BIO(规模与门禁见 TEST_PLAN §10)。

17. FR-PRIV 私有资料问答(客户上传资料 → 向量化 → 追加向量库 → 问答可检索)

模块范围:客户通过对话输入框上传 PDF/DOCX/TXT 资料,资料向量化后追加进向量库(复用既有 docgen/vstore 上传链路);任何问答提问同时并行检索私有资料(全局融合),命中时在原 QA 答案后追加独立「私有资料参考」块(片段+相关度+带引用短答,两路并行不混排);未命中或服务故障用户无感;提供「我的资料」管理界面(列表+删除)。QA 8091 金标树零改动;私有资料回答由 BFF 新端点直连 DeepSeek 生成。

FR-PRIV-001 上传入库(回归确认):客户拖拽 PDF/DOCX/TXT 到输入框 → POST /api/docgen/library → vstore /api/vstore/ingest 向量化加密入库 → BFF 落 doc_library。(验收:上传成功返回条目;「我的资料」列表可见;原有限制已解除——无大小/数量限制、有进度条)

FR-PRIV-002 chunk 级索引:入库时正文按段落聚合切块(目标 600 字/单块上限 8 段/相邻重叠 1 段/每文档上限 200 块,表格矩阵化参与),经 input 数组批量嵌入(batch 16 × 并发 4)追加进独立 chunk 索引(与原 doc 级 title 索引并存、互不影响)。(验收:ingest 响应含 chunk_count>0 且 chunk_ok=true;正文片段可被 search-chunks 命中;doc 级 /search 响应与改动前逐字段一致)

FR-PRIV-003 全局并行检索:ask/search 两模式提问同时触发私有资料检索(fire-and-forget,失败静默)。(验收:命中出块;未命中/服务故障零痕迹——不出现任何块与提示,原 QA 答案不受影响)

FR-PRIV-004 私有资料回答:BFF 新端点 POST /api/qa/private 检索 chunk 索引,命中则直连 DeepSeek 生成 300 字内带 [资料n] 引用的 markdown 短答(system 约束:只能依据资料回答、不得编造、不足则答「资料中未找到相关信息」)。(验收:answer 引用编号与 items 一一对应;未命中返回 hit:false;vstore/LLM 故障返回错误信封且前端静默)

FR-PRIV-005 私有资料参考块:命中时助手消息追加 private_doc 块(标题「私有资料参考」+ 短答 + 条目列表[编号、资料名、相关度、片段]);与 QA 答案两路并行不混排;终态持久化、刷新后完整恢复;流未收口时私有结果不被 complete 覆盖(pending+flush)。(验收:ask/search 两模式卡片并行展示;刷新恢复;竞态用例不丢块)

FR-PRIV-006 我的资料管理:文档 TAB 空态区展示「我的资料」列表(名称/大小/时间)与删除(二次确认;BFF doc_library 行删除 + vstore 密文与 chunk 联动删除)。(验收:列表加载正常;删除后列表刷新,且该资料不再被检索命中)

FR-PRIV-007 存量重建与健康:存量资料(现 210 条)经后台 CLI 重建 chunk 索引(不进 HTTP,避免超时);/health 暴露 chunk_count。(验收:重建完成后 chunk_count>0;重建期间 /health /search 保持可服务)

FR-PRIV-008 降级与隔离:私有检索/LLM 故障不影响原 QA 问答;docgen 模板检索(doc 级索引)行为零变化;QA 金标树(8091)与红线文件零改动。(验收:停 vstore 后 QA 问答照常;docgen 全链路回归通过;红线 diff 为空)

索引行追加:PRIV: 001–008(8)|上述 113 + PRIV 8 = 合计 121 个功能点。私有资料用例追溯必须覆盖全部 8 项 FR-PRIV(用例表与门禁见 docs/PRIVATE_DOCS_TEST_PLAN.md)。