Files
kangkang/康康/AI/ModelManifest.swift
link2026 cbacd9461a feat(AI): MNN 文本模型升到 Qwen3.5-4B(taobao-mnn 预转换)
现场机 iPhone 17(A19/SME2)内存与加速均可承载 4B,质量优于 2B。

- ModelKind.mnnLLM rawValue → "Qwen3.5-4B-MNN",displayName → Qwen3.5-4B (MNN/SME2)
- ModelManifest:7 个运行时文件(llm.mnn.weight ~2.45GB + 拆分的
  visual.mnn.weight 188MB),总计 2,836,770,850 bytes(~2.64GiB)
- ModelManifestTests:文件数 7 / 总字节 / URL 更新到 Qwen3.5-4B-MNN
- CLAUDE.md §2:MNN 主模型记为 Qwen3.5-4B,MLX 兜底仍 2B

模拟器 ModelManifestTests TEST SUCCEEDED。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 20:28:14 +08:00

90 lines
5.1 KiB
Swift

import Foundation
/// : + ()
struct ModelFile: Equatable, Sendable {
let path: String
let bytes: Int
}
///
/// , README.md / .gitattributes()
/// ,
/// docs/superpowers/specs/2026-05-29-model-download-design.md A
nonisolated enum ModelManifest {
/// Caddy ( HTTPS )
/// IP( App ATS ): http://101.132.124.52:5244/
static let baseURL = URL(string: "https://file.myv0.com/")!
static func files(for kind: ModelKind) -> [ModelFile] {
switch kind {
case .llm:
// Qwen3.5-2B-4bit:, LLMModelFactory qwen3_5
// mlx-community/Qwen3.5-2B-4bit blob (HF API,2026-06 )
// tokenizer vocab.json + tokenizer.json( merges.txt /
// special_tokens_map.json / added_tokens.json),chat_template .jinja
// (preprocessor / processor / video_preprocessor),
// ,
return [
ModelFile(path: "config.json", bytes: 3_113),
ModelFile(path: "model.safetensors", bytes: 1_722_271_785),
ModelFile(path: "model.safetensors.index.json", bytes: 81_722),
ModelFile(path: "tokenizer.json", bytes: 19_989_343),
ModelFile(path: "tokenizer_config.json", bytes: 1_139),
ModelFile(path: "vocab.json", bytes: 6_722_759),
ModelFile(path: "chat_template.jinja", bytes: 7_755),
ModelFile(path: "preprocessor_config.json", bytes: 390),
ModelFile(path: "processor_config.json", bytes: 1_300),
ModelFile(path: "video_preprocessor_config.json", bytes: 385),
]
case .vl:
// Qwen3-VL-4B-Instruct-4bit: mlx-community blob
// (HF API blobs=true,2026-05 ),
// :( README.md / .gitattributes),
// mlx-vlm , VLMModelFactory
// chat_template(.json + .jinja ) video ,
// swift-transformers / Qwen3VLProcessor
return [
ModelFile(path: "config.json", bytes: 7_137),
ModelFile(path: "model.safetensors", bytes: 3_093_767_283),
ModelFile(path: "model.safetensors.index.json", bytes: 64_742),
ModelFile(path: "tokenizer.json", bytes: 11_422_654),
ModelFile(path: "tokenizer_config.json", bytes: 5_445),
ModelFile(path: "vocab.json", bytes: 2_776_833),
ModelFile(path: "merges.txt", bytes: 1_671_853),
ModelFile(path: "special_tokens_map.json", bytes: 613),
ModelFile(path: "added_tokens.json", bytes: 707),
ModelFile(path: "generation_config.json", bytes: 269),
ModelFile(path: "chat_template.json", bytes: 5_502),
ModelFile(path: "chat_template.jinja", bytes: 5_292),
ModelFile(path: "preprocessor_config.json", bytes: 782),
ModelFile(path: "video_preprocessor_config.json", bytes: 817),
]
case .mnnLLM:
// taobao-mnn/Qwen3.5-4B-MNN MNN (HF API ,2026-06)
// :config.json(MNN llm )+ llm_config.json()+ llm.mnn()
// + llm.mnn.weight( ~2.45GB)+ tokenizer.txt + visual.mnn/visual.mnn.weight(,
// mllm,) README/.gitattributes dump
return [
ModelFile(path: "config.json", bytes: 652),
ModelFile(path: "llm_config.json", bytes: 8_693),
ModelFile(path: "llm.mnn", bytes: 3_651_096),
ModelFile(path: "llm.mnn.weight", bytes: 2_629_387_626),
ModelFile(path: "tokenizer.txt", bytes: 6_465_727),
ModelFile(path: "visual.mnn", bytes: 488_096),
ModelFile(path: "visual.mnn.weight", bytes: 196_768_960),
]
}
}
static func totalBytes(for kind: ModelKind) -> Int {
files(for: kind).reduce(0) { $0 + $1.bytes }
}
/// URL = baseURL / <> / <>
static func fileURL(for kind: ModelKind, file: ModelFile) -> URL {
baseURL
.appendingPathComponent(kind.rawValue, isDirectory: true)
.appendingPathComponent(file.path)
}
}