Skip to main content
Mirobody 不填任何 API key 也能跑:一个模型回答问题,一个模型读文档,都在同一台机器上 (怎么跑见 local-models.md)。这一页记录 2026-09-30 的实测结果、它对「看图」 意味着什么,以及让整套东西装进一台普通电脑的计划。

结论

  • 现在的默认(1.5.4)是小号:MiniCPM5-2B(Q4_K_M,1.6 GB)回答问题,GLM-OCR-0.9B(1.4 GB)读文档, 合计 3.0 GB,跑在 llama.cpp 上,16 GB 内存、没有显卡就行。在现已发布的 benchmarks/local_models/ 评测上,它 24 道题过了 19 道(Claude Code 评分 248 分得 215),12 份文档的 140 个印刷行全部存对,31 条日记条目写出 22 条; 在 1.5.4 改 harness(见下)之前,24 道题过了 16 道,140 个印刷行存对 45 个,31 条日记条目一条也没写出来。
  • 大号是 Qwen3.8-27B(GSQ-RCO IQ3_S,13 GB),实测见下:在我们的题目上答得和云端模型一样对,也能看照片, 但要约 20 GB 内存:32 GB 内存的 Mac,或 24 GB 显存的显卡。
  • 1.6.0 交付目标:把这两个小模型针对 Mirobody 做后训练,作为 Mirobody 自己的模型发布(再训练), 合计约 3 GB,和今天的小号一样,16 GB 内存、没有显卡就能跑。是两个模型,不合并成一个。只有通过了和被替换的模型同样的评测,才替换默认。
  • 看图:GLM-OCR 只读印刷的文字和表格,别的一概不会。看懂一张照片拍的是什么,比如一盘菜的热量、一块皮疹, 需要能看图的模型:大号,或云端模型。这对小模型做不到,Mirobody 会直说,而不是去猜。
  • 和云端模型比:model-choice.zh-CN.md 把小号和五个云端模型(DeepSeek V4.1 Flash、Claude Sonnet 5.5、 Claude Opus 5.5、Gemini 3.8 Flash、GPT-6 Luna)放在同一套题目上比,也写了各自的费用和谁会读到数据。

实测了什么

Apple M4 Pro 48 GB,llama.cpp b11269,demo 数据。八道题各问两遍:三个月趋势图、最新值、 变化统计、用药、化验单、基因、别人共享给我的记录、常识题。一次运行算通过:调对工具、用对视图、 要图就画图、用提问的语言作答、并且答完。然后逐个核对回答里的每个数是否在库里有来处, 每个「偏高 / 正常」是否按报告上印的范围判断。 耗时只在同一台机器、同一时段内可比。产出这些数字的评测工具没有发布;取代它的评测是 benchmarks/local_models/:通过产品自己的 API 问 24 道题、读 12 份文档和 15 句日记, 云端参照和本地两种大小一起跑。

MiniCPM5-2B 细看

它快(大多 2–70 秒一答),结构也对,毛病很集中:
  • 2026-09-30 问「过去三个月」,它没传日期,拿到一整年真实的每日读数,回答的却是 2026 年 10 月到 12 月:92 个点和三个月均值,全都不存在。
  • 有一道题(共享记录里的胆固醇)两次都没答出来(594 秒、375 秒)。
  • 要它按 JSON 输出一个读数,它把数值写进了名字。
MiniCPM5-1B 用的是 Q8_0,排除量化的影响,16 次里 12 次一个工具都不调,反过来问用户要哪种「view」、什么时区,所以后训练的底座选 2B。 这些都不是缺知识,是日期、算数、照工具的格式来,正是后训练擅长修的,也是 harness 可以整个 从模型手里拿走的。

看图

GLM-OCR 官方只有四种提示:Text Recognition:、Table Recognition:、Formula Recognition:, 以及按 JSON 模板做信息抽取。四张图(显示 128/91、心率 76 的监护仪,中文营养成分表,FDA 样例标签, 一盘菜): 所以 Mirobody 只给 GLM-OCR 发它的文字和表格两种提示(config.llm.yaml 里 local-ocr 条目), 从不发 JSON 模板,也从不问开放问题;128 和 91 是血压,由读这段文字的推理模型来判断。 从餐食照片估热量,即使模型能看图,也只能给个区间。 从 1.5.4 起,agent 会问模型服务它的模型能不能看图(llama.cpp 的 /props、Ollama 的 /api/show; mirobody/utils/config/served.py)。不能看图的模型收到的是照片的 OCR 文字而不是图片,并被告知 这只是印刷文字;问题问的是图里的东西时,它要说自己看不到这张图。

计划

先改 harness

这些对所有模型都有用,云端的也一样,而且让小模型少出错的地方。1.5.4 做到了哪一步:
  1. 算数交给工具。 均值、月均值、差值、趋势由工具算好返回,模型只负责转述。已具备:view="stats" 返回条数、 最小、最大、均值、第一条和最后一条读数及其日期、两者之差,view="month" 返回月均值;1.5.4 让 stats 的日期 成为读数自己的本地日期,日、周、月视图也说明一天怎么计。还差的是模型去用它们:2026-10-06 的评测里,小号有两道题 (p002-rhr-monthly、p003-weight-change)是自己拿原始行算的平均。
  2. 日期交给工具。 「过去三个月」变成一个由服务端解析的参数,模型从不自己算日期。还没做。
  3. 图表引用工具的行。 图表的点直接取自工具结果,不再由模型一个个手写;那 92 个假点就是手写出来的。 还没做:点仍由模型写。1.5.4 只是让网页端把多了一个括号的图画出来,画不了就明说。
  4. 每个数显示前都要核对。 回答里的数如果在任何工具结果和文档里都找不到,就标出来并重新生成。 还没做:评测的 score.py 事后数这样的数,产品本身不核对。
  5. 给小模型一个更短的提示词,按 benchmarks/local_agent/ 里那份提示词的量法来量。agent 的提示词还没做。 日记请求现在先给两个示范回答;两次评测之间,MiniCPM5-2B 的日记从 31 条写出 0 条变成最终版代码上的 22 条(第一轮改动之后是 24 条)。
1.5.4 还做了这些,不在上面的清单里(每条都在 CHANGELOG 里):
  • 表格按表头读、不用模型,不管配置的是什么模型;原生 PDF 的文字层、印刷页和 OCR 模型给出的表格都行;文本模型只拿到规则读剩的部分,并被告知那是一份医学报告的其余内容;
  • 长报告逐页读,记录和日志带上每行自己的日期给出读数;印在两页上的同一个读数只存一次,页面的打印日期不再当作读数的日期;
  • 循环输出的提取以文本长度为上限,并保留已完整的部分;
  • 没指定指标就要某种视图时返回指标目录;分钟到月的视图只保留最新的 92 个点,不再撑爆上下文;
  • 关键词不管单位和拼写都能找到读数(FER、haemoglobin、复数);
  • 所有 JSON schema 都是封闭的,OpenAI 的模型也能读上传的文件和日记;
  • 一个模型的两个槽共用一个 KV 池,一道题可以用满整个上下文。

再训练

这就是 1.6.0 要交付的,作为 Mirobody 自己的模型发布(model-choice.zh-CN.md)。 1.5.4 把 P0 做到了这里:上面的 harness 改动;评测发布在 benchmarks/local_models/ 和 benchmarks/local_ocr/,MiniCPM5-2B 的基线已记下(2026-10-06),云端参照也一起跑了。 还没做的:200–500 道题,并分成训练、验证、测试三份。 已经具备的:
  • 许可:MiniCPM5-2B 是 Apache-2.0,GLM-OCR 权重是 MIT,两家都给了官方微调路径 (MiniCPM:TRL + PEFT、LLaMA-Factory、ms-swift、unsloth;GLM-OCR:LLaMA-Factory 教程)。
  • 老师模型:大号 27B 每次都通过,并按报告印的范围判断。
  • 能算出来的奖励:回答里每个数在不在记录里,可以机械地核对,也能用来筛老师的运行。
  • 零标注成本的数据:demo 生成器能造任意多的人和时间序列;从已知数值渲染出的报告,天生带标注。
算力不大:2B 模型的 LoRA 一张 24–48 GB 的卡就够,0.9B 的 OCR 模型更少。只有训练出的模型 通过了和被替换的模型同样的检查,默认才会换。

暂不纳入

  • 看懂照片。 MiniCPM5-2B 是纯文本模型,GLM-OCR 只读字。用这对小模型时,餐食照片得到的回答是 「请描述一下吃了什么」;看懂照片仍交给能看图的模型(大号 27B,或云端 key)。小的视觉模型另立项。
  • 合并成一个模型。 两个任务要的数据和测试都不同,合并后出了回归也难定位。Mirobody 本来就把 agent 和文档分给不同的条目,两个模型直接插上即可。等两个都各自达标,再量一量一个小视觉模型同时做两件事值不值。
  • 保持更新。 工具的格式一改就要再训练一次,所以评测每晚对训练出的模型跑一遍。