☰
从代码读懂 LLM Checker:DeterministicModelSelector 与评分核心实现原理
2026/9/29 23:31:40 网站建设 项目流程

从代码读懂 LLM Checker:DeterministicModelSelector 与评分核心实现原理

【免费下载链接】llm-checkerAdvanced CLI tool that scans your hardware and tells you exactly which LLM or sLLM models you can run locally, with full Ollama integration.项目地址: https://gitcode.com/gh_mirrors/ll/llm-checker

LLM Checker 是一个本地 LLM 模型选择器,它能扫描你的硬件,判断你到底能跑哪些本地大语言模型(LLM / sLLM),并给出带完整 Ollama 集成的推荐。这篇文章面向新手,用大白话拆解它的"大脑"——DeterministicModelSelector(确定性模型选择器)和统一评分核心(scoring core)的实现原理:四个分数怎么算、权重怎么配、为什么你的机器能拿到 70B 模型的推荐。

先看全景:一条"从硬件到推荐"的流水线

整个推荐过程可以拆成 5 步,全部发生在 src/models/deterministic-selector.js 里:

硬件画像 → 模型池 → 分类过滤 → 逐个打分(0-100) → 排序取 Top N
阶段做什么关键方法
Phase 0 数据采集读 CPU/GPU/内存,算出"可用预算"usableMemGBgetHardware/normalizeHardwareProfile
建模型池优先用本地 Ollama 缓存,没有就回退到静态目录 src/models/catalog.jsonloadModelPool
分类过滤按任务类别(coding、multimodal…)筛掉不相关的模型filterByCategory
逐个评估选最优量化 → 估内存 → 算 Q/S/F/C 四个分量 → 加权出总分evaluateModel
收尾排序、补齐"中间档"候选、可选实测探针selectModels

入口就是 selectModels(),它接收一个任务类别(默认general),返回带分数、量化建议和推荐理由(rationale)的候选列表。

Phase 0:硬件画像与"内存预算"

评分的第一步不是看模型,而是看机器。getHardware()(第 156 行起)采集 CPU、GPU、内存、加速能力,然后算出一个关键数字——可用内存预算:

  • 普通机器:min(0.8 × 总内存, 总内存 - 2GB),给系统和应用留足余量;
  • 有独显时,预算优先取VRAM;
  • Apple 统一内存(M 系列芯片)则取0.85 × 总内存。

之后 normalizeHardwareProfile() 会把来自不同检测器(src/hardware/ 下的 detector)的五花八门的数据,统一成memory.totalGB、gpu.vramGB、acceleration.supports_*的规范形状。多卡场景有个小心思:只有明确知道 VRAM 是"单卡值"时才会乘以卡数,避免把"双卡 24GB"误算成 48GB。

模型池:本地缓存优先,静态目录兜底

loadModelPool()的数据来源有两层:

  1. Ollama 抓取缓存(~/.llm-checker/cache/ollama/等),覆盖全量模型,还会检查索引是否过期(超过 14 天标记为 stale);
  2. 静态目录catalog.json 兜底,保证离线也能用。

外部模型会经过normalizeExternalModels()归一化:拆出量化变体、推断参数量、打上 coder / vision / embedding 等标签,并按model_identifier去重。

评分核心:Q / S / F / C 四个分量

真正干活的函数是 evaluateModel(),它给每个"模型 × 量化"组合打出四个 0-100 的分量:

1️⃣ Q —— 质量(Quality),calculateQualityPrior() 优先查实测基准(HumanEval+、LiveBench、MMLU-Pro 等,存于 src/data/quality-evals.js),查不到才用估算:

  • 基础分按参数量查表:0.5B ≈ 45 分,7B ≈ 75 分,70B ≈ 95 分(baseQualityByParams,第 39-46 行);
  • 模型家族加成:qwen3+4、deepseek-r1+5,yi反而 -3;
  • 量化惩罚:Q8_0 不扣分,Q4_K_M -5,Q2_K -12;
  • 新鲜度:弃用模型 -12,越新的模型越高;
  • 任务对齐:coding 类下非 coder/instruct 模型直接 -15。

2️⃣ S —— 速度(Speed),estimateSpeedProfile() 的公式非常直观:

基础TPS ≈ K(后端) ÷ 有效参数量 × 量化加速系数 × 线程/显卡加成

各后端的 K 值(backendK,第 94-99 行):

后端K 值
CUDA(NVIDIA)220
Metal(Apple 芯片)160
ARM CPU90
x86 CPU70

量化越压缩跑得越快(Q2_K ×1.35,Q8_0 只有 ×0.8)。最后把估算 TPS 与该类别的目标速度(targetSpeeds:general 40 tok/s、coding 40、summarization 60)相除,封顶 100 分。

3️⃣ F —— 契合度(Fit),calculateFitScore() 最简单:所需内存占预算比例 ≤ 0.9 得 100 分,≤ 1.0 得 70 分,超预算直接淘汰(estimateMemoryBreakdown() 会精确拆出权重内存 + KV Cache + 运行时开销;MoE 模型按总参数量算内存,避免"236B 看起来只要 14GB"的误判)。

4️⃣ C —— 上下文(Context),calculateContextScore():支持目标长度 100 分,一半 70 分,更少 0 分。注意上下文不够的模型不会被直接淘汰,只是在这个分量上失分——这体现了"降权而非排除"的设计哲学。

权重怎么配:按类别说话

四个分量的权重来自集中配置 DETERMINISTIC_WEIGHTS:

类别[Q, S, F, C]解读
general[0.45, 0.35, 0.15, 0.05]质量为主,兼顾速度
coding[0.55, 0.20, 0.15, 0.10]代码更看重质量
reasoning[0.60, 0.10, 0.20, 0.10]推理最重质量、最不重速度
embeddings[0.30, 0.50, 0.20, 0.00]向量模型只拼速度

最终分数就是加权和,再加一个大内存档位修正(见下节),截断到 0-100。用户还可以通过optimizeFor切换 speed / quality / context / coding 等偏好,getScoringWeights() 会把类别权重和用户偏好按"用户意图优先"的原则融合。

亮点机制:高容量档位修正(H 分量)

这是 PR #89 带来的修正,解决"大内存机器被推荐一堆小模型"的问题。calculateHighCapacitySizeAdjustment() 的逻辑:

  • 预算 ≥ 32GB 才触发。getHighCapacitySizeTarget()给出档位目标:≥128GB → 保底 30B、甜区 70B;48-80GB → 保底 20B、甜区 34B;32GB → 保底 13B、甜区 30B;
  • 参数低于保底线:按比例扣最多 24 分;
  • 接近甜区:最高加 12 分。

配套的 ensureFeasibleMidTierCoverage() 还会检查 Top N 里有没有"中间档"(≥7B)和多卡机的 30B 级候选,没有就从全量候选里补一个进来——保证推荐列表覆盖高中低,而不是清一色小模型。

统一评分核心:三条命令,一个裁判

早期项目里check、recommend、smart-recommend三条命令各用一套打分引擎,结果会互相矛盾。src/models/scoring-core.js 就是为了解决这个问题(对应 GitHub issue #88):

  • 把DeterministicModelSelector确立为唯一权威排序核心,共享一个无状态实例canonicalSelector(第 37 行);
  • 各命令喂给引擎的模型"形状"不同(扩展数据库行、SQL 变体行、Ollama 目录行),normalizeToDeterministic() 负责统一转换成确定性形状,并在__source字段里保留原对象引用,方便调用方拿回原始数据;
  • 对外只有一个入口 rankModels():相同的(模型,硬件)输入,任何命令都得到完全相同的分数。

调用方包括 src/ai/multi-objective-selector.js、src/models/intelligent-selector.js 和 src/data/registry-recommender.js,全部经由rankModels走同一个裁判。

可选的"实测探针":用真速度修正估算

估算终归是估算。开启enableProbe后(runQuickProbes()),选择器会对 Top 候选发一段 128 token 的真实提示词,测出实际 tok/s,再用同一套权重重新打分。实测结果按"硬件指纹 + 模型@量化"缓存到~/.llm-checker/bench.json,7 天内有效——同一台机器上重复推荐时直接命中缓存,秒出结果。

小结:为什么推荐结果"可解释"

读完全文你会发现,LLM Checker 的每个推荐都附带 rationale(如fits in 4.4/16GB, Q4_K_M, coder-tuned, CUDA backend, 7B is sweet spot,由 buildRationale() 生成),因为它的本质是一个确定性打分器:

  1. 所有输入(硬件、模型、量化)都被归一化,无随机成分,结果可复现;
  2. 分数可拆解为 Q/S/F/C + H,每一项都能说出理由;
  3. 实测基准优先于估算,且会明确标注measured/estimated来源;
  4. 统一评分核心保证三条命令口径一致。

想继续深入,可以阅读 docs/reference/technical-docs.md 了解完整技术文档,或查看 tests/deterministic-model-pool-check.js 里针对模型池的回归测试。

延伸阅读

  • 硬件检测器:src/hardware/detector.js
  • Ollama 集成客户端:src/ollama/client.js
  • 多目标选择器:src/ai/multi-objective-selector.js
  • 模型目录数据:src/models/catalog.json

【免费下载链接】llm-checkerAdvanced CLI tool that scans your hardware and tells you exactly which LLM or sLLM models you can run locally, with full Ollama integration.项目地址: https://gitcode.com/gh_mirrors/ll/llm-checker

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询