deerflow-code/.zcode/plans/plan-sess_bc89c1c7-ec32-43b9-886f-70fa2ae83a13.md
2026-09-07 18:24:55 +08:00

61 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 深度研究第三轮:检索稳定性修复 + 参考文献确定性 + 页面对齐 AI 写作改造
## A. 两个 bug 的排查结论与修复
### A1. 第二次检索「网络波动」——确认是真问题(DDG 限流 + 错误语义混淆 + 零重试)
**排查结论**(用户判断"确实是网络波动"基本正确,但代码层面放大了它):
- 「网络波动」文案不存在于任何代码中——是收集员 LLM 看到 `{"error": "No results found"}` 信封后自己编的解释
- 真实根因:DDG html 端点对同 IP 快速连续请求限流(403/429 挑战页)→ `DDGSException` → `ddg_search/tools.py::_search_text` 把异常吞成 `[]` → 上层把「被限流」和「真没结果」混成同一个错误信封;工具层完全没有重试
**修复**(`packages/harness/deerflow/community/ddg_search/tools.py`):
1. `_search_text` 对异常加 2 次重试 + 指数退避(约 1.5s / 3s + 抖动)
2. 错误信封区分场景:真无结果 → `no results`;多次尝试仍失败 → `web search failed after N attempts (rate limited or network), 换一组检索词稍后重试`——让模型不再瞎猜「网络波动」
3. 收集员 SOUL.md 行为准则加一条(同步改种子资产 + 已安装副本 `.deer-flow/agents/deep-research-collector/`):搜索返回 error 信封时先换检索词重试一轮,而不是直接告知用户网络异常
### A2. 参考文献缺失——代码确有隐患(当前是模型自发行为,时有时无)
**排查结论**:后端没有任何「参考来源」追加逻辑;四个 runner 的报告 prompt 只要求内联 `[N]` 引用。出现过的参考列表是模型看到上下文头 `[N] 标题(URL)` 后**自发**补写的——弱模型下不可靠,与"信息够不够"无必然关系。
**修复**(prompt 指示 + 确定性兜底双保险):
1. 四个 runner(basic / detailed / deep / multi_agent)的报告 prompt 各加一条:报告最后附「## 参考来源」,按 `[N] 标题. URL` 列出正文实际引用过的来源
2. `basic.py` 新增共享函数 `ensure_reference_section(report, context_list, materials)`:报告缺少参考小节时,解析正文引用的 `[N]` 编号,按压缩上下文顺序生成编号列表追加(无编号时列全部来源,封顶 20 条;已有参考小节则不重复追加)。在各 runner 最终 `write_text("report.md", ...)` 前调用(约 7 个调用点,跳过零材料 fallback)
3. 新增测试 `tests/test_deep_research_references.py`:helper 单测(正常追加/编号映射/不重复追加/无 URL 来源)+ runner 集成断言
## B. 页面改造(核心需求):左列复用 AI 写作对话形态,右列改真沙箱
### B1. 左列 = AI 写作式对话收集面板(仿 WritingSetupChat)
- **空状态欢迎屏**(无消息时隐藏头部,展示欢迎卡片,WritingWelcome 式)+ 有消息后 `MessageList`(沿用现有绑 collector 线程的接线)+ 首 token 前「正在整理…」占位条
- **输入框换成白卡片 PromptInput 套件**(与 AI 写作完全同款组件):卡片内一行「当前对话模型」Select(沿用 ModelNameSelect)+ 高级配置入口;下方 PromptInputTextarea + PromptInputFooter + PromptInputSubmit(`status` ready/streaming,流式中变停止按钮)。经典模式入口保留在高级配置对话框
- **配置卡片进对话流**(对标 AI 写作「识别出意图后出现表单」):
- `message-list.tsx` 最小扩展(约 15 行):新增分组 `assistant:research-approval`(识别 `additional_kwargs.setup_research_approval`)+ 可选 prop `researchApprovalSlot?: ReactNode`;不传 slot 或无该载荷时零行为变化——普通对话/AI 写作完全不受影响
- workbench:收集回合结束(awaiting_report,即"意图识别完成")时向 `displayThread` 尾部注入一条虚拟 ai 消息(WritingSetupChat 的 displayThread 同款手法),slot 传现有 `ReportConfigCard` → 卡片作为助手下一轮出现在对话流里
- 写作进度卡、完成卡、摘要气泡、追问列表保留在列表下方卡片区(报告正文移到右侧沙箱)
### B2. 右列 = 工作区真沙箱(Step2SandboxLayout 的 stub 线程模式)
- 新建 `deep-research/ResearchSandboxPanel.tsx`(约 100 行,含关闭/重开)+ `useReportSandbox.ts` hook(仿 `useStep3Report` 的 stub 机制):
- threadStub:`messages = [{type:'ai', tool_calls:[{name:'write_file', args:{path:'/mnt/user-data/outputs/report.md', content: <流式报告>}}]}]`,`isLoading = job 运行中 && phase !== 'summarizing'`
- `report_delta` 首帧 → `openArtifact(write-file: 虚拟URL)` 自动展开右栏;`run.report` 每帧 upsert stub(带防抹空守卫);刷新/切换会话用 `session.reportMarkdown` 重建
- `ArtifactFileDetail` 自带能力全部免费获得:**流式期 code 视图自动滚底 → 报告写完 isLoading 翻 false 自动切 preview + 脉冲提示**(正是「生成完直接切预览」)、Streamdown 渲染的 Markdown(比现在的好看)、另存 Word/复制/下载、默认走展示层脱敏
- 布局:ResizablePanelGroup chat 60 / sandbox 40(对齐 ChatBox/圆桌),沙箱可关闭、头部按钮重开
- **删除自定义 `ResearchSandbox` 组件**;legacy 会话与经典模式共用同一右栏(`run.report` 数据源相同,行为一致)
- 已知小限制(可接受):报告配图模式下沙箱内图片可能无法经 artifacts API 解析(配图默认关闭;真需要时后续把产物落 thread artifacts)
### B3. 验证
- 后端:`PYTHONPATH=. uv run --no-sync pytest tests/ -k deep_research -q --ignore=tests/test_notification_templates.py` 全绿 + ruff;改完配置/SOUL 后 touch 触发 dev 服务重载
- 前端:`pnpm typecheck` 零新增错误(基线 51)
- 手动走查:连续两次检索不再误报、弱模型报告末尾必带参考来源、页面全流程(欢迎屏 → 对话收集 → 流内配置卡 → 沙箱流式 → 自动预览 → 摘要/追问)
## 涉及文件
**后端**:`community/ddg_search/tools.py`、`deep_research/runners/{basic,detailed,deep,multi_agent}.py`、收集员 SOUL.md(种子 + 已安装副本)、`tests/test_deep_research_references.py`(新)
**前端**:`components/workspace/messages/message-list.tsx`(可选 slot 分组)、`pages/deep-research/DeepResearchWorkbench.tsx`(大改)、`pages/deep-research/ResearchSandboxPanel.tsx`(新)、`pages/deep-research/useReportSandbox.ts`(新)
## 明确不动
- AI 写作 / 普通对话现有组件行为(message-list.tsx 仅加可选分组,缺省零变化)
- 报告写作管线的写作逻辑本身(prompt 加一条要求 + 末尾确定性追加参考小节,均为附加式)
- 深度研究后端会话/任务/事件模型(本轮不动)