ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

local-deep-research 前端回归修复解析:FastAPI 迁移后的状态一致性保障(changelog 6037)

local-deep-research 前端回归修复解析:FastAPI 迁移后的状态一致性保障(changelog 6037) local-deep-research 前端回归修复解析FastAPI 迁移后的状态一致性保障changelog #6037【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10 search engines - arXiv, PubMed, your private documents. Everything Local Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research本篇基于 changelog 片段 changelog.d/6037.bugfix.md 展开系统讲解 Local Deep ResearchLDR在完成前端从 Flask 到 FastAPI 迁移后针对过期异步更新、重复提交、设置保存乱序、流式聊天答案、下载完成判定等前端回归所做的一整批修复并结合 settings.js、research.js 等源码实现与 fastapi-migration-quality.yml 迁移 CI说明这些修复背后的排队保存queued save机制与验证手段。读完后你将理解 LDR 前端如何处理多次设置变更并发保存时的最终一致性以及如何在本地复现迁移质量门禁。一、这是一份什么样的 changelogtowncrier 片段模型changelog.d/6037.bugfix.md是 LDR 采用 towncrier 管理的每 PR 一个片段式发布说明。按 changelog.d/README.md 的约定文件名格式为changelog.d/id.category.md其中id是 PR 或 issue 编号此处为6037category取breaking、security、feature、bugfix、removal、misc之一bugfix渲染到发布说明的Bug Fixes分组每个片段只写一小段面向用户的行为描述发布工作流会在打 tag 时执行towncrier build渲染进docs/release_notes/X.Y.Z.md并附到 GitHub Release 正文本地预览可用pdm run towncrier build --draft --version X.Y.Z只读预览需要真实写文件时加--keep保留片段。因此本文主体就是对该片段中列出的每一项用户可见修复做逐条拆解它修的是什么现象、为什么会在 FastAPI 迁移后出现、以及源码中对应的机制证据。二、修复主题一迁移引入的前端回归异步更新、重复提交与流式答案片段第一段原文Fix frontend regressions after the FastAPI migration, including stale asynchronous updates, repeated submissions, ordered settings saves, streamed chat answers, and download completion.这一句话实际上覆盖了五类典型回归都是前端请求/状态机与后端新异步语义错位导致的stale asynchronous updates过期异步更新设置页/结果页对同一字段连续发起保存时后发请求可能先返回先返回的旧响应又把旧值刷回 UI。源码中可以看到为此建立的防护settings.js 中维护了pendingSaveDataL84 附近与按 key 索引的pendingSettingsSaveByKeyL2340、L3092 附近读取当前值时优先从仍在途的保存里取值避免旧响应覆盖新值。repeated submissions重复提交研究表单等入口在响应未返回前可被再次触发。对应修复思路是在提交进行中禁用/合并重复请求research.js 中的policyScopeSaveQueue Promise.resolve()L993L1033 处链式追加展示了本项目惯用的Promise 链串行化模式同类机制同样用于 results.js 的评分保存ratingSaveTailL1124-L1129。ordered settings saves有序的设置保存多个设置的写入必须按用户操作顺序落地否则先开 A 再关 A这类反转可能被乱序提交吞掉。片段第三、四段专门点名了 JSON control reversals while earlier writes are pending早期写入仍在途时保存普通设置与 JSON 控制的反转说明修复保证了反转值不会被更早的排队写入覆盖。streamed chat answers流式聊天答案迁移后聊天回答经 SSE/流式接口下发此前存在流未正确结束或完成事件丢失的问题本批修复恢复了完整的流式渲染闭环。download completion下载完成判定导出类下载如报告 PDF的完成信号在迁移后判定不准修复后以前端确认响应真正落地为准。这些现象的共同根源是Flask 时代前端与同步路由交互响应到达顺序大致可预测迁移到 FastAPI 的异步路由 Socket.IO 事件投递后响应/事件到达顺序不再保证凡是前端用最后一个响应赢假设写 UI 的地方都会产生回归。LDR 的应对不是让后端串行化而是在前端建立在途写入登记表如pendingSettingsSaveByKey并在读取与后续写入时优先引用在途值。三、修复主题二Background sweep 开关的最后确认态保持片段第二段原文Keep the Background sweep toggle at its last confirmed state when consecutive queued saves fail, while preserving conservative handling of its legacy setting.含义拆解Background sweep后台清扫开关的 UI 状态以最后一次服务端确认成功的值为准当连续多次排队保存失败时开关不会跳回某个未确认的乐观值而是停在最后一次被后端确认的状态上。同时保留了对其 legacy旧格式设置的保守处理路径——即读取到的旧配置键不会被激进迁移只按兼容语义解释。这与第二段第一段提到的ordered settings saves是同一套排队机制的两面失败不前进状态、成功才前进状态等价于把开关当成一个有确认回执的有限状态机。源码层面settings.js 中保存失败后不清空pendingSaveData、由后续保存重试携带旧值的逻辑L831-L852 一带的pendingSaveData[key] value/ 成功后delete pendingSaveData[key]模式正是这种未确认不丢值策略的载体。四、修复主题三Reset All 的排队顺序与轮询/日志回归片段第三段原文列了五件事Keep Reset All ordered after pending settings saves, avoid duplicate page/socket polling and recursive logging when the log panel is unavailable, preserve newer note ordering during error recovery, serialize news history insertion and clearing, and retain completed research results when cancellation arrives too late.逐条对应到源码证据Reset All 必须排在所有在途保存之后。settings.js L3513-L3538 直接印证了这一点注释写明flush the queued writes before resetting. Otherwise an older queued save may land after the reset实现是先把pendingSaveData快照、用Promise.allSettled(pendingSaves)等在途保存全部落地无论成败再请求URLS.SETTINGS_API.RESET_TO_DEFAULTS。如果不做这一步重置会先于旧保存到达后端旧保存随后又把刚重置的键写回旧值——这正是ordered settings saves在最危险场景整体重置下的具体应用。避免重复的页面/socket 轮询迁移后页面轮询与 Socket.IO 事件通道可能同时驱动同一数据刷新造成双倍请求修复去重后单一数据源驱动更新。日志面板不可用时的递归日志原实现在获取日志失败的异常分支里又写日志触发同样的失败请求形成递归风暴修复后该分支做短路处理。错误恢复时保留较新的笔记顺序笔记列表在失败恢复重试/回读路径中曾按旧的缓存顺序覆盖新顺序修复后以更新的时间序为准。新闻历史的插入与清理事务化serialize插入与清理由并发改为串行队列执行避免插入 A 的同时历史被清空之类的交错。取消到达过晚时保留已完成的研究结果这是一个典型的竞态——研究实际已完成并落库而取消请求晚于完成到达修复后不再因迟到的取消抹掉已完成结果。对应后端契约测试可见 test_research_lifecycle_states.py 中test_cancel_research_endpoint_leaves_the_flag_for_the_worker与test_cleanup_research_can_release_the_slot_but_preserve_its_stop_signal在 fastapi-migration-quality.yml L310-L312 引用验证取消只留停止信号给 worker、不清掉结果的行为。五、修复主题四设置反转、自动索引与基准测试轮询片段第四、五段原文Preserve the confirmed auto-index setting after failed queued saves, save ordinary and JSON control reversals while earlier writes are pending, and keep benchmark progress updating when status requests exceed the polling interval. Keep benchmark recent results and search-quality monitoring updating during slow polling, and preserve pending local-only preferences when leaving the Private-only scope.auto-index自动索引设置与 Background sweep 同策略——排队保存失败后UI 保持上一次被后端确认的值不把失败当作值已被保存。普通设置与 JSON 控制的反转可保存用户在 JSON 设置面板中改回某值、而前一次写入仍在途时反转值必须被保留并最终落库依赖pendingSettingsSaveByKey在途登记表见上文。基准测试benchmark进度在状态请求慢于轮询间隔时继续更新旧逻辑假设每次轮询窗口内必收到一次状态当某次状态请求耗时超过轮询周期慢网络/重负载进度条会卡死。修复后以最近一次成功状态为准推进而不是以轮询节拍为准。基准最近结果与搜索质量监控在慢轮询下保持更新同一根因的另一处表现——数据视图不因单个慢请求停摆。离开 Private-only scope 时保留未完成的 local-only 偏好这是一个作用域scope切换场景——当用户从仅本地的检索/隐私作用域切出时尚未确认落库的 local-only 偏好不会被直接丢弃而是随排队机制保留。research.js 中的policyScopeSaveQueueL993/L1033正是作用域设置串行保存队列从源码结构看这类scope 偏好的保存就是走该队列的。从源码结构看上述四段修复共享同一套前端原语按 key 的在途保存登记表 Promise 链串行队列 成功才前进状态、失败不丢值的回执语义。理解了这一原语片段中几乎所有条目都能映射到同一实现。六、修复的验证浏览器入口点的 Vitest 覆盖与迁移 CI片段第一段末尾还要求原文Add Vitest coverage for browser entry points and run the full shuffled frontend suite in migration CI.仓库中的落地证据Vitest 配置vite.config.js 的test段声明environment: happy-dom、globals: true、include: [tests/js/**/*.test.js]、setupFiles: [tests/js/setup.js]即浏览器端 JSsrc/local_deep_research/web/static/js/下的入口单测统一由 Vitest 以 DOM 环境运行。迁移 CI 强制跑完整打乱套件fastapi-migration-quality.yml 的vitestjobL127-L152在 Node 24 上执行npm ci后运行npm test -- --sequence.shuffle --sequence.seed3299——固定种子 3299 的全量 shuffle。打乱执行顺序是为了暴露用例间的隐式依赖迁移期最常见的测试腐化形态固定种子则保证结果可复现。后端契约测试同步把关同一 workflow 的第二个 jobL154 起用 PDM 安装依赖后运行一批精选 pytest设置持久化契约、Socket.IO 契约、研究生命周期、队列并发、CSRF 与恶意输入矩阵等L217-L320并额外校验 JUnit 报告中不允许出现 skipped 用例L330-L345——即任何被跳过的迁移测试都会直接让 CI 失败。触发条件也说明意图L5-L57只有web/fastapi_app.py、web/routers/**、web/static/js/**、tests/js/**等迁移敏感路径变更时才跑该 workflow属于迁移期质量门禁而非全量 CI。对开发者而言本地复现这两个检查只需npm ci npm test -- --sequence.shuffle --sequence.seed3299 # 与迁移 CI 相同的前端门禁以及pdm sync -d --clean后运行 workflow 中列出的精选 pytest 子集后端侧。前端脚本定义见 package.json 的test/test:coveragevitest run/vitest run --coverage。七、小结一次状态一致性专项修复综合 changelog.d/6037.bugfix.md 的五段描述与仓库源码#6037 并非零散的 UI 修补而是一次针对 FastAPI 迁移暴露出的前端异步状态一致性的专项修复其不变式可以概括为三条任何设置的 UI 值只跟随服务端已确认的状态前进失败不回滚、不丢失在途值Background sweep、auto-index、设置反转均适用破坏性/聚合操作Reset All、历史清空必须排在所有在途写入之后执行Promise.allSettled等齐后再发重置请求轮询驱动型视图benchmark 进度、结果与质量监控以最近一次成功响应推进不被单个慢请求或超期轮询卡死。配合浏览器入口点 Vitest 覆盖 固定种子全量 shuffle 的迁移 CI这些不变式在后续 PR 触碰 settings.js、research.js 等文件时会被 fastapi-migration-quality.yml 门禁持续守护这正是 LDR 在保持Everything Local Encrypted的本地部署架构下把一次大规模后端迁移的前端回归风险收敛下来的工程方式。【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10 search engines - arXiv, PubMed, your private documents. Everything Local Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表