Commit Graph

7 Commits

Author SHA1 Message Date
link2026
ad1b045e12 feat(ai): LLMSession 接 MLX-Swift,跑 Qwen3-1.7B 流式生成
按 W2 plan Task 6 + docs/superpowers/notes/2026-05-25-mlx-api-corrections.md
落地 LLM 推理底座:

- actor LLMSession 包装 MLXLLM.ModelContainer
- load(folderURL:) 用 ModelConfiguration(directory:) + LLMModelFactory.shared.loadContainer
- generate(prompt:maxTokens:) 返回 AsyncThrowingStream<TokenChunk, Error>
- 内部 container.perform { (context: ModelContext) in ... } 拿到模型上下文
- UserInput → processor.prepare → MLXLMCommon.generate(顶层函数, AsyncStream)
- Generation switch 穷举 3 个 case(chunk / info / toolCall)
- maxTokens 通过 GenerateParameters 传递,温度 0.6 topP 0.9
- 取消传播:continuation.onTermination 同步 task.cancel()
- 每 chunk yield 时计算 tok/s decodeRate

API 基线:mlx-swift-examples tag 2.29.1, commit 9bff95ca。

需用户手动:
1. Xcode 把 LLMSession.swift 拖入 体己 target (AI group)
2. ⌘B 验证 AIRuntime 不再报 "Cannot find LLMSession"
3. 把 ~/tiji-models/Qwen3-1.7B-4bit/ 拷到模拟器沙盒 Application Support/Models/
4. Task 7 (DebugAIRunner) 才能跑通

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:03:04 +08:00
link2026
ef0fbeac97 fix(ai,persistence): ModelStore + FileVault 标 @unchecked Sendable
Xcode 26 默认开启 Swift 6 严格并发检查。AIRuntime(actor)
调用 ModelStore.shared.isReady(...) 跨 actor 边界,因 ModelStore
非 Sendable 而编译报错"Expression is 'async' but is not marked
with 'await'; this is an error in the Swift 6 language mode"。

两个类的内部状态只读(rootURL: let),方法只做线程安全的
filesystem I/O,符合 Sendable 语义,标 @unchecked Sendable
即可,不必加锁或重构。

修复目标错误:
- AIRuntime.swift:48 - guard ModelStore.shared.isReady(.llm) ...
- 后续 CaptureService 调 FileVault.shared.writeJPEG 同样路径

不影响:
- HomeView/B5ResultView 里 Text "+" 的 macOS 26.0 deprecation 是
  warning,不阻塞 build,留待 UI polish 周清理

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:00:47 +08:00
link2026
771b28e7ef fix(ai): ModelKind rawValue 改为真实 HF mlx-community 仓库名
实际查 HuggingFace 后,mlx-community 下的仓库名:
- Qwen3-1.7B-4bit(不是 Qwen3-1.7B-MLX-4bit)
- Qwen2.5-VL-3B-Instruct-4bit(VL 模型带 Instruct 后缀)

改动:
- ModelKind.llm/vl rawValue 改名,这也是沙盒 Models/ 下的子目录名
- 加 huggingFaceRepo computed:"mlx-community/\(rawValue)"
- CLAUDE.md §2 表格补 HF 仓库 ID
- spec §2.2 模型来源行修正

W2 plan 中的下载脚本已陈旧(用了 huggingface-cli + 错名),
W2 retro 时会修正。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:50:20 +08:00
link2026
e7cdb45472 harden(ai): AIRuntime 去掉冗余 weak self,prepare loading 路径加注释
按 code quality review 反馈(2×P0):
- generate() 的 Task 闭包不再 [weak self];actor 单例 strong capture
  没有循环引用风险,且避免 Swift 5.10+ weak-on-actor 警告
- prepare() 的 case .loading: return 加注释说明这是有意设计,
  调用方需轮询或显示 loading UI(W3 引入 prepare 队列优化)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:33:51 +08:00
link2026
4dcd951821 feat(ai): add AIRuntime actor skeleton + TokenChunk
按 W2 plan Task 5 落地推理串行化骨架:
- TokenChunk: Sendable struct (text + decodeRate tok/s)
- AIRuntime: actor 单例
  - Status: notReady / loading / ready / error(msg)
  - prepare() async throws: 幂等加载,失败回滚 status
  - generate(prompt:maxTokens:) -> AsyncThrowingStream: 流式输出
    跨 actor 边界用 snapshot 模式捕获 self.status/llmSession
  - lastDecodeRate: 给 UI 顶部条 / Live Activity 取
- AIRuntimeError: LocalizedError, 三种 case

WIP: Build will fail until Task 6 lands LLMSession (intentional).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:30:47 +08:00
link2026
d40cb7d1e0 harden(ai): ModelStore seedFromBundle 在 DEBUG 报错,加空目录测试
按 code quality review 反馈:
- seedFromBundle 找不到 bundle 资源时,DEBUG 下 assertionFailure 提示
  target membership(release 仍静默 return),避免 W6 启用时排查困难
- 补 totalBytesReturnsZeroWhenFolderMissing 测试,覆盖 folder 不存在时
  enumerator 为 nil 的 guard 路径

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:12:26 +08:00
link2026
ad6fb660f0 feat(ai): add ModelStore with path management and bundle seed
按 W2 plan Task 4 落地模型路径管理:
- ModelKind enum: llm (Qwen3-1.7B-MLX-4bit) / vl (Qwen2.5-VL-3B-MLX-4bit)
- 用 config.json 作为 sentinel 判定模型是否就绪
- isReady / localURL / totalBytes 三个查询接口
- seedFromBundle(_:) 占位:Demo 现场预装模型旁路(W6 启用)
- shared 单例用 Application Support/Models/

测试 3 条:fresh / mark-ready / totalBytes,均用临时目录隔离 + defer cleanup。

注:.swift 文件需用户在 Xcode 拖入 target,⌘U 确认绿后 amend build commit。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:09:51 +08:00