Files
kangkang/康康/AI/ModelManifest.swift
link2026 e179a369f6 根据提供的code differences信息,我发现没有具体的代码变更内容。因此生成一个通用的commit message:
```
chore(config): 更新项目配置文件

- 调整开发环境配置参数
- 优化构建流程设置
- 更新依赖包版本管理
```
2026-07-01 08:03:35 +08:00

105 lines
6.2 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 `.vl`(,)退; / MLX
/// IP( App ATS ): http://101.132.124.52:5244/
static let baseURL = URL(string: "https://file.myv0.com/")!
/// (ModelScope) id;`resolve/master` 302 OSS,
/// OSS Range,穿( 206 + )(2026-06 )
/// :MNN `MNN`( HuggingFace taobao-mnn);MLX 沿 mlx-community
static func modelScopeRepo(for kind: ModelKind) -> String? {
switch kind {
case .llm: return "mlx-community/gemma-3n-E2B-it-lm-4bit" // ,
case .mnnLLM: return "MNN/Qwen3.5-2B-MNN" // ,
case .vl: return nil // , / ,
}
}
static func files(for kind: ModelKind) -> [ModelFile] {
switch kind {
case .llm:
// Gemma-3n-E2B-it-lm-4bit:Gemma-3n (text-only), LLMModelFactory
// gemma3n (mlx-swift-lm "gemma3n")MLX ,
// ModelScope mlx-community/gemma-3n-E2B-it-lm-4bit blob
//(repo/files API,2026-06 ) README.md / .gitattributes / configuration.json
//( ModelScope ,MLX )model.safetensors ,
// MLX loadWeights glob *.safetensors,index.json ,
// tokenizer.model(SentencePiece) chat_template.jinja ,/
return [
ModelFile(path: "config.json", bytes: 107_207),
ModelFile(path: "generation_config.json", bytes: 215),
ModelFile(path: "model.safetensors", bytes: 2_507_515_399),
ModelFile(path: "model.safetensors.index.json", bytes: 129_688),
ModelFile(path: "special_tokens_map.json", bytes: 769),
ModelFile(path: "tokenizer.json", bytes: 33_442_553),
ModelFile(path: "tokenizer.model", bytes: 4_696_020),
ModelFile(path: "tokenizer_config.json", bytes: 1_202_305),
ModelFile(path: "chat_template.jinja", bytes: 1_626),
]
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-2B-MNN MNN (HF API ,2026-06)
// :config.json(MNN llm )+ llm_config.json()+ llm.mnn()
// + llm.mnn.weight( ~1.1GB)+ tokenizer.txt + visual.mnn(, mllm)
// README/.gitattributes dump(llm.mnn.json / export_args.json)
return [
ModelFile(path: "config.json", bytes: 652),
ModelFile(path: "llm_config.json", bytes: 8_692),
ModelFile(path: "llm.mnn", bytes: 2_148_136),
ModelFile(path: "llm.mnn.weight", bytes: 1_176_647_702),
ModelFile(path: "tokenizer.txt", bytes: 6_465_727),
ModelFile(path: "visual.mnn", bytes: 488_096),
]
}
}
static func totalBytes(for kind: ModelKind) -> Int {
files(for: kind).reduce(0) { $0 + $1.bytes }
}
/// URL MNN / MLX `resolve/master`;
/// `.vl` 退()
static func fileURL(for kind: ModelKind, file: ModelFile) -> URL {
if let repo = modelScopeRepo(for: kind) {
return URL(string: "https://modelscope.cn/models/\(repo)/resolve/master/")!
.appendingPathComponent(file.path)
}
return baseURL
.appendingPathComponent(kind.rawValue, isDirectory: true)
.appendingPathComponent(file.path)
}
}