fix(memory): enforce compatible runtime dependencies and refresh bridge#268
fix(memory): enforce compatible runtime dependencies and refresh bridge#268End0rph1nww wants to merge 2 commits into
Conversation
Reviewer's Guide by Ameath小爱会顺着关键路径看下去,尽量让核对更清楚。 关键调用链为: 文件级变更
关联 Issue
Tips and commands
Original review guide in EnglishThe key call paths are: |
There was a problem hiding this comment.
小爱从行间细节开始逐处确认,有需要留意的地方会直接说明。
小爱已完成全部变更审查,共发布 1 条行级建议(高风险 0,中风险 1)。
Prompt for AI Agents
请逐项处理以下审查问题;修改前先核实上下文,修改后运行相关测试。
1. Windows symlink 预热使用了不同的缓存键 / Prime the snapshot workers' cache key
core/model_assets/downloads.py:46 (RIGHT)
<issue_to_address>are_symlinks_supported 会以传入目录作为缓存键。snapshot_download 的 worker 创建 .../snapshots/<revision>/... pointer 时传入的是 pointer 的父目录;这里预热的是 storage_folder(<cache>/<repo>),因此不是同一个键。没有 symlink 权限的 Windows 首次多文件下载仍可能让一个 worker 在探测完成前读到乐观的 True,并在创建 pointer 时触发 WinError 1314。
are_symlinks_supported caches by its directory argument. Snapshot workers call it for the parent of each .../snapshots/<revision>/... pointer, while this code primes storage_folder (<cache>/<repo>). The keys differ, so first multi-file downloads on Windows without symlink privileges can still race into WinError 1314.</issue_to_address>
| repo_type=str(repo_type or "model"), | ||
| ) | ||
| with _HUGGINGFACE_SYMLINK_PROBE_LOCK: | ||
| are_symlinks_supported(storage_folder) |
There was a problem hiding this comment.
[MEDIUM · correctness] Windows symlink 预热使用了不同的缓存键 / Prime the snapshot workers' cache key
are_symlinks_supported 会以传入目录作为缓存键。snapshot_download 的 worker 创建 .../snapshots/<revision>/... pointer 时传入的是 pointer 的父目录;这里预热的是 storage_folder(<cache>/<repo>),因此不是同一个键。没有 symlink 权限的 Windows 首次多文件下载仍可能让一个 worker 在探测完成前读到乐观的 True,并在创建 pointer 时触发 WinError 1314。
are_symlinks_supported caches by its directory argument. Snapshot workers call it for the parent of each .../snapshots/<revision>/... pointer, while this code primes storage_folder (<cache>/<repo>). The keys differ, so first multi-file downloads on Windows without symlink privileges can still race into WinError 1314.
置信度 94% · 可直接回复讨论 · 👍/👎 会影响后续审查
|
@Ame4th review |
There was a problem hiding this comment.
小爱从这里开始逐处看看,把想确认的地方说清楚。
小爱已完成全部变更审查,共发布 2 条行级建议(高风险 0,中风险 2)。
Prompt for AI Agents
请逐项处理以下审查问题;修改前先核实上下文,修改后运行相关测试。
1. 依赖修复会静默结束正在进行的聊天
frontend/src/features/api-settings/MemorySettingsSection.tsx:209 (RIGHT)
<issue_to_address>安装成功后这里无条件重启完整 bridge。BridgeProcess::stop 会先 POST /api/chat/close,而 _close_chat 会终止 active chat child、关闭并删除 stream session;独立的 chat 窗口仍停留在 /chat-stage,随后只能重连到新 bridge 的空会话。因此,用户在对话进行中从设置页修复长期记忆依赖会无提示终止当前对话。请在重启前保留/协调会话,或明确确认这一破坏性操作。
Original in English
After a successful install this unconditionally restarts the whole bridge. BridgeProcess::stop first posts /api/chat/close; _close_chat terminates the active chat child and closes and deletes its stream session. The independent chat window remains at /chat-stage and can only reconnect to an empty session on the new bridge. Repairing long-term-memory dependencies while a conversation is live therefore silently ends it. Preserve or coordinate the session, or require explicit confirmation before this destructive restart.
2. Windows symlink 预热未覆盖 worker 缓存目录
core/model_assets/downloads.py:63 (RIGHT)
<issue_to_address>are_symlinks_supported 按传入目录缓存结果,但这里预热的是仓库的 models--... 存储目录。Hugging Face Hub 0.36.2 的并发下载 worker 在创建 snapshots/<revision> 指针时会按该指针父目录再次查询;首次无创建 symlink 权限的 Windows 下载因此仍可让多个 worker 命中乐观缓存并抛出 WinError 1314。这使本 PR 试图修复的首下载失败路径仍然可达。请将预热/同步范围对齐到 worker 实际使用的指针目录。
Original in English
are_symlinks_supported caches by its input directory, while this only primes the models--... storage folder. Hugging Face Hub 0.36.2 concurrent download workers query it again for the parent of each snapshots/<revision> pointer. On a first Windows download without symlink privileges, workers can still observe the optimistic cache and raise WinError 1314, so the intended first-download failure remains reachable. Prime or synchronize the actual pointer-directory key used by the workers.
| }, | ||
| ); | ||
| if (isTauriDesktop()) { | ||
| await restartDesktopBridge(); |
There was a problem hiding this comment.
[MEDIUM · bug] 依赖修复会静默结束正在进行的聊天
安装成功后这里无条件重启完整 bridge。BridgeProcess::stop 会先 POST /api/chat/close,而 _close_chat 会终止 active chat child、关闭并删除 stream session;独立的 chat 窗口仍停留在 /chat-stage,随后只能重连到新 bridge 的空会话。因此,用户在对话进行中从设置页修复长期记忆依赖会无提示终止当前对话。请在重启前保留/协调会话,或明确确认这一破坏性操作。
Original in English
After a successful install this unconditionally restarts the whole bridge. BridgeProcess::stop first posts /api/chat/close; _close_chat terminates the active chat child and closes and deletes its stream session. The independent chat window remains at /chat-stage and can only reconnect to an empty session on the new bridge. Repairing long-term-memory dependencies while a conversation is live therefore silently ends it. Preserve or coordinate the session, or require explicit confirmation before this destructive restart.
置信度 99% · 可直接回复讨论 · 👍/👎 会影响后续审查
There was a problem hiding this comment.
这里是有意的维护行为,不作为 bug 处理。依赖修复会替换当前 Python 运行时中的核心包;如果不重启 bridge,当前进程仍会持有旧模块,甚至形成新旧依赖混用的状态。该重启只发生在用户从设置页主动触发依赖修复且安装成功之后,因此活跃聊天随 bridge 生命周期结束是此操作的预期结果。本 PR 不尝试跨运行时替换保留旧会话;若后续需要额外的 UX 提示,可以作为独立改进处理。
There was a problem hiding this comment.
这边已经顺着讨论整理好了,小爱就先把话题轻轻收在这里。
重启 bridge 以加载替换后的 Python 依赖是合理且必要的;问题不在于“是否应重启”,而在于这个会终止聊天的副作用对用户不可见。
当前触发入口是设置页的依赖修复操作,用户无法从该按钮及现有流程得知它会:
- 终止正在运行的 chat child;
- 删除 stream session;
- 使独立聊天窗口重连到空会话。
“用户主动安装依赖”并不等同于“用户已确认丢弃当前对话”。尤其安装完成后才执行重启,此时再发现对话被终止已经无法撤销。
不要求本 PR 实现跨 bridge 的会话迁移,但至少应在开始安装前(或检测到活跃会话时)明确告知并要求确认,例如提示“修复完成后将重启服务并结束当前对话,是否继续?”。用户取消时不应开始安装,以避免安装已完成却无法安全应用的状态。
因此,重启作为维护机制可以保留,但无提示终止活动聊天的审查结论仍然成立。
There was a problem hiding this comment.
这边已经接上了,小爱把话题轻轻收回来。
该重启用于加载新依赖是必要的,这一点没有异议;但当前实现的用户可见行为仍是:点击“安装/修复依赖”后,安装成功才无条件调用 restartDesktopBridge(),并在未提示的情况下结束活跃聊天、删除流会话。
“用户主动修复依赖”不能替代对丢弃当前会话的确认,尤其该副作用发生在安装完成后,用户已无法取消。无需在本 PR 实现跨 bridge 会话迁移,但建议在开始安装前检测活跃聊天,明确提示“修复完成后将重启服务并结束当前对话”,并允许取消;取消时不应启动安装。
若产品明确接受此破坏性行为,至少也应在按钮说明或确认弹窗中告知。否则该问题仍建议修复后再关闭。
There was a problem hiding this comment.
这边已经收束好了,小爱把话题轻轻接回来了。
重启以加载新依赖是必要的,但这不消除其破坏性副作用:当前代码会在安装成功后无条件关闭活跃 chat child 并删除 stream session,而用户在操作前没有得到提示或取消机会。
建议在启动安装前,针对活跃会话显示明确确认:“修复完成后将重启服务并结束当前对话,是否继续?”。用户取消则不安装、不重启。若决定接受此行为,也应在界面中明确告知;否则该问题仍建议保留。
| repo_type=str(repo_type or "model"), | ||
| ) | ||
| with _HUGGINGFACE_SYMLINK_PROBE_LOCK: | ||
| are_symlinks_supported(storage_folder) |
There was a problem hiding this comment.
[MEDIUM · bug] Windows symlink 预热未覆盖 worker 缓存目录
are_symlinks_supported 按传入目录缓存结果,但这里预热的是仓库的 models--... 存储目录。Hugging Face Hub 0.36.2 的并发下载 worker 在创建 snapshots/<revision> 指针时会按该指针父目录再次查询;首次无创建 symlink 权限的 Windows 下载因此仍可让多个 worker 命中乐观缓存并抛出 WinError 1314。这使本 PR 试图修复的首下载失败路径仍然可达。请将预热/同步范围对齐到 worker 实际使用的指针目录。
Original in English
are_symlinks_supported caches by its input directory, while this only primes the models--... storage folder. Hugging Face Hub 0.36.2 concurrent download workers query it again for the parent of each snapshots/<revision> pointer. On a first Windows download without symlink privileges, workers can still observe the optimistic cache and raise WinError 1314, so the intended first-download failure remains reachable. Prime or synchronize the actual pointer-directory key used by the workers.
置信度 98% · 可直接回复讨论 · 👍/👎 会影响后续审查
There was a problem hiding this comment.
这条在本 PR 固定的 huggingface-hub 0.36.2 中不成立。该版本的 _create_symlink() 正常缓存路径并不是直接把 pointer 的父目录传给 are_symlinks_supported(),而是:
commonpath = os.path.commonpath([abs_src, abs_dst])
_support_symlinks = are_symlinks_supported(commonpath)Hub 缓存中的 abs_src 为 <storage_folder>/blobs/...,abs_dst 为 <storage_folder>/snapshots/<revision>/...,所以两者的 commonpath 正好就是本 PR 预热的 storage_folder。are_symlinks_supported() 还会对两边执行相同的 Path(...).resolve() 规范化。我也用当前实际的 D 盘缓存路径核对过,预热键与 worker 键完全相同(same_key=True)。
源码中改用 abs_dst_folder 的分支仅发生在计算 common path 出现 PermissionError 或只读文件系统错误时;Windows 无 symlink 权限是在 are_symlinks_supported() 自身的探测中被捕获并将同一个 storage_folder 键缓存为 False,不会进入上述 fallback。实际全新缓存的首次并发下载也已完成。因此这里不需要修改。
There was a problem hiding this comment.
小爱把这段回应接住了,后面的交流就顺着往下走吧。
感谢澄清。基于你给出的 huggingface-hub==0.36.2 调用路径,这条意见不成立:
- 正常
_create_symlink()路径以abs_src(blobs/...)和abs_dst(snapshots/<revision>/...)计算commonpath; - 对同一仓库缓存而言,该值就是
<cache_dir>/models--...存储目录,与这里预热传入are_symlinks_supported()的路径一致; - 两处还会经过相同的
Path.resolve()规范化,因此缓存键一致; - 无 Windows 创建 symlink 权限的情形由
are_symlinks_supported()的探测处理并缓存为False,不需要进入commonpath计算失败时的 fallback。
在调用预热发生于 snapshot_download 创建并发 worker 之前的前提下,现有全局锁足以保证该存储目录对应的探测完成后,worker 才会读取稳定结果。已提供全新缓存的并发下载验证。
撤回此 finding,无需针对此项修改。
Summary
mem0ai[extras]repair with one version-aware runtime dependency contract shared by Tauri startup and the memory settings pagehuggingface-hub==0.36.2, Transformers 4, Sentence Transformers 5,mem0ai[nlp], spaCy, Click, and FastEmbedpythonw.exetqdm deadlocks while preserving application progress callbacksRoot cause
mem0ai[extras]can install Transformers 5, while the bundled Moondream integration requirestransformers>=4.51.1,<5. Transformers 4 also requires Hugging Face Hub below 1.0, but the desktop core runtime previously pinned Hub 1.24.0. The old checks only verified whether selected modules were importable, so upgrades and repairs could leave an installed-but-incompatible runtime, and the running bridge continued to expose stale module versions after installation.On Windows, Hugging Face Hub 0.x has two additional first-download edge cases:
pythonw.exe,sys.stderris unavailable. Hugging Face's internal per-file tqdm bars can then block on tqdm's global lock, leaving the UI at0 / 11 fileswhile zero-byte.incompletefiles remain.The downloader now completes the symlink probes before starting workers and disables only Hugging Face's terminal bars when no writable stderr exists. Shinsekai's own byte/file progress callback remains active.
User impact
mem0MEM0_TELEMETRY=Truestill enables mem0 telemetry when requestedValidation
pip check, actual mem0 disk-Qdrant add/search, and spaCy model loadingpythonw.exeregression probe: the formerly stuck parallel download completed normally after the terminal-progress guard.incompletefiles; the UI ended atmem0 已就绪 · 模型已就绪Refs #252
Summary by Ameath
小爱先把需要留意的部分整理出来,方便快速查看。
该 PR 将长期记忆的运行时依赖改为版本感知校验,并调整 Windows 模型下载和 Tauri bridge 刷新;审阅发现 Windows symlink 探测仍未覆盖 Hugging Face worker 使用的缓存目录,且设置页修复依赖会静默终止正在进行的聊天。
Enhancements
Tests
Original summary in English
This PR makes long-term-memory dependency checks version-aware and changes Windows model downloading and Tauri bridge refresh. The review found that the Windows symlink probe still misses the cache directories used by Hugging Face workers, and that repairing dependencies from Settings silently ends an active chat.
Enhancements
Tests